338 lines
12 KiB
HTML
338 lines
12 KiB
HTML
|
|
<!DOCTYPE html>
|
||
|
|
<html lang="zh-CN">
|
||
|
|
<head>
|
||
|
|
<meta charset="UTF-8">
|
||
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
|
|
<title>B2B AI 助手 - 调试版本</title>
|
||
|
|
<style>
|
||
|
|
body {
|
||
|
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||
|
|
max-width: 1400px;
|
||
|
|
margin: 0 auto;
|
||
|
|
padding: 20px;
|
||
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
|
|
min-height: 100vh;
|
||
|
|
}
|
||
|
|
.container {
|
||
|
|
display: grid;
|
||
|
|
grid-template-columns: 1fr 1fr;
|
||
|
|
gap: 20px;
|
||
|
|
}
|
||
|
|
.left-panel, .right-panel {
|
||
|
|
background: white;
|
||
|
|
border-radius: 10px;
|
||
|
|
padding: 20px;
|
||
|
|
box-shadow: 0 10px 40px rgba(0,0,0,0.1);
|
||
|
|
}
|
||
|
|
h1 {
|
||
|
|
color: #333;
|
||
|
|
text-align: center;
|
||
|
|
margin-bottom: 10px;
|
||
|
|
grid-column: 1 / -1;
|
||
|
|
}
|
||
|
|
.subtitle {
|
||
|
|
text-align: center;
|
||
|
|
color: #666;
|
||
|
|
margin-bottom: 30px;
|
||
|
|
grid-column: 1 / -1;
|
||
|
|
}
|
||
|
|
h2 {
|
||
|
|
color: #667eea;
|
||
|
|
border-bottom: 2px solid #667eea;
|
||
|
|
padding-bottom: 10px;
|
||
|
|
margin-top: 0;
|
||
|
|
}
|
||
|
|
.log-container {
|
||
|
|
background: #1e1e1e;
|
||
|
|
color: #00ff00;
|
||
|
|
padding: 15px;
|
||
|
|
border-radius: 5px;
|
||
|
|
height: 400px;
|
||
|
|
overflow-y: auto;
|
||
|
|
font-family: 'Courier New', monospace;
|
||
|
|
font-size: 12px;
|
||
|
|
}
|
||
|
|
.log-entry {
|
||
|
|
margin: 5px 0;
|
||
|
|
padding: 3px 0;
|
||
|
|
}
|
||
|
|
.log-info { color: #00ff00; }
|
||
|
|
.log-warn { color: #ffaa00; }
|
||
|
|
.log-error { color: #ff4444; }
|
||
|
|
.log-success { color: #44ff44; }
|
||
|
|
.status-box {
|
||
|
|
background: #f8f9fa;
|
||
|
|
border-left: 4px solid #667eea;
|
||
|
|
padding: 15px;
|
||
|
|
margin: 10px 0;
|
||
|
|
border-radius: 5px;
|
||
|
|
}
|
||
|
|
.status-item {
|
||
|
|
display: flex;
|
||
|
|
justify-content: space-between;
|
||
|
|
padding: 8px 0;
|
||
|
|
border-bottom: 1px solid #ddd;
|
||
|
|
}
|
||
|
|
.status-item:last-child {
|
||
|
|
border-bottom: none;
|
||
|
|
}
|
||
|
|
.status-label {
|
||
|
|
font-weight: bold;
|
||
|
|
color: #667eea;
|
||
|
|
}
|
||
|
|
.status-value {
|
||
|
|
color: #333;
|
||
|
|
}
|
||
|
|
.test-buttons {
|
||
|
|
display: flex;
|
||
|
|
gap: 10px;
|
||
|
|
flex-wrap: wrap;
|
||
|
|
margin: 15px 0;
|
||
|
|
}
|
||
|
|
.test-btn {
|
||
|
|
background: #667eea;
|
||
|
|
color: white;
|
||
|
|
border: none;
|
||
|
|
padding: 10px 20px;
|
||
|
|
border-radius: 5px;
|
||
|
|
cursor: pointer;
|
||
|
|
font-size: 14px;
|
||
|
|
transition: background 0.3s;
|
||
|
|
}
|
||
|
|
.test-btn:hover {
|
||
|
|
background: #5568d3;
|
||
|
|
}
|
||
|
|
.test-btn:disabled {
|
||
|
|
background: #ccc;
|
||
|
|
cursor: not-allowed;
|
||
|
|
}
|
||
|
|
.clear-btn {
|
||
|
|
background: #ff4444;
|
||
|
|
}
|
||
|
|
.clear-btn:hover {
|
||
|
|
background: #dd3333;
|
||
|
|
}
|
||
|
|
</style>
|
||
|
|
</head>
|
||
|
|
<body>
|
||
|
|
<h1>🤖 B2B AI 智能客服助手 - 调试面板</h1>
|
||
|
|
<p class="subtitle">实时监控 Widget 状态和消息流</p>
|
||
|
|
|
||
|
|
<div class="container">
|
||
|
|
<div class="left-panel">
|
||
|
|
<h2>📊 连接状态</h2>
|
||
|
|
<div class="status-box">
|
||
|
|
<div class="status-item">
|
||
|
|
<span class="status-label">Chatwoot 服务:</span>
|
||
|
|
<span class="status-value" id="chatwootStatus">检查中...</span>
|
||
|
|
</div>
|
||
|
|
<div class="status-item">
|
||
|
|
<span class="status-label">Widget SDK:</span>
|
||
|
|
<span class="status-value" id="widgetStatus">未加载</span>
|
||
|
|
</div>
|
||
|
|
<div class="status-item">
|
||
|
|
<span class="status-label">WebSocket:</span>
|
||
|
|
<span class="status-value" id="wsStatus">未连接</span>
|
||
|
|
</div>
|
||
|
|
<div class="status-item">
|
||
|
|
<span class="status-label">当前会话:</span>
|
||
|
|
<span class="status-value" id="conversationId">无</span>
|
||
|
|
</div>
|
||
|
|
<div class="status-item">
|
||
|
|
<span class="status-label">Website Token:</span>
|
||
|
|
<span class="status-value" id="websiteToken">39PNCMvbMk3NvB7uaDNucc6o</span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<h2>🧪 测试操作</h2>
|
||
|
|
<div class="test-buttons">
|
||
|
|
<button class="test-btn" onclick="checkChatwootService()">检查服务</button>
|
||
|
|
<button class="test-btn" onclick="refreshWidget()">刷新 Widget</button>
|
||
|
|
<button class="test-btn" onclick="getConversationInfo()">获取会话信息</button>
|
||
|
|
<button class="test-btn clear-btn" onclick="clearLogs()">清除日志</button>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<h2>📝 快速测试问题(点击复制到剪贴板)</h2>
|
||
|
|
<div class="test-buttons">
|
||
|
|
<button class="test-btn" onclick="sendTestMessage('你好')">👋 你好</button>
|
||
|
|
<button class="test-btn" onclick="sendTestMessage('查询订单 202071324')">📦 查询订单</button>
|
||
|
|
<button class="test-btn" onclick="sendTestMessage('如何退货?')">❓ 如何退货</button>
|
||
|
|
<button class="test-btn" onclick="sendTestMessage('营业时间')">🕐 营业时间</button>
|
||
|
|
</div>
|
||
|
|
<p style="color: #666; font-size: 14px; margin-top: 10px;">
|
||
|
|
💡 提示:点击按钮后,在右下角聊天窗口中按 Ctrl+V 粘贴并发送
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="right-panel">
|
||
|
|
<h2>📋 实时日志</h2>
|
||
|
|
<div class="log-container" id="logContainer">
|
||
|
|
<div class="log-entry log-info">[系统] 日志系统已启动...</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<script>
|
||
|
|
const logContainer = document.getElementById('logContainer');
|
||
|
|
|
||
|
|
function addLog(message, type = 'info') {
|
||
|
|
const timestamp = new Date().toLocaleTimeString();
|
||
|
|
const logEntry = document.createElement('div');
|
||
|
|
logEntry.className = `log-entry log-${type}`;
|
||
|
|
logEntry.textContent = `[${timestamp}] ${message}`;
|
||
|
|
logContainer.appendChild(logEntry);
|
||
|
|
logContainer.scrollTop = logContainer.scrollHeight;
|
||
|
|
}
|
||
|
|
|
||
|
|
function clearLogs() {
|
||
|
|
logContainer.innerHTML = '<div class="log-entry log-info">[系统] 日志已清除</div>';
|
||
|
|
}
|
||
|
|
|
||
|
|
// 检查 Chatwoot 服务
|
||
|
|
async function checkChatwootService() {
|
||
|
|
addLog('检查 Chatwoot 服务状态...', 'info');
|
||
|
|
const statusEl = document.getElementById('chatwootStatus');
|
||
|
|
|
||
|
|
try {
|
||
|
|
const response = await fetch('http://localhost:3000', { mode: 'no-cors' });
|
||
|
|
statusEl.textContent = '✅ 运行中';
|
||
|
|
statusEl.style.color = '#28a745';
|
||
|
|
addLog('✅ Chatwoot 服务运行正常', 'success');
|
||
|
|
} catch (error) {
|
||
|
|
statusEl.textContent = '❌ 无法访问';
|
||
|
|
statusEl.style.color = '#dc3545';
|
||
|
|
addLog(`❌ 无法连接到 Chatwoot: ${error.message}`, 'error');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 发送测试消息 - 直接复制到剪贴板
|
||
|
|
function sendTestMessage(message) {
|
||
|
|
addLog(`📋 已复制消息到剪贴板: "${message}"`, 'info');
|
||
|
|
addLog('→ 请在右下角聊天窗口中粘贴并发送', 'warn');
|
||
|
|
|
||
|
|
// 复制到剪贴板
|
||
|
|
navigator.clipboard.writeText(message).then(() => {
|
||
|
|
// 可选:自动打开 Widget
|
||
|
|
if (window.$chatwoot && window.$chatwoot.toggle) {
|
||
|
|
try {
|
||
|
|
window.$chatwoot.toggle('open');
|
||
|
|
addLog('✅ 聊天窗口已打开', 'success');
|
||
|
|
} catch (e) {
|
||
|
|
addLog('⚠️ 无法自动打开聊天窗口', 'warn');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}).catch(err => {
|
||
|
|
addLog(`❌ 复制失败: ${err.message}`, 'error');
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
// 刷新 Widget
|
||
|
|
function refreshWidget() {
|
||
|
|
addLog('刷新 Widget...', 'info');
|
||
|
|
location.reload();
|
||
|
|
}
|
||
|
|
|
||
|
|
// 获取会话信息
|
||
|
|
function getConversationInfo() {
|
||
|
|
if (window.$chatwoot) {
|
||
|
|
try {
|
||
|
|
const info = window.$chatwoot.getConversationInfo();
|
||
|
|
addLog(`会话信息: ${JSON.stringify(info)}`, 'info');
|
||
|
|
} catch (error) {
|
||
|
|
addLog(`无法获取会话信息: ${error.message}`, 'warn');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 页面加载时检查服务
|
||
|
|
window.addEventListener('load', function() {
|
||
|
|
setTimeout(checkChatwootService, 1000);
|
||
|
|
});
|
||
|
|
|
||
|
|
// ==================== Chatwoot Widget 配置 ====================
|
||
|
|
|
||
|
|
window.chatwootSettings = {
|
||
|
|
"position": "right",
|
||
|
|
"type": "expanded_bubble",
|
||
|
|
"launcherTitle": "Chat with us"
|
||
|
|
};
|
||
|
|
|
||
|
|
(function(d,t) {
|
||
|
|
var BASE_URL = "http://localhost:3000";
|
||
|
|
var g = d.createElement(t), s = d.getElementsByTagName(t)[0];
|
||
|
|
g.src = BASE_URL + "/packs/js/sdk.js";
|
||
|
|
g.async = true;
|
||
|
|
g.onload = function() {
|
||
|
|
addLog('Chatwoot SDK 文件已加载', 'success');
|
||
|
|
document.getElementById('widgetStatus').textContent = '✅ 已加载';
|
||
|
|
|
||
|
|
window.chatwootSDK.run({
|
||
|
|
websiteToken: '39PNCMvbMk3NvB7uaDNucc6o',
|
||
|
|
baseUrl: BASE_URL
|
||
|
|
});
|
||
|
|
|
||
|
|
addLog('Website Token: 39PNCMvbMk3NvB7uaDNucc6o', 'info');
|
||
|
|
addLog('Base URL: ' + BASE_URL, 'info');
|
||
|
|
|
||
|
|
// 监听 Widget 就绪事件
|
||
|
|
setTimeout(function() {
|
||
|
|
if (window.$chatwoot) {
|
||
|
|
addLog('✅ Chatwoot Widget 已初始化', 'success');
|
||
|
|
document.getElementById('wsStatus').textContent = '✅ 已连接';
|
||
|
|
|
||
|
|
// 设置用户信息(可选)
|
||
|
|
window.$chatwoot.setUser('debug_user_' + Date.now(), {
|
||
|
|
email: 'debug@example.com',
|
||
|
|
name: 'Debug User'
|
||
|
|
});
|
||
|
|
|
||
|
|
addLog('用户信息已设置', 'info');
|
||
|
|
} else {
|
||
|
|
addLog('❌ Widget 初始化失败', 'error');
|
||
|
|
document.getElementById('widgetStatus').textContent = '❌ 初始化失败';
|
||
|
|
}
|
||
|
|
}, 2000);
|
||
|
|
};
|
||
|
|
|
||
|
|
g.onerror = function() {
|
||
|
|
addLog('❌ Chatwoot SDK 加载失败', 'error');
|
||
|
|
document.getElementById('widgetStatus').textContent = '❌ 加载失败';
|
||
|
|
};
|
||
|
|
|
||
|
|
s.parentNode.insertBefore(g, s);
|
||
|
|
})(document, "script");
|
||
|
|
|
||
|
|
// 监听网络错误
|
||
|
|
window.addEventListener('error', function(e) {
|
||
|
|
if (e.message.includes('404')) {
|
||
|
|
addLog(`⚠️ 404 错误: ${e.filename}`, 'warn');
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
// 拦截 fetch 请求
|
||
|
|
const originalFetch = window.fetch;
|
||
|
|
window.fetch = function(...args) {
|
||
|
|
const url = args[0];
|
||
|
|
|
||
|
|
// 记录发送到 Chatwoot API 的请求
|
||
|
|
if (typeof url === 'string' && url.includes('localhost:3000')) {
|
||
|
|
const method = args[1]?.method || 'GET';
|
||
|
|
addLog(`API 请求: ${method} ${url}`, 'info');
|
||
|
|
}
|
||
|
|
|
||
|
|
return originalFetch.apply(this, args).then(response => {
|
||
|
|
// 记录错误响应
|
||
|
|
if (!response.ok && url.includes('localhost:3000')) {
|
||
|
|
addLog(`API 响应: ${response.status} ${response.statusText} - ${url}`, 'error');
|
||
|
|
}
|
||
|
|
return response;
|
||
|
|
});
|
||
|
|
};
|
||
|
|
|
||
|
|
addLog('调试系统已初始化', 'success');
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<!-- Chatwoot Widget 会自动加载 -->
|
||
|
|
</body>
|
||
|
|
</html>
|