Files
xinmi/website-docs/.vitepress/theme/Landing.vue
T
yawan f7fc992f57
Anydoc / anydoc parser engine (push) Canceled after 0s
App / Format, vet, test, and build (push) Canceled after 0s
CLI / test (macos-latest / go 1.26) (push) Canceled after 0s
CLI / test (ubuntu-latest / go 1.26) (push) Canceled after 0s
CLI / test (windows-latest / go 1.26) (push) Canceled after 0s
Build and Push Docker Image / build-ui (push) Canceled after 0s
Build and Push Docker Image / build-docreader (push) Canceled after 0s
Build and Push Docker Image / build-sandbox (push) Canceled after 0s
Build and Push Docker Image / build-app (amd64, linux/amd64, ubuntu-latest) (push) Canceled after 0s
Build and Push Docker Image / build-app (arm64, linux/arm64, ubuntu-24.04-arm) (push) Canceled after 0s
DocReader / Python tests and Go client tests (push) Canceled after 0s
Build & Publish (dsh-weknora) / Typecheck, test, pack (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (pinned) (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (latest, advisory) (push) Canceled after 0s
Frontend / Test, type-check, and build (push) Canceled after 0s
Go Lint Cache / warm lint cache (.) (push) Canceled after 0s
Go Lint Cache / warm lint cache (cli) (push) Canceled after 0s
Go Lint Cache / warm lint cache (client) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.10) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.11) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.12) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.13) (push) Canceled after 0s
Build and Push Docker Image / merge (push) Canceled after 0s
Build & Publish (dsh-weknora) / Publish to npm (push) Canceled after 0s
Build & Publish (mcp-server) / Build sdist + wheel (push) Canceled after 0s
Build & Publish (mcp-server) / Publish to PyPI (push) Canceled after 0s
WeKnora deployment source with the reviewed wiki identity, summary and recovery fixes
2026-09-22 16:19:06 +08:00

