初始化项目:前端 React+TS+Tailwind+antd 脚手架,后端 Go,保留原型设计稿

This commit is contained in:
yml2213
2026-07-14 11:01:33 +08:00
commit cbe81f7dfb
27 changed files with 12233 additions and 0 deletions
+469
View File
@@ -0,0 +1,469 @@
<!DOCTYPE html>
<html lang="zh-CN" class="light">
<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);
--color-background: var(--neutral-0);
--color-foreground: var(--neutral-900);
--color-card: var(--neutral-0);
--color-card-foreground: var(--neutral-900);
--color-muted: var(--neutral-100);
--color-muted-foreground: var(--neutral-500);
--color-accent: var(--neutral-100);
--color-accent-foreground: var(--neutral-900);
--color-border: var(--neutral-200);
--color-input: var(--neutral-200);
--color-ring: var(--brand-primary);
--color-secondary: var(--neutral-100);
--color-secondary-foreground: var(--neutral-900);
--color-destructive: var(--state-error);
--color-destructive-foreground: var(--neutral-0);
--radius-sm: var(--radius-sm);
--radius-md: var(--radius-md);
--radius-lg: var(--radius-lg);
}
@layer base {
body { background: var(--neutral-0); 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="min-h-screen font-sans antialiased" style="font-family: var(--font-family-base);">
<main>
<!-- Admin Layout: Sidebar + Main Content -->
<div class="flex min-h-screen">
<!-- Left Sidebar (240px) -->
<aside class="w-[240px] shrink-0 border-r flex flex-col" style="border-color: var(--neutral-200); background: var(--neutral-50);">
<!-- Logo Area -->
<div class="h-[var(--header-height)] flex items-center px-5 border-b shrink-0" style="border-color: var(--neutral-200);">
<div class="flex items-center gap-2 min-w-0">
<div class="w-7 h-7 rounded-md shrink-0 flex items-center justify-center" style="background: var(--brand-primary);">
<i data-lucide="message-square" class="w-4 h-4" style="color: var(--neutral-0);"></i>
</div>
<div class="min-w-0">
<span class="text-sm font-semibold truncate block" style="color: var(--neutral-900);">客服云</span>
<span class="text-[10px] truncate block" style="color: var(--neutral-500);">运营管理</span>
</div>
</div>
</div>
<!-- Sidebar Label -->
<div class="px-5 pt-5 pb-2">
<span class="text-[11px] font-medium uppercase tracking-wider" style="color: var(--neutral-400);">管理端</span>
</div>
<!-- Navigation -->
<nav class="flex-1 px-3 space-y-1">
<a href="#" id="admin-nav-dashboard" class="flex items-center gap-3 px-3 py-2 rounded-md text-sm font-medium transition-colors" style="color: var(--neutral-600); background: transparent;">
<i data-lucide="layout-dashboard" class="w-4 h-4 shrink-0"></i>
<span class="truncate">运营概览</span>
</a>
<a href="#" id="admin-nav-tenants" class="flex items-center gap-3 px-3 py-2 rounded-md text-sm font-medium transition-colors" style="color: var(--neutral-600); background: transparent;">
<i data-lucide="building-2" class="w-4 h-4 shrink-0"></i>
<span class="truncate">租户管理</span>
</a>
<a href="#" id="admin-nav-plans" class="flex items-center gap-3 px-3 py-2 rounded-md text-sm font-semibold transition-colors" style="color: var(--brand-primary); background: var(--brand-primary-light);">
<i data-lucide="credit-card" class="w-4 h-4 shrink-0"></i>
<span class="truncate">套餐定价</span>
</a>
<a href="#" id="admin-nav-ops" class="flex items-center gap-3 px-3 py-2 rounded-md text-sm font-medium transition-colors" style="color: var(--neutral-600); background: transparent;">
<i data-lucide="settings" class="w-4 h-4 shrink-0"></i>
<span class="truncate">系统运维</span>
</a>
</nav>
<!-- Bottom User Area -->
<div class="px-5 py-4 border-t shrink-0" style="border-color: var(--neutral-200);">
<div class="flex items-center gap-3">
<div class="w-8 h-8 rounded-full shrink-0 flex items-center justify-center" style="background: var(--neutral-200); color: var(--neutral-600);">
<i data-lucide="user" class="w-4 h-4"></i>
</div>
<div class="min-w-0">
<p class="text-sm font-medium truncate" style="color: var(--neutral-800);">系统管理员</p>
<p class="text-xs truncate" style="color: var(--neutral-400);">admin@kefu.cloud</p>
</div>
</div>
</div>
</aside>
<!-- Right Main Content Area -->
<div class="flex-1 min-w-0 flex flex-col">
<!-- Top Header Bar -->
<header class="h-[var(--header-height)] flex items-center justify-between px-8 border-b shrink-0" style="border-color: var(--neutral-200);">
<h1 class="text-xl font-bold truncate" style="color: var(--neutral-900);">套餐管理</h1>
<div class="flex items-center gap-3 shrink-0">
<button class="inline-flex items-center justify-center gap-2 px-4 py-2 rounded-md text-sm font-medium whitespace-nowrap transition-colors" style="background: var(--brand-primary); color: var(--neutral-0);">
<i data-lucide="plus" class="w-4 h-4"></i>
<span>新建套餐</span>
</button>
</div>
</header>
<!-- Content Body -->
<div class="flex-1 overflow-y-auto p-8">
<!-- Plan Cards Grid (3 Columns) -->
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6 mb-8">
<!-- Basic Plan Card -->
<div class="rounded-lg border p-6 flex flex-col" style="border-color: var(--neutral-200); background: var(--neutral-0); box-shadow: var(--shadow-sm);">
<div class="flex items-center justify-between mb-4">
<h2 class="text-lg font-bold truncate" style="color: var(--neutral-900);">基础版</h2>
<span class="inline-flex items-center justify-center px-2 py-0.5 rounded-md text-xs font-medium whitespace-nowrap" style="background: var(--state-success-bg); color: var(--state-success);">在售</span>
</div>
<div class="mb-6">
<span class="text-4xl font-bold" style="color: var(--neutral-900);">¥299</span>
<span class="text-sm ml-1" style="color: var(--neutral-500);">/月</span>
</div>
<ul class="space-y-3 flex-1 mb-6">
<li class="flex items-start gap-2 text-sm" style="color: var(--neutral-700);">
<i data-lucide="check" class="w-4 h-4 shrink-0 mt-0.5" style="color: var(--state-success);"></i>
<span>坐席数量:<strong class="font-semibold">5 个</strong></span>
</li>
<li class="flex items-start gap-2 text-sm" style="color: var(--neutral-700);">
<i data-lucide="check" class="w-4 h-4 shrink-0 mt-0.5" style="color: var(--state-success);"></i>
<span>对话记录保存:<strong class="font-semibold">30 天</strong></span>
</li>
<li class="flex items-start gap-2 text-sm" style="color: var(--neutral-700);">
<i data-lucide="check" class="w-4 h-4 shrink-0 mt-0.5" style="color: var(--state-success);"></i>
<span>知识库容量:<strong class="font-semibold">100 条</strong></span>
</li>
<li class="flex items-start gap-2 text-sm" style="color: var(--neutral-700);">
<i data-lucide="check" class="w-4 h-4 shrink-0 mt-0.5" style="color: var(--state-success);"></i>
<span>数据统计报表:<strong class="font-semibold">基础</strong></span>
</li>
<li class="flex items-start gap-2 text-sm" style="color: var(--neutral-400);">
<i data-lucide="x" class="w-4 h-4 shrink-0 mt-0.5" style="color: var(--neutral-300);"></i>
<span>API 接口</span>
</li>
<li class="flex items-start gap-2 text-sm" style="color: var(--neutral-700);">
<i data-lucide="check" class="w-4 h-4 shrink-0 mt-0.5" style="color: var(--state-success);"></i>
<span>多渠道接入:<strong class="font-semibold">网页</strong></span>
</li>
<li class="flex items-start gap-2 text-sm" style="color: var(--neutral-400);">
<i data-lucide="x" class="w-4 h-4 shrink-0 mt-0.5" style="color: var(--neutral-300);"></i>
<span>自定义品牌</span>
</li>
<li class="flex items-start gap-2 text-sm" style="color: var(--neutral-400);">
<i data-lucide="x" class="w-4 h-4 shrink-0 mt-0.5" style="color: var(--neutral-300);"></i>
<span>专属客服支持</span>
</li>
</ul>
<div class="flex items-center justify-between pt-4 border-t" style="border-color: var(--neutral-200);">
<span class="text-sm" style="color: var(--neutral-500);">
<i data-lucide="users" class="w-4 h-4 inline-block align-middle mr-1" style="vertical-align: -2px;"></i>
128 个租户
</span>
<button class="inline-flex items-center justify-center px-3 py-1.5 rounded-md text-sm font-medium whitespace-nowrap border transition-colors" style="border-color: var(--neutral-200); color: var(--neutral-700); background: var(--neutral-0);">
编辑
</button>
</div>
</div>
<!-- Professional Plan Card (Recommended) -->
<div class="rounded-lg border-2 p-6 flex flex-col relative" style="border-color: var(--brand-primary); background: var(--neutral-0); box-shadow: var(--shadow-lg);">
<!-- Recommended Badge (brand blue triangle at top-right) -->
<div class="absolute top-0 right-0" style="width: 0; height: 0; border-left: 48px solid transparent; border-top: 48px solid var(--brand-primary);"></div>
<span class="absolute top-2 right-2 text-[10px] font-semibold text-white whitespace-nowrap" style="transform: rotate(45deg); transform-origin: center;">推荐</span>
<div class="flex items-center justify-between mb-4">
<h2 class="text-lg font-bold truncate" style="color: var(--neutral-900);">专业版</h2>
<span class="inline-flex items-center justify-center px-2 py-0.5 rounded-md text-xs font-medium whitespace-nowrap" style="background: var(--state-success-bg); color: var(--state-success);">在售</span>
</div>
<div class="mb-6">
<span class="text-4xl font-bold" style="color: var(--brand-primary);">¥699</span>
<span class="text-sm ml-1" style="color: var(--neutral-500);">/月</span>
</div>
<ul class="space-y-3 flex-1 mb-6">
<li class="flex items-start gap-2 text-sm" style="color: var(--neutral-700);">
<i data-lucide="check" class="w-4 h-4 shrink-0 mt-0.5" style="color: var(--brand-primary);"></i>
<span>坐席数量:<strong class="font-semibold">20 个</strong></span>
</li>
<li class="flex items-start gap-2 text-sm" style="color: var(--neutral-700);">
<i data-lucide="check" class="w-4 h-4 shrink-0 mt-0.5" style="color: var(--brand-primary);"></i>
<span>对话记录保存:<strong class="font-semibold">90 天</strong></span>
</li>
<li class="flex items-start gap-2 text-sm" style="color: var(--neutral-700);">
<i data-lucide="check" class="w-4 h-4 shrink-0 mt-0.5" style="color: var(--brand-primary);"></i>
<span>知识库容量:<strong class="font-semibold">1000 条</strong></span>
</li>
<li class="flex items-start gap-2 text-sm" style="color: var(--neutral-700);">
<i data-lucide="check" class="w-4 h-4 shrink-0 mt-0.5" style="color: var(--brand-primary);"></i>
<span>数据统计报表:<strong class="font-semibold">高级</strong></span>
</li>
<li class="flex items-start gap-2 text-sm" style="color: var(--neutral-700);">
<i data-lucide="check" class="w-4 h-4 shrink-0 mt-0.5" style="color: var(--brand-primary);"></i>
<span>API 接口</span>
</li>
<li class="flex items-start gap-2 text-sm" style="color: var(--neutral-700);">
<i data-lucide="check" class="w-4 h-4 shrink-0 mt-0.5" style="color: var(--brand-primary);"></i>
<span>多渠道接入:<strong class="font-semibold">网页 + 微信</strong></span>
</li>
<li class="flex items-start gap-2 text-sm" style="color: var(--neutral-400);">
<i data-lucide="x" class="w-4 h-4 shrink-0 mt-0.5" style="color: var(--neutral-300);"></i>
<span>自定义品牌</span>
</li>
<li class="flex items-start gap-2 text-sm" style="color: var(--neutral-700);">
<i data-lucide="check" class="w-4 h-4 shrink-0 mt-0.5" style="color: var(--brand-primary);"></i>
<span>专属客服支持:<strong class="font-semibold">工作日</strong></span>
</li>
</ul>
<div class="flex items-center justify-between pt-4 border-t" style="border-color: var(--brand-primary-light);">
<span class="text-sm" style="color: var(--neutral-500);">
<i data-lucide="users" class="w-4 h-4 inline-block align-middle mr-1" style="vertical-align: -2px;"></i>
256 个租户
</span>
<button class="inline-flex items-center justify-center px-3 py-1.5 rounded-md text-sm font-medium whitespace-nowrap transition-colors" style="background: var(--brand-primary); color: var(--neutral-0);">
编辑
</button>
</div>
</div>
<!-- Enterprise Plan Card -->
<div class="rounded-lg border p-6 flex flex-col" style="border-color: var(--neutral-200); background: var(--neutral-0); box-shadow: var(--shadow-sm);">
<div class="flex items-center justify-between mb-4">
<h2 class="text-lg font-bold truncate" style="color: var(--neutral-900);">企业版</h2>
<span class="inline-flex items-center justify-center px-2 py-0.5 rounded-md text-xs font-medium whitespace-nowrap" style="background: var(--neutral-100); color: var(--neutral-500);">已下架</span>
</div>
<div class="mb-6">
<span class="text-4xl font-bold" style="color: var(--neutral-900);">¥1999</span>
<span class="text-sm ml-1" style="color: var(--neutral-500);">/月</span>
</div>
<ul class="space-y-3 flex-1 mb-6">
<li class="flex items-start gap-2 text-sm" style="color: var(--neutral-700);">
<i data-lucide="check" class="w-4 h-4 shrink-0 mt-0.5" style="color: var(--state-success);"></i>
<span>坐席数量:<strong class="font-semibold">无限</strong></span>
</li>
<li class="flex items-start gap-2 text-sm" style="color: var(--neutral-700);">
<i data-lucide="check" class="w-4 h-4 shrink-0 mt-0.5" style="color: var(--state-success);"></i>
<span>对话记录保存:<strong class="font-semibold">永久</strong></span>
</li>
<li class="flex items-start gap-2 text-sm" style="color: var(--neutral-700);">
<i data-lucide="check" class="w-4 h-4 shrink-0 mt-0.5" style="color: var(--state-success);"></i>
<span>知识库容量:<strong class="font-semibold">无限</strong></span>
</li>
<li class="flex items-start gap-2 text-sm" style="color: var(--neutral-700);">
<i data-lucide="check" class="w-4 h-4 shrink-0 mt-0.5" style="color: var(--state-success);"></i>
<span>数据统计报表:<strong class="font-semibold">自定义</strong></span>
</li>
<li class="flex items-start gap-2 text-sm" style="color: var(--neutral-700);">
<i data-lucide="check" class="w-4 h-4 shrink-0 mt-0.5" style="color: var(--state-success);"></i>
<span>API 接口</span>
</li>
<li class="flex items-start gap-2 text-sm" style="color: var(--neutral-700);">
<i data-lucide="check" class="w-4 h-4 shrink-0 mt-0.5" style="color: var(--state-success);"></i>
<span>多渠道接入:<strong class="font-semibold">全渠道</strong></span>
</li>
<li class="flex items-start gap-2 text-sm" style="color: var(--neutral-700);">
<i data-lucide="check" class="w-4 h-4 shrink-0 mt-0.5" style="color: var(--state-success);"></i>
<span>自定义品牌</span>
</li>
<li class="flex items-start gap-2 text-sm" style="color: var(--neutral-700);">
<i data-lucide="check" class="w-4 h-4 shrink-0 mt-0.5" style="color: var(--state-success);"></i>
<span>专属客服支持:<strong class="font-semibold">7×24</strong></span>
</li>
</ul>
<div class="flex items-center justify-between pt-4 border-t" style="border-color: var(--neutral-200);">
<span class="text-sm" style="color: var(--neutral-500);">
<i data-lucide="users" class="w-4 h-4 inline-block align-middle mr-1" style="vertical-align: -2px;"></i>
42 个租户
</span>
<button class="inline-flex items-center justify-center px-3 py-1.5 rounded-md text-sm font-medium whitespace-nowrap border transition-colors" style="border-color: var(--neutral-200); color: var(--neutral-700); background: var(--neutral-0);">
编辑
</button>
</div>
</div>
</div>
<!-- Pricing Rules Section -->
<section class="rounded-lg border p-6" style="border-color: var(--neutral-200); background: var(--neutral-0);">
<h3 class="text-base font-bold mb-4" style="color: var(--neutral-900);">定价规则说明</h3>
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<div class="flex items-start gap-3">
<div class="w-8 h-8 rounded-md shrink-0 flex items-center justify-center" style="background: var(--brand-primary-light);">
<i data-lucide="calendar" class="w-4 h-4" style="color: var(--brand-primary);"></i>
</div>
<div class="min-w-0">
<p class="text-sm font-semibold truncate" style="color: var(--neutral-800);">按月订阅</p>
<p class="text-sm leading-relaxed" style="color: var(--neutral-500);">标准月度计费,按自然月结算,支持随时升降配</p>
</div>
</div>
<div class="flex items-start gap-3">
<div class="w-8 h-8 rounded-md shrink-0 flex items-center justify-center" style="background: var(--brand-primary-light);">
<i data-lucide="percent" class="w-4 h-4" style="color: var(--brand-primary);"></i>
</div>
<div class="min-w-0">
<p class="text-sm font-semibold truncate" style="color: var(--neutral-800);">年度优惠</p>
<p class="text-sm leading-relaxed" style="color: var(--neutral-500);">年付享 8 折优惠,一次性支付 12 个月费用</p>
</div>
</div>
<div class="flex items-start gap-3">
<div class="w-8 h-8 rounded-md shrink-0 flex items-center justify-center" style="background: var(--brand-primary-light);">
<i data-lucide="user-plus" class="w-4 h-4" style="color: var(--brand-primary);"></i>
</div>
<div class="min-w-0">
<p class="text-sm font-semibold truncate" style="color: var(--neutral-800);">按坐席计费</p>
<p class="text-sm leading-relaxed" style="color: var(--neutral-500);">超出套餐坐席数后按每坐席 ¥49/月额外计费</p>
</div>
</div>
</div>
</section>