初始化项目:前端 React+TS+Tailwind+antd 脚手架,后端 Go,保留原型设计稿
This commit is contained in:
@@ -0,0 +1,332 @@
|
||||
<!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>
|
||||
Reference in New Issue
Block a user