feat: 新增打开企业微信客服组件

This commit is contained in:
2025-12-15 14:26:01 +08:00
parent 1854a85394
commit 5e536afeae
4 changed files with 1257 additions and 681 deletions

187
common/js/wxwork-jssdk.js Normal file
View File

@@ -0,0 +1,187 @@
/**
* 企业微信JS-SDK调用
*/
let WxWork = function () {
// 企业微信JS-SDK
this.wxwork = null;
/**
* 初始化企业微信JS-SDK
* @param {Object} params - 初始化参数
* @param {string} params.corpId - 企业ID
* @param {string} params.agentId - 应用ID
* @param {string} params.timestamp - 时间戳
* @param {string} params.nonceStr - 随机字符串
* @param {string} params.signature - 签名
* @param {Array} params.jsApiList - 需要使用的JS接口列表
*/
this.init = function (params) {
if (typeof wx !== 'undefined' && wx.config) {
// 小程序环境下的企业微信
this.wxwork = wx;
} else if (typeof WWOpenData !== 'undefined') {
// H5环境下的企业微信
this.wxwork = WWOpenData;
} else {
console.error('企业微信JS-SDK未加载');
return false;
}
this.wxwork.config({
beta: true, // 必须这么写否则wx.invoke调用形式的jsapi会有问题
debug: false, // 开启调试模式
corpId: params.corpId, // 必填,企业号的唯一标识
agentId: params.agentId, // 必填企业微信应用ID
timestamp: params.timestamp, // 必填,生成签名的时间戳
nonceStr: params.nonceStr, // 必填,生成签名的随机串
signature: params.signature, // 必填,签名
jsApiList: params.jsApiList || [
'openUserProfile',
'openEnterpriseChat',
'getContext',
'getCurExternalContact',
'openExistedChatWithMsg'
] // 必填需要使用的JS接口列表
});
return true;
};
/**
* 添加企业微信联系人
* @param {Object} params - 参数
* @param {string} params.userId - 用户ID
* @param {Function} success - 成功回调
* @param {Function} fail - 失败回调
*/
this.addContact = function (params, success, fail) {
if (!this.wxwork) {
console.error('企业微信JS-SDK未初始化');
if (fail) fail('企业微信JS-SDK未初始化');
return;
}
this.wxwork.ready(() => {
this.wxwork.invoke('openUserProfile', {
type: 'external', // 外部联系人
userId: params.userId // 用户ID
}, (res) => {
if (res.err_msg === 'openUserProfile:ok') {
if (success) success(res);
} else {
console.error('打开用户资料失败:', res);
if (fail) fail(res.err_msg);
}
});
});
};
/**
* 打开企业微信客服会话
* @param {Object} params - 参数
* @param {string} params.corpId - 企业ID
* @param {string} params.url - 客服URL
* @param {string} params.name - 会话名称
* @param {Function} success - 成功回调
* @param {Function} fail - 失败回调
*/
this.openCustomerService = function (params, success, fail) {
if (!this.wxwork) {
console.error('企业微信JS-SDK未初始化');
if (fail) fail('企业微信JS-SDK未初始化');
return;
}
this.wxwork.ready(() => {
// #ifdef MP-WEIXIN
if (typeof wx !== 'undefined' && wx.openCustomerServiceChat) {
// 微信小程序环境
wx.openCustomerServiceChat({
extInfo: {
url: params.url
},
corpId: params.corpId,
showMessageCard: true,
sendMessageTitle: params.sendMessageTitle || '',
sendMessagePath: params.sendMessagePath || '',
sendMessageImg: params.sendMessageImg || ''
});
if (success) success();
}
// #endif
// #ifdef H5
else if (typeof WWOpenData !== 'undefined') {
// H5环境
window.location.href = params.url;
if (success) success();
}
// #endif
else {
// 直接跳转链接
window.location.href = params.url;
if (success) success();
}
});
};
/**
* 生成企业微信活码链接
* @param {Object} params - 参数
* @param {string} params.configId - 活码配置ID
* @param {string} params.userId - 用户ID
* @returns {string} 活码链接
*/
this.generateContactUrl = function (params) {
// 企业微信活码链接格式
const baseUrl = 'https://work.weixin.qq.com/kfid';
if (params.configId) {
return `${baseUrl}/${params.configId}`;
}
return null;
};
/**
* 检查环境是否支持企业微信
* @returns {boolean} 是否支持
*/
this.isSupported = function () {
// #ifdef MP-WEIXIN
return typeof wx !== 'undefined' && wx.openCustomerServiceChat;
// #endif
// #ifdef H5
return typeof WWOpenData !== 'undefined' || /wxwork/i.test(navigator.userAgent);
// #endif
return false;
};
/**
* 获取当前环境信息
* @returns {Object} 环境信息
*/
this.getEnvironment = function () {
// #ifdef MP-WEIXIN
return {
platform: 'miniprogram',
isWxWork: false,
supportContact: typeof wx !== 'undefined' && wx.openCustomerServiceChat
};
// #endif
// #ifdef H5
const isWxWork = /wxwork/i.test(navigator.userAgent);
return {
platform: 'h5',
isWxWork: isWxWork,
supportContact: isWxWork || typeof WWOpenData !== 'undefined'
};
// #endif
return {
platform: 'unknown',
isWxWork: false,
supportContact: false
};
};
}
export {
WxWork
}

