|
|
@ -2,6 +2,30 @@ |
|
|
<div class="getCode_container"> |
|
|
<div class="getCode_container"> |
|
|
<div class="content"> |
|
|
<div class="content"> |
|
|
<el-card shadow="never"> |
|
|
<el-card shadow="never"> |
|
|
|
|
|
<!-- 客服选择 --> |
|
|
|
|
|
<div class="kefu-selector"> |
|
|
|
|
|
<span class="kefu-label">指定客服:</span> |
|
|
|
|
|
<el-select |
|
|
|
|
|
v-model="selectedKefuId" |
|
|
|
|
|
placeholder="不指定(系统自动分配)" |
|
|
|
|
|
clearable |
|
|
|
|
|
size="small" |
|
|
|
|
|
style="width: 240px;" |
|
|
|
|
|
@change="onKefuChange" |
|
|
|
|
|
> |
|
|
|
|
|
<el-option |
|
|
|
|
|
v-for="item in kefuList" |
|
|
|
|
|
:key="item.id" |
|
|
|
|
|
:label="item.nickName" |
|
|
|
|
|
:value="item.id" |
|
|
|
|
|
> |
|
|
|
|
|
<div style="display: flex; align-items: center; gap: 8px;"> |
|
|
|
|
|
<el-avatar :src="item.headImageThumb" :size="24" v-if="item.headImageThumb" /> |
|
|
|
|
|
<span>{{ item.nickName }}</span> |
|
|
|
|
|
</div> |
|
|
|
|
|
</el-option> |
|
|
|
|
|
</el-select> |
|
|
|
|
|
</div> |
|
|
<!-- 使用悬浮球设置组件 --> |
|
|
<!-- 使用悬浮球设置组件 --> |
|
|
<FloatBallSetting |
|
|
<FloatBallSetting |
|
|
ref="floatBallSettingRef" |
|
|
ref="floatBallSettingRef" |
|
|
@ -15,7 +39,7 @@ |
|
|
<alink :tokeninfo="token" :site-url="siteUrl" :unique-token="uniqueToken" @cget-copy="getCopy"></alink> |
|
|
<alink :tokeninfo="token" :site-url="siteUrl" :unique-token="uniqueToken" @cget-copy="getCopy"></alink> |
|
|
</el-collapse-item> |
|
|
</el-collapse-item> |
|
|
<el-collapse-item title="网页内嵌" name="2"> |
|
|
<el-collapse-item title="网页内嵌" name="2"> |
|
|
<wangye :tokeninfo="token" :site-url="siteUrl" :unique-token="uniqueToken" :float-config="floatBallConfig" @cget-copy="getCopy"></wangye> |
|
|
<wangye :tokeninfo="token" :site-url="siteUrl" :unique-token="uniqueToken" :kefu-id="selectedKefuId" :float-config="floatBallConfig" @cget-copy="getCopy"></wangye> |
|
|
</el-collapse-item> |
|
|
</el-collapse-item> |
|
|
</el-collapse> |
|
|
</el-collapse> |
|
|
</el-card> |
|
|
</el-card> |
|
|
@ -30,8 +54,10 @@ import { ref, computed, onMounted, getCurrentInstance } from 'vue'; |
|
|
import alink from './components/alink.vue'; |
|
|
import alink from './components/alink.vue'; |
|
|
import wangye from './components/wangye.vue'; |
|
|
import wangye from './components/wangye.vue'; |
|
|
import FloatBallSetting from './components/FloatBallSetting.vue'; |
|
|
import FloatBallSetting from './components/FloatBallSetting.vue'; |
|
|
|
|
|
import { listUser } from '@/api/im/user/customer'; |
|
|
import type { FloatBallConfig } from './components/FloatBallSetting.vue'; |
|
|
import type { FloatBallConfig } from './components/FloatBallSetting.vue'; |
|
|
import { getInfo } from '@/api/login'; |
|
|
import { getInfo } from '@/api/login'; |
|
|
|
|
|
import { getDefaultKefu, saveDefaultKefu } from '@/api/im/agent'; |
|
|
// import kaifa from './components/kaifa'; |
|
|
// import kaifa from './components/kaifa'; |
|
|
// import setting from './components/setting'; |
|
|
// import setting from './components/setting'; |
|
|
|
|
|
|
|
|
@ -57,6 +83,9 @@ const siteUrl = ref(`${location.origin}`); |
|
|
const cloneTip = ref(false); |
|
|
const cloneTip = ref(false); |
|
|
const canCustomerServer = ref(''); |
|
|
const canCustomerServer = ref(''); |
|
|
|
|
|
|
|
|
|
|
|
const selectedKefuId = ref<number | ''>(''); |
|
|
|
|
|
const kefuList = ref<any[]>([]); |
|
|
|
|
|
|
|
|
const linkUrl = computed(() => `${location.origin}/chat/index?token=${token.value?.token_md5}&noCanClose=1`); |
|
|
const linkUrl = computed(() => `${location.origin}/chat/index?token=${token.value?.token_md5}&noCanClose=1`); |
|
|
onMounted(() => { |
|
|
onMounted(() => { |
|
|
// 页面加载就获取当前代理的 uniqueToken ✅ |
|
|
// 页面加载就获取当前代理的 uniqueToken ✅ |
|
|
@ -86,13 +115,45 @@ async function fetchAgentToken() { |
|
|
if (res.data?.tokenInfo?.uniqueToken) { |
|
|
if (res.data?.tokenInfo?.uniqueToken) { |
|
|
// 拿到真正的 token! |
|
|
// 拿到真正的 token! |
|
|
uniqueToken.value = res.data.tokenInfo.uniqueToken; |
|
|
uniqueToken.value = res.data.tokenInfo.uniqueToken; |
|
|
console.log('✅ 获取成功 uniqueToken =', uniqueToken.value); |
|
|
await Promise.all([loadKefuList(), loadDefaultKefu()]); |
|
|
} |
|
|
} |
|
|
} catch (e) { |
|
|
} catch (e) { |
|
|
console.error('获取token失败', e); |
|
|
console.error('获取token失败', e); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async function loadKefuList() { |
|
|
|
|
|
try { |
|
|
|
|
|
const res = await listUser(); |
|
|
|
|
|
const data = (res as any)?.rows || []; |
|
|
|
|
|
kefuList.value = data; |
|
|
|
|
|
} catch (e) { |
|
|
|
|
|
console.error('获取客服列表失败', e); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 加载已保存的默认客服ID |
|
|
|
|
|
async function loadDefaultKefu() { |
|
|
|
|
|
try { |
|
|
|
|
|
const kefuId = await getDefaultKefu(); |
|
|
|
|
|
if (kefuId.data) { |
|
|
|
|
|
selectedKefuId.value = kefuId.data; |
|
|
|
|
|
} |
|
|
|
|
|
} catch (e) { |
|
|
|
|
|
console.error('获取默认客服失败', e); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async function onKefuChange(val: number | '') { |
|
|
|
|
|
try { |
|
|
|
|
|
await saveDefaultKefu(val || null); |
|
|
|
|
|
proxy?.$Message?.success('已保存'); |
|
|
|
|
|
} catch (e) { |
|
|
|
|
|
console.error('保存默认客服失败', e); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// 处理悬浮球配置更新 |
|
|
// 处理悬浮球配置更新 |
|
|
function handleFloatBallConfigUpdate(config: FloatBallConfig) { |
|
|
function handleFloatBallConfigUpdate(config: FloatBallConfig) { |
|
|
floatBallConfig.value = config; |
|
|
floatBallConfig.value = config; |
|
|
|