<!DOCTYPE html><html lang="zh"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>访问受限</title><style>body{margin:0;padding:0;height:100vh;background:linear-gradient(135deg,#f5f0ff,#e8e0f5);font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Microsoft YaHei",sans-serif;display:flex;align-items:center;justify-content:center;color:#5a4a7a}.box{background:rgba(255,255,255,0.85);padding:40px;border-radius:20px;box-shadow:0 8px 32px rgba(150,130,200,0.15);text-align:center;max-width:400px}.box h1{font-size:22px;margin-bottom:16px}.box p{font-size:14px;line-height:1.8;color:#7a6a9a;margin-bottom:8px}.contact{margin-top:20px;padding-top:20px;border-top:1px solid rgba(200,180,255,0.3);font-size:13px;color:#8a7aaa}</style></head><body><div class="box"><h1>访问受限</h1><p>您的IP触发了安全规则。</p><p>如有疑问请联系管理员。</p><div class="contact">邮箱: qinghuany@foxmail.com<br>QQ: 1469725211</div></div></body></html>';
}

if (isBlacklisted($_SERVER['REMOTE_ADDR'] ?? '0.0.0.0')) {
    showBlockPage();
    exit;
}

// ========== 请求处理 ==========
$requestMethod = $_SERVER['REQUEST_METHOD'];
$cacheKey = 'chat_messages_' . date('Y-m-d');

// 内存消息存储（Redis不可用时降级到Session）
if (!isset($_SESSION['chat_messages'])) {
    $_SESSION['chat_messages'] = [];
}

function getMessages() {
    global $redis, $cacheKey;
    if ($redis) {
        $cached = $redis->get($cacheKey);
        if ($cached) {
            $decoded = json_decode($cached, true);
            if (is_array($decoded)) return $decoded;
        }
    }
    return $_SESSION['chat_messages'] ?? [];
}

function saveMessages($messages) {
    global $redis, $cacheKey;
    if ($redis) {
        $redis->setex($cacheKey, 3600, json_encode($messages));
    }
    $_SESSION['chat_messages'] = $messages;
}

// ========== POST 处理 ==========
if ($requestMethod === 'POST') {
    header('Content-Type: application/json; charset=utf-8');

    $rawInput = file_get_contents('php://input');
    $data = json_decode($rawInput, true);

    if (json_last_error() !== JSON_ERROR_NONE) {
        echo json_encode(['success' => false, 'message' => '请求数据格式错误']);
        exit;
    }

    if (!isset($data['content']) || trim($data['content']) === '') {
        echo json_encode(['success' => false, 'message' => '内容不能为空']);
        exit;
    }

    $content = trim($data['content']);
    $referrer = $_SERVER['HTTP_REFERER'] ?? '直接访问';

    // 转人工
    if (strpos($content, '转人工') !== false) {
        $messages = getMessages();
        $messages[] = [
            'type' => 'user',
            'content' => htmlspecialchars($content, ENT_QUOTES, 'UTF-8'),
            'created_at' => date('Y-m-d H:i:s'),
            'source' => $referrer
        ];
        saveMessages($messages);
        echo json_encode(['success' => true, 'message' => '已请求人工客服']);
        exit;
    }

    // 检查是否已请求人工
    $messages = getMessages();
    $hasHuman = false;
    foreach ($messages as $msg) {
        if (($msg['type'] ?? '') === 'user' && strpos($msg['content'] ?? '', '转人工') !== false) {
            $hasHuman = true;
            break;
        }
    }

    if (!$hasHuman) {
        $messages[] = [
            'type' => 'user',
            'content' => htmlspecialchars($content, ENT_QUOTES, 'UTF-8'),
            'created_at' => date('Y-m-d H:i:s'),
            'source' => $referrer
        ];
        saveMessages($messages);
        echo json_encode(['success' => true, 'message' => '已发送消息', 'showHint' => true]);
        exit;
    }

    // 调用AI回复
    $aiResponse = getAIResponse($content);

    $messages = getMessages();
    $messages[] = [
        'type' => 'user',
        'content' => htmlspecialchars($content, ENT_QUOTES, 'UTF-8'),
        'created_at' => date('Y-m-d H:i:s'),
        'source' => $referrer
    ];
    $messages[] = [
        'type' => 'ai',
        'content' => $aiResponse,
        'created_at' => date('Y-m-d H:i:s')
    ];

    saveMessages($messages);
    echo json_encode(['success' => true, 'message' => $aiResponse]);
    exit;
}

// ========== GET 处理 ==========
if ($requestMethod === 'GET') {
    header('Content-Type: application/json; charset=utf-8');
    $action = $_GET['action'] ?? '';
    $action = preg_replace('/[^a-zA-Z0-9_]/', '', $action);

    if ($action === 'get_messages') {
        echo json_encode(['success' => true, 'messages' => getMessages()]);
        exit;
    }

    if ($action === 'clear_messages') {
        if ($redis) $redis->del($cacheKey);
        $_SESSION['chat_messages'] = [];
        echo json_encode(['success' => true]);
        exit;
    }

    if ($action === 'get_last_staff_name') {
        echo json_encode(['success' => true, 'staff_name' => '萌哒云客服']);
        exit;
    }

    echo json_encode(['success' => false, 'message' => '未知操作']);
    exit;
}

// ========== AI接口 ==========
function getAIResponse($userMessage) {
    $apiKey = 'sk-8NZ9R5a57V8OCbeFBGKyTFybQ9iNuIE3bPFSjthfQORrkbGP';
    $url = 'https://api.chatanywhere.tech/v1/chat/completions';
    $data = [
        'model' => 'gpt-3.5-turbo',
        'messages' => [['role' => 'user', 'content' => $userMessage]],
        'temperature' => 0.7,
        'top_p' => 1.0,
        'presence_penalty' => 1.0
    ];

    if (!function_exists('curl_init')) {
        error_log("[AI Error] cURL extension not available");
        return '抱歉，服务器配置异常，暂时无法连接AI服务。';
    }

    $ch = curl_init($url);
    if (!$ch) {
        error_log("[AI Error] curl_init failed");
        return '抱歉，网络服务初始化失败。';
    }

    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'Content-Type: application/json',
        'Authorization: Bearer ' . $apiKey
    ]);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
    curl_setopt($ch, CURLOPT_TIMEOUT, 15);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);

    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $curlErr = curl_errno($ch);
    $curlErrMsg = curl_error($ch);
    curl_close($ch);

    if ($curlErr) {
        error_log("[AI cURL Error] #$curlErr: $curlErrMsg");
        return '抱歉，网络连接异常，请稍后重试。';
    }

    if ($httpCode !== 200) {
        error_log("[AI HTTP Error] Code: $httpCode, Response: " . substr($response, 0, 300));
        return '抱歉，AI服务暂时不可用（' . $httpCode . '），请稍后重试。';
    }

    $responseData = json_decode($response, true);
    if (json_last_error() !== JSON_ERROR_NONE) {
        error_log("[AI JSON Error] " . json_last_error_msg());
        return '抱歉，AI响应解析失败，请稍后重试。';
    }

    if (isset($responseData['choices'][0]['message']['content'])) {
        return trim($responseData['choices'][0]['message']['content']);
    }

    if (isset($responseData['error']['message'])) {
        error_log("[AI API Error] " . $responseData['error']['message']);
        return '抱歉，AI服务返回错误：' . $responseData['error']['message'];
    }

    error_log("[AI Unexpected Response] " . substr($response, 0, 500));
    return '抱歉，无法获取AI回复，请稍后重试。';
}
?>
<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title>萌哒云 - 智能客服</title>
    <style>
