Browse Source

API Key 绑定客服角色

dev-mcp
wanghanlin 2 weeks ago
parent
commit
1d1b4460a2
  1. 28
      client/dist/chatbot-sdk.js
  2. 2
      client/dist/chatbot-sdk.js.map
  3. 2
      client/dist/chatbot-sdk.min.js
  4. 2
      client/dist/chatbot-sdk.min.js.map
  5. 24
      client/src/api.ts
  6. 2
      client/src/config.ts
  7. 3
      client/src/index.ts
  8. 10
      client/src/types.ts
  9. 151
      src/main/resources/static/sdk/chatbot-sdk.js
  10. 2
      src/main/resources/static/sdk/chatbot-sdk.js.map
  11. 2
      src/main/resources/static/sdk/chatbot-sdk.min.js
  12. 2
      src/main/resources/static/sdk/chatbot-sdk.min.js.map
  13. 55
      src/main/resources/static/sdk/test.html

28
client/dist/chatbot-sdk.js

@ -258,6 +258,8 @@ var ChatbotSDK = (function () {
onError: typeof raw.onError === 'function' ? raw.onError : undefined,
onReady: typeof raw.onReady === 'function' ? raw.onReady : undefined,
onMessage: typeof raw.onMessage === 'function' ? raw.onMessage : undefined,
token: raw.token,
roles: raw.roles,
chatId: '', // 初始为空,由 chatId 初始化流程填充
};
logger.info(`配置解析完成 integrateId(=roleId)=${config.integrateId} userId(=accountId)=${config.userId || '(未设置)'} requestDomain=${config.requestDomain}`);
@ -443,6 +445,10 @@ var ChatbotSDK = (function () {
function setApiConfig(config) {
currentConfig = config;
}
/** 清空当前配置(销毁 SDK 时调用) */
function clearApiConfig() {
currentConfig = null;
}
/** 更新当前 chatId(对话 ID) */
function updateChatId(chatId) {
if (currentConfig) {
@ -542,7 +548,26 @@ var ChatbotSDK = (function () {
}
}
try {
const response = await fetch(url, Object.assign(Object.assign({}, options), { signal: controller.signal, mode: 'cors', credentials: 'include' }));
// 注入 SDK Token 认证头(仅对 /ai/ 路径注入,避免将 SDK Token 发送到管理接口)
const headers = {};
if (options.headers) {
if (options.headers instanceof Headers) {
options.headers.forEach((value, key) => { headers[key] = value; });
}
else if (Array.isArray(options.headers)) {
options.headers.forEach(([key, value]) => { headers[key] = value; });
}
else {
Object.assign(headers, options.headers);
}
}
if ((currentConfig === null || currentConfig === void 0 ? void 0 : currentConfig.token) && url.includes('/ai/')) {
headers['Authorization'] = `Bearer ${currentConfig.token}`;
}
const response = await fetch(url, Object.assign(Object.assign({}, options), { headers, signal: controller.signal, mode: 'cors', credentials: 'include' }));
if (response.status === 401 && url.includes('/ai/')) {
logger.error('SDK 认证失败:Token 缺失或已过期,请重新调用 /open-api/auth/token 换取 Token');
}
return response;
}
catch (err) {
@ -4679,6 +4704,7 @@ var ChatbotSDK = (function () {
hideLoadingFn = null;
badgeEl = null;
audioCtx = null;
clearApiConfig();
logger.lifecycleDestroy(oldIntegrateId || '');
}
function open() {

2
client/dist/chatbot-sdk.js.map
File diff suppressed because it is too large
View File

2
client/dist/chatbot-sdk.min.js
File diff suppressed because it is too large
View File

2
client/dist/chatbot-sdk.min.js.map
File diff suppressed because it is too large
View File

24
client/src/api.ts

@ -20,6 +20,11 @@ export function setApiConfig(config: ResolvedConfig): void {
currentConfig = config;
}
/** 清空当前配置(销毁 SDK 时调用) */
export function clearApiConfig(): void {
currentConfig = null;
}
/** 更新当前 chatId(对话 ID) */
export function updateChatId(chatId: string): void {
if (currentConfig) {
@ -141,12 +146,31 @@ async function safeFetch(
}
try {
// 注入 SDK Token 认证头(仅对 /ai/ 路径注入,避免将 SDK Token 发送到管理接口)
const headers: Record<string, string> = {};
if (options.headers) {
if (options.headers instanceof Headers) {
options.headers.forEach((value, key) => { headers[key] = value; });
} else if (Array.isArray(options.headers)) {
options.headers.forEach(([key, value]) => { headers[key] = value; });
} else {
Object.assign(headers, options.headers as Record<string, string>);
}
}
if (currentConfig?.token && url.includes('/ai/')) {
headers['Authorization'] = `Bearer ${currentConfig.token}`;
}
const response = await fetch(url, {
...options,
headers,
signal: controller.signal,
mode: 'cors',
credentials: 'include',
});
if (response.status === 401 && url.includes('/ai/')) {
logger.error('SDK 认证失败:Token 缺失或已过期,请重新调用 /open-api/auth/token 换取 Token');
}
return response;
} catch (err: unknown) {
// 用户主动中断(停止生成),不算错误

2
client/src/config.ts

@ -188,6 +188,8 @@ export function parseConfig(raw: SDKConfig): ResolvedConfig | null {
onError: typeof raw.onError === 'function' ? raw.onError : undefined,
onReady: typeof raw.onReady === 'function' ? raw.onReady : undefined,
onMessage: typeof raw.onMessage === 'function' ? raw.onMessage : undefined,
token: raw.token,
roles: raw.roles,
chatId: '', // 初始为空,由 chatId 初始化流程填充
};

3
client/src/index.ts

@ -10,7 +10,7 @@
import { SDKConfig, ResolvedConfig, ChatbotSDKInstance } from './types';
import { parseConfig } from './config';
import { setDebug, logger, setErrorCallback } from './logger';
import { setApiConfig } from './api';
import { setApiConfig, clearApiConfig } from './api';
import { injectStyles, removeStyles } from './styles';
import { createLauncher, createChatWindow, enableDrag, enableLauncherDrag } from './dom';
import { initChat, initChatHistory, getMessages, setCategory, loadHistoryConversations, sendQuickReply, retryFromMessage, handleFeedback } from './chat';
@ -378,6 +378,7 @@ function destroy(): void {
hideLoadingFn = null;
badgeEl = null;
audioCtx = null;
clearApiConfig();
logger.lifecycleDestroy(oldIntegrateId || '');
}

10
client/src/types.ts

@ -19,6 +19,12 @@ export interface SDKConfig {
/** 宿主用户标识 → 后端 accountId 参数(客户账号 ID),账号可绑定角色 */
userId?: string;
// === 鉴权配置 ===
/** SDK JWT Token(从 /open-api/auth/token 换取),用于访问 /ai/** 接口 */
token?: string;
/** 可用客服角色列表(与 token 配套使用,决定用户可选择哪些角色) */
roles?: Array<{ id: string | number; name?: string }>;
// === 知识库 ===
/** 默认知识库分类 ID */
categoryId?: number;
@ -92,6 +98,10 @@ export interface ResolvedConfig {
requestDomain: string;
/** 客户账号 ID → 后端 accountId */
userId?: string;
/** SDK JWT Token → 访问 /ai/** 接口的认证头 */
token?: string;
/** 可用客服角色列表 */
roles?: Array<{ id: string | number; name?: string }>;
/** 知识库分类 ID */
categoryId?: number;
/** 是否显示知识库切换 */

151
src/main/resources/static/sdk/chatbot-sdk.js

@ -258,17 +258,10 @@ var ChatbotSDK = (function () {
onError: typeof raw.onError === 'function' ? raw.onError : undefined,
onReady: typeof raw.onReady === 'function' ? raw.onReady : undefined,
onMessage: typeof raw.onMessage === 'function' ? raw.onMessage : undefined,
// SDK 鉴权:token 和 roles(可选,用于新版鉴权模式)
token: typeof raw.token === 'string' && raw.token.trim() ? raw.token.trim() : undefined,
roles: Array.isArray(raw.roles) && raw.roles.length > 0 ? raw.roles : undefined,
token: raw.token,
roles: raw.roles,
chatId: '', // 初始为空,由 chatId 初始化流程填充
};
// 鉴权模式日志
if (config.token) {
logger.info(`鉴权模式: SDK Token 已配置, roles=${config.roles ? config.roles.length + '个' : '未配置'}`);
} else {
logger.info('兼容模式: 未配置 token,使用 integrateId 作为 roleId');
}
logger.info(`配置解析完成 integrateId(=roleId)=${config.integrateId} userId(=accountId)=${config.userId || '(未设置)'} requestDomain=${config.requestDomain}`);
return config;
}
@ -452,6 +445,10 @@ var ChatbotSDK = (function () {
function setApiConfig(config) {
currentConfig = config;
}
/** 清空当前配置(销毁 SDK 时调用) */
function clearApiConfig() {
currentConfig = null;
}
/** 更新当前 chatId(对话 ID) */
function updateChatId(chatId) {
if (currentConfig) {
@ -492,9 +489,8 @@ var ChatbotSDK = (function () {
const params = new URLSearchParams();
params.set('message', message);
params.set('chatId', currentConfig.chatId);
// 鉴权模式使用 selectedRoleId,兼容模式使用 integrateId
const roleId = currentConfig.token ? selectedRoleId : currentConfig.integrateId;
setIfPresent(params, 'roleId', roleId);
// integrateId 映射为 roleId
setIfPresent(params, 'roleId', currentConfig.integrateId);
// userId 映射为 accountId
setIfPresent(params, 'accountId', currentConfig.userId);
return buildUrl(`/ai/assistant_app/chat/sync?${params.toString()}`);
@ -506,9 +502,7 @@ var ChatbotSDK = (function () {
const params = new URLSearchParams();
params.set('message', message);
params.set('chatId', currentConfig.chatId);
// 鉴权模式使用 selectedRoleId,兼容模式使用 integrateId
const roleId = currentConfig.token ? selectedRoleId : currentConfig.integrateId;
setIfPresent(params, 'roleId', roleId);
setIfPresent(params, 'roleId', currentConfig.integrateId);
setIfPresent(params, 'accountId', currentConfig.userId);
setIfPresent(params, 'categoryId', categoryId !== null && categoryId !== void 0 ? categoryId : currentConfig.categoryId);
return buildUrl(`/ai/assistant_app/chat/sse?${params.toString()}`);
@ -521,9 +515,7 @@ var ChatbotSDK = (function () {
params.set('message', message);
params.set('chatId', currentConfig.chatId);
params.set('rewriteStrategy', currentConfig.rewriteStrategy || 'REWRITE');
// 鉴权模式使用 selectedRoleId,兼容模式使用 integrateId
const roleId = currentConfig.token ? selectedRoleId : currentConfig.integrateId;
setIfPresent(params, 'roleId', roleId);
setIfPresent(params, 'roleId', currentConfig.integrateId);
setIfPresent(params, 'accountId', currentConfig.userId);
setIfPresent(params, 'categoryId', categoryId !== null && categoryId !== void 0 ? categoryId : currentConfig.categoryId);
return buildUrl(`/ai/assistant_app/chat/rag/sse?${params.toString()}`);
@ -536,9 +528,7 @@ var ChatbotSDK = (function () {
params.set('message', message);
params.set('chatId', currentConfig.chatId);
params.set('rewriteStrategy', currentConfig.rewriteStrategy || 'REWRITE');
// 鉴权模式使用 selectedRoleId,兼容模式使用 integrateId
const roleId = currentConfig.token ? selectedRoleId : currentConfig.integrateId;
setIfPresent(params, 'roleId', roleId);
setIfPresent(params, 'roleId', currentConfig.integrateId);
setIfPresent(params, 'accountId', currentConfig.userId);
setIfPresent(params, 'categoryId', categoryId !== null && categoryId !== void 0 ? categoryId : currentConfig.categoryId);
return buildUrl(`/ai/assistant_app/rag/sources?${params.toString()}`);
@ -557,13 +547,27 @@ var ChatbotSDK = (function () {
externalSignal.addEventListener('abort', () => controller.abort(), { once: true });
}
}
// 注入 SDK Token 认证头(仅对 /ai/ 路径注入,避免将 SDK Token 发送到管理接口)
const headers = Object.assign({}, options.headers || {});
if (currentConfig && currentConfig.token && url.includes('/ai/')) {
headers['Authorization'] = `Bearer ${currentConfig.token}`;
}
try {
// 注入 SDK Token 认证头(仅对 /ai/ 路径注入,避免将 SDK Token 发送到管理接口)
const headers = {};
if (options.headers) {
if (options.headers instanceof Headers) {
options.headers.forEach((value, key) => { headers[key] = value; });
}
else if (Array.isArray(options.headers)) {
options.headers.forEach(([key, value]) => { headers[key] = value; });
}
else {
Object.assign(headers, options.headers);
}
}
if ((currentConfig === null || currentConfig === void 0 ? void 0 : currentConfig.token) && url.includes('/ai/')) {
headers['Authorization'] = `Bearer ${currentConfig.token}`;
}
const response = await fetch(url, Object.assign(Object.assign({}, options), { headers, signal: controller.signal, mode: 'cors', credentials: 'include' }));
if (response.status === 401 && url.includes('/ai/')) {
logger.error('SDK 认证失败:Token 缺失或已过期,请重新调用 /open-api/auth/token 换取 Token');
}
return response;
}
catch (err) {
@ -845,9 +849,8 @@ var ChatbotSDK = (function () {
const params = new URLSearchParams();
if (currentConfig === null || currentConfig === void 0 ? void 0 : currentConfig.userId)
params.set('accountId', currentConfig.userId);
const roleId = currentConfig.token ? selectedRoleId : currentConfig.integrateId;
if (roleId)
params.set('roleId', roleId);
if (currentConfig === null || currentConfig === void 0 ? void 0 : currentConfig.integrateId)
params.set('roleId', currentConfig.integrateId);
const url = buildUrl(`/ai/sdk/conversation/${conversationId}/messages?${params.toString()}`);
try {
const response = await safeFetch(url);
@ -872,9 +875,8 @@ var ChatbotSDK = (function () {
const params = new URLSearchParams();
if (currentConfig === null || currentConfig === void 0 ? void 0 : currentConfig.userId)
params.set('accountId', currentConfig.userId);
const roleId = currentConfig.token ? selectedRoleId : currentConfig.integrateId;
if (roleId)
params.set('roleId', roleId);
if (currentConfig === null || currentConfig === void 0 ? void 0 : currentConfig.integrateId)
params.set('roleId', currentConfig.integrateId);
const url = buildUrl(`/ai/sdk/conversation/${conversationId}?${params.toString()}`);
try {
const response = await safeFetch(url, { method: 'DELETE' });
@ -897,9 +899,8 @@ var ChatbotSDK = (function () {
const params = new URLSearchParams();
if (currentConfig === null || currentConfig === void 0 ? void 0 : currentConfig.userId)
params.set('accountId', currentConfig.userId);
const roleId = currentConfig.token ? selectedRoleId : currentConfig.integrateId;
if (roleId)
params.set('roleId', roleId);
if (currentConfig === null || currentConfig === void 0 ? void 0 : currentConfig.integrateId)
params.set('roleId', currentConfig.integrateId);
return buildUrl(`/ai/sdk/conversation/${conversationId}/export?${params.toString()}`);
}
// ==================== chatId 自动初始化 ====================
@ -924,8 +925,7 @@ var ChatbotSDK = (function () {
}
// 2. 查询后端会话列表
try {
const roleId = currentConfig.token ? (selectedRoleId || currentConfig.integrateId) : currentConfig.integrateId;
const result = await fetchConversationList(1, 5, currentConfig.userId, roleId);
const result = await fetchConversationList(1, 5, currentConfig.userId, currentConfig.integrateId);
if (result.list.length > 0) {
// 使用最新会话的 conversationId 作为 chatId
const latestConv = result.list[0];
@ -1355,26 +1355,6 @@ var ChatbotSDK = (function () {
70% { box-shadow: 0 0 0 6px rgba(110, 231, 183, 0); }
100% { box-shadow: 0 0 0 0 rgba(110, 231, 183, 0); }
}
.csk-role-selector {
margin-left: 8px;
padding: 2px 6px;
font-size: 11px;
border: 1px solid rgba(255,255,255,0.3);
border-radius: 6px;
background: rgba(255,255,255,0.15);
color: #fff;
cursor: pointer;
outline: none;
max-width: 120px;
appearance: auto;
}
.csk-role-selector:focus {
border-color: rgba(255,255,255,0.6);
}
.csk-role-selector option {
color: #333;
background: #fff;
}
.csk-header__actions {
display: flex;
align-items: center;
@ -2562,8 +2542,6 @@ var ChatbotSDK = (function () {
actions.appendChild(closeBtn);
header.appendChild(headerLeft);
header.appendChild(actions);
// 渲染角色选择器(鉴权模式下,≥2 角色时显示下拉框)
renderRoleSelector(header);
// === 消息区 ===
const messagesContainer = document.createElement('div');
messagesContainer.id = 'csk-messages';
@ -4312,8 +4290,7 @@ var ChatbotSDK = (function () {
return;
listEl.innerHTML = `<div class="csk-history-panel__loading">加载中...</div>`;
try {
const roleId = config$1.token ? (selectedRoleId || config$1.integrateId) : config$1.integrateId;
const result = await fetchConversationList(1, 50, config$1.userId, roleId);
const result = await fetchConversationList(1, 50, config$1.userId, config$1.integrateId);
historyItems = result.list.map(c => ({
id: c.conversationId || '',
chatId: c.conversationId || '',
@ -4415,62 +4392,12 @@ var ChatbotSDK = (function () {
let launcherPos = null;
/** 提示气泡元素 */
let teaserEl = null;
/** SDK 鉴权:当前选中的角色 ID(从 roles 列表中选择) */
let selectedRoleId = null;
/** 提示气泡定时器 */
let teaserTimer = null;
/** 未读徽章元素(挂在 launcher 内部) */
let badgeEl = null;
/** 音频上下文(提示音用) */
let audioCtx = null;
// ==================== 角色选择器 ====================
/**
* 渲染角色选择器下拉框挂在 header 区域
* - 只有 1 个角色时自动选定不渲染下拉框
* - 2 个角色时渲染下拉框支持切换
* - localStorage 恢复上次选择
*/
function renderRoleSelector(headerEl) {
if (!currentConfig || !currentConfig.token || !currentConfig.roles) {
return;
}
const roles = currentConfig.roles;
if (roles.length === 0) {
return;
}
if (roles.length === 1) {
// 只有一个角色:自动选定,不渲染下拉框
selectedRoleId = String(roles[0].id);
return;
}
// ≥2 个角色:渲染下拉框
const select = document.createElement('select');
select.className = 'csk-role-selector';
roles.forEach(role => {
const option = document.createElement('option');
option.value = String(role.id);
option.textContent = role.name;
select.appendChild(option);
});
// 从 localStorage 恢复上次选择
const storageKey = `csk_role_${currentConfig.integrateId}_${currentConfig.userId || 'default'}`;
const savedRoleId = localStorage.getItem(storageKey);
if (savedRoleId && roles.some(r => String(r.id) === savedRoleId)) {
select.value = savedRoleId;
selectedRoleId = savedRoleId;
} else {
selectedRoleId = String(roles[0].id);
}
select.addEventListener('change', () => {
selectedRoleId = select.value;
localStorage.setItem(storageKey, select.value);
logger.info(`切换角色 roleId=${selectedRoleId}`);
});
// 挂到 header 的左侧区域后面
headerEl.appendChild(select);
}
// ==================== 公开 API ====================
/** 初始化 SDK */
function init(rawConfig) {
@ -4760,7 +4687,6 @@ var ChatbotSDK = (function () {
launcherDragCleanup = null;
}
launcherPos = null;
selectedRoleId = null;
removeStyles();
document.removeEventListener('keydown', onKeyDown);
window.removeEventListener('resize', onResize);
@ -4778,6 +4704,7 @@ var ChatbotSDK = (function () {
hideLoadingFn = null;
badgeEl = null;
audioCtx = null;
clearApiConfig();
logger.lifecycleDestroy(oldIntegrateId || '');
}
function open() {

2
src/main/resources/static/sdk/chatbot-sdk.js.map
File diff suppressed because it is too large
View File

2
src/main/resources/static/sdk/chatbot-sdk.min.js
File diff suppressed because it is too large
View File

2
src/main/resources/static/sdk/chatbot-sdk.min.js.map
File diff suppressed because it is too large
View File

55
src/main/resources/static/sdk/test.html

@ -201,7 +201,7 @@ body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Noto Sans S
</div>
</div>
<div class="actions">
<button class="btn btn-primary btn-full" onclick="doInit()">🚀 初始化 SDK</button>
<button class="btn btn-primary btn-full" id="btn-init" onclick="doInit()">🚀 初始化 SDK</button>
</div>
<div class="actions">
<button class="btn btn-outline btn-sm" onclick="domAction('open')">👁 打开窗口</button>
@ -277,7 +277,7 @@ body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Noto Sans S
</div>
</div>
<script src="/sdk/chatbot-sdk.min.js"></script>
<script src="/sdk/chatbot-sdk.min.js?v=2"></script>
<script>
(function() {
@ -315,6 +315,7 @@ body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Noto Sans S
function getCfg() {
const token = getEl('cfg-token').value.trim() || undefined;
console.log('[getCfg] token input value:', getEl('cfg-token').value, 'trimmed:', token);
const cfg = {
integrateId: getEl('cfg-iid').value, // 对应后端 roleId
requestDomain: getEl('cfg-domain').value || window.location.origin,
@ -337,9 +338,22 @@ body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Noto Sans S
// roles 从 Token 换取接口获取(缓存在 window.__sdkRoles)
if (window.__sdkRoles) cfg.roles = window.__sdkRoles;
}
console.log('[getCfg] final cfg:', cfg);
return cfg;
}
/**
* 根据 Token 输入框内容更新初始化按钮状态
*/
function updateInitButton() {
const btn = getEl('btn-init');
if (!btn) return;
const hasToken = !!getEl('cfg-token').value.trim();
btn.disabled = !hasToken;
btn.style.opacity = hasToken ? '1' : '0.6';
btn.title = hasToken ? '' : '请先获取 SDK Token';
}
/**
* 用 API Key 换取 SDK Token
*/
@ -368,18 +382,28 @@ body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Noto Sans S
if (data.roles && data.roles.length > 0) {
getEl('cfg-iid').value = data.roles[0].id;
}
// 刷新接入代码
generateCode();
// 如果 SDK 已加载,自动用 Token 重新初始化
if (document.getElementById('csk-launcher')) {
ChatbotSDK.destroy();
setTimeout(() => ChatbotSDK.init(getCfg()), 100);
}
btn.textContent = '✅ 已获取';
btn.style.background = '#059669';
setTimeout(() => { btn.textContent = '获取 Token'; btn.style.background = ''; btn.disabled = false; }, 2000);
updateInitButton();
} else {
alert('换取失败: ' + (data.message || '未知错误'));
btn.textContent = '获取 Token';
btn.disabled = false;
updateInitButton();
}
} catch (e) {
alert('请求失败: ' + e.message);
btn.textContent = '获取 Token';
btn.disabled = false;
updateInitButton();
}
};
function sleep(ms){return new Promise(r=>setTimeout(r,ms));}
@ -426,7 +450,15 @@ body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Noto Sans S
params.push(' integrateId: ' + iidLit + ', // 必传:客服角色 ID(对应后端 roleId)');
params.push(' requestDomain: ' + JSON.stringify(domain) + ', // 必传:后端 API 域名');
// Token 鉴权(推荐)
params.push(' token: ' + "'<从后端获取的 SDK Token>', // 推荐:SDK JWT Token(POST /open-api/auth/token 换取)");
const token = getEl('cfg-token').value.trim();
if (token) {
params.push(' token: ' + JSON.stringify(token) + ', // SDK JWT Token(有效期约2小时,生产环境请从后端动态换取)');
if (window.__sdkRoles) {
params.push(' roles: ' + JSON.stringify(window.__sdkRoles) + ', // 可用客服角色列表');
}
} else {
params.push(' token: ' + "'<从后端获取的 SDK Token>', // 推荐:SDK JWT Token(POST /open-api/auth/token 换取)");
}
// 可选参数:仅输出与默认值不同的项
if (cfg.userId) params.push(' userId: ' + JSON.stringify(cfg.userId) + ', // 可选:外部用户ID(对应后端 accountId)');
if (cfg.title !== SDK_DEFAULTS.title) params.push(' title: ' + JSON.stringify(cfg.title) + ', // 弹窗标题');
@ -522,7 +554,17 @@ body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Noto Sans S
generateCode();
};
window.doInit=function(){ChatbotSDK.destroy();ChatbotSDK.init(getCfg());const tag=getEl('tag-sdk');if(document.getElementById('csk-launcher')){tag.className='tag tag--pass';tag.textContent='✅ SDK 就绪';}};
window.doInit=function(){
const token = getEl('cfg-token').value.trim();
if (!token) {
alert('请先点击「获取 Token」按钮,用 API Key 换取 SDK Token 后再初始化。');
return;
}
ChatbotSDK.destroy();
ChatbotSDK.init(getCfg());
const tag=getEl('tag-sdk');
if(document.getElementById('csk-launcher')){tag.className='tag tag--pass';tag.textContent='✅ SDK 就绪';}
};
window.doDestroy=function(){ChatbotSDK.destroy();const tag=getEl('tag-sdk');tag.className='tag tag--idle';tag.textContent='⭕ SDK 未加载';};
window.doClearHistory=function(){ChatbotSDK.clearHistory();};
window.domAction=function(act){if(!document.getElementById('csk-launcher'))ChatbotSDK.init(getCfg());ChatbotSDK[act]();};
@ -623,8 +665,13 @@ body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Noto Sans S
if(!el)return;
el.addEventListener('input', generateCode);
el.addEventListener('change', generateCode);
if(id==='cfg-token'){
el.addEventListener('input', updateInitButton);
el.addEventListener('change', updateInitButton);
}
});
generateCode();
updateInitButton();
// 后端连通性探测(使用 Token 或直接请求)
const probeToken = getEl('cfg-token').value.trim();
const probeHeaders = probeToken ? { 'Authorization': 'Bearer ' + probeToken } : {};

Loading…
Cancel
Save