View File

@@ -89,19 +89,7 @@
switch (this.config.type) { switch (this.config.type) {
case 'wxwork': case 'wxwork':
// #ifdef H5 this.openWxWorkService();
location.href = this.config.wxwork_url;
// #endif
// #ifdef MP-WEIXIN
wx.openCustomerServiceChat({
extInfo: { url: this.config.wxwork_url },
corpId: this.config.corpid,
showMessageCard: true,
sendMessageTitle: this.sendMessageTitle,
sendMessagePath: this.sendMessagePath,
sendMessageImg: this.sendMessageImg
});
// #endif
break; break;
case 'third': case 'third':
location.href = this.config.third_url; location.href = this.config.third_url;
@@ -113,6 +101,64 @@
this.makePhoneCall(); this.makePhoneCall();
} }
}, },
/**
* 打开企业微信客服
* @param {boolean} useOriginalService 是否使用原有客服方式
*/
openWxWorkService(useOriginalService = false) {
// #ifdef MP-WEIXIN
if (this.config.wxwork_contact_url && !useOriginalService) {
// 直接使用活码链接跳转
wx.navigateToMiniProgram({
appId: 'wxeb490c6f9b154ef9', // 企业微信小程序AppID
path: `pages/contacts/externalContactDetail?url=${encodeURIComponent(this.config.wxwork_contact_url)}`,
success: () => {
console.log('跳转企业微信成功');
},
fail: (err) => {
console.error('跳转企业微信失败:', err);
// 降级处理:使用原有客服方式
this.fallbackToOriginalService();
}
});
} else {
// 使用原有的客服会话方式
wx.openCustomerServiceChat({
extInfo: { url: this.config.wxwork_url },
corpId: this.config.corpid,
showMessageCard: true,
sendMessageTitle: this.sendMessageTitle,
sendMessagePath: this.sendMessagePath,
sendMessageImg: this.sendMessageImg
});
}
// #endif
// #ifdef H5
if (this.config.wxwork_contact_url) {
// H5环境直接跳转活码链接
window.location.href = this.config.wxwork_contact_url;
} else {
location.href = this.config.wxwork_url;
}
// #endif
},
/**
* 降级处理:使用原有客服方式
*/
fallbackToOriginalService() {
uni.showModal({
title: '提示',
content: '无法直接添加企业微信客服,是否使用其他方式联系客服?',
success: (res) => {
if (res.confirm) {
console.log('降级处理:使用原有客服方式');
this.openWxWorkService(true);
}
}
});
},
/** /**
* 店铺联系方式 * 店铺联系方式
*/ */

View File