:root {
    --primary: #7c6fae; --primary-light: #a898d8; --primary-dark: #5d4e8a;
    --accent: #c4b5e0; --bg: #f7f4fc; --bg-card: rgba(255,255,255,0.85);
    --bg-input: rgba(255,255,255,0.92); --border: rgba(180,165,220,0.25);
    --border-focus: rgba(124,111,174,0.5); --shadow: 0 4px 20px rgba(120,100,170,0.1);
    --shadow-hover: 0 6px 28px rgba(120,100,170,0.16); --text: #4a3f6a;
    --text-secondary: #7a6f9a; --text-muted: #a098b8;
    --user-bg: linear-gradient(135deg,#e2d9f4,#d8cef0);
    --ai-bg: linear-gradient(135deg,#f3effa,#ebe5f5);
    --radius: 16px; --radius-sm: 10px;
    --transition: all 0.3s cubic-bezier(0.25,0.46,0.45,0.94);
}
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes fadeInUp { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: translateY(0); } }
@keyframes slideIn { from { opacity: 0; transform: translateY(10px) scale(0.97); } to { opacity: 1; transform: translateY(0) scale(1); } }
@keyframes pulse-ring { 0% { box-shadow: 0 0 0 0 rgba(124,111,174,0.35); } 70% { box-shadow: 0 0 0 10px rgba(124,111,174,0); } 100% { box-shadow: 0 0 0 0 rgba(124,111,174,0); } }
@keyframes float { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-4px); } }
@keyframes typing-bounce { 0%,60%,100% { transform: translateY(0); opacity: 0.4; } 30% { transform: translateY(-3px); opacity: 1; } }
@keyframes spin { to { transform: rotate(360deg); } }
* { box-sizing: border-box; margin: 0; padding: 0; }
html, body { font-family: -apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Microsoft YaHei",sans-serif; height: 100%; background: var(--bg); color: var(--text); -webkit-font-smoothing: antialiased; overflow: hidden; }
#app { display: flex; flex-direction: column; height: 100vh; max-width: 100%; margin: 0 auto; background: var(--bg); position: relative; }
.chat-header { display: flex; align-items: center; justify-content: space-between; padding: 12px 16px; background: linear-gradient(135deg,rgba(180,168,216,0.9),rgba(160,148,200,0.9)); backdrop-filter: blur(20px); border-bottom: 1px solid rgba(255,255,255,0.15); flex-shrink: 0; z-index: 10; }
.header-left { display: flex; align-items: center; gap: 10px; }
.header-avatar { width: 36px; height: 36px; border-radius: 50%; background: linear-gradient(135deg,#c8b8e4,#a898d8); display: flex; align-items: center; justify-content: center; box-shadow: 0 2px 8px rgba(0,0,0,0.08); border: 2px solid rgba(255,255,255,0.3); flex-shrink: 0; }
.header-avatar svg { width: 20px; height: 20px; fill: #fff; }
.header-info { line-height: 1.3; }
.header-title { font-size: 15px; font-weight: 600; color: #fff; letter-spacing: 0.3px; }
.header-status { font-size: 11px; color: rgba(255,255,255,0.85); display: flex; align-items: center; gap: 5px; }
.status-dot { width: 6px; height: 6px; background: #88e098; border-radius: 50%; box-shadow: 0 0 5px rgba(136,224,152,0.5); animation: pulse-ring 2.5s ease-in-out infinite; }
.header-actions { display: flex; gap: 6px; }
.icon-btn { width: 32px; height: 32px; border-radius: 50%; border: none; background: rgba(255,255,255,0.18); color: #fff; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: var(--transition); }
.icon-btn:hover { background: rgba(255,255,255,0.3); transform: scale(1.08); }
.icon-btn svg { width: 16px; height: 16px; fill: currentColor; }
.quick-tags { display: flex; gap: 8px; padding: 10px 14px; background: rgba(248,245,255,0.6); border-bottom: 1px solid var(--border); overflow-x: auto; scrollbar-width: none; flex-shrink: 0; }
.quick-tags::-webkit-scrollbar { display: none; }
.tag { flex-shrink: 0; padding: 5px 14px; border-radius: 18px; border: 1px solid rgba(180,165,220,0.35); background: rgba(255,255,255,0.6); color: var(--text-secondary); font-size: 12px; cursor: pointer; transition: var(--transition); display: flex; align-items: center; gap: 4px; white-space: nowrap; }
.tag:hover { background: rgba(180,165,220,0.2); border-color: rgba(124,111,174,0.45); transform: translateY(-1px); }
.tag svg { width: 13px; height: 13px; fill: currentColor; opacity: 0.7; }
.messages-wrap { flex: 1; overflow-y: auto; padding: 14px; scroll-behavior: smooth; position: relative; }
.messages-wrap::-webkit-scrollbar { width: 4px; }
.messages-wrap::-webkit-scrollbar-track { background: transparent; }
.messages-wrap::-webkit-scrollbar-thumb { background: rgba(180,165,220,0.35); border-radius: 10px; }
.welcome { text-align: center; padding: 30px 0 20px; animation: fadeIn 0.5s ease-out; }
.welcome-icon { width: 56px; height: 56px; background: linear-gradient(135deg,#c8b8e4,#a898d8); border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; margin-bottom: 14px; box-shadow: 0 4px 16px rgba(168,152,216,0.25); }
.welcome-icon svg { width: 28px; height: 28px; fill: #fff; }
.welcome h3 { font-size: 17px; font-weight: 600; color: var(--text); margin-bottom: 6px; }
.welcome p { font-size: 13px; color: var(--text-muted); line-height: 1.7; }
.msg { display: flex; align-items: flex-end; margin-bottom: 14px; animation: slideIn 0.3s ease-out forwards; opacity: 0; }
.msg-user { justify-content: flex-end; }
.msg-ai { justify-content: flex-start; }
.msg-avatar { width: 32px; height: 32px; border-radius: 50%; object-fit: cover; flex-shrink: 0; border: 2px solid rgba(180,165,220,0.25); }
.msg-wrap { display: flex; align-items: flex-end; gap: 8px; max-width: 82%; }
.msg-user .msg-wrap { flex-direction: row-reverse; }
.msg-body { padding: 9px 13px; border-radius: var(--radius-sm); font-size: 13.5px; line-height: 1.65; word-break: break-word; box-shadow: 0 1px 6px rgba(120,100,170,0.06); transition: var(--transition); }
.msg-body:hover { transform: translateY(-1px); }
.msg-user .msg-body { background: var(--user-bg); border-radius: var(--radius-sm) var(--radius-sm) 3px var(--radius-sm); color: var(--text); border: 1px solid rgba(180,165,220,0.2); }
.msg-ai .msg-body { background: var(--ai-bg); border-radius: var(--radius-sm) var(--radius-sm) var(--radius-sm) 3px; color: var(--text); border: 1px solid rgba(180,165,220,0.2); }
.msg-name { font-size: 11px; font-weight: 600; color: var(--primary-dark); margin-bottom: 3px; opacity: 0.85; }
.msg-time { font-size: 10px; color: var(--text-muted); margin-top: 4px; opacity: 0.65; }
.typing { display: flex; align-items: center; gap: 3px; padding: 10px 14px; background: var(--ai-bg); border-radius: var(--radius-sm) var(--radius-sm) var(--radius-sm) 3px; border: 1px solid rgba(180,165,220,0.2); width: fit-content; }
.typing span { width: 6px; height: 6px; background: var(--accent); border-radius: 50%; animation: typing-bounce 1.4s ease-in-out infinite; }
.typing span:nth-child(2) { animation-delay: 0.2s; }
.typing span:nth-child(3) { animation-delay: 0.4s; }
.input-area { padding: 10px 14px 12px; background: rgba(248,245,255,0.5); border-top: 1px solid var(--border); flex-shrink: 0; z-index: 10; }
.toolbar { display: flex; gap: 4px; margin-bottom: 8px; padding-bottom: 8px; border-bottom: 1px solid rgba(180,165,220,0.1); }
.tool-btn { width: 30px; height: 30px; border-radius: 7px; border: none; background: rgba(255,255,255,0.5); color: var(--text-secondary); cursor: pointer; display: flex; align-items: center; justify-content: center; transition: var(--transition); }
.tool-btn:hover { background: rgba(180,165,220,0.2); color: var(--primary-dark); }
.tool-btn svg { width: 15px; height: 15px; fill: currentColor; }
.msg-input { width: 100%; min-height: 48px; max-height: 100px; padding: 10px 12px; border-radius: var(--radius-sm); border: 1.5px solid var(--border); background: var(--bg-input); font-size: 13.5px; line-height: 1.55; color: var(--text); resize: none; outline: none; font-family: inherit; transition: var(--transition); }
.msg-input::placeholder { color: var(--text-muted); font-size: 13px; }
.msg-input:focus { border-color: var(--border-focus); box-shadow: 0 0 0 3px rgba(124,111,174,0.08); background: #fff; }
.send-row { display: flex; justify-content: space-between; align-items: center; margin-top: 8px; }
.char-count { font-size: 11px; color: var(--text-muted); }
.send-btn { padding: 7px 20px; border-radius: 18px; border: none; background: linear-gradient(135deg,#a090d0,#7c6fae); color: #fff; font-size: 13px; font-weight: 500; cursor: pointer; transition: var(--transition); box-shadow: 0 3px 10px rgba(124,111,174,0.25); display: flex; align-items: center; gap: 5px; }
.send-btn:hover { transform: translateY(-1px); box-shadow: 0 5px 16px rgba(124,111,174,0.35); }
.send-btn:disabled { opacity: 0.45; cursor: not-allowed; transform: none; }
.send-btn svg { width: 14px; height: 14px; fill: currentColor; }
.bottom-bar { display: flex; gap: 6px; padding: 8px 14px; background: rgba(248,245,255,0.4); border-top: 1px solid rgba(180,165,220,0.08); flex-shrink: 0; }
.bottom-btn { flex: 1; padding: 7px 10px; border-radius: var(--radius-sm); border: 1px solid rgba(180,165,220,0.2); background: rgba(255,255,255,0.45); color: var(--text-secondary); font-size: 11.5px; cursor: pointer; transition: var(--transition); display: flex; align-items: center; justify-content: center; gap: 4px; }
.bottom-btn:hover { background: rgba(180,165,220,0.15); border-color: rgba(124,111,174,0.3); }
.bottom-btn svg { width: 13px; height: 13px; fill: currentColor; opacity: 0.7; }
.loading-mask { display: none; position: absolute; inset: 0; background: rgba(255,255,255,0.8); z-index: 50; justify-content: center; align-items: center; flex-direction: column; gap: 10px; backdrop-filter: blur(6px); }
.loading-mask::before { content: ''; width: 32px; height: 32px; border: 3px solid rgba(180,165,220,0.25); border-top-color: var(--primary); border-radius: 50%; animation: spin 0.8s linear infinite; }
.loading-mask span { font-size: 12px; color: var(--text-secondary); }
.offline-bar { display: none; padding: 7px 14px; background: linear-gradient(90deg,#fef6e8,#fdf0d8); color: #b07020; font-size: 11px; text-align: center; border-bottom: 1px solid rgba(255,200,130,0.25); flex-shrink: 0; z-index: 10; }
#toast-box { position: fixed; top: 16px; left: 50%; transform: translateX(-50%); z-index: 10000; display: flex; flex-direction: column; gap: 6px; pointer-events: none; }
.toast-item { padding: 9px 18px; border-radius: var(--radius-sm); font-size: 12px; font-weight: 500; animation: fadeInDown 0.25s ease-out; pointer-events: auto; box-shadow: 0 3px 12px rgba(0,0,0,0.08); backdrop-filter: blur(10px); display: flex; align-items: center; gap: 6px; }
.toast-item svg { width: 14px; height: 14px; flex-shrink: 0; }
.toast-err { background: rgba(255,235,238,0.95); color: #b05060; border: 1px solid rgba(255,180,190,0.35); }
.toast-ok { background: rgba(232,245,233,0.95); color: #3a8a5a; border: 1px solid rgba(180,220,190,0.35); }
.toast-info { background: rgba(243,240,250,0.95); color: var(--primary-dark); border: 1px solid rgba(180,165,220,0.35); }
.captcha-mask { position: fixed; inset: 0; background: rgba(0,0,0,0.55); z-index: 9999; display: none; align-items: center; justify-content: center; backdrop-filter: blur(8px); }
.captcha-mask iframe { width: 90%; max-width: 400px; height: 340px; border-radius: var(--radius); border: 0; box-shadow: 0 16px 48px rgba(0,0,0,0.25); background: #fff; }
.confirm-mask { position: fixed; inset: 0; background: rgba(0,0,0,0.45); z-index: 9998; display: none; align-items: center; justify-content: center; backdrop-filter: blur(4px); }
.confirm-box { background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius); padding: 24px; max-width: 320px; width: 88%; text-align: center; box-shadow: var(--shadow-hover); backdrop-filter: blur(20px); animation: fadeInUp 0.3s ease-out; }
.confirm-box h4 { font-size: 16px; color: var(--text); margin-bottom: 10px; }
.confirm-box p { font-size: 13px; color: var(--text-secondary); line-height: 1.7; margin-bottom: 18px; }
.confirm-btns { display: flex; gap: 10px; justify-content: center; }
.confirm-btns button { padding: 7px 20px; border-radius: 18px; border: none; font-size: 13px; cursor: pointer; transition: var(--transition); }
.btn-ok { background: linear-gradient(135deg,#a090d0,#7c6fae); color: #fff; }
.btn-cancel { background: rgba(180,165,220,0.15); color: var(--text-secondary); border: 1px solid rgba(180,165,220,0.25) !important; }
.confirm-btns button:hover { transform: translateY(-1px); }
.float-btn { position: fixed; bottom: 24px; right: 24px; width: 56px; height: 56px; background: linear-gradient(135deg,#a090d0,#7c6fae); border-radius: 50%; display: flex; justify-content: center; align-items: center; cursor: pointer; box-shadow: 0 5px 20px rgba(124,111,174,0.35); color: #fff; transition: var(--transition); animation: float 3s ease-in-out infinite; border: 2px solid rgba(255,255,255,0.3); z-index: 1000; }
.float-btn:hover { transform: scale(1.08); box-shadow: 0 7px 28px rgba(124,111,174,0.45); }
.float-btn svg { width: 26px; height: 26px; fill: currentColor; }
.float-badge { position: absolute; top: -2px; right: -2px; min-width: 18px; height: 18px; background: linear-gradient(135deg,#e07080,#f090a0); border-radius: 9px; font-size: 10px; font-weight: 700; display: flex; align-items: center; justify-content: center; padding: 0 5px; box-shadow: 0 2px 6px rgba(224,112,128,0.35); border: 2px solid #fff; display: none; }
.embed-wrap { display: none; position: fixed; top: 50%; left: 50%; transform: translate(-50%,-50%); width: 78%; max-width: 800px; height: 72vh; background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius); padding: 16px; z-index: 1002; box-shadow: var(--shadow-hover); backdrop-filter: blur(24px); animation: fadeInUp 0.35s ease-out; flex-direction: column; }
.embed-head { display: flex; justify-content: space-between; align-items: center; padding-bottom: 10px; margin-bottom: 10px; border-bottom: 1px solid var(--border); }
.embed-head h4 { font-size: 15px; color: var(--text); display: flex; align-items: center; gap: 6px; }
.embed-head h4 svg { width: 16px; height: 16px; fill: var(--primary); }
.embed-wrap iframe { flex: 1; width: 100%; border: none; border-radius: var(--radius-sm); background: #fff; }
@media (max-width: 480px) { .msg-wrap { max-width: 86%; } .msg-avatar { width: 28px; height: 28px; } .msg-body { padding: 8px 11px; font-size: 13px; } .welcome-icon { width: 48px; height: 48px; } .welcome-icon svg { width: 24px; height: 24px; } .quick-tags { padding: 8px 10px; } .tag { padding: 4px 11px; font-size: 11px; } .input-area { padding: 8px 10px 10px; } .bottom-bar { padding: 6px 10px; } .embed-wrap { width: 94%; height: 80vh; padding: 12px; } }
@media (prefers-reduced-motion: reduce) { * { animation: none !important; transition: none !important; } }
    </style>
</head>
<body>
<div id="toast-box"></div>
<div class="captcha-mask" id="captchaMask"><iframe src="captcha.php" id="captchaFrame"></iframe></div>
<div class="confirm-mask" id="confirmMask">
    <div class="confirm-box">
        <h4 id="confirmTitle">确认</h4>
        <p id="confirmText">确定执行此操作？</p>
        <div class="confirm-btns">
            <button class="btn-cancel" id="confirmCancel">取消</button>
            <button class="btn-ok" id="confirmOk">确定</button>
        </div>
    </div>
</div>
<div class="float-btn" id="floatBtn" onclick="toggleChat()">
    <svg viewBox="0 0 24 24"><path d="M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2z"/></svg>
    <div class="float-badge" id="floatBadge">0</div>
</div>
<div id="chatWindow" style="display:none;position:fixed;bottom:90px;right:24px;width:400px;max-width:calc(100vw - 40px);height:560px;max-height:calc(100vh - 110px);background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius);box-shadow:var(--shadow-hover);overflow:hidden;z-index:1001;flex-direction:column;backdrop-filter:blur(24px);">
    <div class="chat-header">
        <div class="header-left">
            <div class="header-avatar">
                <svg viewBox="0 0 24 24"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 3c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zm0 14.2c-2.5 0-4.71-1.28-6-3.22.03-1.99 4-3.08 6-3.08 1.99 0 5.97 1.09 6 3.08-1.29 1.94-3.5 3.22-6 3.22z"/></svg>
            </div>
            <div class="header-info">
                <div class="header-title">萌哒云智能客服</div>
                <div class="header-status"><span class="status-dot"></span>在线服务中</div>
            </div>
        </div>
        <div class="header-actions">
            <button class="icon-btn" onclick="toggleEmbed()" title="服务">
                <svg viewBox="0 0 24 24"><path d="M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.07-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L3.16 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.07.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z"/></svg>
            </button>
            <button class="icon-btn" onclick="toggleChat()" title="关闭">
                <svg viewBox="0 0 24 24"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
            </button>
        </div>
    </div>
    <div class="offline-bar" id="offlineBar">
        <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="vertical-align:middle;margin-right:4px;"><path d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"/></svg>
        网络连接已断开，正在尝试重新连接...
    </div>
    <div class="quick-tags">
        <button class="tag" onclick="sendQuick('产品价格')">
            <svg viewBox="0 0 24 24"><path d="M11.8 10.9c-2.27-.59-3-1.2-3-2.15 0-1.09 1.01-1.85 2.7-1.85 1.78 0 2.44.85 2.5 2.1h2.21c-.07-1.72-1.12-3.3-3.21-3.81V3h-3v2.16c-1.94.42-3.5 1.68-3.5 3.61 0 2.31 1.91 3.46 4.7 4.13 2.5.6 3 1.48 3 2.41 0 .69-.49 1.79-2.7 1.79-2.06 0-2.87-.92-2.98-2.1h-2.2c.12 2.19 1.76 3.42 3.68 3.83V21h3v-2.15c1.95-.37 3.5-1.5 3.5-3.55 0-2.84-2.43-3.81-4.7-4.4z"/></svg>
            产品价格
        </button>
        <button class="tag" onclick="sendQuick('技术支持')">
            <svg viewBox="0 0 24 24"><path d="M22.7 19l-9.1-9.1c.9-2.3.4-5-1.5-6.9-2-2-5-2.4-7.4-1.3L9 6 6 9 1.6 4.7C.4 7.1.9 10.1 2.9 12.1c1.9 1.9 4.6 2.4 6.9 1.5l9.1 9.1c.4.4 1 .4 1.4 0l2.3-2.3c.5-.4.5-1.1.1-1.4z"/></svg>
            技术支持
        </button>
        <button class="tag" onclick="sendQuick('售后服务')">
            <svg viewBox="0 0 24 24"><path d="M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4zm0 10.99h7c-.53 4.12-3.28 7.79-7 8.94V12H5V6.3l7-3.11v8.8z"/></svg>
            售后服务
        </button>
        <button class="tag" onclick="sendQuick('转人工')">
            <svg viewBox="0 0 24 24"><path d="M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5c-1.66 0-3 1.34-3 3s1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5C6.34 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5z"/></svg>
            转人工
        </button>
    </div>
    <div class="messages-wrap" id="messagesWrap">
        <div class="welcome" id="welcomeMsg">
            <div class="welcome-icon">
                <svg viewBox="0 0 24 24"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/></svg>
            </div>
            <h3>欢迎来到萌哒云</h3>
            <p>我是您的智能客服助手，随时为您解答问题<br>发送"转人工"可快速联系人工客服</p>
        </div>
    </div>
    <div class="input-area">
        <div class="toolbar">
            <button class="tool-btn" onclick="formatText('bold')" title="加粗">
                <svg viewBox="0 0 24 24"><path d="M15.6 10.79c.97-.67 1.65-1.77 1.65-2.79 0-2.26-1.75-4-4-4H7v14h7.04c2.09 0 3.71-1.7 3.71-3.79 0-1.52-.86-2.82-2.15-3.42zM10 6.5h3c.83 0 1.5.67 1.5 1.5s-.67 1.5-1.5 1.5h-3v-3zm3.5 9H10v-3h3.5c.83 0 1.5.67 1.5 1.5s-.67 1.5-1.5 1.5z"/></svg>
            </button>
            <button class="tool-btn" onclick="formatText('italic')" title="斜体">
                <svg viewBox="0 0 24 24"><path d="M10 4v3h2.21l-3.42 8H6v3h8v-3h-2.21l3.42-8H18V4z"/></svg>
            </button>
            <button class="tool-btn" onclick="formatText('underline')" title="下划线">
                <svg viewBox="0 0 24 24"><path d="M12 17c3.31 0 6-2.69 6-6V3h-2.5v8c0 1.93-1.57 3.5-3.5 3.5S8.5 12.93 8.5 11V3H6v8c0 3.31 2.69 6 6 6zm-7 2v2h14v-2H5z"/></svg>
            </button>
            <button class="tool-btn" onclick="insertEmoji()" title="表情">
                <svg viewBox="0 0 24 24"><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm3.5-9c.83 0 1.5-.67 1.5-1.5S16.33 8 15.5 8 14 8.67 14 9.5s.67 1.5 1.5 1.5zm-7 0c.83 0 1.5-.67 1.5-1.5S9.33 8 8.5 8 7 8.67 7 9.5 7.67 11 8.5 11zm3.5 6.5c2.33 0 4.31-1.46 5.11-3.5H6.89c.8 2.04 2.78 3.5 5.11 3.5z"/></svg>
            </button>
            <button class="tool-btn" onclick="document.getElementById('imgInput').click()" title="图片">
                <svg viewBox="0 0 24 24"><path d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"/></svg>
            </button>
            <input type="file" id="imgInput" accept="image/*" style="display:none" onchange="handleImage(this)">
        </div>
        <textarea class="msg-input" id="msgInput" placeholder="请输入您要咨询的内容..." rows="2" onkeydown="onKeydown(event)" oninput="updateCount()"></textarea>
        <div class="send-row">
            <span class="char-count" id="charCount">0/500</span>
            <button class="send-btn" id="sendBtn" onclick="sendMsg()">
                <span>发送</span>
                <svg viewBox="0 0 24 24" width="14" height="14"><path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"/></svg>
            </button>
        </div>
    </div>
    <div class="bottom-bar">
        <button class="bottom-btn" onclick="clearAll()">
            <svg viewBox="0 0 24 24"><path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"/></svg>
            清空记录
        </button>
        <button class="bottom-btn" onclick="sendQuick('常见问题')">
            <svg viewBox="0 0 24 24"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 17h-2v-2h2v2zm2.07-7.75l-.9.92C13.45 12.9 13 13.5 13 15h-2v-.5c0-1.1.45-2.1 1.17-2.83l1.24-1.26c.37-.36.59-.86.59-1.41 0-1.1-.9-2-2-2s-2 .9-2 2H8c0-2.21 1.79-4 4-4s4 1.79 4 4c0 .88-.36 1.68-.93 2.25z"/></svg>
            常见问题
        </button>
        <button class="bottom-btn" onclick="sendQuick('联系客服')">
            <svg viewBox="0 0 24 24"><path d="M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z"/></svg>
            联系客服
        </button>
    </div>
    <div class="loading-mask" id="loadingMask"><span>加载中...</span></div>
</div>
<div class="embed-wrap" id="embedWrap">
    <div class="embed-head">
        <h4>
            <svg viewBox="0 0 24 24"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z"/></svg>
            服务中心
        </h4>
        <button class="icon-btn" onclick="toggleEmbed()" style="background:rgba(0,0,0,0.06);color:#666;">
            <svg viewBox="0 0 24 24"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
        </button>
    </div>
    <iframe id="embedFrame" src=""></iframe>
</div>
<script>
var isOnline = true;
var pollTimer = null;
var retryCount = 0;
var msgCount = 0;
var captchaLock = false;
var confirmCallback = null;

function $(id) { return document.getElementById(id); }

function toast(msg, type, dur) {
    type = type || 'info';
    dur = dur || 3000;
    var box = $('toast-box');
    var el = document.createElement('div');
    el.className = 'toast-item toast-' + (type === 'error' ? 'err' : type === 'success' ? 'ok' : 'info');
    var iconSvg = '';
    if (type === 'error') {
        iconSvg = '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/></svg>';
    } else if (type === 'success') {
        iconSvg = '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>';
    } else {
        iconSvg = '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/></svg>';
    }
    el.innerHTML = iconSvg + '<span>' + msg + '</span>';
    box.appendChild(el);
    setTimeout(function() {
        el.style.opacity = '0';
        el.style.transform = 'translateY(-8px)';
        setTimeout(function() { el.remove(); }, 250);
    }, dur);
}

function confirmBox(title, text, onOk) {
    $('confirmTitle').textContent = title;
    $('confirmText').textContent = text;
    $('confirmMask').style.display = 'flex';
    confirmCallback = onOk;
}

$('confirmOk').onclick = function() {
    $('confirmMask').style.display = 'none';
    if (confirmCallback) confirmCallback();
};

$('confirmCancel').onclick = function() {
    $('confirmMask').style.display = 'none';
    confirmCallback = null;
};

$('confirmMask').onclick = function(e) {
    if (e.target === $('confirmMask')) $('confirmMask').style.display = 'none';
};

async function safeFetch(url, opts) {
    opts = opts || {};
    opts.headers = opts.headers || {};
    opts.headers['X-Captcha-Token'] = localStorage.getItem('captcha_token') || '';
    try {
        var res = await fetch(url, opts);
        if (res.status === 401) {
            localStorage.removeItem('captcha_token');
            if (!captchaLock) {
                captchaLock = true;
                $('captchaMask').style.display = 'flex';
            }
            var err = new Error('need_captcha');
            err._captcha = true;
            throw err;
        }
        captchaLock = false;
        return res;
    } catch (e) {
        if (e._captcha) throw e;
        isOnline = false;
        $('offlineBar').style.display = 'block';
        throw e;
    }
}

window.addEventListener('message', function(e) {
    if (e.origin !== location.origin) return;
    if (e.data && e.data.action === 'captcha_ok') {
        localStorage.setItem('captcha_token', e.data.token);
        captchaLock = false;
        $('captchaMask').style.display = 'none';
        loadMsgs().then(function() {
            if (!pollTimer) pollTimer = setInterval(loadMsgs, 5000);
        });
    }
});

if (!localStorage.getItem('captcha_token')) {
    captchaLock = true;
    $('captchaMask').style.display = 'flex';
}

function toggleChat() {
    var win = $('chatWindow');
    var btn = $('floatBtn');
    var showing = win.style.display === 'flex';
    if (showing) {
        win.style.display = 'none';
        btn.style.display = 'flex';
    } else {
        win.style.display = 'flex';
        btn.style.display = 'none';
        $('msgInput').focus();
        loadMsgs();
        if (!pollTimer) pollTimer = setInterval(loadMsgs, 5000);
    }
}

function toggleEmbed() {
    var wrap = $('embedWrap');
    var frame = $('embedFrame');
    if (wrap.style.display === 'flex') {
        wrap.style.display = 'none';
        frame.src = '';
    } else {
        frame.src = 'https://mhuany.xyz/m.html';
        wrap.style.display = 'flex';
    }
}

function updateCount() {
    var len = $('msgInput').value.length;
    $('charCount').textContent = len + '/500';
    $('charCount').style.color = len > 500 ? '#d06070' : '';
}

function onKeydown(e) {
    if (e.key === 'Enter' && !e.shiftKey) {
        e.preventDefault();
        sendMsg();
    }
}

function formatText(cmd) {
    var el = $('msgInput');
    var s = el.selectionStart, e = el.selectionEnd;
    var text = el.value, sel = text.substring(s, e);
    var wrap = cmd === 'bold' ? '**' : cmd === 'italic' ? '*' : '__';
    if (sel) {
        el.value = text.substring(0, s) + wrap + sel + wrap + text.substring(e);
        el.selectionStart = s; el.selectionEnd = e + wrap.length * 2;
    } else {
        el.value = text.substring(0, s) + wrap + wrap + text.substring(e);
        el.selectionStart = el.selectionEnd = s + wrap.length;
    }
    el.focus();
    updateCount();
}

function insertEmoji() {
    var el = $('msgInput');
    var s = el.selectionStart;
    el.value = el.value.substring(0, s) + '(^_^)' + el.value.substring(s);
    el.selectionStart = el.selectionEnd = s + 5;
    el.focus();
    updateCount();
}

async function handleImage(input) {
    var file = input.files[0];
    if (!file) return;
    if (file.size > 5 * 1024 * 1024) { toast('图片大小不能超过5MB', 'error'); return; }
    var fd = new FormData();
    fd.append('image', file);
    showLoad(true);
    try {
        var res = await safeFetch('/api/chat.php?action=upload_image', { method: 'POST', body: fd });
        var data = await res.json();
        if (data.success) { toast('图片上传成功', 'success'); loadMsgs(); }
        else throw new Error(data.message || '上传失败');
    } catch (err) {
        toast('图片上传失败: ' + (err.message || err), 'error');
    } finally {
        showLoad(false);
        input.value = '';
    }
}

function sendQuick(text) {
    $('msgInput').value = text;
    updateCount();
    sendMsg();
}

function showLoad(show) {
    $('loadingMask').style.display = show ? 'flex' : 'none';
}

async function loadMsgs() {
    showLoad(true);
    try {
        var res = await safeFetch('/api/chat.php?action=get_messages', {
            headers: { 'Cache-Control': 'no-cache', 'X-Requested-With': 'XMLHttpRequest' }
        });
        if (!res.ok) throw new Error('加载失败');
        var data = await res.json();
        if (data.success) {
            renderMsgs(data.messages);
            retryCount = 0;
            isOnline = true;
            $('offlineBar').style.display = 'none';
        }
    } catch (err) {
        console.error('加载失败:', err);
        if (err._captcha) {
            if (pollTimer) { clearInterval(pollTimer); pollTimer = null; }
            return;
        }
        if (++retryCount >= 3) {
            isOnline = false;
            $('offlineBar').style.display = 'block';
            if (pollTimer) { clearInterval(pollTimer); pollTimer = null; }
            setTimeout(function() { retryCount = 0; if (!pollTimer) { loadMsgs(); pollTimer = setInterval(loadMsgs, 5000); } }, 30000);
        }
    } finally {
        showLoad(false);
    }
}

function renderMsgs(msgs) {
    var wrap = $('messagesWrap');
    var atBottom = wrap.scrollTop + wrap.clientHeight >= wrap.scrollHeight - 20;
    wrap.innerHTML = '';
    if (!msgs || msgs.length === 0) {
        wrap.innerHTML = '<div class="welcome" id="welcomeMsg"><div class="welcome-icon"><svg viewBox="0 0 24 24"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/></svg></div><h3>欢迎来到萌哒云</h3><p>我是您的智能客服助手，随时为您解答问题<br>发送"转人工"可快速联系人工客服</p></div>';
        return;
    }
    var frag = document.createDocumentFragment();
    var lastDate = '';
    msgs.forEach(function(m, i) {
        var d = m.created_at ? m.created_at.split(' ')[0] : '';
        if (d && d !== lastDate) {
            lastDate = d;
            var div = document.createElement('div');
            div.style.cssText = 'text-align:center;margin:10px 0;font-size:11px;color:#a098b8;';
            div.textContent = d;
            frag.appendChild(div);
        }
        var isU = m.type === 'user';
        var div = document.createElement('div');
        div.className = 'msg ' + (isU ? 'msg-user' : 'msg-ai');
        div.style.animationDelay = (i * 0.04) + 's';
        var t = m.created_at ? new Date(m.created_at).toLocaleTimeString('zh-CN', {hour:'2-digit', minute:'2-digit'}) : '';
        var ava = isU ? 'https://y.mhuany.xyz/1.png' : 'Image.png';
        var name = isU ? '您' : '萌哒云客服';
        var html = '<div class="msg-wrap"><img src="' + ava + '" alt="' + name + '" class="msg-avatar" onerror="this.style.display=\'none\'"><div class="msg-body"><div class="msg-name">' + name + '</div>' + escHtml(m.content) + '<div class="msg-time">' + t + '</div></div></div>';
        div.innerHTML = html;
        frag.appendChild(div);
    });
    wrap.appendChild(frag);
    if (atBottom || msgCount !== msgs.length) wrap.scrollTop = wrap.scrollHeight;
    msgCount = msgs.length;
}

function escHtml(t) {
    if (!t) return '';
    var d = document.createElement('div');
    d.textContent = t;
    return d.innerHTML.replace(/\n/g, '<br>');
}

async function sendMsg() {
    var el = $('msgInput');
    var content = el.value.trim();
    if (!content) { toast('请输入内容', 'info'); return; }
    if (content.length > 500) { toast('消息不能超过500字', 'error'); return; }
    var btn = $('sendBtn');
    btn.disabled = true;
    btn.innerHTML = '<span>发送中</span><span style="display:inline-flex;gap:3px;margin-left:4px;"><span style="width:4px;height:4px;background:#fff;border-radius:50%;animation:typing-bounce 1.4s ease-in-out infinite;"></span><span style="width:4px;height:4px;background:#fff;border-radius:50%;animation:typing-bounce 1.4s ease-in-out 0.2s infinite;"></span><span style="width:4px;height:4px;background:#fff;border-radius:50%;animation:typing-bounce 1.4s ease-in-out 0.4s infinite;"></span></span>';
    addLocal(content, 'user');
    el.value = '';
    updateCount();
    try {
        var res = await safeFetch('/api/chat.php', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest' },
            body: JSON.stringify({ content: content, timestamp: Date.now() })
        });
        if (!res.ok) throw new Error('发送失败(' + res.status + ')');
        var data = await res.json();
        if (data.showHint) toast('小提示：发送"转人工"可快速联系人工客服', 'info', 5000);
        if (data.message) {
            if (data.message === '已请求人工客服') toast('已为您转接人工客服，请稍候', 'success');
            addLocal(data.message, 'ai');
        }
        loadMsgs();
    } catch (err) {
        console.error('发送失败:', err);
        if (!err._captcha) toast('发送失败: ' + (err.message || err), 'error');
    } finally {
        btn.disabled = false;
        btn.innerHTML = '<span>发送</span><svg viewBox="0 0 24 24" width="14" height="14"><path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"/></svg>';
    }
}

function addLocal(content, type) {
    var wrap = $('messagesWrap');
    var welcome = wrap.querySelector('.welcome');
    if (welcome) welcome.remove();
    var isU = type === 'user';
    var div = document.createElement('div');
    div.className = 'msg ' + (isU ? 'msg-user' : 'msg-ai');
    var ava = isU ? 'https://y.mhuany.xyz/1.png' : 'Image.png';
    var name = isU ? '您' : '萌哒云客服';
    var t = new Date().toLocaleTimeString('zh-CN', {hour:'2-digit', minute:'2-digit'});
    div.innerHTML = '<div class="msg-wrap"><img src="' + ava + '" alt="' + name + '" class="msg-avatar" onerror="this.style.display=\'none\'"><div class="msg-body"><div class="msg-name">' + name + '</div>' + escHtml(content) + '<div class="msg-time">' + t + '</div></div></div>';
    wrap.appendChild(div);
    wrap.scrollTop = wrap.scrollHeight;
    msgCount++;
}

function clearAll() {
    confirmBox('清空记录', '确定要清除所有咨询信息吗？', async function() {
        showLoad(true);
        try {
            var res = await safeFetch('/api/chat.php?action=clear_messages', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest' }
            });
            var data = await res.json();
            if (data.success) {
                $('messagesWrap').innerHTML = '<div class="welcome" id="welcomeMsg"><div class="welcome-icon"><svg viewBox="0 0 24 24"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/></svg></div><h3>欢迎来到萌哒云</h3><p>我是您的智能客服助手，随时为您解答问题<br>发送"转人工"可快速联系人工客服</p></div>';
                msgCount = 0;
                toast('咨询信息已清除', 'success');
            } else throw new Error(data.message || '清除失败');
        } catch (err) {
            toast('清除失败: ' + (err.message || err), 'error');
        } finally {
            showLoad(false);
        }
    });
}

window.addEventListener('online', function() {
    retryCount = 0;
    if (!pollTimer) { loadMsgs(); pollTimer = setInterval(loadMsgs, 5000); }
});

window.addEventListener('offline', function() {
    isOnline = false;
    $('offlineBar').style.display = 'block';
});

document.addEventListener('DOMContentLoaded', function() {
    loadMsgs().then(function() {
        pollTimer = setInterval(loadMsgs, 5000);
    });
});
</script>
</body>
</html>