|
|
@@ -51,6 +51,7 @@ const LOGIN_STORAGE_KEY = 'wecom_session_expire';
|
|
|
export default {
|
|
|
name: 'ConversationPanel',
|
|
|
props: {
|
|
|
+ corpId: { type: String, default: null },
|
|
|
customerId: { type: String, default: null },
|
|
|
customerAvatar: { type: String, default: '' },
|
|
|
staffUserId: { type: String, default: null }
|
|
|
@@ -72,19 +73,32 @@ export default {
|
|
|
domain: ''
|
|
|
},
|
|
|
configReady: false,
|
|
|
+ tokenCheckTimer: null // 声明定时器变量
|
|
|
};
|
|
|
},
|
|
|
watch: {
|
|
|
customerId(newId, oldId) {
|
|
|
- if (newId && newId !== oldId && this.isLoggedIn && this.staffUserId && this.configReady) {
|
|
|
+ if (newId && newId !== oldId && this.isLoggedIn && this.staffUserId && this.configReady && this.corpId) {
|
|
|
this.resetAndReload();
|
|
|
}
|
|
|
},
|
|
|
staffUserId(newStaffId, oldStaffId) {
|
|
|
- if (newStaffId && newStaffId !== oldStaffId && this.customerId && this.isLoggedIn && this.configReady) {
|
|
|
+ if (newStaffId && newStaffId !== oldStaffId && this.customerId && this.isLoggedIn && this.configReady && this.corpId) {
|
|
|
this.resetAndReload();
|
|
|
}
|
|
|
},
|
|
|
+ corpId(newId, oldId) {
|
|
|
+ if (newId && newId !== oldId) {
|
|
|
+ this.destroyChat();
|
|
|
+ this.clearLoginState();
|
|
|
+ this.isLoggedIn = false;
|
|
|
+ this.isReady = false;
|
|
|
+ this._sdkInited = false;
|
|
|
+ this.configReady = false;
|
|
|
+ this.initConfig();
|
|
|
+ this.handleAuthAndLoad();
|
|
|
+ }
|
|
|
+ },
|
|
|
customerAvatar: {
|
|
|
handler(newAvatar) {
|
|
|
if (this.chatInstance && newAvatar) {
|
|
|
@@ -97,15 +111,34 @@ export default {
|
|
|
async mounted() {
|
|
|
await this.initConfig();
|
|
|
await this.handleAuthAndLoad();
|
|
|
+ console.log('configReady:', this.configReady);
|
|
|
+ console.log('corpId:', this.corpId);
|
|
|
+ // 每 1.5 小时检查一次登录态
|
|
|
+ this.tokenCheckTimer = setInterval(async () => {
|
|
|
+ if (this.isLoggedIn && this.configReady) {
|
|
|
+ try {
|
|
|
+ await this.getAgentConfigSignature();
|
|
|
+ } catch (e) {
|
|
|
+ // 签名失败会触发重新登录,清除定时器
|
|
|
+ clearInterval(this.tokenCheckTimer);
|
|
|
+ this.tokenCheckTimer = null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }, 90 * 60 * 1000);
|
|
|
},
|
|
|
beforeDestroy() {
|
|
|
+ if (this.tokenCheckTimer) {
|
|
|
+ clearInterval(this.tokenCheckTimer);
|
|
|
+ this.tokenCheckTimer = null;
|
|
|
+ }
|
|
|
this.destroyChat();
|
|
|
},
|
|
|
methods: {
|
|
|
// ========== 配置初始化 ==========
|
|
|
async initConfig() {
|
|
|
+ if (!this.corpId) return;
|
|
|
try {
|
|
|
- const configRes = await getQwSessionConfig();
|
|
|
+ const configRes = await getQwSessionConfig(this.corpId);
|
|
|
const configData = this._extractResponse(configRes);
|
|
|
if (!configData.corpid || !configData.agentid) {
|
|
|
throw new Error('配置数据不完整');
|
|
|
@@ -132,13 +165,13 @@ export default {
|
|
|
window.history.replaceState({}, '', newUrl);
|
|
|
await this.handleLogin(code);
|
|
|
this.storeLoginState();
|
|
|
- if (this.customerId && this.staffUserId) {
|
|
|
+ if (this.customerId && this.staffUserId && this.corpId) {
|
|
|
await this.loadFirstPage();
|
|
|
}
|
|
|
} else {
|
|
|
if (this.checkLoginState()) {
|
|
|
this.isLoggedIn = true;
|
|
|
- if (this.customerId && this.staffUserId) {
|
|
|
+ if (this.customerId && this.staffUserId && this.corpId) {
|
|
|
await this.loadFirstPage();
|
|
|
}
|
|
|
} else {
|
|
|
@@ -148,7 +181,7 @@ export default {
|
|
|
},
|
|
|
|
|
|
async handleLogin(code) {
|
|
|
- const res = await qwLogin({ code });
|
|
|
+ const res = await qwLogin({ code, corpid: this.corpId });
|
|
|
const resp = this._extractResponse(res);
|
|
|
if (resp.errcode !== 0) {
|
|
|
throw new Error(resp.errmsg || '登录失败');
|
|
|
@@ -157,9 +190,10 @@ export default {
|
|
|
},
|
|
|
|
|
|
createLoginPanel() {
|
|
|
- //const redirectUri = this.config.domain + '/companySale/companySession';
|
|
|
+ // const redirectUri = 'http://sestest.ylrzcloud.com' + '/companySale/companySession';
|
|
|
+ // 若需动态获取,可使用:const redirectUri = window.location.href.split('?')[0].split('#')[0];
|
|
|
const redirectUri = window.location.href.split('?')[0].split('#')[0];
|
|
|
- console.log("重定向链接:"+redirectUri)
|
|
|
+ console.log("重定向链接:" + redirectUri);
|
|
|
ww.createWWLoginPanel({
|
|
|
el: document.getElementById('login-container'),
|
|
|
params: {
|
|
|
@@ -173,7 +207,7 @@ export default {
|
|
|
onLoginSuccess: async ({ code }) => {
|
|
|
await this.handleLogin(code);
|
|
|
this.storeLoginState();
|
|
|
- if (this.customerId && this.staffUserId) {
|
|
|
+ if (this.customerId && this.staffUserId && this.corpId) {
|
|
|
await this.loadFirstPage();
|
|
|
}
|
|
|
},
|
|
|
@@ -201,8 +235,21 @@ export default {
|
|
|
// ========== SDK 与签名 ==========
|
|
|
async getAgentConfigSignature() {
|
|
|
const currentUrl = window.location.href.split('#')[0];
|
|
|
- const res = await qwSignature({ url: currentUrl });
|
|
|
+ console.log('请求签名的 URL:', currentUrl);
|
|
|
+ const res = await qwSignature({ url: currentUrl, corpid: this.corpId });
|
|
|
const data = this._extractResponse(res);
|
|
|
+ console.log('签名响应:', data);
|
|
|
+ // 如果有 errcode 且不为 0,则认为失败
|
|
|
+ if (data.errcode && data.errcode !== 0) {
|
|
|
+ console.error('获取签名失败,将重新登录', data);
|
|
|
+ this.clearLoginState();
|
|
|
+ this.isLoggedIn = false;
|
|
|
+ this.isReady = false;
|
|
|
+ this.destroyChat();
|
|
|
+ this.$nextTick(() => this.createLoginPanel());
|
|
|
+ throw new Error(`签名失败: ${data.errmsg}`);
|
|
|
+ }
|
|
|
+ // 否则认为成功
|
|
|
return {
|
|
|
timestamp: data.timestamp,
|
|
|
nonceStr: data.nonceStr,
|
|
|
@@ -235,7 +282,8 @@ export default {
|
|
|
customerId: this.customerId,
|
|
|
staffUserId: this.staffUserId,
|
|
|
limit: 100,
|
|
|
- cursor: this.cursor
|
|
|
+ cursor: this.cursor,
|
|
|
+ corpid: this.corpId
|
|
|
});
|
|
|
const data = this._extractResponse(res);
|
|
|
if (data.errcode !== 0) {
|
|
|
@@ -265,7 +313,8 @@ export default {
|
|
|
customerId: this.customerId,
|
|
|
staffUserId: this.staffUserId,
|
|
|
limit: 50,
|
|
|
- cursor: this.cursor
|
|
|
+ cursor: this.cursor,
|
|
|
+ corpid: this.corpId
|
|
|
});
|
|
|
const data = this._extractResponse(res);
|
|
|
if (data.errcode !== 0) {
|
|
|
@@ -277,7 +326,6 @@ export default {
|
|
|
this.cursor = data.next_cursor || '';
|
|
|
this.hasMore = data.has_more === 1;
|
|
|
if (this.chatInstance) {
|
|
|
- // 直接更新整个 msgList,模板中使用原始字段 send_time_str
|
|
|
this.chatInstance.setData({ msgList: this.msgList });
|
|
|
} else {
|
|
|
await this.renderOrUpdateChat();
|
|
|
@@ -300,7 +348,6 @@ export default {
|
|
|
const container = document.getElementById('chat-container');
|
|
|
if (!container) return;
|
|
|
|
|
|
- // 如果已存在实例,更新数据
|
|
|
if (this.chatInstance) {
|
|
|
this.chatInstance.setData({ msgList: this.msgList });
|
|
|
return;
|
|
|
@@ -366,7 +413,6 @@ export default {
|
|
|
}
|
|
|
},
|
|
|
handleModal: ({ modalUrl, modalSize }) => {
|
|
|
- // 外部浏览器预览多媒体
|
|
|
const iframe = document.createElement('iframe');
|
|
|
iframe.src = modalUrl;
|
|
|
iframe.style.position = 'fixed';
|
|
|
@@ -395,7 +441,6 @@ export default {
|
|
|
});
|
|
|
},
|
|
|
|
|
|
- // ========== 重置与销毁 ==========
|
|
|
async resetAndReload() {
|
|
|
this.destroyChat();
|
|
|
this.msgList = [];
|
|
|
@@ -416,7 +461,6 @@ export default {
|
|
|
}
|
|
|
},
|
|
|
|
|
|
- // ========== 工具方法 ==========
|
|
|
_extractResponse(res) {
|
|
|
if (!res) return {};
|
|
|
if (res.errcode !== undefined || res.timestamp || res.corpid) return res;
|
|
|
@@ -427,7 +471,6 @@ export default {
|
|
|
}
|
|
|
};
|
|
|
</script>
|
|
|
-
|
|
|
<style>
|
|
|
#chat-container,
|
|
|
#chat-container > div,
|