1547 lines
43 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import { useData } from 'vitepress/client'
import { withBase } from 'vitepress'
import Illus from './Illus.vue'
const { theme } = useData()
const versionLabel = theme.value.weknoraVersion ?? 'unknown'
const stats = [
{ value: '25', unit: '种', label: '文件格式:文档、网页、扫描件、图片、音频' },
{ value: '26', unit: '家+', label: '模型厂商,也可全部换成本地推理' },
{ value: '9', unit: '个', label: '使用入口:Web、IM、插件、命令行、MCP' },
{ value: '4', unit: '路', label: '索引同时生效:向量、关键词、Wiki、图谱' },
]
const schema = [
{
step: '01',
name: '接入',
hint: '资料从哪里来',
items: ['文件上传', 'URL 抓取', '飞书', 'Notion', '语雀', 'RSS'],
},
{
step: '02',
name: '理解',
hint: '转成结构化文本',
items: ['版式分析', '扫描件 OCR', '表格抽取', '图片描述', '音频转写'],
},
{
step: '03',
name: '索引',
hint: '四路可同时开启',
items: ['自适应分块', '向量', '关键词', 'Wiki', '知识图谱'],
},
{
step: '04',
name: '应用',
hint: '对外提供的能力',
items: ['知识问答', 'Agent 推理', 'Wiki 站点', '数据分析', 'FAQ'],
},
]
const chain = [
{
step: '01',
icon: 'read',
title: '读懂文档',
desc: '扫描件走 OCR、插图交给视觉模型描述、音频由语音模型转写、Excel 合并单元格自动补齐。独立的 docreader 服务把 PDF、Office、网页、图片与音频还原成带版式的文本,而不是只抽出一段纯文字。',
href: '/03-features/03-document-parsing',
},
{
step: '02',
icon: 'chunk',
title: '切好知识',
desc: '按文档特征在标题、启发式、递归三档策略间自动选择切法,父子分块让检索命中小块、送进模型的却是完整上下文。同一份文档可同时写入向量、关键词、Wiki 与知识图谱四路索引。',
href: '/02-architecture/03-document-pipeline',
},
{
step: '03',
icon: 'retrieve',
title: '找准证据',
desc: '先做意图识别与查询改写,向量与 BM25 并行召回后用 RRF 融合,再由重排模型定序;开启知识图谱时补一批实体关系证据,覆盖「A 和 B 什么关系」这类问题。',
href: '/03-features/05-retrieval-engines',
},
{
step: '04',
icon: 'answer',
title: '给出可核对的回答',
desc: '常规问题单轮检索直接生成;复杂任务交给 ReAct Agent 自行决定检索几轮、调哪些工具、要不要跑数据分析。回答流式返回,逐段标注出处,可点开原文核对。',
href: '/03-features/07-agent',
},
]
const surfaces = [
{ icon: 'console', name: 'Web 控制台', desc: '知识库管理、对话、Wiki 浏览与系统配置的完整界面。' },
{ icon: 'extension', name: 'Chrome 插件', desc: '网页侧边栏问答,支持正文剪藏与 Markdown 速记入库。' },
{ icon: 'embed', name: '网页嵌入挂件', desc: '一段 script 即可在自有站点提供悬浮问答,访客无需登录。' },
{ icon: 'desktop', name: '桌面客户端', desc: '单机运行的桌面应用,自带后端与本地存储;尚未正式发布,需自行构建。' },
{ icon: 'bot', name: 'IM 机器人', desc: '企业微信、飞书、钉钉、Slack 等 10 个平台的官方适配器。' },
{ icon: 'mobile', name: '微信小程序', desc: '移动端入口,支持网页收藏入库与提问。' },
{ icon: 'cli', name: '命令行 weknora', desc: '文档管理、检索与带引用的流式问答,默认 JSON 输出,便于脚本化。' },
{ icon: 'api', name: 'REST API 与 Go SDK', desc: '完整 /api/v1 接口;API Key 支持按能力与知识库范围授权。' },
{ icon: 'mcp', name: 'MCP Server', desc: '将 WeKnora 暴露为 MCP 工具,供 Claude、Cursor 等客户端检索。' },
]
const features = [
{
icon: 'wiki',
title: 'Wiki 模式',
desc: '由模型从文档中抽取实体与概念,生成互相链接且标注出处的页面,并自动组织为目录树与关系图谱。适用于资料分散、缺少整体索引的场景。',
href: '/03-features/14-wiki',
tag: '知识组织',
},
{
icon: 'version',
title: '分块级编辑与版本管理',
desc: '解析结果可在分块粒度直接修正,保存后即时重建索引,每次修改保留历史版本并支持回滚。Wiki 页面同样具备版本历史,并区分管道、Agent 与人工三类编辑来源。',
href: '/03-features/02-knowledge-base',
tag: '可维护性',
},
{
icon: 'channels',
title: '多渠道统一接入',
desc: '同一个 Agent 可同时发布到 10 个 IM 平台、自有站点的嵌入挂件与浏览器插件,会话、权限与知识范围沿用同一套配置。',
href: '/03-features/12-im-integration',
tag: '接入',
},
{
icon: 'mcp',
title: 'MCP 双向集成',
desc: '作为客户端接入外部 MCP 服务,支持 OAuth 授权与工具级人工审批;同时可作为 MCP Server 对外提供检索能力。',
href: '/03-features/08-mcp',
tag: '工具生态',
},
{
icon: 'govern',
title: '多空间隔离与审计',
desc: '工作空间级数据隔离与四级角色矩阵,API Key 可按能力与知识库范围收窄。操作行为写入审计日志,后台任务提供队列面板,问答链路支持 Langfuse 追踪。',
href: '/03-features/20-platform-admin',
tag: '企业部署',
},
{
icon: 'pluggable',
title: '可插拔架构',
desc: '解析引擎、分块策略、检索引擎、模型厂商、搜索引擎与存储后端均以注册表接入,可按配置替换;知识库支持分别绑定不同的向量库与存储实例。',
href: '/06-development/03-extension-points',
tag: '架构',
},
{
icon: 'graph',
title: '知识图谱增强检索',
desc: '入库时由模型抽取实体与关系存入图数据库,提问时顺着关系补充召回,用于回答「A 与 B 之间是什么关系」这类向量检索不擅长的问题。适合人物、组织、合同条款等关系密集的资料。',
href: '/03-features/09-knowledge-graph',
tag: '检索',
},
{
icon: 'sync',
title: '数据源持续同步',
desc: '飞书、Notion、语雀与 RSS 绑定一次凭据后按计划自动同步:首次全量,之后按修改时间增量拉取,源端删除的文档同步下架,避免知识库随时间过期。',
href: '/03-features/10-datasource',
tag: '数据接入',
},
{
icon: 'faq',
title: 'FAQ 精确问答',
desc: '退货政策、报销流程这类答案固定的问题可直接维护成问答对,按「标准问 + 相似问 + 反例问」匹配问题而非文档片段。可与文档库被同一 Agent 检索,形成先查标准答案再翻文档的顺序。',
href: '/03-features/17-faq',
tag: '答案质量',
},
]
const map = [
{
index: '01',
icon: 'start',
title: '快速开始',
brief: '按顺序读完四篇,可完成部署并跑通首次问答。',
items: [
{ text: '产品介绍', link: '/01-getting-started/01-introduction' },
{ text: '安装部署', link: '/01-getting-started/02-installation' },
{ text: '快速上手', link: '/01-getting-started/03-quickstart' },
{ text: '配置详解', link: '/01-getting-started/04-configuration' },
],
},
{
index: '02',
icon: 'arch',
title: '架构',
brief: '系统全貌,以及文档入库与检索问答两条主干流水线。',
items: [
{ text: '总体架构', link: '/02-architecture/01-overview' },
{ text: 'Go 后端设计', link: '/02-architecture/02-backend-design' },
{ text: '文档入库流程', link: '/02-architecture/03-document-pipeline' },
{ text: '检索问答流程', link: '/02-architecture/04-rag-pipeline' },
{ text: '异步任务系统', link: '/02-architecture/05-async-tasks' },
],
},
{
index: '03',
icon: 'modules',
title: '功能模块',
brief: '二十一项能力的配置项、行为约定与实现路径。',
items: [
{ text: '租户、用户与认证授权', link: '/03-features/01-tenant-auth' },
{ text: '知识库与知识管理', link: '/03-features/02-knowledge-base' },
{ text: '文档解析服务 docreader', link: '/03-features/03-document-parsing' },
{ text: '分块机制', link: '/03-features/04-chunking' },
{ text: '检索引擎与向量存储', link: '/03-features/05-retrieval-engines' },
{ text: '模型管理', link: '/03-features/06-models' },
{ text: 'Agent 引擎', link: '/03-features/07-agent' },
{ text: 'MCP 集成', link: '/03-features/08-mcp' },
{ text: '知识图谱', link: '/03-features/09-knowledge-graph' },
{ text: '数据源导入', link: '/03-features/10-datasource' },
{ text: '网络搜索与网页抓取', link: '/03-features/11-web-search' },
{ text: 'IM 集成', link: '/03-features/12-im-integration' },
{ text: '网页嵌入 Embed', link: '/03-features/13-embed-channel' },
{ text: 'Wiki 能力', link: '/03-features/14-wiki' },
{ text: '评估能力', link: '/03-features/15-evaluation' },
{ text: '可观测性与审计', link: '/03-features/16-observability' },
{ text: 'FAQ 能力', link: '/03-features/17-faq' },
{ text: '会话与对话体验', link: '/03-features/18-chat-experience' },
{ text: '存储后端', link: '/03-features/19-storage-backends' },
{ text: '平台管理与系统管理员', link: '/03-features/20-platform-admin' },
{ text: '图片与文件的对外访问', link: '/03-features/21-file-access' },
],
},
{
index: '04',
icon: 'api',
title: 'API 参考',
brief: '约 360 个端点,含权限要求、参数表与 curl 示例。',
items: [
{ text: 'API 总览', link: '/04-api/01-api-overview' },
{ text: 'Agent、MCP 与技能', link: '/04-api/02-api-agent-mcp' },
{ text: '认证与用户', link: '/04-api/02-api-auth' },
{ text: 'IM、Embed 与文件', link: '/04-api/02-api-channels' },
{ text: '会话、消息与聊天', link: '/04-api/02-api-chat' },
{ text: 'FAQ 与 Wiki', link: '/04-api/02-api-faq-wiki' },
{ text: '基础设施与数据源', link: '/04-api/02-api-infra' },
{ text: '知识库与知识', link: '/04-api/02-api-knowledge' },
{ text: '分块与标签', link: '/04-api/02-api-chunks' },
{ text: '模型与初始化', link: '/04-api/02-api-model-system' },
{ text: '系统与平台管理', link: '/04-api/02-api-system' },
{ text: '组织与共享', link: '/04-api/02-api-org' },
{ text: '租户与成员', link: '/04-api/02-api-tenant' },
],
},
{
index: '05',
icon: 'clients',
title: '客户端',
brief: '七种客户端:Web、CLI、SDK、小程序、桌面端、浏览器插件与 Skill。',
items: [
{ text: 'Web 前端', link: '/05-clients/01-frontend' },
{ text: '命令行工具 CLI', link: '/05-clients/02-cli' },
{ text: 'Go SDK', link: '/05-clients/03-go-sdk' },
{ text: '微信小程序', link: '/05-clients/04-miniprogram' },
{ text: '桌面客户端', link: '/05-clients/05-desktop' },
{ text: 'Chrome 插件', link: '/05-clients/06-chrome-extension' },
{ text: 'Claw Skill', link: '/05-clients/07-claw-skill' },
],
},
{
index: '06',
icon: 'dev',
title: '开发指南',
brief: '本地开发环境、数据库迁移,以及九类可插拔扩展点。',
items: [
{ text: '开发指南', link: '/06-development/01-dev-guide' },
{ text: '数据库与迁移', link: '/06-development/02-database-schema' },
{ text: '扩展点指南', link: '/06-development/03-extension-points' },
],
},
]
const deployments = [
{ icon: 'compose', name: 'Docker Compose', desc: '标准部署,12 个可选 profile 组合基础设施', note: '' },
{ icon: 'helm', name: 'Helm', desc: 'Kubernetes 集群编排,适用于生产多副本', note: '' },
{
icon: 'lite',
name: 'Lite(单二进制 / 桌面应用)',
desc: 'SQLite + 进程内队列,无需 Docker 与外部数据库;提供命令行与图形界面两种形式',
note: '桌面应用尚未正式发布,需自行构建',
},
]
</script>
<template>
<div class="landing">
<!-- ============================= Hero ============================= -->
<section class="hero">
<div class="shell hero-grid">
<div class="hero-copy">
<p class="eyebrow">Tencent 开源 · WeKnora {{ versionLabel }} · 官方文档</p>
<h1 class="display">
开源的知识库问答系统
</h1>
<p class="lede">WeKnora(维娜拉)将 PDF、Word、网页与飞书 / Notion / 语雀等来源的资料汇入知识库,提供检索增强的问答能力,回答标注可追溯的出处。除基础问答外,还提供 <strong>Wiki 自动成书</strong>、<strong>ReAct Agent 与 MCP 双向集成</strong>、<strong>知识图谱增强检索</strong>,以及面向团队的<strong>多空间隔离、四级 RBAC、作用域 API Key 与审计日志</strong>。支持完整私有部署,模型可全部替换为本地推理。</p>
<p class="lede lede-sub">本文档覆盖部署与配置、功能说明、约 360 个 API 端点的接口参考,以及二次开发的扩展点。</p>
<div class="actions">
<a class="btn btn-solid" :href="withBase('/01-getting-started/01-introduction')">开始阅读</a>
<a class="btn btn-ghost" :href="withBase('/02-architecture/01-overview')">系统架构</a>
<a
class="btn btn-text"
href="https://weknora.weixin.qq.com"
target="_blank"
rel="noreferrer"
>
官方网站 ↗
</a>
<a
class="btn btn-text"
href="https://github.com/Tencent/WeKnora"
target="_blank"
rel="noreferrer"
>
GitHub 仓库 ↗
</a>
</div>
</div>
<aside class="hero-side">
<div class="schema" aria-label="能力分层">
<p class="schema-title">能力分层</p>
<ol class="schema-layers">
<li v-for="layer in schema" :key="layer.name" class="layer">
<span class="layer-step">{{ layer.step }}</span>
<div class="layer-body">
<p class="layer-head">
<span class="layer-name">{{ layer.name }}</span>
<span class="layer-hint">{{ layer.hint }}</span>
</p>
<div class="layer-items">
<span v-for="n in layer.items" :key="n" class="chip">{{ n }}</span>
</div>
</div>
</li>
</ol>
<p class="schema-note">各层实现均可替换,未使用的能力可关闭;模型支持本地部署。</p>
</div>
</aside>
</div>
<svg class="wave" viewBox="0 0 1440 120" preserveAspectRatio="none" aria-hidden="true">
<path
d="M0 74C180 40 360 34 540 52c180 18 300 44 480 42s240-30 420-52"
fill="none"
stroke="var(--wk-ink)"
stroke-opacity="0.16"
stroke-width="1.5"
/>
<path
d="M0 92C200 62 380 58 560 74c180 16 300 40 470 36s250-26 410-44"
fill="none"
stroke="var(--wk-gold)"
stroke-opacity="0.45"
stroke-width="1.2"
/>
<path
d="M0 108C220 84 400 82 580 94c180 12 320 32 500 28s260-22 360-34"
fill="none"
stroke="var(--wk-ink)"
stroke-opacity="0.08"
stroke-width="1"
/>
</svg>
</section>
<!-- ============================ 全景 ============================ -->
<section class="panorama">
<div class="shell">
<Illus name="flow" class="panorama-illus" />
<p class="panorama-note">
资料从文件、网页、音频与图片进来,统一解析后并行写入向量、关键词、Wiki 与知识图谱四路索引;
同一套知识库与 Agent 再展开成九种客户端,换入口不用换一套系统。
</p>
</div>
</section>
<!-- ============================ 数字 ============================ -->
<section class="stats">
<div class="shell stats-row">
<div v-for="s in stats" :key="s.label" class="stat">
<span class="stat-value">{{ s.value }}<i>{{ s.unit }}</i></span>
<span class="stat-label">{{ s.label }}</span>
</div>
</div>
</section>
<!-- ============================ 主链路 ============================ -->
<section class="chapter">
<div class="shell">
<header class="chapter-head">
<span class="marker">处理流程</span>
<h2 class="chapter-title">从一份 PDF,到一句带出处的回答</h2>
<p class="chapter-sub">问答效果不好,问题往往不在模型,而在这条链路上:扫描件没读出文字、表格被切碎、召回的段落答非所问。下面四个环节各自对应一类失分点,且实现均可按需替换。</p>
</header>
<ol class="chain">
<li v-for="c in chain" :key="c.step" class="chain-item">
<a :href="withBase(c.href)">
<span class="chain-head">
<Illus :name="c.icon" class="chain-icon" />
<span class="chain-step">{{ c.step }}</span>
</span>
<h3 class="chain-title">{{ c.title }}</h3>
<p class="chain-desc">{{ c.desc }}</p>
</a>
</li>
</ol>
</div>
</section>
<!-- ============================ 特色能力 ============================ -->
<section class="chapter chapter-alt">
<div class="shell">
<header class="chapter-head">
<span class="marker">核心能力</span>
<h2 class="chapter-title">超出基础检索问答的部分</h2>
<p class="chapter-sub">以下能力为 WeKnora 的主要投入方向,可作为技术选型时的对比维度。</p>
</header>
<div class="features">
<a v-for="f in features" :key="f.title" class="feature" :href="withBase(f.href)">
<span class="feature-head">
<Illus :name="f.icon" class="feature-icon" />
<span class="feature-tag">{{ f.tag }}</span>
</span>
<h3 class="feature-title">{{ f.title }}</h3>
<p class="feature-desc">{{ f.desc }}</p>
</a>
</div>
</div>
</section>
<!-- ============================ 触达方式 ============================ -->
<section class="chapter">
<div class="shell">
<header class="chapter-head">
<span class="marker">接入方式</span>
<h2 class="chapter-title">九种客户端与集成入口</h2>
<p class="chapter-sub">同一套知识库与 Agent 配置,可从浏览器、IM、自有站点、终端与外部智能体访问,无需为各入口重复搭建。</p>
</header>
<div class="surfaces">
<div v-for="s in surfaces" :key="s.name" class="surface">
<h3 class="surface-name">
<Illus :name="s.icon" class="surface-icon" />
{{ s.name }}
</h3>
<p class="surface-desc">{{ s.desc }}</p>
</div>
</div>
<div class="surfaces-actions">
<a class="btn btn-ghost" :href="withBase('/05-clients/01-frontend')">查看客户端文档</a>
<a class="btn btn-text" :href="withBase('/03-features/13-embed-channel')">网页嵌入 ↗</a>
<a class="btn btn-text" :href="withBase('/03-features/12-im-integration')">IM 集成 ↗</a>
</div>
</div>
</section>
<!-- ============================ 文档地图 ============================ -->
<section class="chapter chapter-alt">
<div class="shell">
<header class="chapter-head">
<span class="marker">文档地图</span>
<h2 class="chapter-title">六个部分,五十三篇</h2>
<p class="chapter-sub">覆盖部署上手、系统架构、功能说明、接口参考、客户端与二次开发。</p>
</header>
<div class="map">
<section
v-for="m in map"
:key="m.index"
class="map-block"
:class="{ 'map-block-wide': m.items.length > 8 }"
>
<div class="map-head">
<span class="map-index">{{ m.index }}</span>
<h3 class="map-title">
<Illus :name="m.icon" class="map-icon" />
{{ m.title }}
</h3>
<p class="map-brief">{{ m.brief }}</p>
</div>
<ul class="map-list">
<li v-for="it in m.items" :key="it.link">
<a :href="withBase(it.link)">{{ it.text }}</a>
</li>
</ul>
</section>
</div>
</div>
</section>
<!-- ============================ 部署 ============================ -->
<section class="chapter">
<div class="shell deploy">
<div class="deploy-copy">
<span class="marker">部署</span>
<h2 class="chapter-title">部署形态</h2>
<p class="chapter-sub">标准部署克隆代码、改两个密钥、一条命令拉起全套服务;本机试用可选 Lite 模式,不依赖 PostgreSQL 与 Redis。</p>
<ul class="deploy-list">
<li v-for="d in deployments" :key="d.name">
<span class="deploy-name">
<Illus :name="d.icon" class="deploy-icon" />
{{ d.name }}
</span>
<span class="deploy-desc">
{{ d.desc }}
<span v-if="d.note" class="deploy-note">{{ d.note }}</span>
</span>
</li>
</ul>
<a class="btn btn-ghost" :href="withBase('/01-getting-started/02-installation')">查看安装部署</a>
</div>
<div class="deploy-code">
<div class="code-bar">
<span>标准部署 · Docker Compose</span>
</div>
<pre><code><span class="c"># 1 获取代码</span>
git clone https://github.com/Tencent/WeKnora.git
cd WeKnora
<span class="c"># 2 准备配置:至少修改 JWT_SECRET 与 SYSTEM_AES_KEY</span>
cp .env.example .env
<span class="c"># 3 拉起全部服务(首次需拉取镜像)</span>
docker compose up -d --pull always
<span class="c"># 4 确认服务就绪</span>
docker compose ps
curl http://localhost:8080/health
<span class="c"># 5 打开前端(默认 80 端口,可用 FRONTEND_PORT 改)</span>
open http://localhost
<span class="c"># 停止:docker compose down</span></code></pre>
<p class="deploy-code-note">
首次打开前端会落到注册页,注册后在初始化向导里配置对话模型与向量模型,即可建库提问。后端 API 与前端同域,走 <code>http://localhost/api/v1</code>。
完整步骤见<a :href="withBase('/01-getting-started/03-quickstart')">快速上手</a>,其余部署形态与参数见<a :href="withBase('/01-getting-started/02-installation')">安装部署</a>。
</p>
</div>
</div>
</section>
<!-- ============================ 结尾 ============================ -->
<footer class="closing">
<div class="shell closing-inner">
<div class="closing-brand">
<svg width="34" height="26" viewBox="0 0 34 26" fill="none" aria-hidden="true">
<path
d="M20.6 3.2c.36-.5 1.16-.22 1.13.39l-.53 10.2-6.9-.05c-.6 0-.86-.75-.4-1.13L20.6 3.2z"
fill="currentColor"
/>
<path
d="M1.5 18.4c6.4-1.9 12.2-1.1 18.1.35 4.3 1.05 8.2 1.6 12.9.1"
stroke="currentColor"
stroke-width="2.1"
stroke-linecap="round"
/>
<path
d="M4.4 22.1c5.6-1.35 10.8-.7 16 .5 3.8.87 7.2 1.2 11.3.15"
stroke="var(--wk-gold)"
stroke-width="1.4"
stroke-linecap="round"
/>
</svg>
<span>WeKnora</span>
</div>
<p class="closing-note">文档基于仓库 {{ versionLabel }} 源码整理。源码路径均相对仓库根目录,API 路径默认带 <code>/api/v1</code> 前缀,配置示例中的密钥均为占位符。</p>
<div class="closing-links">
<a :href="withBase('/01-getting-started/01-introduction')">快速开始</a>
<a :href="withBase('/04-api/01-api-overview')">API 总览</a>
<a :href="withBase('/06-development/03-extension-points')">扩展点</a>
<a href="https://github.com/Tencent/WeKnora" target="_blank" rel="noreferrer">GitHub</a>
</div>
<p class="closing-copy">© Tencent WeKnora · MIT License</p>
</div>
</footer>
</div>
</template>
<style scoped>
.landing {
/* 与文档页铺满视口的正文列保持同一量级,避免首页明显更窄 */
--shell: 1600px;
color: var(--wk-ink);
}
.shell {
max-width: var(--shell);
margin: 0 auto;
padding: 0 32px;
}
.marker {
display: inline-block;
font-family: var(--wk-font-mono);
font-size: 10.5px;
letter-spacing: 0.2em;
text-transform: uppercase;
color: var(--wk-gold);
margin-bottom: 22px;
}
.marker::before {
content: "";
display: inline-block;
width: 22px;
height: 1px;
background: var(--wk-gold);
vertical-align: middle;
margin-right: 12px;
}
/* ------------------------------- Hero ------------------------------- */
.hero {
position: relative;
padding: clamp(80px, 13vw, 168px) 0 clamp(96px, 12vw, 150px);
overflow: hidden;
}
.hero::before {
content: "";
position: absolute;
inset: 0;
background:
radial-gradient(120% 80% at 78% -10%, rgba(184, 134, 59, 0.09), transparent 62%),
radial-gradient(90% 70% at 8% 0%, rgba(16, 31, 56, 0.06), transparent 60%);
pointer-events: none;
}
.hero-grid {
position: relative;
display: grid;
grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
gap: 76px;
align-items: center;
}
.eyebrow {
font-family: var(--wk-font-mono);
font-size: 11px;
letter-spacing: 0.22em;
text-transform: uppercase;
color: var(--wk-ink-mute);
margin: 0 0 34px;
}
.display {
font-family: var(--wk-font-serif);
font-weight: 500;
font-size: clamp(34px, 4.1vw, 58px);
line-height: 1.2;
letter-spacing: -0.025em;
margin: 0;
}
.lede {
margin: 34px 0 0;
max-width: 60ch;
font-size: 16.5px;
line-height: 1.85;
color: var(--wk-ink-soft);
}
/* 第二段说明这个站点本身是什么,弱化一档以免与定位句抢注意力 */
.lede-sub {
margin-top: 14px;
font-size: 15px;
color: var(--wk-ink-mute);
}
.actions {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 14px;
margin-top: 46px;
}
.btn {
display: inline-flex;
align-items: center;
height: 46px;
padding: 0 26px;
border-radius: 2px;
font-size: 14px;
font-weight: 550;
letter-spacing: 0.02em;
text-decoration: none;
transition: all 0.22s ease;
}
.btn-solid {
background: var(--wk-ink);
color: var(--wk-paper);
border: 1px solid var(--wk-ink);
}
.btn-solid:hover {
background: transparent;
color: var(--wk-ink);
}
.btn-ghost {
border: 1px solid var(--wk-rule);
color: var(--wk-ink);
}
.btn-ghost:hover {
border-color: var(--wk-gold);
color: var(--wk-gold);
}
.btn-text {
padding: 0 6px;
color: var(--wk-ink-mute);
}
.btn-text:hover {
color: var(--wk-ink);
}
/* 系统组件概览 */
/* 全景图:整条链路加九个客户端,横向铺得很开,
塞进首屏右栏那张卡片里只会挤成一团,所以单独占一条通栏 */
.panorama {
padding: clamp(18px, 3vw, 40px) 0 clamp(28px, 4vw, 56px);
}
.panorama-illus {
display: block;
width: 100%;
max-width: 1180px;
height: auto;
margin: 0 auto;
color: var(--wk-ink);
opacity: 0.9;
}
.panorama-note {
max-width: 860px;
margin: 26px auto 0;
text-align: center;
font-size: 13.5px;
line-height: 1.8;
color: var(--wk-ink-mute);
}
/* 能力分层:序号列 + 贯穿的竖轴表达自上而下的流向,
原来只靠层间一个小箭头,读者看不出这是一条流水线 */
.schema {
padding: 26px 26px 22px;
border: 1px solid var(--wk-rule);
border-radius: 4px;
background: color-mix(in srgb, var(--wk-paper-2) 60%, transparent);
}
.schema-title {
margin: 0 0 20px;
font-family: var(--wk-font-mono);
font-size: 10.5px;
letter-spacing: 0.16em;
text-transform: uppercase;
color: var(--wk-ink-mute);
}
.schema-layers {
margin: 0;
padding: 0;
list-style: none;
}
.layer {
position: relative;
display: grid;
grid-template-columns: 34px 1fr;
gap: 14px;
padding: 0 0 22px;
}
.layer:last-child {
padding-bottom: 0;
}
/* 竖轴连接各层序号;最后一层不再向下延伸 */
.layer:not(:last-child)::before {
content: "";
position: absolute;
left: 11px;
top: 24px;
bottom: 4px;
width: 1px;
background: var(--wk-rule);
}
.layer-step {
z-index: 1;
display: grid;
place-items: center;
width: 23px;
height: 23px;
border: 1px solid var(--wk-rule);
border-radius: 50%;
background: var(--wk-paper);
font-family: var(--wk-font-mono);
font-size: 10px;
color: var(--wk-ink-mute);
}
.layer-head {
display: flex;
align-items: baseline;
gap: 10px;
margin: 3px 0 10px;
}
.layer-name {
font-size: 14px;
font-weight: 600;
letter-spacing: 0.02em;
color: var(--wk-ink);
}
.layer-hint {
font-size: 12px;
color: var(--wk-ink-mute);
}
.layer-items {
display: flex;
flex-wrap: wrap;
gap: 6px;
}
.chip {
font-size: 12px;
line-height: 1.5;
padding: 4px 10px;
border: 1px solid var(--wk-rule);
border-radius: 2px;
color: var(--wk-ink-soft);
background: color-mix(in srgb, var(--wk-paper) 70%, transparent);
white-space: nowrap;
}
.schema-note {
margin: 22px 0 0;
padding-top: 16px;
border-top: 1px solid var(--wk-rule-soft);
font-size: 12px;
line-height: 1.7;
color: var(--wk-ink-mute);
}
.wave {
position: absolute;
left: 0;
right: 0;
bottom: -1px;
width: 100%;
height: 120px;
pointer-events: none;
}
/* ------------------------------- 数字 ------------------------------- */
.stats {
border-top: 1px solid var(--wk-rule-soft);
border-bottom: 1px solid var(--wk-rule-soft);
background: var(--wk-paper-2);
}
.stats-row {
display: grid;
grid-template-columns: repeat(4, 1fr);
}
@media (max-width: 900px) {
.stats-row {
grid-template-columns: repeat(2, 1fr);
}
}
.stat {
padding: 34px 0;
text-align: center;
border-left: 1px solid var(--wk-rule-soft);
}
.stat:first-child {
border-left: none;
}
.stat-value {
display: block;
font-family: var(--wk-font-serif);
font-size: 34px;
line-height: 1;
font-weight: 500;
letter-spacing: -0.02em;
}
.stat-value i {
font-style: normal;
font-size: 0.6em;
color: var(--wk-gold);
margin-left: 2px;
}
.stat-label {
display: block;
/* 中文可在任意字符间断行,宽度卡在词中间就会拆出「扫描 / 件」这种断法。
放宽一档并让浏览器均衡两行长度,词组更容易落在同一行 */
max-width: 26ch;
/* keep-all 让中文只在顿号、冒号处断行,不再从词中间劈开 */
word-break: keep-all;
text-wrap: balance;
margin: 12px auto 0;
font-size: 12.5px;
line-height: 1.7;
letter-spacing: 0.04em;
color: var(--wk-ink-mute);
}
/* ------------------------------ 章节通用 ------------------------------ */
.chapter {
padding: clamp(72px, 9vw, 124px) 0;
}
.chapter-alt {
background: var(--wk-paper-2);
border-top: 1px solid var(--wk-rule-soft);
border-bottom: 1px solid var(--wk-rule-soft);
}
.chapter-head {
max-width: 780px;
margin-bottom: 68px;
}
.chapter-title {
font-family: var(--wk-font-serif);
font-weight: 500;
font-size: clamp(27px, 3.2vw, 40px);
line-height: 1.3;
letter-spacing: -0.02em;
margin: 0;
border: none;
padding: 0;
}
.chapter-sub {
margin: 20px 0 0;
font-size: 15.5px;
line-height: 1.85;
color: var(--wk-ink-soft);
}
/* ------------------------------- 主链路 ------------------------------- */
.chain {
list-style: none;
margin: 0;
padding: 0;
display: grid;
grid-template-columns: repeat(4, 1fr);
border-top: 1px solid var(--wk-rule);
}
.chain-item {
border-left: 1px solid var(--wk-rule-soft);
}
.chain-item:first-child {
border-left: none;
}
.chain-item a {
display: block;
height: 100%;
padding: 32px 28px 40px 0;
text-decoration: none;
color: inherit;
transition: opacity 0.22s ease;
}
.chain-item:not(:first-child) a {
padding-left: 28px;
}
.chain-item a:hover {
opacity: 0.62;
}
.chain-head {
display: flex;
align-items: center;
gap: 12px;
}
.chain-icon {
width: 26px;
height: 26px;
flex: none;
color: var(--wk-ink);
}
.chain-step {
font-family: var(--wk-font-mono);
font-size: 11px;
letter-spacing: 0.18em;
color: var(--wk-gold);
}
.chain-title {
font-family: var(--wk-font-serif);
font-size: 21px;
font-weight: 500;
margin: 16px 0 14px;
letter-spacing: -0.01em;
}
.chain-desc {
margin: 0;
font-size: 14px;
line-height: 1.8;
color: var(--wk-ink-soft);
}
/* ------------------------------ 特色能力 ------------------------------ */
.features {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
border-top: 1px solid var(--wk-rule);
}
.feature {
display: block;
padding: 30px 30px 36px 0;
border-bottom: 1px solid var(--wk-rule-soft);
border-left: 1px solid var(--wk-rule-soft);
text-decoration: none;
color: inherit;
transition: opacity 0.22s ease;
}
.feature:nth-child(3n + 1) {
border-left: none;
}
.feature:not(:nth-child(3n + 1)) {
padding-left: 30px;
}
.feature:nth-last-child(-n + 3) {
border-bottom: none;
}
.feature:hover {
opacity: 0.62;
}
.feature-head {
display: flex;
align-items: center;
gap: 11px;
}
.feature-icon {
width: 24px;
height: 24px;
flex: none;
color: var(--wk-ink);
}
.feature-tag {
font-family: var(--wk-font-mono);
font-size: 11px;
letter-spacing: 0.16em;
color: var(--wk-gold);
}
.feature-title {
font-family: var(--wk-font-serif);
font-size: 20px;
font-weight: 500;
margin: 14px 0 12px;
letter-spacing: -0.01em;
}
.feature-desc {
margin: 0;
font-size: 14px;
line-height: 1.8;
color: var(--wk-ink-soft);
}
/* ------------------------------ 触达方式 ------------------------------ */
.surfaces {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 28px 56px;
}
.surface {
padding-top: 18px;
border-top: 1px solid var(--wk-rule-soft);
}
.surface-name {
display: flex;
align-items: center;
gap: 10px;
font-size: 15px;
font-weight: 600;
margin: 0 0 8px;
letter-spacing: 0.01em;
}
.surface-icon {
width: 20px;
height: 20px;
flex: none;
color: var(--wk-ink);
}
.surface-desc {
margin: 0;
font-size: 13.5px;
line-height: 1.75;
color: var(--wk-ink-soft);
}
.surfaces-actions {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 18px;
margin-top: 44px;
}
/* ------------------------------ 文档地图 ------------------------------ */
.map {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 0 72px;
}
.map-block {
padding: 40px 0;
border-top: 1px solid var(--wk-rule);
}
.map-head {
display: grid;
grid-template-columns: 46px 1fr;
align-items: baseline;
row-gap: 10px;
}
.map-index {
font-family: var(--wk-font-mono);
font-size: 11px;
letter-spacing: 0.14em;
color: var(--wk-gold);
}
.map-title {
display: flex;
align-items: center;
gap: 12px;
font-family: var(--wk-font-serif);
font-size: 24px;
font-weight: 500;
margin: 0;
letter-spacing: -0.01em;
}
.map-icon {
width: 22px;
height: 22px;
flex: none;
color: var(--wk-ink);
}
.map-brief {
grid-column: 2;
margin: 0;
font-size: 13.8px;
line-height: 1.75;
color: var(--wk-ink-mute);
}
.map-list {
list-style: none;
margin: 26px 0 0 46px;
padding: 0;
columns: 1;
}
.map-block-wide {
grid-column: 1 / -1;
}
.map-block-wide .map-list {
columns: 3;
column-gap: 72px;
}
.map-block-wide .map-brief {
max-width: 52ch;
}
.map-list li {
border-bottom: 1px solid var(--wk-rule-soft);
}
.map-list a {
display: block;
padding: 11px 0;
font-size: 14.5px;
color: var(--wk-ink-soft);
text-decoration: none;
transition: color 0.18s ease, padding-left 0.18s ease;
}
.map-list a:hover {
color: var(--wk-ink);
padding-left: 8px;
}
/* ------------------------------- 部署 ------------------------------- */
.deploy {
display: grid;
grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
gap: 72px;
align-items: start;
}
.deploy-list {
list-style: none;
margin: 38px 0;
padding: 0;
border-top: 1px solid var(--wk-rule-soft);
}
.deploy-list li {
display: grid;
/* 名称列要装下图标 + 「Lite(单二进制 / 桌面应用)」,比原来放宽一档 */
grid-template-columns: 178px 1fr;
gap: 16px;
padding: 15px 0;
border-bottom: 1px solid var(--wk-rule-soft);
}
.deploy-name {
display: grid;
grid-template-columns: 20px 1fr;
align-items: start;
gap: 10px;
font-size: 14px;
font-weight: 600;
}
.deploy-icon {
width: 20px;
height: 20px;
margin-top: 1px;
color: var(--wk-ink);
}
/* 「尚未正式发布」这类限定跟在说明之后。放在名称列会被 150px 的窄列挤断,
放这里既不断字,也仍然紧贴对应条目。 */
.deploy-note {
display: inline-block;
margin-left: 6px;
padding: 1px 7px;
border: 1px solid var(--wk-rule);
border-radius: 2px;
font-family: var(--wk-font-mono);
font-size: 10.5px;
line-height: 1.7;
letter-spacing: 0.04em;
white-space: nowrap;
color: var(--wk-ink-mute);
}
.deploy-desc {
font-size: 13.8px;
line-height: 1.7;
color: var(--wk-ink-mute);
}
.deploy-code {
border: 1px solid var(--wk-rule);
border-radius: 4px;
overflow: hidden;
background: #0d1626;
}
.code-bar {
padding: 12px 20px;
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
font-family: var(--wk-font-mono);
font-size: 10.5px;
letter-spacing: 0.18em;
text-transform: uppercase;
color: rgba(230, 236, 245, 0.45);
}
.deploy-code pre {
margin: 0;
padding: 24px 22px 28px;
overflow-x: auto;
}
.deploy-code code {
font-family: var(--wk-font-mono);
font-size: 13px;
line-height: 2;
color: #dfe7f2;
}
.deploy-code .c {
color: rgba(217, 169, 79, 0.75);
}
/* 代码块本身只到「服务起来了」,后续动作与延伸阅读放在下面这行,
避免读者以为跑完命令就结束了 */
.deploy-code-note {
margin: 0;
padding: 16px 22px 20px;
border-top: 1px solid rgba(255, 255, 255, 0.08);
font-size: 12.5px;
line-height: 1.9;
color: rgba(223, 231, 242, 0.62);
}
.deploy-code-note code {
font-family: var(--wk-font-mono);
font-size: 12px;
color: rgba(223, 231, 242, 0.85);
}
.deploy-code-note a {
color: var(--wk-gold-light);
text-decoration: none;
border-bottom: 1px solid rgba(217, 169, 79, 0.4);
}
.deploy-code-note a:hover {
border-bottom-color: var(--wk-gold-light);
}
/* ------------------------------- 结尾 ------------------------------- */
.closing {
border-top: 1px solid var(--wk-rule-soft);
background: var(--wk-paper-2);
padding: 70px 0 60px;
}
.closing-inner {
display: grid;
gap: 26px;
justify-items: center;
text-align: center;
}
.closing-brand {
display: flex;
align-items: center;
gap: 12px;
font-family: var(--wk-font-sans);
font-size: 14px;
font-weight: 600;
letter-spacing: 0.18em;
text-transform: uppercase;
}
.closing-note {
max-width: 58ch;
margin: 0;
font-size: 13.5px;
line-height: 1.9;
color: var(--wk-ink-mute);
}
.closing-note code {
font-family: var(--wk-font-mono);
font-size: 0.9em;
}
.closing-links {
display: flex;
flex-wrap: wrap;
gap: 28px;
}
.closing-links a {
font-size: 13.5px;
color: var(--wk-ink-soft);
text-decoration: none;
border-bottom: 1px solid transparent;
padding-bottom: 2px;
transition: all 0.2s ease;
}
.closing-links a:hover {
color: var(--wk-ink);
border-bottom-color: var(--wk-gold);
}
.closing-copy {
margin: 0;
font-family: var(--wk-font-mono);
font-size: 11px;
letter-spacing: 0.1em;
color: var(--wk-ink-mute);
}
/* ------------------------------ 响应式 ------------------------------ */
@media (max-width: 1080px) {
.hero-grid {
grid-template-columns: minmax(0, 1fr);
gap: 56px;
}
.map-block-wide .map-list {
columns: 2;
column-gap: 48px;
}
.chain {
grid-template-columns: repeat(2, 1fr);
}
.chain-item:nth-child(odd) {
border-left: none;
}
.chain-item:nth-child(n + 3) {
border-top: 1px solid var(--wk-rule-soft);
}
.chain-item a,
.chain-item:not(:first-child) a {
padding-left: 0;
}
.chain-item:nth-child(even) a {
padding-left: 28px;
}
.features {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.feature,
.feature:not(:nth-child(3n + 1)) {
padding-left: 0;
border-left: none;
}
.feature:nth-child(even) {
padding-left: 30px;
border-left: 1px solid var(--wk-rule-soft);
}
.feature:nth-last-child(-n + 3) {
border-bottom: 1px solid var(--wk-rule-soft);
}
.feature:nth-last-child(-n + 2) {
border-bottom: none;
}
.surfaces {
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 24px 40px;
}
.map {
grid-template-columns: minmax(0, 1fr);
gap: 0;
}
.deploy {
grid-template-columns: minmax(0, 1fr);
gap: 48px;
}
.stats-row {
grid-template-columns: repeat(3, 1fr);
}
.stat:nth-child(3n + 1) {
border-left: none;
}
.stat:nth-child(n + 4) {
border-top: 1px solid var(--wk-rule-soft);
}
}
@media (max-width: 640px) {
.shell {
padding: 0 22px;
}
.display br {
display: none;
}
.chain {
grid-template-columns: minmax(0, 1fr);
}
.chain-item {
border-left: none;
}
.chain-item:not(:first-child) {
border-top: 1px solid var(--wk-rule-soft);
}
.chain-item:nth-child(even) a {
padding-left: 0;
}
.surfaces {
grid-template-columns: minmax(0, 1fr);
gap: 20px;
}
.features {
grid-template-columns: minmax(0, 1fr);
}
.feature,
.feature:nth-child(even) {
padding-left: 0;
border-left: none;
border-bottom: 1px solid var(--wk-rule-soft);
}
.feature:last-child {
border-bottom: none;
}
.stats-row {
grid-template-columns: repeat(2, 1fr);
}
.stat {
border-left: 1px solid var(--wk-rule-soft);
}
.stat:nth-child(odd) {
border-left: none;
}
.stat:nth-child(n + 3) {
border-top: 1px solid var(--wk-rule-soft);
}
.map-block-wide .map-list {
columns: 1;
}
.map-head {
grid-template-columns: 1fr;
}
.map-brief {
grid-column: 1;
}
.map-list {
margin-left: 0;
}
.deploy-list li {
grid-template-columns: 1fr;
gap: 6px;
}
}
</style>