@@ -0,0 +1,285 @@
<template>
<view class="wxwork-contact-wrap">
<slot></slot>
<button
type="default"
hover-class="none"
class="contact-button"
@click="addWxWorkContact">
<text class="btn-text">{{ btnText }}</text>
</button>
<!-- 确认弹窗 -->
<uni-popup ref="confirmPopup" type="center">
<view class="confirm-popup">
<view class="popup-header">
<text>添加企业微信客服</text>
</view>
<view class="popup-body">
<text>点击确定后将跳转至企业微信添加专业客服为您服务</text>
</view>
<view class="popup-footer">
<button class="cancel-btn" @click="closePopup">取消</button>
<button class="confirm-btn" @click="confirmAdd">确定</button>
</view>
</view>
</uni-popup>
</view>
</template>
<script>
import { WxWork } from '@/common/js/wxwork-jssdk.js';
export default {
name: 'wxwork-contact',
props: {
// 按钮文字
btnText: {
type: String,
default: '添加企业微信客服'
},
// 企业微信配置
corpId: {
type: String,
default: ''
},
// 客服ID或活码配置ID
contactId: {
type: String,
default: ''
},
// 活码链接
contactUrl: {
type: String,
default: ''
},
// 是否显示确认弹窗
showConfirm: {
type: Boolean,
default: true
}
},
data() {
return {
wxWorkSDK: null
};
},
mounted() {
this.initWxWork();
},
methods: {
/**
* 初始化企业微信SDK
*/
async initWxWork() {
try {
// 获取企业微信配置
const res = await this.$api.sendRequest({
url: '/api/wxwork/config',
data: {
corp_id: this.corpId
}
});
if (res.code === 0 && res.data) {
this.wxWorkSDK = new WxWork();
const initResult = this.wxWorkSDK.init({
corpId: res.data.corp_id,
agentId: res.data.agent_id,
timestamp: res.data.timestamp,
nonceStr: res.data.nonceStr,
signature: res.data.signature,
jsApiList: ['openUserProfile', 'openEnterpriseChat']
});
if (!initResult) {
console.error('企业微信SDK初始化失败');
}
}
} catch (error) {
console.error('获取企业微信配置失败:', error);
}
},
/**
* 点击添加企业微信客服
*/
addWxWorkContact() {
if (this.showConfirm) {
this.$refs.confirmPopup.open();
} else {
this.confirmAdd();
}
},
/**
* 确认添加
*/
confirmAdd() {
this.closePopup();
// #ifdef MP-WEIXIN
if (this.contactUrl) {
// 方案1直接跳转到企业微信活码
this.jumpToWxWorkContact();
} else if (this.contactId) {
// 方案2使用SDK打开用户资料
this.openUserProfile();
} else {
this.showError('未配置企业微信客服信息');
}
// #endif
// #ifdef H5
if (this.contactUrl) {
// H5环境直接跳转
window.location.href = this.contactUrl;
} else {
this.showError('未配置企业微信客服信息');
}
// #endif
},
/**
* 跳转到企业微信客服
*/
jumpToWxWorkContact() {
uni.navigateToMiniProgram({
appId: 'wxeb490c6f9b154ef9', // 企业微信小程序AppID
path: `pages/contacts/externalContactDetail?url=${encodeURIComponent(this.contactUrl)}`,
success: () => {
console.log('跳转企业微信成功');
this.$util.showToast({
title: '跳转成功',
icon: 'success'
});
},
fail: (err) => {
console.error('跳转企业微信失败:', err);
this.showError('跳转失败,请检查企业微信配置');
}
});
},
/**
* 打开用户资料
*/
openUserProfile() {
if (!this.wxWorkSDK) {
this.showError('企业微信SDK未初始化');
return;
}
this.wxWorkSDK.addContact({
userId: this.contactId
}, (res) => {
console.log('打开用户资料成功:', res);
}, (err) => {
console.error('打开用户资料失败:', err);
this.showError('打开用户资料失败');
});
},
/**
* 显示错误提示
*/
showError(message) {
uni.showModal({
title: '提示',
content: message,
showCancel: false
});
},
/**
* 关闭弹窗
*/
closePopup() {
this.$refs.confirmPopup.close();
}
}
};
</script>
<style lang="scss" scoped>
.wxwork-contact-wrap {
width: 100%;
height: 100%;
position: relative;
.contact-button {
width: 100%;
height: 100%;
background: linear-gradient(135deg, #1e7dd8 0%, #1482e0 100%);
color: #fff;
border: none;
border-radius: 8rpx;
font-size: 28rpx;
display: flex;
align-items: center;
justify-content: center;
.btn-text {
font-weight: 500;
}
&:active {
opacity: 0.8;
}
}
}
.confirm-popup {
width: 600rpx;
background: #fff;
border-radius: 16rpx;
overflow: hidden;
.popup-header {
padding: 40rpx 30rpx 20rpx;
text-align: center;
font-size: 32rpx;
font-weight: 600;
color: #333;
border-bottom: 1px solid #f0f0f0;
}
.popup-body {
padding: 30rpx;
text-align: center;
font-size: 28rpx;
color: #666;
line-height: 1.6;
}
.popup-footer {
display: flex;
border-top: 1px solid #f0f0f0;
button {
flex: 1;
height: 88rpx;
line-height: 88rpx;
text-align: center;
font-size: 30rpx;
border: none;
border-radius: 0;
&.cancel-btn {
background: #fff;
color: #999;
border-right: 1px solid #f0f0f0;
}
&.confirm-btn {
background: #1e7dd8;
color: #fff;
}
&:active {
opacity: 0.8;
}
}
}
}
</style>

View File

@@ -19,7 +19,26 @@
<!-- #ifdef MP-WEIXIN --> <!-- #ifdef MP-WEIXIN -->
<view class="view_ul view_ul_one clearfix"> <view class="view_ul view_ul_one clearfix">
<view class="view_li w50_li text-center"> <view class="view_li w50_li text-center">
<button class="bl bor" hoverClass="none" openType="contact" sessionFrom="weapp" showMessageCard="true" style="margin: 0;"> <wxwork-contact
v-if="wxworkConfig && wxworkConfig.enabled"
:corp-id="wxworkConfig.corpId"
:contact-id="wxworkConfig.contactId"
:contact-url="wxworkConfig.contactUrl"
btn-text="企业微信客服"
:show-confirm="false">
<view class="bl bor" style="margin: 0;">
<image mode="heightFix" :src="$util.img('public/static/img/wxwork_kefu.png')"></image>
<view class="name bl line1">企业微信</view>
</view>
</wxwork-contact>
<button
v-else
class="bl bor"
hoverClass="none"
openType="contact"
sessionFrom="weapp"
showMessageCard="true"
style="margin: 0;">
<image mode="heightFix" :src="$util.img('public/static/img/kefu.png')"></image> <image mode="heightFix" :src="$util.img('public/static/img/kefu.png')"></image>
<view class="name bl line1">专属客服</view> <view class="name bl line1">专属客服</view>
</button> </button>
@@ -137,7 +156,12 @@
</template> </template>
<script> <script>
import wxworkContact from '@/components/wxwork-contact/wxwork-contact.vue';
export default { export default {
components: {
wxworkContact
},
data() { data() {
return { return {
dataList: [], dataList: [],
@@ -148,6 +172,7 @@ export default {
remark:'' remark:''
}, },
wxworkConfig: null, // 企业微信配置
markers:[ markers:[
{ {
id:1, id:1,
@@ -174,6 +199,39 @@ export default {
onLoad(option) { onLoad(option) {
//刷新多语言 //刷新多语言
this.$langConfig.refresh(); this.$langConfig.refresh();
this.loadWxWorkConfig(); // 加载企业微信配置
this.loadPersonnel();
},
methods: {
/**
* 加载企业微信配置
*/
loadWxWorkConfig() {
this.$api.sendRequest({
url: '/api/wxwork/config',
success: res => {
if (res.code === 0 && res.data) {
this.wxworkConfig = {
enabled: true,
corpId: res.data.corp_id,
contactId: res.data.contact_id,
contactUrl: res.data.contact_url
};
} else {
this.wxworkConfig = { enabled: false };
}
},
fail: () => {
this.wxworkConfig = { enabled: false };
}
});
},
/**
* 加载人员信息
*/
loadPersonnel() {
this.$api.sendRequest({ this.$api.sendRequest({
url: '/api/member/personnel', url: '/api/member/personnel',
success: res => { success: res => {