Files
kefu_cloud/docs/agent/visitor-chat.html
T

333 lines
18 KiB
HTML

<!DOCTYPE html>
<html class="light" lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>在线客服 - 访客聊天窗口</title>
<style id="theme-vars">
/* Online Customer Service System — Brand CSS */
/* Professional & Efficient Style — Cool Blue-Gray */
:root {
/* === Brand Primary === */
--brand-primary: #2563eb;
--brand-primary-hover: #1d4ed8;
--brand-primary-active: #1e40af;
--brand-primary-light: #dbeafe;
--brand-primary-lighter: #eff6ff;
--brand-primary-dark: #1e3a8a;
/* === Neutrals === */
--neutral-0: #ffffff;
--neutral-50: #f8fafc;
--neutral-100: #f1f5f9;
--neutral-200: #e2e8f0;
--neutral-300: #cbd5e1;
--neutral-400: #94a3b8;
--neutral-500: #64748b;
--neutral-600: #475569;
--neutral-700: #334155;
--neutral-800: #1e293b;
--neutral-900: #0f172a;
--neutral-950: #020617;
/* === State Colors === */
--state-success: #16a34a;
--state-success-bg: #f0fdf4;
--state-warning: #d97706;
--state-warning-bg: #fffbeb;
--state-error: #dc2626;
--state-error-bg: #fef2f2;
--state-info: #0891b2;
--state-info-bg: #ecfeff;
/* === Typography === */
--font-family-base: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif;
--font-family-mono: 'JetBrains Mono', 'Fira Code', 'Consolas', monospace;
--font-size-xs: 12px;
--font-size-sm: 13px;
--font-size-base: 14px;
--font-size-md: 15px;
--font-size-lg: 16px;
--font-size-xl: 18px;
--font-size-2xl: 20px;
--font-size-3xl: 24px;
--font-size-4xl: 30px;
--font-weight-normal: 400;
--font-weight-medium: 500;
--font-weight-semibold: 600;
--font-weight-bold: 700;
--line-height-tight: 1.25;
--line-height-normal: 1.5;
--line-height-relaxed: 1.625;
/* === Spacing === */
--space-0: 0px;
--space-1: 4px;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--space-5: 20px;
--space-6: 24px;
--space-8: 32px;
--space-10: 40px;
--space-12: 48px;
/* === Radius === */
--radius-sm: 4px;
--radius-md: 8px;
--radius-lg: 12px;
--radius-full: 9999px;
/* === Shadows (static: alpha <= 0.05; floating layers only may exceed) === */
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.03);
--shadow-md: 0 2px 8px rgba(0, 0, 0, 0.04);
--shadow-lg: 0 4px 16px rgba(0, 0, 0, 0.05);
--shadow-floating: 0 8px 24px rgba(0, 0, 0, 0.12);
/* === Transitions === */
--transition-fast: 150ms ease;
--transition-normal: 200ms ease;
--transition-slow: 300ms ease;
/* === Layout === */
--sidebar-width: 240px;
--sidebar-collapsed-width: 64px;
--header-height: 56px;
--panel-width: 320px;
--chat-panel-min: 300px;
--chat-panel-max: 600px;
}
/* Dark mode */
.dark {
--brand-primary: #3b82f6;
--brand-primary-hover: #60a5fa;
--brand-primary-active: #2563eb;
--brand-primary-light: #1e3a5f;
--brand-primary-lighter: #172554;
--brand-primary-dark: #93c5fd;
--neutral-0: #0f172a;
--neutral-50: #1e293b;
--neutral-100: #334155;
--neutral-200: #475569;
--neutral-300: #64748b;
--neutral-400: #94a3b8;
--neutral-500: #cbd5e1;
--neutral-600: #e2e8f0;
--neutral-700: #f1f5f9;
--neutral-800: #f8fafc;
--neutral-900: #ffffff;
--neutral-950: #ffffff;
--state-success-bg: #052e16;
--state-warning-bg: #451a03;
--state-error-bg: #450a0a;
--state-info-bg: #083344;
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.2);
--shadow-md: 0 2px 8px rgba(0, 0, 0, 0.3);
--shadow-lg: 0 4px 16px rgba(0, 0, 0, 0.35);
--shadow-floating: 0 8px 24px rgba(0, 0, 0, 0.5);
}
</style>
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4.3.1/dist/index.global.js"></script>
<script src="https://unpkg.com/lucide@1.8.0/dist/umd/lucide.min.js"></script>
<style type="text/tailwindcss">
@theme inline {
--color-primary: var(--brand-primary);
--color-primary-foreground: var(--neutral-0);
}
@layer base {
body { background: var(--neutral-50); color: var(--neutral-900); }
td, th { @apply break-words; word-break: break-all; word-break: auto-phrase; }
th { @apply whitespace-nowrap; }
}
</style>
<style>
.no-scrollbar::-webkit-scrollbar { display: none; }
.no-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }
[data-icon] {
display: inline-flex;
align-items: center;
justify-content: center;
-webkit-mask-size: contain;
mask-size: contain;
-webkit-mask-repeat: no-repeat;
mask-repeat: no-repeat;
-webkit-mask-position: center;
mask-position: center;
background-color: currentColor;
}
</style>
</head>
<body class="antialiased" style="margin:0; padding:0; overflow:hidden;">
<!-- Simulated webpage background (blurred) -->
<div style="position:fixed; inset:0; background:var(--neutral-100); z-index:0;">
<div style="max-width:960px; margin:0 auto; padding:40px 24px; filter:blur(4px); opacity:0.4;">
<div style="height:40px; width:60%; background:var(--neutral-200); border-radius:var(--radius-sm); margin-bottom:16px;"></div>
<div style="height:16px; width:90%; background:var(--neutral-200); border-radius:var(--radius-sm); margin-bottom:12px;"></div>
<div style="height:16px; width:75%; background:var(--neutral-200); border-radius:var(--radius-sm); margin-bottom:24px;"></div>
<div style="display:flex; gap:16px; margin-bottom:24px;">
<div style="width:200px; height:120px; background:var(--neutral-200); border-radius:var(--radius-md);"></div>
<div style="width:200px; height:120px; background:var(--neutral-200); border-radius:var(--radius-md);"></div>
<div style="width:200px; height:120px; background:var(--neutral-200); border-radius:var(--radius-md);"></div>
</div>
<div style="height:16px; width:85%; background:var(--neutral-200); border-radius:var(--radius-sm); margin-bottom:12px;"></div>
<div style="height:16px; width:70%; background:var(--neutral-200); border-radius:var(--radius-sm); margin-bottom:12px;"></div>
<div style="height:16px; width:80%; background:var(--neutral-200); border-radius:var(--radius-sm); margin-bottom:24px;"></div>
<div style="height:200px; width:100%; background:var(--neutral-200); border-radius:var(--radius-md);"></div>
</div>
</div>
<!-- Chat Window (floating component) -->
<main style="position:fixed; z-index:10; right:max(24px, calc((100vw - 400px)/2)); bottom:max(24px, calc((100vh - 600px)/2)); width:400px; height:600px; max-width:calc(100vw - 32px); max-height:calc(100vh - 32px); display:flex; flex-direction:column; border-radius:var(--radius-lg); overflow:hidden; box-shadow:var(--shadow-floating); background:var(--neutral-0);">
<!-- ===== Window Header ===== -->
<header style="flex-shrink:0; padding:var(--space-4) var(--space-4); background:var(--brand-primary); color:var(--neutral-0); display:flex; align-items:center; gap:var(--space-3);">
<!-- Agent avatar -->
<div style="width:40px; height:40px; border-radius:var(--radius-full); background:rgba(255,255,255,0.2); flex-shrink:0; display:flex; align-items:center; justify-content:center;">
<i data-lucide="headset" style="width:20px; height:20px; color:var(--neutral-0);"></i>
</div>
<!-- Title block -->
<div style="flex:1; min-width:0;">
<h1 style="margin:0; font-size:var(--font-size-md); font-weight:var(--font-weight-semibold); line-height:var(--line-height-tight); color:var(--neutral-0);">在线客服</h1>
<p style="margin:0; font-size:var(--font-size-xs); line-height:var(--line-height-normal); color:rgba(255,255,255,0.8); display:flex; align-items:center; gap:var(--space-1);">
<span style="width:6px; height:6px; border-radius:var(--radius-full); background:var(--state-success); display:inline-block;"></span>
正在为您服务
</p>
</div>
<!-- Window controls -->
<div style="display:flex; align-items:center; gap:var(--space-1); flex-shrink:0;">
<button style="width:28px; height:28px; border-radius:var(--radius-sm); border:none; background:rgba(255,255,255,0.15); cursor:pointer; display:flex; align-items:center; justify-content:center;" aria-label="最小化">
<i data-lucide="minus" style="width:16px; height:16px; color:var(--neutral-0);"></i>
</button>
<button style="width:28px; height:28px; border-radius:var(--radius-sm); border:none; background:rgba(255,255,255,0.15); cursor:pointer; display:flex; align-items:center; justify-content:center;" aria-label="关闭">
<i data-lucide="x" style="width:16px; height:16px; color:var(--neutral-0);"></i>
</button>
</div>
</header>
<!-- ===== Message Area ===== -->
<section style="flex:1; overflow-y:auto; padding:var(--space-4); display:flex; flex-direction:column; gap:var(--space-3); background:var(--neutral-50);">
<!-- System welcome message -->
<div style="display:flex; flex-direction:column; align-items:center; gap:var(--space-3);">
<div style="padding:var(--space-2) var(--space-4); border-radius:var(--radius-lg); background:var(--neutral-0); border:1px solid var(--neutral-200); max-width:85%; text-align:center;">
<p style="margin:0; font-size:var(--font-size-sm); color:var(--neutral-600); line-height:var(--line-height-normal);">您好!欢迎咨询,请问有什么可以帮您?</p>
</div>
</div>
<!-- Quick question tags -->
<div style="display:flex; flex-wrap:wrap; gap:var(--space-2); justify-content:center;">
<button style="padding:var(--space-1) var(--space-3); border-radius:var(--radius-full); border:1px solid var(--brand-primary); background:var(--neutral-0); color:var(--brand-primary); font-size:var(--font-size-xs); cursor:pointer; white-space:nowrap; line-height:var(--line-height-normal);">查询订单状态</button>
<button style="padding:var(--space-1) var(--space-3); border-radius:var(--radius-full); border:1px solid var(--brand-primary); background:var(--neutral-0); color:var(--brand-primary); font-size:var(--font-size-xs); cursor:pointer; white-space:nowrap; line-height:var(--line-height-normal);">退换货政策</button>
<button style="padding:var(--space-1) var(--space-3); border-radius:var(--radius-full); border:1px solid var(--brand-primary); background:var(--neutral-0); color:var(--brand-primary); font-size:var(--font-size-xs); cursor:pointer; white-space:nowrap; line-height:var(--line-height-normal);">配送时效说明</button>
</div>
<!-- Customer message (right aligned, blue) -->
<div style="display:flex; justify-content:flex-end; max-width:85%; margin-left:auto;">
<div style="padding:var(--space-3) var(--space-4); border-radius:var(--radius-lg); background:var(--brand-primary); color:var(--neutral-0); font-size:var(--font-size-sm); line-height:var(--line-height-normal);">
<p style="margin:0;">你好,我想查询一下我的订单什么时候能到?</p>
</div>
</div>
<!-- Agent message (left aligned, gray, with avatar) -->
<div style="display:flex; gap:var(--space-2); max-width:85%;">
<div style="width:32px; height:32px; border-radius:var(--radius-full); background:var(--neutral-200); flex-shrink:0; display:flex; align-items:center; justify-content:center; margin-top:2px;">
<i data-lucide="headset" style="width:16px; height:16px; color:var(--neutral-500);"></i>
</div>
<div style="padding:var(--space-3) var(--space-4); border-radius:var(--radius-lg); background:var(--neutral-0); border:1px solid var(--neutral-200); font-size:var(--font-size-sm); color:var(--neutral-800); line-height:var(--line-height-normal);">
<p style="margin:0;">您好!请提供一下您的订单编号,我帮您查询最新的物流信息。</p>
</div>
</div>
<!-- Customer message with image -->
<div style="display:flex; flex-direction:column; align-items:flex-end; gap:var(--space-2); max-width:85%; margin-left:auto;">
<div style="padding:var(--space-3) var(--space-4); border-radius:var(--radius-lg); background:var(--brand-primary); color:var(--neutral-0); font-size:var(--font-size-sm); line-height:var(--line-height-normal);">
<p style="margin:0;">订单号是 ORD-20250709-8842</p>
</div>
<div style="padding:var(--space-2); border-radius:var(--radius-lg); background:var(--brand-primary); overflow:hidden; max-width:180px;">
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='100' fill='none'%3E%3Crect width='180' height='100' rx='8' fill='%23dbeafe'/%3E%3Ctext x='50%25' y='50%25' dominant-baseline='middle' text-anchor='middle' font-size='13' fill='%232563eb' font-family='sans-serif'%3E订单截图%3C/text%3E%3C/svg%3E" alt="订单截图" style="display:block; width:100%; border-radius:var(--radius-md);">
</div>
</div>
<!-- Agent message with info -->
<div style="display:flex; gap:var(--space-2); max-width:85%;">
<div style="width:32px; height:32px; border-radius:var(--radius-full); background:var(--neutral-200); flex-shrink:0; display:flex; align-items:center; justify-content:center; margin-top:2px;">
<i data-lucide="headset" style="width:16px; height:16px; color:var(--neutral-500);"></i>
</div>
<div style="padding:var(--space-3) var(--space-4); border-radius:var(--radius-lg); background:var(--neutral-0); border:1px solid var(--neutral-200); font-size:var(--font-size-sm); color:var(--neutral-800); line-height:var(--line-height-normal);">
<p style="margin:0;">查到了,您的包裹目前已经到达本地分拣中心,预计明天下午14:00前送达,请保持手机畅通以便签收。</p>
</div>
</div>
<!-- Customer reply -->
<div style="display:flex; justify-content:flex-end; max-width:85%; margin-left:auto;">
<div style="padding:var(--space-3) var(--space-4); border-radius:var(--radius-lg); background:var(--brand-primary); color:var(--neutral-0); font-size:var(--font-size-sm); line-height:var(--line-height-normal);">
<p style="margin:0;">好的,谢谢!如果需要放快递柜可以吗?</p>
</div>
</div>
<!-- Typing indicator -->
<div style="display:flex; gap:var(--space-2); max-width:85%;">
<div style="width:32px; height:32px; border-radius:var(--radius-full); background:var(--neutral-200); flex-shrink:0; display:flex; align-items:center; justify-content:center; margin-top:2px;">
<i data-lucide="headset" style="width:16px; height:16px; color:var(--neutral-500);"></i>
</div>
<div style="padding:var(--space-3) var(--space-4); border-radius:var(--radius-lg); background:var(--neutral-0); border:1px solid var(--neutral-200); display:flex; align-items:center; gap:var(--space-1);">
<span style="width:6px; height:6px; border-radius:var(--radius-full); background:var(--neutral-400); animation:typingDot 1.4s infinite 0s;"></span>
<span style="width:6px; height:6px; border-radius:var(--radius-full); background:var(--neutral-400); animation:typingDot 1.4s infinite 0.2s;"></span>
<span style="width:6px; height:6px; border-radius:var(--radius-full); background:var(--neutral-400); animation:typingDot 1.4s infinite 0.4s;"></span>
</div>
</div>
<!-- Typing status text -->
<p style="text-align:left; font-size:var(--font-size-xs); color:var(--neutral-400); margin:0; padding-left:42px;">客服正在输入...</p>
</section>
<!-- ===== Input Area ===== -->
<footer style="flex-shrink:0; position:relative; padding:var(--space-3) var(--space-4); background:var(--neutral-0); border-top:1px solid var(--neutral-200);">
<!-- Soul element: subtle brand gradient glow -->
<div style="position:absolute; top:0; left:0; right:0; height:3px; background:linear-gradient(90deg, transparent 0%, var(--brand-primary) 50%, transparent 100%); opacity:0.4; pointer-events:none;"></div>
<!-- Action bar -->
<div style="display:flex; align-items:center; gap:var(--space-2); margin-bottom:var(--space-2);">
<button style="width:32px; height:32px; border-radius:var(--radius-md); border:none; background:transparent; cursor:pointer; display:flex; align-items:center; justify-content:center;" aria-label="发送图片">
<i data-lucide="image" style="width:18px; height:18px; color:var(--neutral-400);"></i>
</button>
<button style="width:32px; height:32px; border-radius:var(--radius-md); border:none; background:transparent; cursor:pointer; display:flex; align-items:center; justify-content:center;" aria-label="发送表情">
<i data-lucide="smile" style="width:18px; height:18px; color:var(--neutral-400);"></i>
</button>
</div>
<!-- Input row -->
<div style="display:flex; align-items:center; gap:var(--space-2);">
<input type="text" placeholder="请输入您的问题..." style="flex:1; min-width:0; height:40px; padding:0 var(--space-3); border-radius:var(--radius-lg); border:1px solid var(--neutral-200); background:var(--neutral-50); font-size:var(--font-size-sm); color:var(--neutral-800); outline:none; font-family:var(--font-family-base);" />
<button style="width:40px; height:40px; border-radius:var(--radius-full); border:none; background:var(--brand-primary); cursor:pointer; display:flex; align-items:center; justify-content:center; flex-shrink:0;" aria-label="发送">
<i data-lucide="send" style="width:18px; height:18px; color:var(--neutral-0);"></i>
</button>
</div>
</footer>
</main>
<script>
lucide.createIcons();
</script>
<style>
@keyframes typingDot {
0%, 60%, 100% { opacity: 0.3; transform: translateY(0); }
30% { opacity: 1; transform: translateY(-3px); }
}
</style>
</body>
</html>