diff --git a/web/app/support/page.tsx b/web/app/support/page.tsx
new file mode 100644
index 0000000..2e792de
--- /dev/null
+++ b/web/app/support/page.tsx
@@ -0,0 +1,5 @@
+import { SupportHelpCenter } from "@/components/support-center/help-center"
+
+export default function SupportPage() {
+ return
+}
diff --git a/web/components/support-center/help-center.tsx b/web/components/support-center/help-center.tsx
new file mode 100644
index 0000000..ed3cb53
--- /dev/null
+++ b/web/components/support-center/help-center.tsx
@@ -0,0 +1,145 @@
+"use client"
+
+import {
+ ArrowRightIcon,
+ BookOpenIcon,
+ BotIcon,
+ ChevronDownIcon,
+ CircleHelpIcon,
+ FileTextIcon,
+ HeadphonesIcon,
+ LightbulbIcon,
+ MessageCircleMoreIcon,
+ SearchIcon,
+ SparklesIcon,
+ TicketCheckIcon,
+ WrenchIcon,
+ type LucideIcon,
+} from "lucide-react"
+import { useMemo, useState } from "react"
+
+import { Badge } from "@/components/ui/badge"
+import { Button } from "@/components/ui/button"
+import { Card, CardContent } from "@/components/ui/card"
+import { Input } from "@/components/ui/input"
+import { cn } from "@/lib/utils"
+
+type Category = {
+ id: string
+ title: string
+ description: string
+ icon: LucideIcon
+ accent: string
+ articles: number
+}
+
+type Article = {
+ title: string
+ description: string
+ category: string
+ readTime: string
+}
+
+type Question = {
+ question: string
+ answer: string
+ category: string
+}
+
+const categories: Category[] = [
+ { id: "getting-started", title: "快速开始", description: "部署、登录和首次配置", icon: SparklesIcon, accent: "bg-sky-500/10 text-sky-600 dark:text-sky-400", articles: 8 },
+ { id: "ai", title: "AI 与模型配置", description: "模型、AI Agent 与工作流", icon: BotIcon, accent: "bg-violet-500/10 text-violet-600 dark:text-violet-400", articles: 12 },
+ { id: "knowledge", title: "知识库与检索", description: "FAQ、文档与回答质量", icon: BookOpenIcon, accent: "bg-emerald-500/10 text-emerald-600 dark:text-emerald-400", articles: 10 },
+ { id: "conversation", title: "会话与工单", description: "转人工、分配与问题闭环", icon: TicketCheckIcon, accent: "bg-amber-500/10 text-amber-600 dark:text-amber-400", articles: 9 },
+ { id: "integration", title: "渠道接入", description: "Web Widget 与第三方渠道", icon: MessageCircleMoreIcon, accent: "bg-rose-500/10 text-rose-600 dark:text-rose-400", articles: 11 },
+ { id: "troubleshooting", title: "故障排查", description: "定位常见配置与运行问题", icon: WrenchIcon, accent: "bg-slate-500/10 text-slate-600 dark:text-slate-400", articles: 14 },
+]
+
+const articles: Article[] = [
+ { title: "用 Docker Compose 在 10 分钟内启动 AgentDesk", description: "了解启动依赖、管理后台入口和首次检查项。", category: "getting-started", readTime: "5 分钟" },
+ { title: "如何配置第一个 AI Agent", description: "连接模型、知识库和转人工策略,完成一条可运行的服务流程。", category: "ai", readTime: "6 分钟" },
+ { title: "FAQ 知识库和文档知识库有什么区别?", description: "按内容形态选择更适合的知识沉淀方式。", category: "knowledge", readTime: "4 分钟" },
+ { title: "将 Web Widget 嵌入你的网站", description: "创建 Web 渠道、复制嵌入代码并完成上线前验证。", category: "integration", readTime: "7 分钟" },
+ { title: "用户请求人工客服后会发生什么?", description: "理解接入池、客服状态、分配规则和上下文交接。", category: "conversation", readTime: "4 分钟" },
+ { title: "Widget 能打开但不能发送消息怎么办?", description: "从渠道状态、域名配置和浏览器网络逐项排查。", category: "troubleshooting", readTime: "6 分钟" },
+]
+
+const questions: Question[] = [
+ { question: "AgentDesk 适合哪些业务场景?", answer: "它适合希望把 AI 首次响应、知识库检索、人工接管和工单跟进连接起来的客服与服务团队。", category: "getting-started" },
+ { question: "聊天模型可用,但知识库为什么没有命中?", answer: "通常需要检查 Embedding 模型、索引状态、检索阈值,以及 AI Agent 是否已绑定正确的知识库。", category: "knowledge" },
+ { question: "如何把会话转给人工客服?", answer: "AI 或客服可以发起转人工;系统会依据服务时间、客服状态、团队和分配规则处理接入。", category: "conversation" },
+ { question: "嵌入 Widget 时,channelId 是做什么的?", answer: "它标识一个具体 Web 渠道,并决定客户会话使用的渠道配置、品牌信息和身份校验策略。", category: "integration" },
+]
+
+export function SupportHelpCenter() {
+ const [query, setQuery] = useState("")
+ const [activeCategory, setActiveCategory] = useState("all")
+ const [openQuestion, setOpenQuestion] = useState(0)
+
+ const normalizedQuery = query.trim().toLocaleLowerCase()
+ const matches = useMemo(() => {
+ const matchesCategory = (category: string) => activeCategory === "all" || category === activeCategory
+ return {
+ articles: articles.filter((article) => matchesCategory(article.category) && `${article.title} ${article.description}`.toLocaleLowerCase().includes(normalizedQuery)),
+ questions: questions.filter((question) => matchesCategory(question.category) && `${question.question} ${question.answer}`.toLocaleLowerCase().includes(normalizedQuery)),
+ }
+ }, [activeCategory, normalizedQuery])
+
+ const isFiltering = activeCategory !== "all" || normalizedQuery.length > 0
+
+ return (
+
+
+
+
+
+
产品使用与接入指南
+
今天想解决什么问题?
+
从快速部署到 AI 配置、渠道接入和故障排查,帮你更快用好 AgentDesk。
+
+
+ setQuery(event.target.value)} placeholder="搜索问题,例如:如何接入 Web Widget?" className="h-13 rounded-2xl border-white bg-white pl-12 pr-4 text-base shadow-[0_12px_30px_rgba(36,117,252,.12)] focus-visible:ring-primary/25 dark:border-border dark:bg-card" />
+
+
热门搜索:
+
+
+
+
+
+
+
+ {categories.map((category) => { const Icon = category.icon; const active = activeCategory === category.id; return
})}
+
+
+
+
+ 推荐阅读
{isFiltering ? "搜索结果" : "从这里开始"}
{isFiltering &&
}
+ {matches.articles.length ? {matches.articles.map((article) =>
{article.title}
{article.description}
阅读约 {article.readTime}
)}
: }
+
+
+
+ 常见问题
把高频问题,变成一次自助解决。
我们整理了首次使用、知识库、转人工和渠道接入中的典型问题。
+ {matches.questions.length ? matches.questions.map((item, index) => { const expanded = openQuestion === index; return
{expanded &&
{item.answer}
}
}) :
}
+
+
+
+
+
+ )
+}
+
+function EmptyState({ compact = false }: { compact?: boolean }) {
+ return
没有找到相关内容。试试更换关键词,或清除当前筛选条件。
+}
diff --git a/web/public/images/logo.jpg b/web/public/images/logo.jpg
new file mode 100644
index 0000000..990779c
Binary files /dev/null and b/web/public/images/logo.jpg differ