diff --git "a/01.\345\205\250\346\240\210/00.overview.html" "b/01.\345\205\250\346\240\210/00.overview.html" deleted file mode 100644 index b46efbab..00000000 --- "a/01.\345\205\250\346\240\210/00.overview.html" +++ /dev/null @@ -1,178 +0,0 @@ - - - - - - 全景一览 | Insight Stack - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Skip to content
21
- - - - 1m

全景一览

- - - - \ No newline at end of file diff --git "a/01.\345\205\250\346\240\210/00.overview.md" "b/01.\345\205\250\346\240\210/00.overview.md" deleted file mode 100644 index 4defa820..00000000 --- "a/01.\345\205\250\346\240\210/00.overview.md" +++ /dev/null @@ -1,9 +0,0 @@ ---- -url: /01.全栈/00.overview.md -description: >- - 本系列围绕现代全栈开发的能力体系展开,从 AI - 时代的工程思维出发,覆盖前端工程(React/Vue/CSS)、全栈基础素养(TypeScript/JavaScript)、工具与资源推荐等核心领域,帮助构建从"认知层 - → 技术领域 → 工程能力 → 基础设施"的完整全栈知识图谱。 ---- - -# 全景一览 diff --git "a/01.\345\205\250\346\240\210/01.AI Native \345\267\245\347\250\213\346\200\235\347\273\264/01.\344\270\215\346\255\242\344\272\216\344\273\243\347\240\201\357\274\232\346\236\204\345\273\272 AI \346\227\266\344\273\243\345\205\250\346\240\210\345\267\245\347\250\213\345\270\210\347\232\204\342\200\234\350\256\244\347\237\245\344\270\211\345\261\202\345\241\224\342\200\235.html" "b/01.\345\205\250\346\240\210/01.AI Native \345\267\245\347\250\213\346\200\235\347\273\264/01.\344\270\215\346\255\242\344\272\216\344\273\243\347\240\201\357\274\232\346\236\204\345\273\272 AI \346\227\266\344\273\243\345\205\250\346\240\210\345\267\245\347\250\213\345\270\210\347\232\204\342\200\234\350\256\244\347\237\245\344\270\211\345\261\202\345\241\224\342\200\235.html" deleted file mode 100644 index bdd9e4c1..00000000 --- "a/01.\345\205\250\346\240\210/01.AI Native \345\267\245\347\250\213\346\200\235\347\273\264/01.\344\270\215\346\255\242\344\272\216\344\273\243\347\240\201\357\274\232\346\236\204\345\273\272 AI \346\227\266\344\273\243\345\205\250\346\240\210\345\267\245\347\250\213\345\270\210\347\232\204\342\200\234\350\256\244\347\237\245\344\270\211\345\261\202\345\241\224\342\200\235.html" +++ /dev/null @@ -1,178 +0,0 @@ - - - - - - 不止于代码:构建 AI 时代全栈工程师的“认知三层塔” | Insight Stack - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Skip to content
2017
- - - - 7.2m

不止于代码:构建 AI 时代全栈工程师的“认知三层塔”

摘要总结:在 AI 重塑软件工程的今天,全栈不再是技术的线性叠加,正在从“技术栈堆砌”转向“认知栈重构”。本文提出 “(工程 + 产品) × AI” 的新公式,助力开发者构建“洞察-架构-杠杆”认知三层塔,利用 AI 杠杆让自己进化为价值创造者。

1. 引言

在很长一段时间里,当我们谈论“全栈工程师”时,脑海中浮现的往往是一张冗长且令人疲惫的技术工序清单

就像我曾经以为的那样,全栈就是线性的技能叠加与物理式的技术拼接,是一种依靠人力去填补技术鸿沟的“西西弗斯式”努力:

  • 线性的技能叠加:我们被迫成为“全能手”,左手用 React/Vue 构建精美的 UI,右手用 Node/Go 编写高并发 API,中间还要处理数据库的 ACID 事务(整个链路基本是这样的:构建前端 UI 交互 -> 编写后端业务API -> 维护底层数据存储与服务稳定)。
  • 物理式的拼接:我们试图用人力去掩盖技术栈之间的裂痕——用各种 Shell 脚本、Docker 配置、Nginx 转发规则,去粘合一个支离破碎的系统。

那个时候,我认为全栈的护城河在于“掌握编程语言的数量”。只要我能写前端、能写后端、偶尔还能写点 Python 爬虫,我就是全栈。我们都在拼命地做加法,试图把自己打磨成一把无所不能的瑞士军刀。

但在 AI 彻底重构代码生产方式的今天,这个定义显得过时且狭隘。当 GPT5/Claude Code/Cursor 等能够在一分钟内生成高质量的 CRUD 代码,甚至自动完成单元测试时,我们掌握语言、语法的价值又还剩多少?如果一个人就能通过 AI 完成一支团队的工作,那么“全栈”的边界到底在哪里?

真正的全栈,已经从“技能的物理叠加” 进化到了 “价值的化学闭环”。如果一个人通过 AI 就能完成过去一支团队的交付量,那么“全栈”的边界就不再是技术栈(Tech Stack),而是认知栈(Insight Stack)。

维度旧全栈 (Legacy Full Stack)新全栈 (AI-Native Full Stack)
关注点语言、框架、语法 (Tools)问题、场景、价值 (Value)
核心能力纯手工编码 (Coding)架构设计、Prompt 工程、代码审查 (Architecting)
交付边界前端页面 + 后端接口需求洞察 \rightarrow 产品设计 \rightarrow 落地运营
AI 的角色辅助工具 (Copilot)核心引擎与分身 (Co-founder)

2. AI 时代的全栈新公式

在重新思考技术演进的逻辑后,笔者思考出了一个更具现代感的全栈价值公式。这不仅仅是技能的组合,更是思维模型的重构:

Full Stack=(Engineering+Product)×AI\mathbf{Full\ Stack} \; = \; (\mathbf{Engineering} \; + \; \mathbf{Product}) \; \times \; \mathbf{AI}

这个公式告诉我们:不要再执着于手里有多少把锤子,而要关注你能构建出怎样的建筑,AI 是那个能够让工程能力和产品思维产生指数级爆炸的乘数。

2.1. Engineering (工程力):从“困于实现”到“敢于设计”

新旧模式对比:

旧模式:熟练记忆 API,手写大量样板代码,关注具体的语言和语法细节。

新模式具备系统级视野,关注架构的健壮性、可维护性以及自动化交付体系。

在 AI 时代,工程力的内核发生了迁移,AI 在逐渐接管 How(怎么写代码),人类必须专注于 What(做什么系统)和 Why(为什么这样设计)。

能力维度核心要点
架构决策当代码生成变得廉价,架构决策变得昂贵。是选择单体还是微服务?是 SQL 还是 NoSQL?这些决定了系统的上限。
代码审计与验收你从"写作者"变成了"编辑"和"审计员",当 AI 帮你写完 80% 的代码后,你是否有能力调试剩下那 20% 最隐蔽的逻辑漏洞?
DevOps 与交付工程力不再止步于 localhost,它意味着你能利用 Docker、K8s、CI/CD 乃至 Serverless,将代码安全、稳定地送达线上,并将产品交付到用户手中。

2.2. Product (产品力):从“需求翻译机”到“价值定义者”

新旧模式对比:

旧模式:被动接收需求文档,关注功能的按时上线。

新模式理解商业模式与用户痛点,能判断“做什么”比“怎么做”更重要。

产品力是技术人员最容易忽视,但在公式中权重极高的变量,它与工程力是相加关系——没有产品力的工程师,只是 AI 的操作员。

维度核心要点
同理心 (Empathy)脱离"技术自嗨",回归"用户感知"。工程师常沉迷于后端架构的完美重构(High Effort),却忽略前端模糊的报错提示(Low Effort)正让用户抓狂。
具备同理心的全栈懂得计算体验 ROI:优先解决阻碍用户达成目标的"可见障碍",而非盲目追求技术实现的"隐性完美"。
MVP 思维 (ROI 意识)精准识别"低成本高价值"的功能。在 AI 辅助下,快速构建最小可行性产品(MVP)验证假设,而非陷入过度设计的泥潭。
业务闭环不仅把功能做出来,还要考虑数据如何回流、用户如何增长。

2.3. AI (AI 杠杆):指数级倍增器

NOTE

旧模式:将 AI 视为搜索引擎的替代品或简单的代码补全工具。

新模式:AI 是你的数字员工、技能分身,是让个人产出这种线性增长变成指数增长的关键变量。

为什么 AI 处于乘数的位置?因为它是对上述两种能力的全方位放大

能力维度核心要点
技能树的补全利用 Cursor/Claude Code 等 AI 编程与 Agentic 工具,后端工程师可以写出像素级完美的前端 CSS,前端工程师可以编写复杂的 SQL 分析语句。AI 抹平了技术栈之间的专业门槛
上下文工程学会如何向 AI 提供高质量的上下文(Context),让 AI 理解你的项目结构、业务逻辑和编码规范,从而生成生产级代码。
时间压缩将从"Idea"到"Demo"的时间从数周压缩到数小时。这让"超级个体(Solo Maker)"成为可能——一个人就是一支队伍。

3. 从 Tech Stack 到 Insight Stack:进阶之路

全栈新时代架构图

过去的“全栈”是指 Tech Stack(技术栈) —— 我们在简历上堆砌的 React、Vue、NestJS、Python、Rust 等名词。

现在的“全栈”是指 Insight Stack(认知栈) —— 我们构建的是一套解决复杂问题的思维模型。

在新的范式下,我们的核心竞争力不再是精通具体的语言特性或掌握庞杂的框架细节——因为 AI 已是最好的“百科全书”与“熟练工”——而是转变为构建以下三层认知模型:

  1. 洞察层:具备 Product Sense,能够发现真实世界中值得解决的问题,并定义清楚需求的边界。
  2. 架构层:具备 Engineering Logic,能够设计出高可用、可扩展的技术方案,并指挥 AI 完成具体的模块实现。
  3. 杠杆层:具备 AI Quotient (AI商),熟练运用 LLM、RAG、Agents 等工具,将上述两层能力指数级放大。

AI 并没有以此消灭全栈工程师,它只是消灭了“平庸的搬运工”。它正在邀请我们,从“代码工人”进化为真正的“价值创造者”。

- - - - \ No newline at end of file diff --git "a/01.\345\205\250\346\240\210/01.AI Native \345\267\245\347\250\213\346\200\235\347\273\264/01.\344\270\215\346\255\242\344\272\216\344\273\243\347\240\201\357\274\232\346\236\204\345\273\272 AI \346\227\266\344\273\243\345\205\250\346\240\210\345\267\245\347\250\213\345\270\210\347\232\204\342\200\234\350\256\244\347\237\245\344\270\211\345\261\202\345\241\224\342\200\235.md" "b/01.\345\205\250\346\240\210/01.AI Native \345\267\245\347\250\213\346\200\235\347\273\264/01.\344\270\215\346\255\242\344\272\216\344\273\243\347\240\201\357\274\232\346\236\204\345\273\272 AI \346\227\266\344\273\243\345\205\250\346\240\210\345\267\245\347\250\213\345\270\210\347\232\204\342\200\234\350\256\244\347\237\245\344\270\211\345\261\202\345\241\224\342\200\235.md" deleted file mode 100644 index 7735102c..00000000 --- "a/01.\345\205\250\346\240\210/01.AI Native \345\267\245\347\250\213\346\200\235\347\273\264/01.\344\270\215\346\255\242\344\272\216\344\273\243\347\240\201\357\274\232\346\236\204\345\273\272 AI \346\227\266\344\273\243\345\205\250\346\240\210\345\267\245\347\250\213\345\270\210\347\232\204\342\200\234\350\256\244\347\237\245\344\270\211\345\261\202\345\241\224\342\200\235.md" +++ /dev/null @@ -1,102 +0,0 @@ ---- -url: /01.全栈/01.AI Native 工程思维/01.不止于代码:构建 AI 时代全栈工程师的“认知三层塔”.md -description: >- - 摘要总结:在 AI 重塑软件工程的今天,全栈不再是技术的线性叠加,正在从“技术栈堆砌”转向“认知栈重构”。本文提出 “(工程 + 产品) × AI” - 的新公式,助力开发者构建“洞察-架构-杠杆”认知三层塔,利用 AI 杠杆让自己进化为价值创造者。 ---- - -# 不止于代码:构建 AI 时代全栈工程师的“认知三层塔” - -> 摘要总结:在 AI 重塑软件工程的今天,全栈不再是技术的线性叠加,正在从“技术栈堆砌”转向“认知栈重构”。本文提出 “(工程 + 产品) × AI” 的新公式,助力开发者构建“洞察-架构-杠杆”认知三层塔,利用 AI 杠杆让自己进化为价值创造者。 - -## 1. 引言 - -在很长一段时间里,当我们谈论“全栈工程师”时,脑海中浮现的往往是一张冗长且令人疲惫的**技术工序清单**。 - -就像我曾经以为的那样,全栈就是**线性的技能叠加与物理式的技术拼接**,是一种依靠人力去填补技术鸿沟的“西西弗斯式”努力: - -* **线性的技能叠加**:我们被迫成为“全能手”,左手用 React/Vue 构建精美的 UI,右手用 Node/Go 编写高并发 API,中间还要处理数据库的 ACID 事务(整个链路基本是这样的:`构建前端 UI 交互 -> 编写后端业务API -> 维护底层数据存储与服务稳定`)。 -* **物理式的拼接**:我们试图用人力去掩盖技术栈之间的裂痕——用各种 Shell 脚本、Docker 配置、Nginx 转发规则,去粘合一个支离破碎的系统。 - -那个时候,我认为全栈的护城河在于“掌握编程语言的数量”。只要我能写前端、能写后端、偶尔还能写点 Python 爬虫,我就是全栈。我们都在拼命地做加法,试图把自己打磨成一把无所不能的瑞士军刀。 - -但在 AI 彻底重构代码生产方式的今天,这个定义显得过时且**狭隘**。当 GPT5/Claude Code/Cursor 等能够在一分钟内生成高质量的 CRUD 代码,甚至自动完成单元测试时,我们掌握语言、语法的价值又还剩多少?如果一个人就能通过 AI 完成一支团队的工作,那么“全栈”的边界到底在哪里? - -真正的全栈,已经**从“技能的物理叠加” 进化到了 “价值的化学闭环”**。如果一个人通过 AI 就能完成过去一支团队的交付量,那么“全栈”的边界就不再是技术栈(Tech Stack),而是认知栈(Insight Stack)。 - -| 维度 | 旧全栈 (Legacy Full Stack) | 新全栈 (AI-Native Full Stack) | -| :--- | :--- | :--- | -| **关注点** | 语言、框架、语法 (Tools) | **问题、场景、价值 (Value)** | -| **核心能力** | 纯手工编码 (Coding) | **架构设计、Prompt 工程、代码审查 (Architecting)** | -| **交付边界** | 前端页面 + 后端接口 | 需求洞察 $\rightarrow$ 产品设计 $\rightarrow$ 落地运营 | -| **AI 的角色** | 辅助工具 (Copilot) | **核心引擎与分身 (Co-founder)** | - -## 2. AI 时代的全栈新公式 - -在重新思考技术演进的逻辑后,笔者思考出了一个更具现代感的全栈价值公式。这不仅仅是技能的组合,更是思维模型的重构: - -$$ -\mathbf{Full\ Stack} ; = ; (\mathbf{Engineering} ; + ; \mathbf{Product}) ; \times ; \mathbf{AI} -$$ - -这个公式告诉我们:不要再执着于手里有多少把锤子,而要关注**你能构建出怎样的建筑**,AI 是那个能够让工程能力和产品思维产生**指数级爆炸**的乘数。 - -### 2.1. Engineering (工程力):从“困于实现”到“敢于设计” - -:::note 新旧模式对比: -**旧模式**:熟练记忆 API,手写大量样板代码,关注具体的语言和语法细节。 - -**新模式**:具备系统级视野,关注架构的健壮性、可维护性以及自动化交付体系。 -::: - -在 AI 时代,工程力的内核发生了迁移,AI 在逐渐接管 `How`(怎么写代码),人类必须专注于 `What`(做什么系统)和 `Why`(为什么这样设计)。 -| 能力维度 | 核心要点 | -|:---|:---| -| **架构决策** | 当代码生成变得廉价,架构决策变得昂贵。是选择单体还是微服务?是 SQL 还是 NoSQL?这些决定了系统的上限。 | -| **代码审计与验收** | 你从"写作者"变成了"编辑"和"审计员",当 AI 帮你写完 80% 的代码后,你是否有能力调试剩下那 20% 最隐蔽的逻辑漏洞? | -| **DevOps 与交付** | 工程力不再止步于 `localhost`,它意味着你能利用 Docker、K8s、CI/CD 乃至 Serverless,将代码安全、稳定地送达线上,并将产品交付到用户手中。 | - -### 2.2. Product (产品力):从“需求翻译机”到“价值定义者” - -:::note 新旧模式对比: -**旧模式**:被动接收需求文档,关注功能的按时上线。 - -**新模式**:理解商业模式与用户痛点,能判断“做什么”比“怎么做”更重要。 -::: - -产品力是技术人员最容易忽视,但在公式中权重极高的变量,它与工程力是**相加**关系——没有产品力的工程师,只是 AI 的操作员。 - -| 维度 | 核心要点 | -|:---|:---| -| **同理心 (Empathy)** | 脱离"技术自嗨",回归"用户感知"。工程师常沉迷于后端架构的完美重构(High Effort),却忽略前端模糊的报错提示(Low Effort)正让用户抓狂。 具备同理心的全栈懂得计算体验 ROI:优先解决阻碍用户达成目标的"可见障碍",而非盲目追求技术实现的"隐性完美"。 | -| **MVP 思维 (ROI 意识)** | 精准识别"低成本高价值"的功能。在 AI 辅助下,快速构建最小可行性产品(MVP)验证假设,而非陷入过度设计的泥潭。 | -| **业务闭环** | 不仅把功能做出来,还要考虑数据如何回流、用户如何增长。 | - -### 2.3. AI (AI 杠杆):指数级倍增器 - -:::note -**旧模式**:将 AI 视为搜索引擎的替代品或简单的代码补全工具。 - -**新模式**:AI 是你的数字员工、技能分身,是让个人产出这种线性增长变成指数增长的关键变量。 -::: - -为什么 AI 处于乘数的位置?因为它是对上述两种能力的**全方位放大**: -| 能力维度 | 核心要点 | -|:---|:---| -| **技能树的补全** | 利用 Cursor/Claude Code 等 AI 编程与 Agentic 工具,后端工程师可以写出像素级完美的前端 CSS,前端工程师可以编写复杂的 SQL 分析语句。*AI 抹平了技术栈之间的专业门槛*。 | -| **上下文工程** | 学会如何向 AI 提供高质量的上下文(Context),让 AI 理解你的项目结构、业务逻辑和编码规范,从而生成生产级代码。 | -| **时间压缩** | 将从"Idea"到"Demo"的时间从数周压缩到数小时。这让"超级个体(Solo Maker)"成为可能——一个人就是一支队伍。 | - -## 3. 从 Tech Stack 到 Insight Stack:进阶之路 - -过去的“全栈”是指 **Tech Stack(技术栈)** —— 我们在简历上堆砌的 React、Vue、NestJS、Python、Rust 等名词。 - -现在的“全栈”是指 **Insight Stack(认知栈)** —— 我们构建的是一套解决复杂问题的思维模型。 - -在新的范式下,我们的核心竞争力不再是精通具体的语言特性或掌握庞杂的框架细节——因为 AI 已是最好的“百科全书”与“熟练工”——而是转变为构建以下三层认知模型: - -1. **洞察层**:具备 Product Sense,能够发现真实世界中值得解决的问题,并定义清楚需求的边界。 -2. **架构层**:具备 Engineering Logic,能够设计出高可用、可扩展的技术方案,并指挥 AI 完成具体的模块实现。 -3. **杠杆层**:具备 AI Quotient (AI商),熟练运用 LLM、RAG、Agents 等工具,将上述两层能力指数级放大。 - -AI 并没有以此消灭全栈工程师,它只是消灭了“平庸的搬运工”。它正在邀请我们,从“代码工人”进化为真正的“价值创造者”。 diff --git "a/01.\345\205\250\346\240\210/01.AI Native \345\267\245\347\250\213\346\200\235\347\273\264/02.\351\207\215\346\236\204\345\274\200\345\217\221\350\200\205\357\274\232AI \346\227\266\344\273\243\344\270\213\347\232\204\345\267\245\347\250\213\345\270\210\350\203\275\345\212\233\345\233\276\350\260\261\344\270\216\346\274\224\350\277\233\346\214\207\345\215\227.html" "b/01.\345\205\250\346\240\210/01.AI Native \345\267\245\347\250\213\346\200\235\347\273\264/02.\351\207\215\346\236\204\345\274\200\345\217\221\350\200\205\357\274\232AI \346\227\266\344\273\243\344\270\213\347\232\204\345\267\245\347\250\213\345\270\210\350\203\275\345\212\233\345\233\276\350\260\261\344\270\216\346\274\224\350\277\233\346\214\207\345\215\227.html" deleted file mode 100644 index 38752ed0..00000000 --- "a/01.\345\205\250\346\240\210/01.AI Native \345\267\245\347\250\213\346\200\235\347\273\264/02.\351\207\215\346\236\204\345\274\200\345\217\221\350\200\205\357\274\232AI \346\227\266\344\273\243\344\270\213\347\232\204\345\267\245\347\250\213\345\270\210\350\203\275\345\212\233\345\233\276\350\260\261\344\270\216\346\274\224\350\277\233\346\214\207\345\215\227.html" +++ /dev/null @@ -1,178 +0,0 @@ - - - - - - 重构开发者:AI 时代下的工程师能力图谱与演进指南 | Insight Stack - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Skip to content
3614
- - - - 12.9m

重构开发者:AI 时代下的工程师能力图谱与演进指南

摘要总结:当 AI 极速降低代码编写门槛,单纯的“业务代码翻译器”角色正加速贬值。本文从技术演进与产品思考的交汇点出发,将 AI 时代的开发者能力图谱重新划分为三大核心圈层:产品应用层(Insight Stack)、Agent 开发层与 AI 基础设施层。无论你是深耕视图层交互、精通 Node.js 等服务端架构的开发者,还是致力于技术落地的探索者,都能在这份演进指南中找到打破能力边界、向“超级个体”与“AI 智能体指挥官”跃迁的破局之道。

about site background

如果你对近两年的技术浪潮保持敏感,大概会得出一个有些残酷但无比真实的结论:代码正在发生“通货膨胀”。随着大模型编程能力的指数级跃升,纯粹的“将业务逻辑翻译成代码”这项技能的溢价正在快速衰减。当 AI 能在几秒钟内吐出包含完整类型定义、错误处理和测试用例的后端接口或是 React 组件时,软件工程师的护城河究竟在哪里?

行业的演进给出了答案:开发者的角色正在经历一次彻底的重构。我们正在从“代码的编写者”转变为“系统的架构者”与“AI 智能体的指挥官”。结合当下的工业界实践,我们可以将 AI 时代的工程师图谱清晰地划分为三大核心圈层:产品应用层、Agent 开发层与 AI 基础设施层

1. 产品应用层(Insight Stack):走向“超级个体”的 AI 原生全栈

核心壁垒:技术视野 + 产品敏锐度 + 极速的架构组装能力,能够单枪匹马或带领极小团队,将一个灵感迅速转化为高可用产品。

在 AI 极大地降低了代码编写门槛的今天,“决定做什么”和“如何利用 AI 构建系统”的价值,已经逐渐超越了“纯手工敲击代码”的价值。这或许是传统前端、后端开发者转型最顺滑、也最能释放巨大商业价值的一层。

在这一层,“全栈工程师”的定义被重新改写为“产品工程师(Product Engineer)”。技术栈不再仅仅是前端框架和数据库,而是包含了“产品 Sense”与“商业洞察”的 Insight Stack。全栈工程师也正在进化为“超级个体”或“产品工程师(Product Engineer)”。问题发现 -> 创意沉淀 -> AI 辅助技术方案 -> AI 驱动代码生成 这一闭环,正是当前最高效的独立开发或小团队敏捷开发范式。

1.1 产品 Sense 与业务洞察

过去,工程师往往是被动接收 PRD。而在 AI 时代,技术门槛的降低意味着工程师可以随时将生活和工作中的“灵感碎片”与“痛点捕获”转化为产品创意。我们需要具备极其敏锐的 AI 边界认知,明确知道哪些场景适合用传统的 CRUD 解决,哪些必须交由 LLM 去处理模糊与非确定性。

在产品应用层,我们还需要具备数据飞轮意识,注重在应用层设计埋点,收集用户的交互与纠错数据,为后续的 Agentic workflow 优化或模型微调提供高质量数据源。

1.2 Agentic Engineering(智能体工程)

这是一种全新的开发范式,开发者不再逐行手敲代码,而是通过撰写严谨的 Spec、利用 TDD(测试驱动开发)和 Lint 强约束,去“驱动”和“管理” AI 编程助手(如 Claude Code、Cursor),全栈基础设施的范畴也扩展到了跨端轻量化应用(例如利用前端技术栈快速构建高价值的浏览器插件)。

能力维度具体要求
规划、设计与迭代能力• 能够快速响应业务需求,规划产品功能,完成技术架构的调研、选型与整体设计。
• 能借助 AI 进行前端视图层、Node.js 后端核心数据流、业务流程的顶层设计。
• 不但能单枪匹马或带领极小团队中的人,还懂得领导、管理 AI 数字员工。
AI 驱动编程基于 Spec、TDD、Hooks(Lint 检查)等强约束机制,驱动 Claude Code / Copilot 等工具生成高规范度代码。
全栈基础设施熟练掌握传统架构体系(数据库选型、Redis、微服务、消息队列),以及跨端/轻量化形态(如 Chrome 插件生态)的工程搭建。
DevOps现代化的自动化部署、CI/CD 流水线搭建与运维。

1.3 AI-First 的交互哲学

AI 应用的体验与传统软件截然不同。为了对抗大模型的延迟与幻觉,工程师必须掌握流式渲染(Streaming UI)、生成式 UI(Generative UI)等新一代交互模式,用优雅的工程设计兜底 AI 的不确定性。

  • 流式渲染(Streaming UI):优化大模型响应的等待体验。
  • 生成式交互(Generative UI):在前端框架(如 React / Next.js)中,根据 AI 返回的结构化状态实时渲染出最合适的交互组件,而非死板的对话框。
  • 容错与兜底机制:优雅处理大模型幻觉(Hallucination),降低用户的挫败感。

2. Agent 开发层:构建连接物理世界的数字中枢

核心壁垒:标准化模块组装 + 复杂 Agentic Workflow 编排 + 严谨的评测体系,这一层负责为 AI 赋予记忆、手脚和专业领域的知识,是连接“底层模型大脑”与“上层应用交互”的核心枢纽。

如果说大模型是大脑,那么 Agent 工程师就是为这个大脑装上“四肢”、“记忆”和“专业工具”的人,这是一个正在爆发的新兴领域,也是实现 AI 业务落地的核心枢纽

2.1 Agentic Workflow 设计

能力维度具体要求
任务拆解与路由基于 CoT(思维链)等技术工程的任务拆解与路由机制,针对不同复杂度的工作流设计稳健的多 Agent 协作与分发机制。
设计模式与编排熟练应用 ReAct、Plan-and-Execute 等智能体设计模式,针对不同的业务场景(如信息爬取、长文总结过滤等自动化处理),设计稳健的多 Agent 协作与路由流。
主流 Agent 框架的核心机制与实战落地熟悉并掌握如 Claude Agent SDK、LangChain、AutoGen 等主流 Agent 框架的核心机制,能够在实际项目中灵活应用,解决复杂的业务场景。

2.2 记忆机制(Memory Management)

要让 Agent 变得“好用”,必须解决上下文遗忘和知识幻觉的问题。这就要求工程师深谙长期记忆/短期记忆的协同管理,以及复杂文档的切块(Chunking)、向量化(Embedding)和混合检索(Hybrid Search)技术。

  • 短期记忆:精准控制 Context Window,进行 Prompt 截断与摘要,即上下文工程能力。
  • 长期记忆:基于图数据库或向量库,持久化存储用户画像与历史交互状态。

2.3 技能的插件化(Agent Skill)

Agent Skill 是由 Anthropic 提出并推动的一种开放式标准,旨在将特定领域的知识、工作流、指令和脚本打包封装成的标准化、模块化资源包,让 AI Agent 按需动态加载这些技能,实现从通用助手向特定任务专家(如代码审计、法律文件分析)的无缝转变。

  • 结构化封装:以目录形式组织(如含 SKILL.md 的文件夹),包含详细的执行规则。
  • 渐进披露 & 按需调用:Agent 仅在处理相关任务时动态激活这些能力,无需每次提示都包含所有技能。
  • 可重用与组合:技能可多次重复使用,或多个技能组合处理复杂流程。

无论是长文抓取、摘要提取还是打标签,都可以被封装为独立的 Skill,在复杂的 Workflow 中被 Agent 动态挂载,即插即用,在构建特定场景的 Agent(例如专注于技术资讯处理的知识管理助手)时,能够像搭积木一样,根据当前任务的上下文动态加载所需的 Skills,从而大幅提升 Agent 的泛化能力和开发效率。

2.4 从硬编码到标准协议与上下文连接

随着 MCP(Model Context Protocol)等标准化协议的成熟,Agent 开发正在摆脱杂乱的胶水代码。我们可以利用熟悉的后端生态(如 Node.js)构建 MCP Server,让 AI 安全、统一地读取外部 API 或是企业内部知识库,打破信息孤岛。

  • 统一数据接入层:不再需要为每一个数据源(如 Notion、本地文件系统、特定的研发工具或外部 API)手写杂乱的胶水代码。通过实现和接入 MCP Server,为大模型提供一套标准化的双向通信协议。
  • 跨生态与端侧集成:能够利用 Node.js 等熟悉的后端生态快速构建 MCP 服务,让大模型统一、安全地读取多源上下文。这对于开发跨端的 AI 应用(如在浏览器插件中打破沙盒限制,直接与本地或云端知识库联动)至关重要。

2.5 模型选型、路由与可观测性

  • 动态 API 路由:在成本与性能之间取舍,灵活调度国内外大模型(Claude、Gemini、GPT-4,以及国内的 DeepSeek、GLM、MiniMax、Qwen等)。
  • Agent 监控:构建测试集(Eval),监控链路执行过程(Tracing),分析 Token 消耗与步骤延迟。

2.6 EDD(评估驱动开发)重塑工程质量

在 Agent 开发中,大模型的输出具有非确定性,如果说开发 Agent 只是完成了从 0 到 1 的“能用”,那么构建完善的评测体系,就是解决从 1 到 100 的“好用”与“敢用”的核心壁垒。成熟的 Agent 工程师必须建立系统的评测与监控体系(Observability),通过构建黄金测试集(Golden Dataset)、引入 LLM-as-a-Judge,以及精确到 Token 级的链路追踪(Tracing),将“感觉不错”的玄学转化为可量化的工程指标。

能力维度具体要求
自动化评测驱动 (EDD)摒弃"肉眼看效果"的游击战,建立特定场景的 Golden Dataset(基准测试集),熟练引入 Promptfoo、Ragas 等评估框架,将评测无缝融入 CI/CD 流水线。
多维指标体系设计针对具体任务(如长文总结、内容归类),设计并量化诸如事实一致性 (Faithfulness)、答案相关性 (Answer Relevance)、幻觉率 (Hallucination Rate) 等核心指标。
LLM-as-a-Judge 与人工对齐使用强模型(如 Claude 4.6/GPT)来批量自动评测弱模型或 Agent 的输出质量,并在关键节点结合 HITL(Human-in-the-loop,人机协同)进行人工微调与对齐。
链路追踪与归因 (Tracing)面对多 Agent 协作或复杂的 RAG 链路,熟练使用 LangSmith、Langfuse 等可观测性工具,记录每一次工具调用、Prompt 组装耗时和 Token 消耗,精准定位 Bad Case 的根因。

3. AI 基础设施层:算力与模型的重工业底座

核心壁垒:深厚的底层算法素养 + 极致的性能压榨 + 大规模分布式系统经验。这一层是 AI 时代的“重工业”底座,负责打造和打磨基础模型,并提供极致性价比的算力支撑。

技术工程背景的工程师可暂时只关注于模型预备训练、后训练、推理等放面的原理与流程,以及如何在大规模分布式系统上高效部署和运行这些模型,而无需深入理解底层的分布式系统和计算架构。

如果前两层是造车和开车的,这一层就是修路和提炼石油的。这属于 AI 的“重工业”,门槛极高,主要由具备深厚算法背景和底层工程能力的顶级大厂或 AI Native 独角兽主导。

能力维度具体要求
模型精炼与对齐随着开源基座模型的强大,预训练已不再是唯一解。后训练(Post-training)阶段的变得至关重要,通过 RL(强化学习)、SFT(监督微调)、RLHF/DPO(人类偏好对齐),将通用模型打磨成特定领域(如代码生成、逻辑推理)的专家。
极致的推理优化随着模型越大,成本越高。熟练掌握 vLLM 等高性能推理框架,运用量化技术(如 FP8/INT4)、KV Cache 优化(如 PagedAttention),在不牺牲精度的前提下榨干每一滴 GPU 算力。
LLMOps 与算力调度在万卡级别的 GPU 集群上,处理节点故障、实现资源负载均衡和容灾恢复,保障极其昂贵的算力资源不被浪费。

4. 找准自己的生态位

面对这股重塑整个行业的洪流,焦虑是本能,但进阶才是解药。

对于绝大多数有着丰富 Web 开发经验(无论是精通前端交互,还是深谙 Node.js/Golang/Java 等后端架构)的工程师而言,“产品应用层”和“Agent 开发层”不仅是最具性价比的切入点,更是能够最大化杠杆原有技能的沃土

我们不应该将自己局限在“写代码的机器”这一狭窄定义中。尝试用产品 Sense 发现问题,用 AI 编程工具快速实现 MVP,用标准的 Agent skills、MCP 协议和高阶 Agentic workflow 设计赋予应用专业深度。

AI 不会淘汰开发者,只会淘汰那些拒绝使用 AI 来放大自身产品价值的开发者。在技术通缩的时代,唯有洞察力和对业务流的把控力,才能迎来真正的价值膨胀。

- - - - \ No newline at end of file diff --git "a/01.\345\205\250\346\240\210/01.AI Native \345\267\245\347\250\213\346\200\235\347\273\264/02.\351\207\215\346\236\204\345\274\200\345\217\221\350\200\205\357\274\232AI \346\227\266\344\273\243\344\270\213\347\232\204\345\267\245\347\250\213\345\270\210\350\203\275\345\212\233\345\233\276\350\260\261\344\270\216\346\274\224\350\277\233\346\214\207\345\215\227.md" "b/01.\345\205\250\346\240\210/01.AI Native \345\267\245\347\250\213\346\200\235\347\273\264/02.\351\207\215\346\236\204\345\274\200\345\217\221\350\200\205\357\274\232AI \346\227\266\344\273\243\344\270\213\347\232\204\345\267\245\347\250\213\345\270\210\350\203\275\345\212\233\345\233\276\350\260\261\344\270\216\346\274\224\350\277\233\346\214\207\345\215\227.md" deleted file mode 100644 index 319cf1d8..00000000 --- "a/01.\345\205\250\346\240\210/01.AI Native \345\267\245\347\250\213\346\200\235\347\273\264/02.\351\207\215\346\236\204\345\274\200\345\217\221\350\200\205\357\274\232AI \346\227\266\344\273\243\344\270\213\347\232\204\345\267\245\347\250\213\345\270\210\350\203\275\345\212\233\345\233\276\350\260\261\344\270\216\346\274\224\350\277\233\346\214\207\345\215\227.md" +++ /dev/null @@ -1,126 +0,0 @@ ---- -url: /01.全栈/01.AI Native 工程思维/02.重构开发者:AI 时代下的工程师能力图谱与演进指南.md -description: >- - 摘要总结:当 AI 极速降低代码编写门槛,单纯的“业务代码翻译器”角色正加速贬值。本文从技术演进与产品思考的交汇点出发,将 AI - 时代的开发者能力图谱重新划分为三大核心圈层:产品应用层(Insight Stack)、Agent 开发层与 AI 基础设施层。无论你是深耕视图层交互、精通 - Node.js 等服务端架构的开发者,还是致力于技术落地的探索者,都能在这份演进指南中找到打破能力边界、向“超级个体”与“AI - 智能体指挥官”跃迁的破局之道。 ---- - -# 重构开发者:AI 时代下的工程师能力图谱与演进指南 - -> **摘要总结**:当 AI 极速降低代码编写门槛,单纯的“业务代码翻译器”角色正加速贬值。本文从技术演进与产品思考的交汇点出发,将 AI 时代的开发者能力图谱重新划分为三大核心圈层:**产品应用层(Insight Stack)、Agent 开发层与 AI 基础设施层**。无论你是深耕视图层交互、精通 Node.js 等服务端架构的开发者,还是致力于技术落地的探索者,都能在这份演进指南中找到打破能力边界、向“超级个体”与“AI 智能体指挥官”跃迁的破局之道。 - -如果你对近两年的技术浪潮保持敏感,大概会得出一个有些残酷但无比真实的结论:**代码正在发生“通货膨胀”**。随着大模型编程能力的指数级跃升,纯粹的“将业务逻辑翻译成代码”这项技能的溢价正在快速衰减。当 AI 能在几秒钟内吐出包含完整类型定义、错误处理和测试用例的后端接口或是 React 组件时,软件工程师的护城河究竟在哪里? - -行业的演进给出了答案:开发者的角色正在经历一次彻底的重构。我们正在**从“代码的编写者”转变为“系统的架构者”与“AI 智能体的指挥官”**。结合当下的工业界实践,我们可以将 AI 时代的工程师图谱清晰地划分为三大核心圈层:**产品应用层、Agent 开发层与 AI 基础设施层**。 - -## 1. 产品应用层(Insight Stack):走向“超级个体”的 AI 原生全栈 - -> **核心壁垒:技术视野 + 产品敏锐度 + 极速的架构组装能力**,能够单枪匹马或带领极小团队,将一个灵感迅速转化为高可用产品。 - -在 AI 极大地降低了代码编写门槛的今天,**“决定做什么”和“如何利用 AI 构建系统”的价值,已经逐渐超越了“纯手工敲击代码”的价值**。这或许是传统前端、后端开发者转型最顺滑、也最能释放巨大商业价值的一层。 - -在这一层,“全栈工程师”的定义被重新改写为“产品工程师(Product Engineer)”。**技术栈不再仅仅是前端框架和数据库,而是包含了“产品 Sense”与“商业洞察”的 Insight Stack**。全栈工程师也正在进化为“超级个体”或“产品工程师(Product Engineer)”。问题发现 -> 创意沉淀 -> AI 辅助技术方案 -> AI 驱动代码生成 这一闭环,正是当前最高效的独立开发或小团队敏捷开发范式。 - -### 1.1 产品 Sense 与业务洞察 - -过去,工程师往往是被动接收 PRD。而在 AI 时代,技术门槛的降低意味着工程师可以随时将生活和工作中的“灵感碎片”与“痛点捕获”转化为产品创意。我们需要具备极其敏锐的 AI 边界认知,明确知道哪些场景适合用传统的 CRUD 解决,哪些必须交由 LLM 去处理模糊与非确定性。 - -在产品应用层,我们还需要具备数据飞轮意识,注重在应用层设计埋点,收集用户的交互与纠错数据,为后续的 Agentic workflow 优化或模型微调提供高质量数据源。 - -### 1.2 Agentic Engineering(智能体工程) - -这是一种全新的开发范式,开发者不再逐行手敲代码,而是通过撰写严谨的 Spec、利用 TDD(测试驱动开发)和 Lint 强约束,去“驱动”和“管理” AI 编程助手(如 Claude Code、Cursor),全栈基础设施的范畴也扩展到了跨端轻量化应用(例如利用前端技术栈快速构建高价值的浏览器插件)。 - -| 能力维度 | 具体要求 | -|---------|---------| -| **规划、设计与迭代能力** | • 能够快速响应业务需求,规划产品功能,完成技术架构的调研、选型与整体设计。 • 能借助 AI 进行前端视图层、Node.js 后端核心数据流、业务流程的顶层设计。• 不但能单枪匹马或带领极小团队中的人,还懂得领导、管理 AI 数字员工。 | -| **AI 驱动编程** | 基于 Spec、TDD、Hooks(Lint 检查)等强约束机制,驱动 Claude Code / Copilot 等工具生成高规范度代码。 | -| **全栈基础设施** | 熟练掌握传统架构体系(数据库选型、Redis、微服务、消息队列),以及跨端/轻量化形态(如 Chrome 插件生态)的工程搭建。 | -| **DevOps** | 现代化的自动化部署、CI/CD 流水线搭建与运维。 | - -### 1.3 AI-First 的交互哲学 - -AI 应用的体验与传统软件截然不同。为了对抗大模型的延迟与幻觉,工程师必须掌握流式渲染(Streaming UI)、生成式 UI(Generative UI)等新一代交互模式,用优雅的工程设计兜底 AI 的不确定性。 - -* **流式渲染(Streaming UI)**:优化大模型响应的等待体验。 -* **生成式交互(Generative UI)**:在前端框架(如 React / Next.js)中,根据 AI 返回的结构化状态实时渲染出最合适的交互组件,而非死板的对话框。 -* **容错与兜底机制**:优雅处理大模型幻觉(Hallucination),降低用户的挫败感。 - -## 2. Agent 开发层:构建连接物理世界的数字中枢 - -> **核心壁垒:标准化模块组装 + 复杂 Agentic Workflow 编排 + 严谨的评测体系**,这一层负责**为 AI 赋予记忆、手脚和专业领域的知识**,是连接“底层模型大脑”与“上层应用交互”的核心枢纽。 - -如果说大模型是大脑,那么 Agent 工程师就是为这个大脑装上“四肢”、“记忆”和“专业工具”的人,这是**一个正在爆发的新兴领域,也是实现 AI 业务落地的核心枢纽**。 - -### 2.1 Agentic Workflow 设计 - -| 能力维度 | 具体要求 | -|---------|---------| -| **任务拆解与路由** | 基于 CoT(思维链)等技术工程的任务拆解与路由机制,针对不同复杂度的工作流设计稳健的多 Agent 协作与分发机制。 | -| **设计模式与编排** | 熟练应用 ReAct、Plan-and-Execute 等智能体设计模式,针对不同的业务场景(如信息爬取、长文总结过滤等自动化处理),设计稳健的多 Agent 协作与路由流。 | -| **主流 Agent 框架的核心机制与实战落地** | 熟悉并掌握如 Claude Agent SDK、LangChain、AutoGen 等主流 Agent 框架的核心机制,能够在实际项目中灵活应用,解决复杂的业务场景。 | - -### 2.2 记忆机制(Memory Management) - -要让 Agent 变得“好用”,必须解决上下文遗忘和知识幻觉的问题。这就**要求工程师深谙长期记忆/短期记忆的协同管理,以及复杂文档的切块(Chunking)、向量化(Embedding)和混合检索(Hybrid Search)技术。** - -* **短期记忆**:精准控制 Context Window,进行 Prompt 截断与摘要,即上下文工程能力。 -* **长期记忆**:基于图数据库或向量库,持久化存储用户画像与历史交互状态。 - -### 2.3 技能的插件化(Agent Skill) - -Agent Skill 是由 Anthropic 提出并推动的一种开放式标准,旨在**将特定领域的知识、工作流、指令和脚本打包封装成的标准化、模块化资源包**,让 AI Agent 按需动态加载这些技能,实现从通用助手向特定任务专家(如代码审计、法律文件分析)的无缝转变。 - -* **结构化封装**:以目录形式组织(如含 `SKILL.md` 的文件夹),包含详细的执行规则。 -* **渐进披露 & 按需调用**:Agent 仅在处理相关任务时动态激活这些能力,无需每次提示都包含所有技能。 -* **可重用与组合**:技能可多次重复使用,或多个技能组合处理复杂流程。 - -无论是长文抓取、摘要提取还是打标签,都可以被封装为独立的 Skill,在复杂的 Workflow 中被 Agent 动态挂载,即插即用,在构建特定场景的 Agent(例如专注于技术资讯处理的知识管理助手)时,能够像搭积木一样,根据当前任务的上下文动态加载所需的 Skills,从而大幅提升 Agent 的泛化能力和开发效率。 - -### 2.4 从硬编码到标准协议与上下文连接 - -随着 MCP(Model Context Protocol)等标准化协议的成熟,Agent 开发正在摆脱杂乱的胶水代码。我们可以利用熟悉的后端生态(如 Node.js)构建 MCP Server,让 AI 安全、统一地读取外部 API 或是企业内部知识库,打破信息孤岛。 - -* **统一数据接入层**:不再需要为每一个数据源(如 Notion、本地文件系统、特定的研发工具或外部 API)手写杂乱的胶水代码。通过实现和接入 MCP Server,为大模型提供一套标准化的双向通信协议。 -* **跨生态与端侧集成**:能够利用 Node.js 等熟悉的后端生态快速构建 MCP 服务,让大模型统一、安全地读取多源上下文。这对于开发跨端的 AI 应用(如在浏览器插件中打破沙盒限制,直接与本地或云端知识库联动)至关重要。 - -### 2.5 模型选型、路由与可观测性 - -* **动态 API 路由**:在成本与性能之间取舍,灵活调度国内外大模型(Claude、Gemini、GPT-4,以及国内的 DeepSeek、GLM、MiniMax、Qwen等)。 -* **Agent 监控**:构建测试集(Eval),监控链路执行过程(Tracing),分析 Token 消耗与步骤延迟。 - -### 2.6 EDD(评估驱动开发)重塑工程质量 - -在 Agent 开发中,大模型的输出具有非确定性,如果说开发 Agent 只是完成了从 0 到 1 的“能用”,那么**构建完善的评测体系,就是解决从 1 到 100 的“好用”与“敢用”的核心壁垒**。成熟的 Agent 工程师必须建立系统的评测与监控体系(Observability),通过构建黄金测试集(Golden Dataset)、引入 LLM-as-a-Judge,以及精确到 Token 级的链路追踪(Tracing),将“感觉不错”的玄学转化为可量化的工程指标。 -| 能力维度 | 具体要求 | -|---------|---------| -| **自动化评测驱动 (EDD)** | 摒弃"肉眼看效果"的游击战,建立特定场景的 Golden Dataset(基准测试集),熟练引入 Promptfoo、Ragas 等评估框架,将评测无缝融入 CI/CD 流水线。 | -| **多维指标体系设计** | 针对具体任务(如长文总结、内容归类),设计并量化诸如事实一致性 (Faithfulness)、答案相关性 (Answer Relevance)、幻觉率 (Hallucination Rate) 等核心指标。 | -| **LLM-as-a-Judge 与人工对齐** | 使用强模型(如 Claude 4.6/GPT)来批量自动评测弱模型或 Agent 的输出质量,并在关键节点结合 HITL(Human-in-the-loop,人机协同)进行人工微调与对齐。 | -| **链路追踪与归因 (Tracing)** | 面对多 Agent 协作或复杂的 RAG 链路,熟练使用 LangSmith、Langfuse 等可观测性工具,记录每一次工具调用、Prompt 组装耗时和 Token 消耗,精准定位 Bad Case 的根因。 | - -## 3. AI 基础设施层:算力与模型的重工业底座 - -> \*\*核心壁垒:\*\*深厚的底层算法素养 + 极致的性能压榨 + 大规模分布式系统经验。这一层是 AI 时代的“重工业”底座,负责打造和打磨基础模型,并提供极致性价比的算力支撑。 -> -> 技术工程背景的工程师可暂时只关注于模型预备训练、后训练、推理等放面的原理与流程,以及如何在大规模分布式系统上高效部署和运行这些模型,而无需深入理解底层的分布式系统和计算架构。 - -如果前两层是造车和开车的,这一层就是修路和提炼石油的。这属于 AI 的“重工业”,门槛极高,主要由具备深厚算法背景和底层工程能力的顶级大厂或 AI Native 独角兽主导。 - -| 能力维度 | 具体要求 | -|---------|---------| -| **模型精炼与对齐** | 随着开源基座模型的强大,预训练已不再是唯一解。后训练(Post-training)阶段的变得至关重要,通过 RL(强化学习)、SFT(监督微调)、RLHF/DPO(人类偏好对齐),将通用模型打磨成特定领域(如代码生成、逻辑推理)的专家。 | -| **极致的推理优化** | 随着模型越大,成本越高。熟练掌握 vLLM 等高性能推理框架,运用量化技术(如 FP8/INT4)、KV Cache 优化(如 PagedAttention),在不牺牲精度的前提下榨干每一滴 GPU 算力。 | -| **LLMOps 与算力调度** | 在万卡级别的 GPU 集群上,处理节点故障、实现资源负载均衡和容灾恢复,保障极其昂贵的算力资源不被浪费。 | - -## 4. 找准自己的生态位 - -> 面对这股重塑整个行业的洪流,焦虑是本能,但进阶才是解药。 - -对于绝大多数有着丰富 Web 开发经验(无论是精通前端交互,还是深谙 Node.js/Golang/Java 等后端架构)的工程师而言,**“产品应用层”和“Agent 开发层”不仅是最具性价比的切入点,更是能够最大化杠杆原有技能的沃土**。 - -我们不应该将自己局限在“写代码的机器”这一狭窄定义中。尝试用产品 Sense 发现问题,用 AI 编程工具快速实现 MVP,用标准的 Agent skills、MCP 协议和高阶 Agentic workflow 设计赋予应用专业深度。 - -AI 不会淘汰开发者,只会淘汰那些拒绝使用 AI 来放大自身产品价值的开发者。在技术通缩的时代,唯有洞察力和对业务流的把控力,才能迎来真正的价值膨胀。 diff --git "a/01.\345\205\250\346\240\210/01.AI Native \345\267\245\347\250\213\346\200\235\347\273\264/10.\350\257\273 Anthropic \347\240\224\347\251\266\346\212\245\345\221\212\357\274\214\346\216\242\345\257\273 AI \346\227\266\344\273\243\347\232\204\345\267\245\347\250\213\350\214\203\345\274\217\351\207\215\345\241\221.html" "b/01.\345\205\250\346\240\210/01.AI Native \345\267\245\347\250\213\346\200\235\347\273\264/10.\350\257\273 Anthropic \347\240\224\347\251\266\346\212\245\345\221\212\357\274\214\346\216\242\345\257\273 AI \346\227\266\344\273\243\347\232\204\345\267\245\347\250\213\350\214\203\345\274\217\351\207\215\345\241\221.html" deleted file mode 100644 index 5f210003..00000000 --- "a/01.\345\205\250\346\240\210/01.AI Native \345\267\245\347\250\213\346\200\235\347\273\264/10.\350\257\273 Anthropic \347\240\224\347\251\266\346\212\245\345\221\212\357\274\214\346\216\242\345\257\273 AI \346\227\266\344\273\243\347\232\204\345\267\245\347\250\213\350\214\203\345\274\217\351\207\215\345\241\221.html" +++ /dev/null @@ -1,178 +0,0 @@ - - - - - - 读 Anthropic 研究报告,探寻 AI 时代的工程范式重塑 | Insight Stack - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Skip to content
4407
- - - - 15.2m

读 Anthropic 研究报告,探寻 AI 时代的工程范式重塑

摘要总结:软件工程正经历从“手写逻辑”向“意图调度”的范式迁徙。Anthropic 的研究揭示了 AI 并非简单的提效工具,而是通过释放 27% 曾经“不划算”的工程任务,重塑了软件质量的密度。在自然语言即编程语言的时代,我们需要通过规格驱动(SDD)与多智能体编排,破解“监督悖论”带来的技能平庸化危机,将 AI 的概率性生成驯化为确定性的工程交付。当编码成本趋于零,工程师的终极壁垒将是定义完美的品味,以及在 AI 迷雾中识破平庸的洞察力。

博客原文

地址How AI is transforming work at Anthropic

核心标签AI辅助编程 工程 范式转移 工作转型 生产力提升 技能发展 人机协作

一句话介绍:Anthropic 不仅仅是 AI 工具的生产者,更是第一个进入“未来实验室”的深度观察者。他们通过内部数月的实验数据告诉我们:大模型对软件工程的改造,绝非简单的“提效”,而是一场关于工程范式与职业认同的重塑。

延伸思考工程团队要用多少年,才会把现在的'人+AI 协作方式',沉淀为一个稳定的工程范式?

1. 引言

软件工程的历史,本质上是一部不断通过“抽象”来对抗“复杂度”的进化史。从汇编语言到高级语言,从手动内存管理到垃圾回收,每一次抽象层的上移,都会让一部分曾经引以为傲的手艺淡出舞台,同时释放出更宏大的创造力。

2025 年底,Anthropic 发布了一份具有里程碑意义的研究报告:《AI 如何改变 Anthropic 的工作方式》。作为大模型的缔造者,Anthropic 将自己变成了一个“AI 时代工作范式的实验室”。他们不仅向外输出模型,更在内部深度观测:当工程师拥有了像 Claude 这样具备自主能力的“AI 同事”后,代码的生产流程、团队的协作边界、甚至是“工程师”这一职业的底层逻辑,究竟发生了怎样的质变?

这份报告揭示了一组迷人且令人警醒的数据:在 AI 辅助下,工程师们不仅在提速,更在处理那 27% 曾经“不划算”或“超出能力边界”的任务。然而,光鲜的数据背后,是“编程技能萎缩”的隐忧和“监督悖论”的挑战。

站在产品与应用工程师的角度看,我最关心的不仅是“AI 能写多快”,而是如何将这种碎片化的、依赖“灵感”的 AI 协作,沉淀为一套稳定的工程范式

本文将基于 Anthropic 的这份深度观测,结合我们在 AI Native 应用架构、以及“规格驱动开发(SDD)”中的一些实践,探讨三个核心命题:

  • 任务重构:当编码成本趋于零时,哪些被长期忽视的“工程债务”将变成核心资产?

  • 能力重塑:在“英语/中文即编程语言”的时代,如何保持技术尖锐度并构建新的“工程 Sense”?

  • 范式落地:我们该如何设计一套人机协作的链路,让 AI 的产出从“不确定的随机性”走向“可交付的工程化”?

2. 盯准任务构成,而非单一速度,重获“工程尊严”的 27%

一句话总结:

AI 对工程团队的真正馈赠,是让我们从繁琐的、“不得不做”的苦力活中抽身,去夺回对软件质量的掌控力。速度是副产品,质量的密度才是衡量 AI 协作水平的终极标准。

在讨论 AI 提效时,我们很容易掉入的陷阱就是 “速度幻觉”。如果单纯观察代码产出行数(LOC)或需求交付周期,我们可能会得出“工程师变快了”的浅层结论,但 Anthropic 的研究给出了一个更具洞察力的视角:AI 带来的最大变量,不是让既有任务变快了,而是改变了“任务的构成比例”

报告中提到的那个关键数字——27%,代表了那些如果没有 AI 辅助,工程师根本不会去碰的任务。这 27% 并非边缘工作,而是软件工程中长期被牺牲掉的“工程尊严”。

2.1 从"技术债务"到"系统韧性"

在传统开发模式下,那些遗留的烂代码、缺失的测试覆盖、疏于维护的内部工具——这些"技术债务"虽不至于让系统立刻崩溃,却如同慢性毒药,持续侵蚀团队的认知资源与开发效率。

Anthropic 的观察揭示了一个关键转折点:当 AI 介入后,清偿这些"技术债务"的成本首次降到了可接受的阈值之下。

  • 重构民主化:曾经需要资深工程师耗费数小时、如履薄冰的手动重构,如今在 AI 辅助下几分钟即可完成初稿并通过基础验证,重构从"高风险操作"变成了"日常习惯"。
  • 测试与文档的范式转移:最令人抵触的单元测试编写和技术文档维护,正逐渐演变为 AI 擅长的"结构化填空"——工程师定义意图与边界,AI 负责填充实现细节,人类则专注于验收与精炼。
  • 可视化与工具的自动化:随着 AI 能力的提升,可视化工具、内部工具等也开始被自动化,工程师可以更专注于业务逻辑的实现,而不是手动维护这些工具。

2.2 从"不划算"到"高价值":任务优先级的重新洗牌

作为产品工程师,我们每天都在做取舍:哪些任务值得投入时间,哪些只能往后放?过去,很多工程改进任务——比如增加可观测性的埋点、搭建内部性能看板——虽然对系统长期健康很重要,但因为做起来太费功夫,往往被无限期搁置。我们心里都明白这些任务有价值,但"性价比"太低,排不上优先级。

AI 的出现改变了这个算式。它像一根杠杆,把那些原本需要花费大量时间的繁琐工作,变成了可以快速完成的"轻量级任务"。过去可能要花一整天写的监控脚本,现在几分钟就能让 AI 生成初稿;以前需要专门排期的重构工作,现在可以随手完成。

这意味着什么?那些曾经因为"太麻烦"而被忽视的任务,现在突然变得"很划算"了。团队不再只是追求开发速度,而是有能力把系统打磨得更健壮、更可维护。我们不再只是跑得更快,而是能跑得更稳、更远。

2.3 跨领域能力的“无痛溢出”

研究还揭示了一个引人注目的现象:工程师的角色边界正在变得愈发模糊,"全栈化"趋势日益明显。

  • 后端工程师借助 AI 轻松涉足复杂的数据可视化前端开发。
  • 研究员也能独立搭建用于实验的内部管理后台。

这种能力的自然延伸并非意味着人人都成为通才,而是 AI 将跨领域协作的摩擦成本大幅降低。当技术壁垒被削平,原本需要数周协调的跨职能配合,如今可在数小时内完成闭环验证——反馈周期实现了量级压缩。

3. 对抗“平庸化” —— 在自然语言编程时代重塑工程 Sense

一句话总结:

抽象层的上移并不意味着底层知识的贬值,反而意味着识别平庸的能力变得空前昂贵。当每个人都有一个能写代码的 AI 同事时,你对“完美工程”的定义能力,决定了你在这个时代的价值上限。

当编程的门槛降低到“只要会说话就能写代码”时,软件工程正经历一场权力的交接:自然语言(英语/中文)正在成为最高级的编程语言。

这种转变带来了一种极其诱人的“Vibe Coding(凭感觉编程)”体验。然而,Anthropic 的研究揭示了一个冷酷的现实:AI 往往表现得像一个“极其聪明但缺乏责任感的初级工程师”。如果我们全盘接受这种便利,而不去有意识地重构自身的职业能力,我们可能会陷入一种“监督悖论(Supervision Paradox)”——即当你失去了手动解决问题的能力时,你也失去了监督 AI 的资格。

3.1 警惕“监督悖论”与能力的平庸化

Anthropic 的报告中提到,有效使用 AI 需要极强的“监督力”,而这种能力恰恰源于那些正在被 AI 取代的底层编码实践。这种转变催生了一个深刻的监督悖论:

  • 技能萎缩的风险:长期依赖 AI 生成代码,会导致开发者对内存管理、并发模型、边界条件等底层细节的敏感度下降。

(附带学习)的丧失: 过去我们在翻阅文档、调试 Bug 的痛苦过程中,会意外学到系统的运行机理。AI 直接给出答案,切断了这种深度学习的路径。

AI Free 的刻意练习:每周或每个迭代,挑选一个核心逻辑块,尝试在完全不求助 AI 的情况下,手写实现并进行性能调优。这就像飞行员必须定期进行手动起降练习一样,是保持底层“肌肉记忆”的唯一方式。

3.2 从 Vibe Coding 进化到规范驱动(SDD)

为了不让工程质量滑向“随机性”的深渊,我们需要将“凭感觉”转化为 “定规范”。在“英语即编程语言”的时代,工程师的独特价值不再是实现细节,而是对约束条件的定义。

  • 定义验收标准:我们需要比以前更清晰地告诉 AI,什么是“正确”。这就要求具备极强的系统架构思维和对业务逻辑的深度拆解能力。
  • 引入工程语义:模糊的指令只会带来模糊的结果。正如近期在实践中推崇的 Specification Driven Development (SDD),我们需要在自然语言与 AI 执行之间,建立一套严谨的语义层。这套语义标准如同工程契约,确保 AI 生成的代码不是随机"发散"的,而是始终锚定于可预期的工程范式之内。

3.3. 构建新型“工程 Sense”:从手艺人到导演

未来的高级工程师,其核心竞争力将体现在对品味与评判权的掌控上。

  • 批判性审美:AI 给出三个方案,你为什么选这一个?是因为它的扩展性更好,还是因为它在特定高并发场景下更稳健?这种基于经验的“选择权”就是新的工程 Sense。
  • 逆向工程能力:能够快速读懂 AI 生成的大体量代码,并在其中精准定位“聪明但危险”的逻辑缺陷。这要求我们必须保持对新技术的“深度阅读”习惯,而非仅仅停留在“调用”层面。

4. 范式落地——在随机性之上,构建确定性的工程基座

一句话总结:

范式的落地不是一蹴而就的规则设定,而是一场伴随模型能力进化的动态博弈。我们要构建的是一套 “宽容输入、严格输出” 的链路:给 AI 足够的空间去创造和提效,但在交付的最后一公里,用最传统的工程理性进行最严苛的审判。

如果说 AI 是一台拥有无限爆发力的引擎,那么软件工程范式就是承载它的底盘。当前最核心的矛盾在于:大模型本质上是概率性的,而工程交付要求的却是确定性的。

如何让"不确定的生成"进化为"可交付的代码"?这不只是技术层面的挑战,更是一个关于全链路治理的系统性命题。我们不能以静态的视角审视现有工具,而需要动态地观察 LLM 能力演进、Agent 架构革新与传统工程设施的深度融合与协同演化。

4.1 从“单点指令”转向“多智能体编排(Multi-Agent Orchestration)”

正如 Anthropic 内部使用 Claude Code 处理日益复杂的任务,未来的落地范式绝非"人与单一窗口的对话",而是一个闭环的多智能体协作流水线。

  • 角色专业化分工:将复杂任务拆解并委派给不同的"专家智能体"。一个 Agent 专注于需求理解与方案设计,另一个负责代码实现,第三个则扮演"红队审查者"的角色,进行自动化的对抗性测试与漏洞挖掘。

  • 迭代式错误收敛:工程确定性不源于单次生成的完美,而来自 "生成-验证-诊断-修复-再验证" 的自动化闭环。在代码合并入主分支之前,它应当已在隔离的沙盒环境中,历经多轮 Agent 驱动的自我修正与质量收敛。

4.2 构建"上下文护城河":从 Prompt 到知识图谱

AI 输出的质量,本质上取决于它对业务语境的理解深度。当前最大的工程化障碍,正是模型面对团队私有知识时的"冷启动"困境——它缺乏对特定代码规范、架构决策和历史演进的隐性认知。

  • 动态上下文注入: 超越传统的 RAG(检索增强生成),将代码库、架构文档乃至团队的代码评审偏好,实时编织为 AI 的"工作记忆"。这不再是简单的信息检索,而是让 AI 真正"融入"团队的工程文化。

  • 工程语义翻译层: 在人类的模糊意图与机器的结构化理解之间,我们需要一座桥梁。这座桥梁将自然语言需求转化为 AI 可精确解析的语义图谱——基于 Graph 的代码索引、依赖关系网络与领域知识建模,共同构成这一翻译层的核心骨架。

4.3 "可观测性":让 AI 的决策过程透明可见

传统 DevOps 关注的是服务器负载、响应时间等机器指标;而在 AI 工程时代,我们需要追踪的是 AI 的"思考过程"。

  • 记录 AI 的决策链路:当 AI 修改代码时,我们不仅要看到"改了什么",更要理解"为什么这么改"——完整还原它的推理链条,让每一次变更都可追溯、可解释。

  • 建立分级信任机制:不是所有任务都需要人工逐一审核。对于 AI 表现稳定的标准化工作(如调整样式、生成单元测试),可以自动放行;一旦发现 AI 在推理过程中反复纠结、多次修正或出现异常,立即触发人工深度审查,形成人机协同的质量把关。

4.4 拥抱"不确定性",但守住"质量底线"

我们需要认清一个现实:未来的软件开发将是人与 AI 协作的过渡态,不会是非黑即白的完全自动化。与其追求每一步都人工可控,不如确保最终结果可验证、可信赖

这意味着工程团队的核心能力要从"亲自写代码"转向 "搭建完善的评估体系"。只要你的测试、监控、回滚机制足够健壮,即使 AI 的输出带有一定随机性,也能被牢牢限制在安全的边界之内。

5. 结语

Anthropic 的这份报告,本质上是为我们展现了一个软件工程的“后工业时代”。在这个时代,AI 不是取代你的收割机,而是给了你“一百万匹马”的爆发力。

正如报告中所揭示的那样:我们不应再纠结于单应仰望更高应仰望更高维度的景观。当写代码变得不再昂贵,对“什么是好代码”的定义权,以及对“系统为何而存在”的理解力,便成了这个行业最后的稀缺品

未来,最优秀的工程师或许不再是那个能手写极致算法的人,而是那个能在随机生成的迷雾中,凭借深厚的底层功底,一眼识破平庸与风险,并为 AI 指明方向的人。

范式的沉淀或许仍需时间,请务必在享受 AI 提效的同时,刻意保持你的技术尖锐度。因为 在“机器执行”的洪流下,人类的品位与责任感,依然是软件工程中那道最坚固、也最温暖的防御线

- - - - \ No newline at end of file diff --git "a/01.\345\205\250\346\240\210/01.AI Native \345\267\245\347\250\213\346\200\235\347\273\264/10.\350\257\273 Anthropic \347\240\224\347\251\266\346\212\245\345\221\212\357\274\214\346\216\242\345\257\273 AI \346\227\266\344\273\243\347\232\204\345\267\245\347\250\213\350\214\203\345\274\217\351\207\215\345\241\221.md" "b/01.\345\205\250\346\240\210/01.AI Native \345\267\245\347\250\213\346\200\235\347\273\264/10.\350\257\273 Anthropic \347\240\224\347\251\266\346\212\245\345\221\212\357\274\214\346\216\242\345\257\273 AI \346\227\266\344\273\243\347\232\204\345\267\245\347\250\213\350\214\203\345\274\217\351\207\215\345\241\221.md" deleted file mode 100644 index 4a0e3e76..00000000 --- "a/01.\345\205\250\346\240\210/01.AI Native \345\267\245\347\250\213\346\200\235\347\273\264/10.\350\257\273 Anthropic \347\240\224\347\251\266\346\212\245\345\221\212\357\274\214\346\216\242\345\257\273 AI \346\227\266\344\273\243\347\232\204\345\267\245\347\250\213\350\214\203\345\274\217\351\207\215\345\241\221.md" +++ /dev/null @@ -1,160 +0,0 @@ ---- -url: /01.全栈/01.AI Native 工程思维/10.读 Anthropic 研究报告,探寻 AI 时代的工程范式重塑.md -description: >- - 软件工程正经历从“手写逻辑”向“意图调度”的范式迁徙。Anthropic 的研究揭示了 AI 并非简单的提效工具,而是通过释放 27% - 曾经“不划算”的工程任务,重塑了软件质量的密度。在自然语言即编程语言的时代,我们需要通过规格驱动(SDD)与多智能体编排,破解“监督悖论”带来的技能平庸化危机,将 - AI 的概率性生成驯化为确定性的工程交付。当编码成本趋于零,工程师的终极壁垒将是定义完美的品味,以及在 AI 迷雾中识破平庸的洞察力。 ---- - -# 读 Anthropic 研究报告,探寻 AI 时代的工程范式重塑 - -> **摘要总结**:软件工程正经历从“手写逻辑”向“意图调度”的范式迁徙。Anthropic 的研究揭示了 AI 并非简单的提效工具,而是通过释放 27% 曾经“不划算”的工程任务,重塑了软件质量的密度。在自然语言即编程语言的时代,我们需要通过规格驱动(SDD)与多智能体编排,破解“监督悖论”带来的技能平庸化危机,将 AI 的概率性生成驯化为确定性的工程交付。当编码成本趋于零,工程师的终极壁垒将是定义完美的品味,以及在 AI 迷雾中识破平庸的洞察力。 - -:::tip 博客原文 -**地址**:[How AI is transforming work at Anthropic](https://www.anthropic.com/research/how-ai-is-transforming-work-at-anthropic) - -**核心标签**:`AI辅助编程` `工程` `范式转移` `工作转型` `生产力提升` `技能发展` `人机协作` - -**一句话介绍**:Anthropic 不仅仅是 AI 工具的生产者,更是第一个进入“未来实验室”的深度观察者。他们通过内部数月的实验数据告诉我们:大模型对软件工程的改造,绝非简单的“提效”,而是一场关于工程范式与职业认同的重塑。 - -**延伸思考**:工程团队要用多少年,才会把现在的'人+AI 协作方式',沉淀为一个稳定的工程范式? -::: - -## 1. 引言 - -软件工程的历史,本质上是一部不断通过“抽象”来对抗“复杂度”的进化史。从汇编语言到高级语言,从手动内存管理到垃圾回收,每一次抽象层的上移,都会让一部分曾经引以为傲的手艺淡出舞台,同时释放出更宏大的创造力。 - -2025 年底,Anthropic 发布了一份具有里程碑意义的研究报告:《AI 如何改变 Anthropic 的工作方式》。作为大模型的缔造者,Anthropic 将自己变成了一个“AI 时代工作范式的实验室”。他们不仅向外输出模型,更在内部深度观测:当工程师拥有了像 Claude 这样具备自主能力的“AI 同事”后,代码的生产流程、团队的协作边界、甚至是“工程师”这一职业的底层逻辑,究竟发生了怎样的质变? - -这份报告揭示了一组迷人且令人警醒的数据:在 AI 辅助下,工程师们不仅在提速,更在处理那 27% 曾经“不划算”或“超出能力边界”的任务。然而,光鲜的数据背后,是“编程技能萎缩”的隐忧和“监督悖论”的挑战。 - -站在产品与应用工程师的角度看,我最关心的不仅是“AI 能写多快”,而是**如何将这种碎片化的、依赖“灵感”的 AI 协作,沉淀为一套稳定的工程范式**。 - -本文将基于 Anthropic 的这份深度观测,结合我们在 AI Native 应用架构、以及“规格驱动开发(SDD)”中的一些实践,探讨三个核心命题: - -* **任务重构**:当编码成本趋于零时,哪些被长期忽视的“工程债务”将变成核心资产? - -* **能力重塑**:在“英语/中文即编程语言”的时代,如何保持技术尖锐度并构建新的“工程 Sense”? - -* **范式落地**:我们该如何设计一套人机协作的链路,让 AI 的产出从“不确定的随机性”走向“可交付的工程化”? - -## 2. 盯准任务构成,而非单一速度,重获“工程尊严”的 27% - -:::note 一句话总结: -AI 对工程团队的真正馈赠,是让我们从繁琐的、“不得不做”的苦力活中抽身,去夺回对软件质量的掌控力。速度是副产品,质量的密度才是衡量 AI 协作水平的终极标准。 -::: - -在讨论 AI 提效时,我们很容易掉入的陷阱就是 **“速度幻觉”**。如果单纯观察代码产出行数(LOC)或需求交付周期,我们可能会得出“工程师变快了”的浅层结论,但 Anthropic 的研究给出了一个更具洞察力的视角:**AI 带来的最大变量,不是让既有任务变快了,而是改变了“任务的构成比例”**。 - -报告中提到的那个关键数字——27%,代表了那些如果没有 AI 辅助,工程师根本不会去碰的任务。这 27% 并非边缘工作,而是软件工程中长期被牺牲掉的“工程尊严”。 - -### 2.1 从"技术债务"到"系统韧性" - -在传统开发模式下,那些遗留的烂代码、缺失的测试覆盖、疏于维护的内部工具——这些"技术债务"虽不至于让系统立刻崩溃,却如同慢性毒药,持续侵蚀团队的认知资源与开发效率。 - -Anthropic 的观察揭示了一个关键转折点:当 AI 介入后,清偿这些"技术债务"的成本首次降到了可接受的阈值之下。 - -* **重构民主化**:曾经需要资深工程师耗费数小时、如履薄冰的手动重构,如今在 AI 辅助下几分钟即可完成初稿并通过基础验证,重构从"高风险操作"变成了"日常习惯"。 -* **测试与文档的范式转移**:最令人抵触的单元测试编写和技术文档维护,正逐渐演变为 AI 擅长的"结构化填空"——工程师定义意图与边界,AI 负责填充实现细节,人类则专注于验收与精炼。 -* **可视化与工具的自动化**:随着 AI 能力的提升,可视化工具、内部工具等也开始被自动化,工程师可以更专注于业务逻辑的实现,而不是手动维护这些工具。 - -### 2.2 从"不划算"到"高价值":任务优先级的重新洗牌 - -作为产品工程师,我们每天都在做取舍:哪些任务值得投入时间,哪些只能往后放?过去,很多工程改进任务——比如增加可观测性的埋点、搭建内部性能看板——虽然对系统长期健康很重要,但因为做起来太费功夫,往往被无限期搁置。我们心里都明白这些任务有价值,但"性价比"太低,排不上优先级。 - -AI 的出现改变了这个算式。它像一根杠杆,把那些原本需要花费大量时间的繁琐工作,变成了可以快速完成的"轻量级任务"。过去可能要花一整天写的监控脚本,现在几分钟就能让 AI 生成初稿;以前需要专门排期的重构工作,现在可以随手完成。 - -这意味着什么?那些曾经因为"太麻烦"而被忽视的任务,现在突然变得"很划算"了。团队不再只是追求开发速度,而是有能力把系统打磨得更健壮、更可维护。我们不再只是跑得更快,而是能跑得更稳、更远。 - -### 2.3 跨领域能力的“无痛溢出” - -研究还揭示了一个引人注目的现象:工程师的角色边界正在变得愈发模糊,"全栈化"趋势日益明显。 - -* 后端工程师借助 AI 轻松涉足复杂的数据可视化前端开发。 -* 研究员也能独立搭建用于实验的内部管理后台。 - -这种能力的自然延伸并非意味着人人都成为通才,而是 AI 将跨领域协作的摩擦成本大幅降低。当技术壁垒被削平,原本需要数周协调的跨职能配合,如今可在数小时内完成闭环验证——反馈周期实现了量级压缩。 - -## 3. 对抗“平庸化” —— 在自然语言编程时代重塑工程 Sense - -:::note 一句话总结: -抽象层的上移并不意味着底层知识的贬值,反而意味着识别平庸的能力变得空前昂贵。当每个人都有一个能写代码的 AI 同事时,你对“完美工程”的定义能力,决定了你在这个时代的价值上限。 -::: - -当编程的门槛降低到“只要会说话就能写代码”时,软件工程正经历一场权力的交接:自然语言(英语/中文)正在成为最高级的编程语言。 - -这种转变带来了一种极其诱人的“Vibe Coding(凭感觉编程)”体验。然而,Anthropic 的研究揭示了一个冷酷的现实:AI 往往表现得像一个“极其聪明但缺乏责任感的初级工程师”。如果我们全盘接受这种便利,而不去有意识地重构自身的职业能力,我们可能会陷入一种\*\*“监督悖论(Supervision Paradox)”\*\*——即当你失去了手动解决问题的能力时,你也失去了监督 AI 的资格。 - -### 3.1 警惕“监督悖论”与能力的平庸化 - -Anthropic 的报告中提到,有效使用 AI 需要极强的“监督力”,而这种能力恰恰源于那些正在被 AI 取代的底层编码实践。这种转变催生了一个深刻的监督悖论: - -* **技能萎缩的风险**:长期依赖 AI 生成代码,会导致开发者对内存管理、并发模型、边界条件等底层细节的敏感度下降。 - -**(附带学习)的丧失:** 过去我们在翻阅文档、调试 Bug 的痛苦过程中,会意外学到系统的运行机理。AI 直接给出答案,切断了这种深度学习的路径。 - -**AI Free 的刻意练习**:每周或每个迭代,挑选一个核心逻辑块,尝试在完全不求助 AI 的情况下,手写实现并进行性能调优。这就像飞行员必须定期进行手动起降练习一样,是保持底层“肌肉记忆”的唯一方式。 - -### 3.2 从 Vibe Coding 进化到规范驱动(SDD) - -为了不让工程质量滑向“随机性”的深渊,我们需要将“凭感觉”转化为 **“定规范”**。在“英语即编程语言”的时代,工程师的独特价值不再是实现细节,而是对**约束条件**的定义。 - -* **定义验收标准**:我们需要比以前更清晰地告诉 AI,什么是“正确”。这就要求具备极强的系统架构思维和对业务逻辑的深度拆解能力。 -* **引入工程语义**:模糊的指令只会带来模糊的结果。正如近期在实践中推崇的 Specification Driven Development (SDD),我们需要在自然语言与 AI 执行之间,建立一套严谨的语义层。这套语义标准如同工程契约,确保 AI 生成的代码不是随机"发散"的,而是始终锚定于可预期的工程范式之内。 - -### 3.3. 构建新型“工程 Sense”:从手艺人到导演 - -未来的高级工程师,其核心竞争力将体现在对**品味与评判权**的掌控上。 - -* **批判性审美**:AI 给出三个方案,你为什么选这一个?是因为它的扩展性更好,还是因为它在特定高并发场景下更稳健?这种基于经验的“选择权”就是新的工程 Sense。 -* **逆向工程能力**:能够快速读懂 AI 生成的大体量代码,并在其中精准定位“聪明但危险”的逻辑缺陷。这要求我们必须保持对新技术的“深度阅读”习惯,而非仅仅停留在“调用”层面。 - -## 4. 范式落地——在随机性之上,构建确定性的工程基座 - -:::note 一句话总结: -范式的落地不是一蹴而就的规则设定,而是一场伴随模型能力进化的动态博弈。我们要构建的是一套 **“宽容输入、严格输出”** 的链路:给 AI 足够的空间去创造和提效,但在交付的最后一公里,用最传统的工程理性进行最严苛的审判。 -::: - -如果说 AI 是一台拥有无限爆发力的引擎,那么软件工程范式就是承载它的底盘。当前最核心的矛盾在于:大模型本质上是概率性的,而工程交付要求的却是确定性的。 - -如何让"不确定的生成"进化为"可交付的代码"?这不只是技术层面的挑战,更是一个关于全链路治理的系统性命题。我们不能以静态的视角审视现有工具,而需要动态地观察 LLM 能力演进、Agent 架构革新与传统工程设施的深度融合与协同演化。 - -### 4.1 从“单点指令”转向“多智能体编排(Multi-Agent Orchestration)” - -正如 Anthropic 内部使用 Claude Code 处理日益复杂的任务,未来的落地范式绝非"人与单一窗口的对话",而是一个闭环的多智能体协作流水线。 - -* **角色专业化分工**:将复杂任务拆解并委派给不同的"专家智能体"。一个 Agent 专注于需求理解与方案设计,另一个负责代码实现,第三个则扮演"红队审查者"的角色,进行自动化的对抗性测试与漏洞挖掘。 - -* **迭代式错误收敛**:工程确定性不源于单次生成的完美,而来自 **"生成-验证-诊断-修复-再验证"** 的自动化闭环。在代码合并入主分支之前,它应当已在隔离的沙盒环境中,历经多轮 Agent 驱动的自我修正与质量收敛。 - -### 4.2 构建"上下文护城河":从 Prompt 到知识图谱 - -AI 输出的质量,本质上取决于它对业务语境的理解深度。当前最大的工程化障碍,正是模型面对团队私有知识时的"冷启动"困境——它缺乏对特定代码规范、架构决策和历史演进的隐性认知。 - -* **动态上下文注入**: 超越传统的 RAG(检索增强生成),将代码库、架构文档乃至团队的代码评审偏好,实时编织为 AI 的"工作记忆"。这不再是简单的信息检索,而是让 AI 真正"融入"团队的工程文化。 - -* **工程语义翻译层**: 在人类的模糊意图与机器的结构化理解之间,我们需要一座桥梁。这座桥梁将自然语言需求转化为 AI 可精确解析的语义图谱——基于 Graph 的代码索引、依赖关系网络与领域知识建模,共同构成这一翻译层的核心骨架。 - -### 4.3 "可观测性":让 AI 的决策过程透明可见 - -传统 DevOps 关注的是服务器负载、响应时间等机器指标;而在 AI 工程时代,我们需要追踪的是 AI 的"思考过程"。 - -* **记录 AI 的决策链路**:当 AI 修改代码时,我们不仅要看到"改了什么",更要理解"为什么这么改"——完整还原它的推理链条,让每一次变更都可追溯、可解释。 - -* **建立分级信任机制**:不是所有任务都需要人工逐一审核。对于 AI 表现稳定的标准化工作(如调整样式、生成单元测试),可以自动放行;一旦发现 AI 在推理过程中反复纠结、多次修正或出现异常,立即触发人工深度审查,形成人机协同的质量把关。 - -### 4.4 拥抱"不确定性",但守住"质量底线" - -我们需要认清一个现实:未来的软件开发将是人与 AI 协作的过渡态,不会是非黑即白的完全自动化。与其追求每一步都人工可控,不如确保**最终结果可验证、可信赖**。 - -这意味着工程团队的核心能力要从"亲自写代码"转向 **"搭建完善的评估体系"**。只要你的测试、监控、回滚机制足够健壮,即使 AI 的输出带有一定随机性,也能被牢牢限制在安全的边界之内。 - -## 5. 结语 - -Anthropic 的这份报告,本质上是为我们展现了一个软件工程的“后工业时代”。在这个时代,AI 不是取代你的收割机,而是给了你“一百万匹马”的爆发力。 - -正如报告中所揭示的那样:我们不应再纠结于单应仰望更高应仰望更高维度的景观。当写代码变得不再昂贵,对“什么是好代码”的定义权,以及对“系统为何而存在”的理解力,便成了这个行业最后的稀缺品。 - -未来,最优秀的工程师或许不再是那个能手写极致算法的人,而是那个能在随机生成的迷雾中,凭借深厚的底层功底,一眼识破平庸与风险,并为 AI 指明方向的人。 - -范式的沉淀或许仍需时间,请务必在享受 AI 提效的同时,刻意保持你的技术尖锐度。因为 在“机器执行”的洪流下,人类的品位与责任感,依然是软件工程中那道最坚固、也最温暖的防御线。 diff --git "a/01.\345\205\250\346\240\210/10.AI \347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227/00.AI\347\274\226\347\250\213\345\267\245\345\205\267\344\270\216\350\265\204\346\272\220.html" "b/01.\345\205\250\346\240\210/10.AI \347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227/00.AI\347\274\226\347\250\213\345\267\245\345\205\267\344\270\216\350\265\204\346\272\220.html" deleted file mode 100644 index 2497532f..00000000 --- "a/01.\345\205\250\346\240\210/10.AI \347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227/00.AI\347\274\226\347\250\213\345\267\245\345\205\267\344\270\216\350\265\204\346\272\220.html" +++ /dev/null @@ -1,177 +0,0 @@ - - - - - - AI 编程工具与资源推荐 | Insight Stack - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Skip to content
3472
- - - - 13.3m

AI 编程工具与资源推荐

摘要总结:本文深度解析了 AI 驱动编程的三大演进范式:Vibe Coding(自然语言零门槛构建)、AI IDE(编辑器深度辅助提效)及 Agentic Engineering(自主工程师执行任务)。通过横向对比 Bolt.new、Cursor、Claude Code 等前沿工具,文章勾勒出一条从“快速原型”到“高效协同”再到“自主交付”的进阶路径。核心旨在指导用户利用 AI 工具矩阵打破技术边界,实现从创意描述到工业级交付的生产力飞跃,重塑软件开发全生命周期。

1. 三种编程范式速览

范式一句话描述你的角色
Vibe Coding用自然语言描述需求,AI 直接生成可运行的完整项目描述需求,让 AI 写代码(新手友好)
AI IDE在编辑器里引入 AI 辅助,边写边补全、边问边改主导开发,让 AI 做副驾驶(更多控制)
Agentic EngineeringAI 作为"自主工程师",接收任务后自动规划并执行全套代码工作流提任务、审结果,让 AI 执行(极致提效)

新手路线建议:先用 Bolt.new 或 v0.dev 体验 Vibe Coding 零门槛出产品的感觉 → 再切换到 Cursor 做日常编码提效 → 最后尝试 Claude Code/opencode 体验 AI 自主完成工程任务,三步感受"AI 如何重塑编程工作流"。

注意:使用 Claude Code 等 CLI Agent 工具,需要订阅官方模型服务(Claude Pro / API)。若暂无订阅,可通过配置自定义模型服务,支持对接兼容 第三方服务(如 GLM、DeepSeek、通义千问),实现低成本上手。

2. Vibe Coding — 用自然语言"说"出一个应用

2.1 关键点说明

适合人群:产品经理、设计师、创业者,或想快速验证想法的非专业开发者。

核心价值:从一段文字描述到可运行的 Web 应用,无需搭建开发环境;天生适合 MVP 原型验证UI 快速迭代

如何上手:打开网站 → 在输入框描述你的应用(如"做一个番茄钟 App,有开始暂停按钮,完成后有提示音")→ AI 生成代码并实时预览 → 继续对话迭代功能。

2.2 六款工具横向对比

💡 快速选择建议

  • 要做完整全栈 Web 并直接上线Bolt.new(成熟度最高)
  • 只需前端 UI 组件嵌入现有项目 → v0
  • 非技术背景想独立做出有数据库的产品 → Lovable
  • 在线学编程或使用 Python / Go 等非 React 语言 → Replit Agent
  • 手头有参考网站想直接还原其界面 → Same.dev
  • 中文用户或目标平台是微信小程序秒哒 Miaoda
工具核心定位输出形态技术栈最适场景上手门槛
Bolt.new应用生成完整 Web 应用React快速生成可部署全栈 Demo
v0UI 组件生成React 组件代码片段React + Tailwind + shadcn/ui前端界面快速出图,嵌入 Next.js 项目
Lovable零代码全栈建站含数据库的完整 Web 产品前端 + Supabase 后端非技术人员独立做出可上线产品
Replit Agent云端多语言全栈多语言完整项目Python / JS / Go 等多语言在线学编程、非 React 技术栈原型⭐⭐
Same.dev网站 UI 克隆前端页面还原代码前端(URL → 代码)参考竞品设计、快速获取建站初始模板
秒哒 Miaoda无代码应用搭建Web 应用 / 微信小程序Web + 小程序双端中文一句话出原型,尤其适合小程序

3. AI IDE — 与代码编辑器深度融合

3.1 关键点说明

适合人群:有一定编程基础、追求研发效率的开发者。

核心价值:上下文感知补全 + 自然语言对话改代码 + Agent 自主多文件重构,让"写代码"变成"描述 + 确认"。

如何上手:安装对应工具 → 打开项目 → 用快捷键呼出 AI 对话框(如 Cursor 的 Cmd+K)→ 用自然语言描述要改什么 → 确认差异后应用。

3.2 三款工具横向对比

💡 选择建议

  • 追求口碑最佳 + 生态最成熟的 AI IDE → Cursor(社区资源最丰富)
  • 数据安全 / 合规要求,或想要免费的国产方案 → Trae IDE
  • 喜欢 AI 自动串联多步任务,享受不中断的"心流"编程体验 → Windsurf
  • 三款均基于 VS Code 改造,现有 VS Code 插件和快捷键习惯均可无缝迁移
工具核心特色Agent 能力数据安全费用最适场景
Cursor多文件上下文感知补全 + Cmd+K 行内生成强 — 多文件规划 + 终端执行一般(代码发往云端)免费额度 + 订阅日常功能开发、多文件重构、代码 Review
Trae IDE国产免费 + 本地优先数据安全强 — 对标 Cursor,含在线 SOLO 版本地优先 + 隐私模式免费有合规需求的国内团队、个人日常开发
WindsurfCascade 前瞻规划 + Tab 一键心流强 — 前瞻 10 步、自动串联多步任务一般(代码发往云端)免费额度 + 订阅复杂多步任务自动执行、追求"心流"开发体验

4. Agentic Engineering — AI 自主完成工程任务

4.1 关键点说明

适合人群:希望将完整工程任务交给 AI 自主处理的资深开发者或团队。

核心价值:AI 不再只是"副驾驶",而是能自主读取代码库、运行测试、修复 Bug、甚至提交 PR 的"自主工程师",适合 Bug 修复、功能迭代、代码重构等完整工程周期。

如何上手(以 Claude Code 为例)npm install -g @anthropic-ai/claude-code → 在项目根目录执行 claude → 输入任务(如"帮我找出 #123 这个 Bug 的根因,写好测试后提交")→ Claude Code 自主读取代码库、执行命令并逐步反馈,审查后确认提交。

4.2 五款 Agentic 工具横向对比

选型建议

  • 个人 / 小项目:优先 Claude Code(体验最流畅),无订阅则用 opencode 接入低成本模型平替。
  • 团队 / 私有部署:用 OpenHands 自托管,统一管控模型与 API Key,保障数据不出域。
  • Issue 驱动的研发流:接入 Devin,让 AI 全程完成 Issue → 代码 → PR 闭环,人工只做 Review。
  • 大型存量代码库:优先 Augment Code,深度索引能力是 CLI Agent 难以替代的。
工具交互方式核心优势适场景典型任务示例费用
Claude Code终端 CLI与本地代码库深度结合,可执行 Shell / Git,多文件读写全自动个人或小团队的重构、批量 Bug 修复、自动提交等完整工程周期claude → "重构 auth 模块,保持接口不变,补齐单测后提交"Claude Pro / API 按量计费
opencode终端 CLI完全开源,内置免费模型,支持接入任意 LLM(含国内模型)无官方订阅、希望接入 DeepSeek / 通义等低成本模型的场景opencode → 配置自定义模型 → 同上工程任务取决于所接模型
DevinWeb 界面高度自主,可持续跟进 GitHub Issue,全链路无人值守有明确 Issue 驱动的团队研发流,AI 自动完成功能开发并提 PR粘贴 Issue URL → 指定验收标准 → 审查 PR付费(企业为主)
OpenHandsWeb / API开源自托管,支持多 LLM,可定制扩展 Agentic 流程企业私有化部署,团队共享 AI 工程师能力,保障数据安全Docker 启动 → 接入 DeepSeek → 批量分配修复任务开源免费,按模型计费
Augment CodeIDE 插件深度索引百万行级代码库,上下文感知精准大型企业存量代码库的日常开发、重构与工程管理圈选模块 → "梳理调用链并生成文档"免费额度 + 订阅
- - - - \ No newline at end of file diff --git "a/01.\345\205\250\346\240\210/10.AI \347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227/00.AI\347\274\226\347\250\213\345\267\245\345\205\267\344\270\216\350\265\204\346\272\220.md" "b/01.\345\205\250\346\240\210/10.AI \347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227/00.AI\347\274\226\347\250\213\345\267\245\345\205\267\344\270\216\350\265\204\346\272\220.md" deleted file mode 100644 index 07056fd5..00000000 --- "a/01.\345\205\250\346\240\210/10.AI \347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227/00.AI\347\274\226\347\250\213\345\267\245\345\205\267\344\270\216\350\265\204\346\272\220.md" +++ /dev/null @@ -1,225 +0,0 @@ ---- -url: /01.全栈/10.AI 编程实践指南/00.AI编程工具与资源.md -description: >- - 摘要总结:本文深度解析了 AI 驱动编程的三大演进范式:Vibe Coding(自然语言零门槛构建)、AI IDE(编辑器深度辅助提效)及 Agentic - Engineering(自主工程师执行任务)。通过横向对比 Bolt.new、Cursor、Claude Code - 等前沿工具,文章勾勒出一条从“快速原型”到“高效协同”再到“自主交付”的进阶路径。核心旨在指导用户利用 AI - 工具矩阵打破技术边界,实现从创意描述到工业级交付的生产力飞跃,重塑软件开发全生命周期。 ---- - -# AI 编程工具与资源推荐 - -> **摘要总结**:本文深度解析了 AI 驱动编程的三大演进范式:Vibe Coding(自然语言零门槛构建)、AI IDE(编辑器深度辅助提效)及 Agentic Engineering(自主工程师执行任务)。通过横向对比 Bolt.new、Cursor、Claude Code 等前沿工具,文章勾勒出一条从“快速原型”到“高效协同”再到“自主交付”的进阶路径。核心旨在指导用户利用 AI 工具矩阵打破技术边界,实现从创意描述到工业级交付的生产力飞跃,重塑软件开发全生命周期。 - -## 1. 三种编程范式速览 - -| 范式 | 一句话描述 | 你的角色 | -|:-----|:---------|:--------| -| **Vibe Coding** | 用自然语言描述需求,AI 直接生成可运行的完整项目 | 描述需求,让 AI 写代码(`新手友好`) | -| **AI IDE** | 在编辑器里引入 AI 辅助,边写边补全、边问边改 | 主导开发,让 AI 做副驾驶(`更多控制`) | -| **Agentic Engineering** | AI 作为"自主工程师",接收任务后自动规划并执行全套代码工作流 | 提任务、审结果,让 AI 执行(`极致提效`) | - -**新手路线建议**:先用 **Bolt.new 或 v0.dev** 体验 `Vibe Coding` 零门槛出产品的感觉 → 再切换到 **Cursor** 做日常编码提效 → 最后尝试 **Claude Code/opencode** 体验 AI 自主完成工程任务,三步感受"AI 如何重塑编程工作流"。 - -**注意**:使用 Claude Code 等 CLI Agent 工具,需要订阅官方模型服务(Claude Pro / API)。若暂无订阅,可通过配置自定义模型服务,支持对接兼容 第三方服务(如 GLM、DeepSeek、通义千问),实现低成本上手。 - -## 2. Vibe Coding — 用自然语言"说"出一个应用 - -### 2.1 关键点说明 - -> **适合人群**:产品经理、设计师、创业者,或想快速验证想法的非专业开发者。 -> -> **核心价值**:从一段文字描述到可运行的 Web 应用,无需搭建开发环境;天生适合 **MVP 原型验证** 与 **UI 快速迭代**。 -> -> **如何上手**:打开网站 → 在输入框描述你的应用(如"做一个番茄钟 App,有开始暂停按钮,完成后有提示音")→ AI 生成代码并实时预览 → 继续对话迭代功能。 - -::: navCard - -```yaml -- name: Bolt.new - desc: StackBlitz 推出的全栈 AI 开发平台,在浏览器中直接生成并运行完整的 React 项目,支持多轮对话迭代,可一键部署到 Netlify / Vercel,零环境配置从描述到上线全链路打通。 - link: https://bolt.new/ - img: https://bolt.new/static/favicon-192x192.png - badge: 一键部署 - badgeType: tip - -- name: v0 (Vercel) - desc: Vercel 推出的 UI 组件生成工具,专注前端界面:用自然语言描述界面,生成 React + Tailwind CSS + shadcn/ui 组件代码,可直接复制进项目,天生与 Next.js 生态无缝衔接,非常适合前端 UI 的快速原型。 - link: https://v0.dev/ - img: https://v0.app/assets/icon-dark-32x32.png - badge: UI 生成 - badgeType: tip - -- name: Lovable - desc: 面向非技术用户的 AI 全栈应用生成器,输入产品想法生成前后端完整应用,内置 Supabase 数据库集成与一键部署,支持实时预览和多轮对话修改,让没有编程基础的人也能独立做出可上线的 Web 产品。 - link: https://lovable.dev/ - img: https://lovable.dev/favicon.ico - badge: 无代码全栈 - badgeType: tip - -- name: Replit Agent - desc: 云端在线 IDE Replit 内置的 AI Agent,能从需求描述自动生成完整项目、安装依赖、运行调试,全程在浏览器内完成,内置托管与分享功能,零本地环境要求,适合快速原型和在线学习编程。 - link: https://replit.com/ - img: https://replit.com/public/icons/favicon-prompt-192.png - badge: 云端全栈 - badgeType: tip - -- name: Same.dev - desc: 专注"克隆任意网站 UI"的 AI 编码工具,输入目标网站 URL,AI 自动还原其界面并生成对应前端代码,适合学习参考优秀设计、快速复现竞品界面,以及建站初始模板快速搭建。 - link: https://same.dev/ - img: https://same.dev/favicon.ico - badge: UI 克隆 - badgeType: tip - -- name: 秒哒 Miaoda - desc: 百度出品的无代码应用搭建平台,口号"一句话做应用"。在输入框用自然语言描述需求,即可一键生成可部署的 Web 应用或微信小程序;内置深度开发模式、插件市场与风格定制,帮助想法从描述直达成品。配套"应用广场"汇聚社区作品,可浏览、点赞并参考他人案例,适合产品原型快速验证、学习参考与演示展示。 - link: https://www.miaoda.cn/ - img: https://resource-static.cdn.bcebos.com/img/favicon.png - badge: 中文体验佳 - badgeType: tip - -``` - -::: - -### 2.2 六款工具横向对比 - -> 💡 **快速选择建议** -> -> * 要做**完整全栈 Web 并直接上线** → **Bolt.new**(成熟度最高) -> * 只需**前端 UI 组件**嵌入现有项目 → **v0** -> * **非技术背景**想独立做出有数据库的产品 → **Lovable** -> * 想**在线学编程**或使用 Python / Go 等非 React 语言 → **Replit Agent** -> * 手头有**参考网站**想直接还原其界面 → **Same.dev** -> * **中文用户**或目标平台是**微信小程序** → **秒哒 Miaoda** - -| 工具 | 核心定位 | 输出形态 | 技术栈 | 最适场景 | 上手门槛 | -|:-----|:--------|:--------|:------|:--------|:-------:| -| **Bolt.new** | 应用生成 | 完整 Web 应用 | React | 快速生成可部署全栈 Demo | ⭐ | -| **v0** | UI 组件生成 | React 组件代码片段 | React + Tailwind + shadcn/ui | 前端界面快速出图,嵌入 Next.js 项目 | ⭐ | -| **Lovable** | 零代码全栈建站 | 含数据库的完整 Web 产品 | 前端 + Supabase 后端 | 非技术人员独立做出可上线产品 | ⭐ | -| **Replit Agent** | 云端多语言全栈 | 多语言完整项目 | Python / JS / Go 等多语言 | 在线学编程、非 React 技术栈原型 | ⭐⭐ | -| **Same.dev** | 网站 UI 克隆 | 前端页面还原代码 | 前端(URL → 代码)| 参考竞品设计、快速获取建站初始模板 | ⭐ | | -| **秒哒 Miaoda** | 无代码应用搭建 | Web 应用 / 微信小程序 | Web + 小程序双端 | 中文一句话出原型,尤其适合小程序 | ⭐ | - -## 3. AI IDE — 与代码编辑器深度融合 - -### 3.1 关键点说明 - -> **适合人群**:有一定编程基础、追求研发效率的开发者。 -> -> **核心价值**:上下文感知补全 + 自然语言对话改代码 + Agent 自主多文件重构,让"写代码"变成"描述 + 确认"。 -> -> **如何上手**:安装对应工具 → 打开项目 → 用快捷键呼出 AI 对话框(如 Cursor 的 `Cmd+K`)→ 用自然语言描述要改什么 → 确认差异后应用。 - -::: navCard - -```yaml -- name: Cursor - desc: 基于 VS Code 深度改造的 AI 原生 IDE,三大核心能力:① Tab 智能补全(感知上下文多文件);② Cmd+K 行内生成与修改;③ Cursor Agent 可自主规划、读写多文件、运行终端完成复杂任务。是目前口碑最好的 AI 编程工具。 - link: https://www.cursor.com/ - img: https://www.cursor.com/favicon.ico - badge: 强烈推荐 - badgeType: tip - -- name: Trae IDE - desc: 国内出品的 AI 原生 IDE,"The Real AI Engineer(真正的 AI 工程师)",免费可用。三大核心能力:① 智能补全与对话式改代码;② 多文件 Agent 自主重构,全面对标 Cursor;③ **数据安全优先** — 坚持"本地优先、最小化数据收集"原则,内置隐私模式,代码默认存于本地。另提供 SOLO 在线轻量版供快速体验,适合关注数据主权的国内开发者与有合规要求的企业团队。 - link: https://www.trae.cn/ - img: https://lf-cdn.trae.com.cn/obj/trae-com-cn/trae_website_prod_cn/favicon.png - badge: 国内自主支持 - badgeType: tip - -- name: Windsurf - desc: Codeium 出品的 AI 原生 IDE,现已迁至独立域名 windsurf.com,口号"开发者做出最佳工作的地方"。两大核心能力:① **Cascade Agent** — 能前瞻 10 步以上,自动规划、编码、修复 Bug,深度理解整个代码库并串联多步骤任务;② **Windsurf Tab** — 一键补全代码、跳转光标、自动导入依赖,保持开发"心流"不中断。支持 GPT-4.5、Gemini 等主流模型,提供个人免费版与企业版。 - link: https://windsurf.com/ - img: https://codeium.com/favicon.ico - badge: 分析代码 - badgeType: tip - -``` - -::: - -### 3.2 三款工具横向对比 - -> 💡 **选择建议** -> -> * 追求**口碑最佳 + 生态最成熟**的 AI IDE → **Cursor**(社区资源最丰富) -> * 有**数据安全 / 合规要求**,或想要**免费**的国产方案 → **Trae IDE** -> * 喜欢 AI **自动串联多步任务**,享受不中断的"心流"编程体验 → **Windsurf** -> * 三款均基于 VS Code 改造,**现有 VS Code 插件和快捷键习惯均可无缝迁移** - -| 工具 | 核心特色 | Agent 能力 | 数据安全 | 费用 | 最适场景 | -|:-----|:--------|:-----------:|:---------|:-------:|:-------:| -| **Cursor** | 多文件上下文感知补全 + Cmd+K 行内生成 | 强 — 多文件规划 + 终端执行 | 一般(代码发往云端) | 免费额度 + 订阅 | 日常功能开发、多文件重构、代码 Review | -| **Trae IDE** | 国产免费 + 本地优先数据安全 | 强 — 对标 Cursor,含在线 SOLO 版 | 本地优先 + 隐私模式 | 免费 | 有合规需求的国内团队、个人日常开发 | -| **Windsurf** | Cascade 前瞻规划 + Tab 一键心流 | 强 — 前瞻 10 步、自动串联多步任务 | 一般(代码发往云端)| 免费额度 + 订阅 | 复杂多步任务自动执行、追求"心流"开发体验 | - -## 4. Agentic Engineering — AI 自主完成工程任务 - -### 4.1 关键点说明 - -> **适合人群**:希望将完整工程任务交给 AI 自主处理的资深开发者或团队。 -> -> **核心价值**:AI 不再只是"副驾驶",而是能自主读取代码库、运行测试、修复 Bug、甚至提交 PR 的"自主工程师",适合 Bug 修复、功能迭代、代码重构等完整工程周期。 -> -> **如何上手(以 Claude Code 为例)**:`npm install -g @anthropic-ai/claude-code` → 在项目根目录执行 `claude` → 输入任务(如"帮我找出 #123 这个 Bug 的根因,写好测试后提交")→ Claude Code 自主读取代码库、执行命令并逐步反馈,审查后确认提交。 - -::: navCard - -```yaml -- name: Claude Code - desc: Anthropic 官方推出的命令行 AI 编程 Agent,在终端中直接与代码库深度对话,支持多文件读写、执行 Shell 命令、Git 操作,能够完成"读懂整个代码库→制定方案→逐步执行"的完整工程任务流,是最贴近真实工程流程的终端 Agent。 - link: https://claude-update-code.squarespace.com/?gad_source=1&gad_campaignid=23635038607&gbraid=0AAAAADBLX79DSBI8Ftftv8_FSgjubKKve&gclid=CjwKCAiAtq_NBhA_EiwA78nNWBwq9FGhmQLtwZ0ImoSZ5098wJU2cJMAwk8pHy9DtfDpt6Zf_TzDNhoCptgQAvD_BwE - img: https://claude.ai/favicon.ico - badge: CLI Agent - badgeType: tip - -- name: opencode - desc: 开源 AI 编程代理,Claude Code 的开源平替,内置免费模型,也可配置、连接任意提供商的任意模型,包括 Claude、GPT、Gemini,以及国内模型。 - link: https://opencode.ai - img: https://opencode.ai/favicon.ico - badge: 开源 CLI Agent - badgeType: tip - -- name: Devin - desc: 全球首个商用"AI 软件工程师",能接收 GitHub Issue 或自然语言任务,自主浏览文档、搜索资料、编写代码、运行测试并提交 PR,具备完整工程任务自主执行闭环,是 Agentic Engineering 的行业标杆。 - link: https://devin.ai/ - img: https://devin.ai/favicon.ico - badge: 自主 Agent 标杆 - badgeType: tip - -- name: OpenHands - desc: 前 OpenDevin,完全开源的 AI 软件工程师平台,Devin 的开源可自托管替代方案,可本地 Docker 部署,支持接入多种 LLM(GPT / Claude / DeepSeek 等),自主执行代码库任务、运行 Shell 命令、浏览网页查阅文档。 - link: https://github.com/All-Hands-AI/OpenHands - img: https://github.githubassets.com/favicons/favicon.svg - badge: 开源可自部署 - badgeType: tip - -- name: Augment Code - desc: 专为大型代码库设计的 AI 编程 Agent 平台,能深度索引企业级代码库(百万行级别),提供精准的上下文感知补全和 Agent 任务执行,适合中大型团队在已有复杂代码库上进行 AI 辅助开发。 - link: https://www.augmentcode.com/ - img: https://www.augmentcode.com/favicon.ico - badge: 企业级 Agent - badgeType: tip - -``` - -::: - -### 4.2 五款 Agentic 工具横向对比 - -> **选型建议** -> -> * **个人 / 小项目**:优先 **Claude Code**(体验最流畅),无订阅则用 **opencode** 接入低成本模型平替。 -> * **团队 / 私有部署**:用 **OpenHands** 自托管,统一管控模型与 API Key,保障数据不出域。 -> * **Issue 驱动的研发流**:接入 **Devin**,让 AI 全程完成 Issue → 代码 → PR 闭环,人工只做 Review。 -> * **大型存量代码库**:优先 **Augment Code**,深度索引能力是 CLI Agent 难以替代的。 - -| 工具 | 交互方式 | 核心优势 | 适场景 | 典型任务示例 | 费用 | -|:-----|:--------|:--------|:--------|:-----------|:--------| -| **Claude Code** | 终端 CLI | 与本地代码库深度结合,可执行 Shell / Git,多文件读写全自动 | 个人或小团队的重构、批量 Bug 修复、自动提交等完整工程周期 | `claude` → "重构 auth 模块,保持接口不变,补齐单测后提交" | Claude Pro / API 按量计费 | -| **opencode** | 终端 CLI | 完全开源,内置免费模型,支持接入任意 LLM(含国内模型) | 无官方订阅、希望接入 DeepSeek / 通义等低成本模型的场景 | `opencode` → 配置自定义模型 → 同上工程任务 | 取决于所接模型 | -| **Devin** | Web 界面 | 高度自主,可持续跟进 GitHub Issue,全链路无人值守 | 有明确 Issue 驱动的团队研发流,AI 自动完成功能开发并提 PR | 粘贴 Issue URL → 指定验收标准 → 审查 PR | 付费(企业为主) | -| **OpenHands** | Web / API | 开源自托管,支持多 LLM,可定制扩展 Agentic 流程 | 企业私有化部署,团队共享 AI 工程师能力,保障数据安全 | Docker 启动 → 接入 DeepSeek → 批量分配修复任务 | 开源免费,按模型计费 | -| **Augment Code** | IDE 插件 | 深度索引百万行级代码库,上下文感知精准 | 大型企业存量代码库的日常开发、重构与工程管理 | 圈选模块 → "梳理调用链并生成文档" | 免费额度 + 订阅 | diff --git "a/01.\345\205\250\346\240\210/40.\345\211\215\347\253\257\345\267\245\347\250\213/01.React \350\256\276\350\256\241\345\223\262\345\255\246\357\274\232AI \345\215\217\344\275\234\346\227\266\344\273\243\347\232\204\347\273\204\344\273\266\345\214\226\345\274\200\345\217\221\345\256\236\350\267\265\346\214\207\345\215\227.html" "b/01.\345\205\250\346\240\210/40.\345\211\215\347\253\257\345\267\245\347\250\213/01.React \350\256\276\350\256\241\345\223\262\345\255\246\357\274\232AI \345\215\217\344\275\234\346\227\266\344\273\243\347\232\204\347\273\204\344\273\266\345\214\226\345\274\200\345\217\221\345\256\236\350\267\265\346\214\207\345\215\227.html" deleted file mode 100644 index 41f6d13f..00000000 --- "a/01.\345\205\250\346\240\210/40.\345\211\215\347\253\257\345\267\245\347\250\213/01.React \350\256\276\350\256\241\345\223\262\345\255\246\357\274\232AI \345\215\217\344\275\234\346\227\266\344\273\243\347\232\204\347\273\204\344\273\266\345\214\226\345\274\200\345\217\221\345\256\236\350\267\265\346\214\207\345\215\227.html" +++ /dev/null @@ -1,178 +0,0 @@ - - - - - - React 设计哲学:AI 协作时代的组件化开发实践指南 | Insight Stack - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Skip to content
5038
- - - - 17.6m

React 设计哲学:AI 协作时代的组件化开发实践指南

1. 引言

在软件工程中,约 70% 的时间应投入于架构设计、需求拆解与接口语义推敲,仅 30% 用于实际编码。进入 AI 协作时代后,这一比例依然坚如磐石——开发者必须先完成深度思考,将“清晰的问题规格(Specification)”交给 AI,AI 才能输出高质量代码。AI 提升的是 30% 编码阶段的执行力,而非取代 70% 的架构裁决。 高质量 React 应用的诞生,依然始于人类心智对数据流、副作用边界与可组合性的透彻推演。

然而,真正驾驭 React 并非易事。许多团队在项目初期享受着组件化带来的快感,却在业务膨胀后陷入"组件地狱"——深嵌套的 prop drilling、失控的状态蔓延、难以追踪的副作用,让代码库逐渐腐化。问题的根源往往不在于 React 本身,而在于我们是否真正理解其背后的设计哲学。

React 的精髓在于以组件化为核心,将复杂的 UI 拆解为独立、可复用的自治单元,让数据沿着从输入(props)到输出(UI 元素)的轨迹形成清晰、可控的闭环。为确保项目的可维护性与抗腐化能力,React 开发者应将以下标准内化为肌肉记忆:
检查项核心标准架构目标
1. 单一职责每个组件是否只做一件事(纯布局或纯逻辑)?控制认知复杂度,防止组件“上帝化”
2. 组合优先是否优先使用了 children 或 Props 传递子组件?消除 Prop Drilling,提升灵活性
3. DOM 扁平是否利用 <>...</> 移除了所有非必要的包装 <div>减小渲染开销,保持 DOM 树纯粹
4. 拥抱 Hooks是否已用 Custom Hooks 替代了 HOC 嵌套?展平组件树,实现逻辑与视图的物理隔离

2. 划分具备分层结构的“自治”组件

组件是 React 对“关注点分离”这一软件工程经典原则的具象化落地。它将 UI 拆分为若干自治单元,每个单元对外仅暴露 props 契约,对内通过 state 管理自身行为。

划分组件必须恪守单一职责(SRP)高内聚低耦合两条铁律:

  • 一事一议:理想状态下,一个组件只负责渲染一块特定的视觉或封装一类特定的交互。随着功能膨胀,必须果断将其裂变为更细粒度的子组件。
  • 显式通信:组件间仅通过 props 与回调通信,杜绝任何形式的隐式状态共享。

在实践中,我们可以通过以下策略压平组件层级,维持架构的清爽:

策略说明
角色界定容器组件(Container):充当"调度中心",负责数据获取、状态管理与业务逻辑,随后将干净的数据流入子组件。避免在容器中混杂复杂的 DOM 结构,利用 Custom Hooks 抽离逻辑,能让 UI 层级瞬间变薄。
展示组件(Presentational):充当"纯函数",专注于接收 props 并渲染视图,保持 DOM 结构的极度扁平。
组合优于嵌套这是解决组件树过深的最强武器。永远不要在组件内部硬编码子组件,而是通过 children 或 render props,将子组件作为参数注入。这在语义上形成了一种"声明式 DSL",让代码本身成为直观的 UI 蓝图。
极简接口组件的 props 契约应绝对最小化,仅暴露必要的输入。

AI 协作小洞察:

我们要先划分层级结构,不应该让 AI 盲目写代码,可以先让它充当“架构助理”进行结构划分与设计:

  • 投喂需求与视觉规格,提供需求描述或 UI 视觉稿截图,要求 AI(如 ChatGPT、Claude 等)辅助分析并输出组件层级树,同时解释其职责划分与层级结构设计的思路。
  • 定义职责约束,在 Prompt 中明确要求 AI 区分"容器组件"与"展示组件",并遵循单一职责原则为其命名——这既能启发思路,也能提前规避命名不当的问题。
  • 人工裁决,评估 AI 输出的结构,微调边界,确保这套“骨架”足够健壮,再进入下一步的实质性编码。

3. 构建纯渲染的静态版本:确立工程基线

在状态与交互介入之前,我们可以先用“数据占位符”把 UI 的纯渲染路径跑通,构建一个剥离了所有动态行为的“静态版本”。此过程不需要过多的逻辑烧脑,而是纯粹的结构编码。

静态版本应保证组件无副作用,能为后续快照测试、服务端渲染(SSR)与 hydration 奠定可靠基础。这一步的工程价值不可估量:

  • 契约验证:强制检验当前的 props 设计是否足以表达所有的视觉状态差异。
  • 前置对齐:让设计师和产品提前验收“像素级”静态产物,规避后期可能出现的视觉返工。
  • 可信基线:为后续增量引入状态(State)与副作用(Effects)提供了一个随时可回滚的基线

在编写代码时,我们通常采用“自顶向下”的构建顺序,即从顶层容器开始,逐层向叶子节点实现。这种策略能确保组件职责清晰,不会过早陷入局部细节,同时保证每个模块都是独立、可测试的。

当然,在 AI 协作时代,借助 AI 生成静态版本无疑是更为高效的方式。但我们不建议直接采用全自动化构建作为最终方案——毕竟静态版本是整个项目的工程基线,一旦存在隐蔽缺陷,将为后续迭代埋下隐患。

更稳健的做法是将全自动化与半自动化并行推进:先让 AI 基于第一阶段评审通过的组件划分树与职责描述,在独立分支中全自动化生成代码;与此同时,开发者在正式分支中以半自动化方式逐步搭建。由于全自动化产出速度极快,我们可以横向对比多份生成结果,择优验证后再整合到正式项目中。这种"边做边验"的模式,既能提升基线质量,也能加深开发者对架构的理解。

进入静态版本构建阶段,我们需要关注以下三个关键环节:

1、前置步骤:脚手架生成
首先利用 AI 编程工具(如 Claude Code / Codex)快速初始化项目结构与配置文件。这一步是后续全自动化与半自动化并行模式的基础——AI 在标准化脚手架搭建上效率极高,能够迅速为我们铺好工程地基。

2、注入规格,启动双轨模式
将第一阶段确认好的"组件层级树与职责描述"作为明确的 Specification 喂给 AI,令其批量生成符合 React 规范的静态组件骨架。此时全自动化与半自动化两条线并行推进:AI 在独立分支快速产出多份候选代码,开发者则在主干分支逐步搭建,形成可对比、可验证的协作闭环。

3、人机结对审查
横向对比 AI 的自动化产出后,择优与人工代码融合,重点 Review 是否真正做到"无副作用"与"幂等渲染"。过程中也可让 AI 与人工协作,一旦发现问题或异常情况,立即通过对话纠正,确保这份静态基线的绝对纯粹——它将是后续引入状态与副作用时唯一可信的回滚锚点。

4. 寻找状态的最简表示,敲定拓扑位置

4.1 什么是 State?什么是 Derived Data(派生数据)?

State 本质上是对应用随时间变化产生的差异的建模,为正确地构建应用,让应用可控,我们需要在这一阶段找出驱动 UI 运转的 State(状态)的最小完整集合

在定义 State 之前,先做灵魂三问。先问自己三个关键问题。如果满足以下任何一条,它就绝对不是 State

  1. 随时间推移保持不变? (如静态配置) -> 不是 State。
  2. 通过 props 从父级传入? (如外部注入的数据) -> 不是 State。
  3. 能通过已有 State 或 props 计算得出? (如根据商品列表计算出的库存总量) -> 坚决不能作为 State。

这些可通过计算得出的数据被称为 Derived Data(派生数据)。正确的做法是在渲染期间动态计算它们,或使用 useMemo 进行性能优化,而不是将其塞入 useState 中徒增同步烦恼。

一份合格的状态必须:最小(剔除可推导字段)且完整(下游 UI 能基于此状态集合进行确定性渲染)。

4.2 敲定 State 的安放位置

小提示:防范状态爆炸与泄漏

  • 单一真实数据源:同一业务实体在组件树中只能存在一份状态副本。如果祖先节点已有,就通过 props 传递,严禁在不同组件内重复 useState
  • 无泄漏下沉:把状态隔离在局部子树时,必须显式定义读写边界——仅对真正需要的子孙暴露接口。禁止在模块顶层声明可变状态,防止状态隐式穿透组件边界。

确定了“是什么”之后,更关键的是“放在哪”。State 的安置需要在状态提升(Lifting State Up)状态下沉(Colocating State)之间寻找动态平衡:

  • 状态提升(Lifting State Up):若多个兄弟组件需要共享同一状态,毫不犹豫地将其提升至它们最近的公共父节点。
  • 状态下沉(Colocating State):若状态仅在特定子树内部流转,应通过局部 Context 或轻量级状态库(Zustand / Jotai)将其隔离,避免污染全局。

架构目标是绘制出一张清晰的数据流拓扑图:状态变更只沿单向轨道流动,出现 Bug 时,可以像排查电路图一样用万用表逐点测量。

4. 建立反向数据流:让回调成为刚性契约

React 的数据流天然是自顶向下的(Top-Down)。这种单向流动牺牲了双向绑定的“便捷性”,换来的是数据流转的绝对清晰与可预测性

当底层展示组件需要向上级反馈用户行为时,我们需要设计反向数据流,其本质是将“UI 事件”转化为严谨的“回调契约”

  1. 父组件通过 props 向子组件下发契约:onXxx: (data: T) => void
  2. 子组件在适当时机触发契约,但不关心父组件如何处理,借此维持自身的纯粹与解耦。
  3. 父组件在回调中执行 setState,触发自顶向下的重新渲染,完成闭环。

这种 事件 -> 回调 -> 状态突变 -> 重渲染 的循环,构成了 React 响应式架构的最小内核。面对跨层级通信时,可以引入 Context 或状态管理工具来收敛"回调地狱",但单向数据流的铁律绝不能被破坏

5. 规范驱动开发(SDD):从执行者转变为立法者

随着前四个阶段的稳步推进,基础架构已然确立,应用项目也进入了更深层次的开发迭代阶段。此时,如何高效地解决"怎么写"的问题?这正是 AI 协作编程大显身手的时刻。

规范驱动开发(Specification-Driven Development,SDD)是一种比 Vibe Coding 更为可靠的人机协作实践模式:人类负责制定规范,AI 负责实现代码。这种分工让开发者从繁琐的编码劳动中解放出来,专注于真正创造价值的方案选择与设计决策。

5.1 SDD 模式的核心流程与实践要点

SDD 模式遵循一个五步闭环:规划阶段 → 生成规范 → 人工 Review → 自动化开发 → 工程验证

阶段描述
规划阶段让 AI 分析业务场景,输出设计文档。这一阶段的核心是明确"做什么"——包括模块边界、数据结构、接口签名、约束条件等。
生成规范基于规划结果,让 AI 生成可指导编程的实现规范(Specification)。规范是一份可执行的契约,包含类型定义、函数签名、测试用例、边界条件等。规范的质量直接决定了代码的质量
人工 Review开发者审核规范的合理性。这是人类决策的关键环节——确保设计符合架构原则、无冗余无泄漏、命名语义清晰、数据流方向明确。Review 通过后,规范成为 AI 实现的唯一依据。
自动化开发确认规范后,让 AI 基于规范实现完整的功能模块。要求 AI 遵循 TDD 模式——先编写测试用例,再实现逻辑,确保行为的可预测性。每次开发应聚焦于一个完整、恰当粒度的功能或独立模块,避免碎片化。
工程验证配置项目的 lint、类型检查与测试套件,由 AI 自动运行验证,形成质量闭环。若发现问题,应优先引导 AI 自行修正,而非手动干预。

SDD 模式的实践要点可归纳为:

  • 规范先行,代码后置:永远不要让 AI 在没有规范的情况下直接写代码。模糊的需求描述只会让 AI 制造技术债务。一份清晰的规范,能让 AI 产出可维护的代码。

  • 恰当粒度,完整交付:每次让 AI 开发一个完整的功能模块,而非零散的代码片段。完整的模块有清晰的边界、完整的测试、可独立验证的行为。这种粒度既能保证开发效率,又能确保代码质量。

  • TDD 内嵌,测试驱动:在规范中明确要求 AI 先写测试、再写实现。测试用例是规范的具象化表达,也是验证代码正确性的唯一标准。

  • 引导修正,避免手动修补:当代码未通过验证时,优先引导 AI 自行修正,而非直接手动修改。手动修补会干扰 AI 对项目上下文的理解,导致后续生成的代码一致性下降。

  • 工程闭环,持续迭代:lint、类型检查、测试套件是质量的三道防线。每次开发完成后必须运行完整验证,确保代码符合项目规范。验证通过后再进入下一个模块的开发。

5.2 SDD 模式的适用场景

SDD 模式适用于多数应用的功能迭代开发阶段。在前端领域,它与 React 的声明式范式尤为契合,特别适合以下场景:

  • 状态管理模块:状态是应用的核心骨架,需要严格的类型约束与变更追踪。SDD 能确保状态设计遵循 SSOT 原则,杜绝冗余与泄漏。

  • 交互逻辑开发:反向数据流涉及组件间的通信契约,是典型的"接口语义推敲"场景。SDD 能确保回调命名语义清晰、数据流方向明确。

  • 独立组件开发:针对功能内聚、可复用的独立组件(如表单控件、数据卡片、模态框等),需先明确其 Props 契约、内部状态边界及副作用生命周期,再交由 AI 实现具体渲染逻辑与交互细节。

  • 基础设施代码:Custom Hooks、工具函数、类型定义等基础设施代码,适合用 SDD 模式批量生成,确保接口一致性。

5.3 为什么 React 与 SDD 天生一对?

React 的声明式(Declarative)特性意味着我们只需描述 State → UI 的映射关系——给定特定的状态输入,界面应当呈现何种输出,完全由开发者声明式地定义,而非通过命令式地操作 DOM 来达成。

如果说 SDD(规格驱动开发)是人机协作的一套"宪法",那么 React 就是完美的"执行机构"。两者的天作之合并非偶然,而是源于底层架构范式的深度契合。React 所倡导的"描述即实现"的声明式编程范式,本质上就是一种显式契约(Props Contract),能够有效压缩 AI 的"幻觉空间"。

当我们在 Spec 中定义好 interface Props 时,实际上是为 AI 划定了一个认知边界。AI 无需费力猜测上下文,只需在 Props 的约束范围内寻找局部最优解。这种高度的封装性从物理层面隔绝了 AI 产生"幻觉"的可能,确保生成的组件是高内聚、低耦合的自治单元。

这与 SDD 的思维高度一致:开发者只需定义"映射规格"(即状态到 UI 的转换规则、组件的 Props 契约、数据的流动路径),而具体的实现细节——如何高效地 diff 虚拟 DOM、如何批量处理状态更新、如何优化重渲染性能——完全交由 AI 填充。在 SDD 模式下,人类聚焦于"做什么"(What)和"为什么"(Why),AI 负责"怎么做"(How)。这正是声明式编程与规范驱动开发在哲学层面的深度契合。

6.结语:工程师的不可替代性

当我们回望 React 设计哲学的四个核心步骤——组件划分、静态基线、状态定位、数据流闭环,会发现它们共同指向一个本质命题:如何在复杂性中建立秩序

组件化是对 UI 复杂性的分解,静态版本是对渲染行为的锚定,最小状态是对数据冗余的剔除,单向数据流是对变更轨迹的约束。这些设计原则并非 React 独有,而是软件工程几十年沉淀下来的智慧结晶——单一职责、关注点分离、显式优于隐式、数据流的可追溯性

AI 时代的到来,并未改变这些原则的内核,反而让它们的价值更加凸显。当 AI 能够以惊人的速度生成代码时,"写什么"的决策权比"怎么写"的执行力更为稀缺。一个清晰的设计规范,能让 AI 产出可维护的代码;而一个模糊的需求描述,只会让 AI 制造更多技术债务。

规范驱动开发(SDD)的本质是将架构思维外化为可执行的契约。开发者不再是代码的"搬运工",而是规范的"立法者"。我们定义组件边界、敲定状态拓扑、设计回调契约——AI 则在我们设定的框架内高效填充实现细节。这种分工,让开发者从繁琐的编码劳动中解放出来,将精力集中于真正创造价值的架构决策。

最后,请记住:工具会迭代,技术会过时,但对复杂性的驾驭能力永远是工程师的核心竞争力。React 的 API 可能会在未来被新的框架取代,但"如何在复杂性中建立秩序"这一命题,将伴随软件工程的始终。愿你在这场技术演进中,始终站在架构设计的高地,用清晰的思维驾驭强大的工具,构建出经得起时间考验的软件系统。

- - - - \ No newline at end of file diff --git "a/01.\345\205\250\346\240\210/40.\345\211\215\347\253\257\345\267\245\347\250\213/01.React \350\256\276\350\256\241\345\223\262\345\255\246\357\274\232AI \345\215\217\344\275\234\346\227\266\344\273\243\347\232\204\347\273\204\344\273\266\345\214\226\345\274\200\345\217\221\345\256\236\350\267\265\346\214\207\345\215\227.md" "b/01.\345\205\250\346\240\210/40.\345\211\215\347\253\257\345\267\245\347\250\213/01.React \350\256\276\350\256\241\345\223\262\345\255\246\357\274\232AI \345\215\217\344\275\234\346\227\266\344\273\243\347\232\204\347\273\204\344\273\266\345\214\226\345\274\200\345\217\221\345\256\236\350\267\265\346\214\207\345\215\227.md" deleted file mode 100644 index 8d1046e4..00000000 --- "a/01.\345\205\250\346\240\210/40.\345\211\215\347\253\257\345\267\245\347\250\213/01.React \350\256\276\350\256\241\345\223\262\345\255\246\357\274\232AI \345\215\217\344\275\234\346\227\266\344\273\243\347\232\204\347\273\204\344\273\266\345\214\226\345\274\200\345\217\221\345\256\236\350\267\265\346\214\207\345\215\227.md" +++ /dev/null @@ -1,180 +0,0 @@ ---- -url: /01.全栈/40.前端工程/01.React 设计哲学:AI 协作时代的组件化开发实践指南.md -description: >- - 本文探讨在 AI 增强开发背景下,如何重塑 React 组件设计原则。涵盖 SRP 职责划分、静态版本基线、最小状态(Derived Data)推导以及 - SDD 人机协作模式的工程落地。 ---- - -# React 设计哲学:AI 协作时代的组件化开发实践指南 - -## 1. 引言 - -在软件工程中,约 70% 的时间应投入于架构设计、需求拆解与接口语义推敲,仅 30% 用于实际编码。进入 AI 协作时代后,这一比例依然坚如磐石——开发者必须先完成深度思考,将“清晰的问题规格(Specification)”交给 AI,AI 才能输出高质量代码。AI 提升的是 30% 编码阶段的执行力,而非取代 70% 的架构裁决。 高质量 React 应用的诞生,依然始于人类心智对数据流、副作用边界与可组合性的透彻推演。 - -然而,真正驾驭 React 并非易事。许多团队在项目初期享受着组件化带来的快感,却在业务膨胀后陷入"组件地狱"——深嵌套的 prop drilling、失控的状态蔓延、难以追踪的副作用,让代码库逐渐腐化。问题的根源往往不在于 React 本身,而在于我们是否真正理解其背后的设计哲学。 - -React 的精髓在于以组件化为核心,将复杂的 UI 拆解为独立、可复用的自治单元,让数据沿着从输入(props)到输出(UI 元素)的轨迹形成清晰、可控的闭环。为确保项目的可维护性与抗腐化能力,React 开发者应将以下标准内化为肌肉记忆: - -| 检查项 | 核心标准 | 架构目标 | -| :--- | :--- | :--- | -| **1. 单一职责** | 每个组件是否只做一件事(纯布局或纯逻辑)? | 控制认知复杂度,防止组件“上帝化” | -| **2. 组合优先** | 是否优先使用了 `children` 或 Props 传递子组件? | 消除 Prop Drilling,提升灵活性 | -| **3. DOM 扁平** | 是否利用 `<>...` 移除了所有非必要的包装 `
`? | 减小渲染开销,保持 DOM 树纯粹 | -| **4. 拥抱 Hooks** | 是否已用 Custom Hooks 替代了 HOC 嵌套? | 展平组件树,实现逻辑与视图的物理隔离 | - -## 2. 划分具备分层结构的“自治”组件 - -组件是 React 对“关注点分离”这一软件工程经典原则的具象化落地。它将 UI 拆分为若干**自治单元**,每个单元对外仅暴露 props 契约,对内通过 state 管理自身行为。 - -划分组件必须恪守**单一职责(SRP)**与**高内聚低耦合**两条铁律: - -* **一事一议**:理想状态下,一个组件只负责渲染一块特定的视觉或封装一类特定的交互。随着功能膨胀,必须果断将其裂变为更细粒度的子组件。 -* **显式通信**:组件间仅通过 props 与回调通信,杜绝任何形式的隐式状态共享。 - -在实践中,我们可以通过以下策略压平组件层级,维持架构的清爽: - -| 策略 | 说明 | -| :--- | :--- | -| **角色界定** | **容器组件(Container)**:充当"调度中心",负责数据获取、状态管理与业务逻辑,随后将干净的数据流入子组件。避免在容器中混杂复杂的 DOM 结构,利用 Custom Hooks 抽离逻辑,能让 UI 层级瞬间变薄。**展示组件(Presentational)**:充当"纯函数",专注于接收 props 并渲染视图,保持 DOM 结构的极度扁平。 | -| **组合优于嵌套** | 这是解决组件树过深的最强武器。**永远不要在组件内部硬编码子组件**,而是通过 `children` 或 render props,将子组件作为参数注入。这在语义上形成了一种"声明式 DSL",让代码本身成为直观的 UI 蓝图。 | -| **极简接口** | 组件的 props 契约应**绝对最小化**,仅暴露必要的输入。 | - -:::tip AI 协作小洞察: -我们要先划分层级结构,不应该让 AI 盲目写代码,可以先让它充当“架构助理”进行结构划分与设计: - -* **投喂需求与视觉规格**,提供需求描述或 UI 视觉稿截图,要求 AI(如 ChatGPT、Claude 等)辅助分析并输出组件层级树,同时解释其职责划分与层级结构设计的思路。 -* **定义职责约束**,在 Prompt 中明确要求 AI 区分"容器组件"与"展示组件",并遵循单一职责原则为其命名——这既能启发思路,也能提前规避命名不当的问题。 -* **人工裁决**,评估 AI 输出的结构,微调边界,确保这套“骨架”足够健壮,再进入下一步的实质性编码。 - ::: - -## 3. 构建纯渲染的静态版本:确立工程基线 - -在状态与交互介入之前,我们可以先用“数据占位符”把 UI 的**纯渲染路径**跑通,构建一个剥离了所有动态行为的“静态版本”。此过程不需要过多的逻辑烧脑,而是纯粹的结构编码。 - -静态版本应保证组件**无副作用**,能为后续快照测试、服务端渲染(SSR)与 hydration 奠定可靠基础。这一步的工程价值不可估量: - -* **契约验证**:强制检验当前的 props 设计是否足以表达所有的视觉状态差异。 -* **前置对齐**:让设计师和产品提前验收“像素级”静态产物,规避后期可能出现的视觉返工。 -* **可信基线**:为后续增量引入状态(State)与副作用(Effects)提供了一个**随时可回滚的基线**。 - -在编写代码时,我们通常采用“自顶向下”的构建顺序,即从顶层容器开始,逐层向叶子节点实现。这种策略能确保组件职责清晰,不会过早陷入局部细节,同时保证每个模块都是独立、可测试的。 - -当然,在 AI 协作时代,借助 AI 生成静态版本无疑是更为高效的方式。但我们不建议直接采用全自动化构建作为最终方案——毕竟静态版本是整个项目的工程基线,一旦存在隐蔽缺陷,将为后续迭代埋下隐患。 - -更稳健的做法是将全自动化与半自动化并行推进:先让 AI 基于第一阶段评审通过的组件划分树与职责描述,在独立分支中全自动化生成代码;与此同时,开发者在正式分支中以半自动化方式逐步搭建。由于全自动化产出速度极快,我们可以横向对比多份生成结果,择优验证后再整合到正式项目中。这种"边做边验"的模式,既能提升基线质量,也能加深开发者对架构的理解。 - -进入静态版本构建阶段,我们需要关注以下三个关键环节: - -1、**前置步骤:脚手架生成**\ -首先利用 AI 编程工具(如 Claude Code / Codex)快速初始化项目结构与配置文件。这一步是后续全自动化与半自动化并行模式的基础——AI 在标准化脚手架搭建上效率极高,能够迅速为我们铺好工程地基。 - -2、**注入规格,启动双轨模式**\ -将第一阶段确认好的"组件层级树与职责描述"作为明确的 Specification 喂给 AI,令其批量生成符合 React 规范的静态组件骨架。此时全自动化与半自动化两条线并行推进:AI 在独立分支快速产出多份候选代码,开发者则在主干分支逐步搭建,形成可对比、可验证的协作闭环。 - -3、**人机结对审查**\ -横向对比 AI 的自动化产出后,择优与人工代码融合,重点 Review 是否真正做到"无副作用"与"幂等渲染"。过程中也可让 AI 与人工协作,一旦发现问题或异常情况,立即通过对话纠正,确保这份静态基线的绝对纯粹——它将是后续引入状态与副作用时唯一可信的回滚锚点。 - -## 4. 寻找状态的最简表示,敲定拓扑位置 - -### 4.1 什么是 State?什么是 Derived Data(派生数据)? - -State 本质上是**对应用随时间变化产生的差异的建模**,为正确地构建应用,让应用可控,我们需要在这一阶段找出驱动 UI 运转的 **State(状态)的最小完整集合**。 - -在定义 State 之前,先做灵魂三问。先问自己三个关键问题。如果满足以下任何一条,**它就绝对不是 State**: - -1. **随时间推移保持不变?** (如静态配置) -> 不是 State。 -2. **通过 props 从父级传入?** (如外部注入的数据) -> 不是 State。 -3. **能通过已有 State 或 props 计算得出?** (如根据商品列表计算出的库存总量) -> 坚决不能作为 State。 - -这些可通过计算得出的数据被称为 **Derived Data(派生数据)**。正确的做法是在渲染期间动态计算它们,或使用 `useMemo` 进行性能优化,而不是将其塞入 `useState` 中徒增同步烦恼。 - -一份合格的状态必须:**最小**(剔除可推导字段)且**完整**(下游 UI 能基于此状态集合进行确定性渲染)。 - -### 4.2 敲定 State 的安放位置 - -:::tip 小提示:防范状态爆炸与泄漏 - -* **单一真实数据源**:同一业务实体在组件树中只能存在一份状态副本。如果祖先节点已有,就通过 props 传递,严禁在不同组件内重复 `useState`。 -* **无泄漏下沉**:把状态隔离在局部子树时,必须显式定义读写边界——**仅对真正需要的子孙暴露接口**。禁止在模块顶层声明可变状态,防止状态隐式穿透组件边界。 - ::: - -确定了“是什么”之后,更关键的是“放在哪”。State 的安置需要在\*\*状态提升(Lifting State Up)**与**状态下沉(Colocating State)\*\*之间寻找动态平衡: - -* **状态提升(Lifting State Up)**:若多个兄弟组件需要共享同一状态,毫不犹豫地将其提升至它们最近的公共父节点。 -* **状态下沉(Colocating State)**:若状态仅在特定子树内部流转,应通过局部 Context 或轻量级状态库(Zustand / Jotai)将其**隔离**,避免污染全局。 - -架构目标是绘制出一张清晰的**数据流拓扑图**:状态变更只沿单向轨道流动,出现 Bug 时,可以像排查电路图一样用万用表逐点测量。 - -## 4. 建立反向数据流:让回调成为刚性契约 - -React 的数据流天然是自顶向下的(Top-Down)。这种单向流动牺牲了双向绑定的“便捷性”,换来的是数据流转的**绝对清晰与可预测性**。 - -当底层展示组件需要向上级反馈用户行为时,我们需要设计反向数据流,其本质是**将“UI 事件”转化为严谨的“回调契约”**: - -1. 父组件通过 props 向子组件下发契约:`onXxx: (data: T) => void`。 -2. 子组件在适当时机触发契约,**但不关心父组件如何处理**,借此维持自身的纯粹与解耦。 -3. 父组件在回调中执行 `setState`,触发自顶向下的重新渲染,完成闭环。 - -这种 `事件 -> 回调 -> 状态突变 -> 重渲染` 的循环,构成了 React **响应式架构的最小内核**。面对跨层级通信时,可以引入 Context 或状态管理工具来收敛"回调地狱",但**单向数据流的铁律绝不能被破坏**。 - -## 5. 规范驱动开发(SDD):从执行者转变为立法者 - -随着前四个阶段的稳步推进,基础架构已然确立,应用项目也进入了更深层次的开发迭代阶段。此时,如何高效地解决"怎么写"的问题?这正是 AI 协作编程大显身手的时刻。 - -规范驱动开发(Specification-Driven Development,SDD)是一种比 Vibe Coding 更为可靠的人机协作实践模式:**人类负责制定规范,AI 负责实现代码**。这种分工让开发者从繁琐的编码劳动中解放出来,专注于真正创造价值的方案选择与设计决策。 - -### 5.1 SDD 模式的核心流程与实践要点 - -SDD 模式遵循一个五步闭环:**规划阶段 → 生成规范 → 人工 Review → 自动化开发 → 工程验证**。 - -| 阶段 | 描述 | -| :--- | :--- | -| **规划阶段** | 让 AI 分析业务场景,输出设计文档。这一阶段的核心是明确"做什么"——包括模块边界、数据结构、接口签名、约束条件等。 | -| **生成规范** | 基于规划结果,让 AI 生成可指导编程的实现规范(Specification)。规范是一份可执行的契约,包含类型定义、函数签名、测试用例、边界条件等。**规范的质量直接决定了代码的质量**。 | -| **人工 Review** | 开发者审核规范的合理性。这是人类决策的关键环节——确保设计符合架构原则、无冗余无泄漏、命名语义清晰、数据流方向明确。Review 通过后,规范成为 AI 实现的唯一依据。 | -| **自动化开发** | 确认规范后,让 AI 基于规范实现完整的功能模块。要求 AI 遵循 TDD 模式——先编写测试用例,再实现逻辑,确保行为的可预测性。每次开发应聚焦于一个完整、恰当粒度的功能或独立模块,避免碎片化。 | -| **工程验证** | 配置项目的 lint、类型检查与测试套件,由 AI 自动运行验证,形成质量闭环。若发现问题,应优先引导 AI 自行修正,而非手动干预。 | - -SDD 模式的实践要点可归纳为: - -* **规范先行,代码后置**:永远不要让 AI 在没有规范的情况下直接写代码。模糊的需求描述只会让 AI 制造技术债务。一份清晰的规范,能让 AI 产出可维护的代码。 - -* **恰当粒度,完整交付**:每次让 AI 开发一个完整的功能模块,而非零散的代码片段。完整的模块有清晰的边界、完整的测试、可独立验证的行为。这种粒度既能保证开发效率,又能确保代码质量。 - -* **TDD 内嵌,测试驱动**:在规范中明确要求 AI 先写测试、再写实现。测试用例是规范的具象化表达,也是验证代码正确性的唯一标准。 - -* **引导修正,避免手动修补**:当代码未通过验证时,优先引导 AI 自行修正,而非直接手动修改。手动修补会干扰 AI 对项目上下文的理解,导致后续生成的代码一致性下降。 - -* **工程闭环,持续迭代**:lint、类型检查、测试套件是质量的三道防线。每次开发完成后必须运行完整验证,确保代码符合项目规范。验证通过后再进入下一个模块的开发。 - -### 5.2 SDD 模式的适用场景 - -SDD 模式适用于多数应用的功能迭代开发阶段。在前端领域,它与 React 的声明式范式尤为契合,特别适合以下场景: - -* **状态管理模块**:状态是应用的核心骨架,需要严格的类型约束与变更追踪。SDD 能确保状态设计遵循 SSOT 原则,杜绝冗余与泄漏。 - -* **交互逻辑开发**:反向数据流涉及组件间的通信契约,是典型的"接口语义推敲"场景。SDD 能确保回调命名语义清晰、数据流方向明确。 - -* **独立组件开发**:针对功能内聚、可复用的独立组件(如表单控件、数据卡片、模态框等),需先明确其 Props 契约、内部状态边界及副作用生命周期,再交由 AI 实现具体渲染逻辑与交互细节。 - -* **基础设施代码**:Custom Hooks、工具函数、类型定义等基础设施代码,适合用 SDD 模式批量生成,确保接口一致性。 - -### 5.3 为什么 React 与 SDD 天生一对? - -React 的\*\*声明式(Declarative)\*\*特性意味着我们只需描述 State → UI 的映射关系——给定特定的状态输入,界面应当呈现何种输出,完全由开发者声明式地定义,而非通过命令式地操作 DOM 来达成。 - -如果说 SDD(规格驱动开发)是人机协作的一套"宪法",那么 React 就是完美的"执行机构"。两者的天作之合并非偶然,而是源于底层架构范式的深度契合。React 所倡导的"描述即实现"的声明式编程范式,本质上就是一种显式契约(Props Contract),能够有效压缩 AI 的"幻觉空间"。 - -当我们在 Spec 中定义好 `interface Props` 时,实际上是为 AI 划定了一个**认知边界**。AI 无需费力猜测上下文,只需在 Props 的约束范围内寻找局部最优解。这种高度的封装性从物理层面隔绝了 AI 产生"幻觉"的可能,确保生成的组件是高内聚、低耦合的自治单元。 - -这与 SDD 的思维高度一致:开发者只需定义"映射规格"(即状态到 UI 的转换规则、组件的 Props 契约、数据的流动路径),而具体的实现细节——如何高效地 diff 虚拟 DOM、如何批量处理状态更新、如何优化重渲染性能——完全交由 AI 填充。在 SDD 模式下,人类聚焦于"做什么"(What)和"为什么"(Why),AI 负责"怎么做"(How)。这正是声明式编程与规范驱动开发在哲学层面的深度契合。 - -## 6.结语:工程师的不可替代性 - -当我们回望 React 设计哲学的四个核心步骤——**组件划分、静态基线、状态定位、数据流闭环**,会发现它们共同指向一个本质命题:**如何在复杂性中建立秩序**。 - -AI 时代的到来,并未改变这些原则的内核,反而让它们的价值更加凸显。当 AI 能够以惊人的速度生成代码时,**"写什么"的决策权比"怎么写"的执行力更为稀缺**。一个清晰的设计规范,能让 AI 产出可维护的代码;而一个模糊的需求描述,只会让 AI 制造更多技术债务。 - -规范驱动开发(SDD)的本质是**将架构思维外化为可执行的契约**。开发者不再是代码的"搬运工",而是规范的"立法者"。我们定义组件边界、敲定状态拓扑、设计回调契约——AI 则在我们设定的框架内高效填充实现细节。这种分工,让开发者从繁琐的编码劳动中解放出来,将精力集中于真正创造价值的架构决策。 - -最后,请记住:工具会迭代,技术会过时,但对复杂性的驾驭能力永远是工程师的核心竞争力。React 的 API 可能会在未来被新的框架取代,但"如何在复杂性中建立秩序"这一命题,将伴随软件工程的始终。愿你在这场技术演进中,始终站在架构设计的高地,用清晰的思维驾驭强大的工具,构建出经得起时间考验的软件系统。 diff --git "a/01.\345\205\250\346\240\210/40.\345\211\215\347\253\257\345\267\245\347\250\213/02.CSS\345\267\245\347\250\213\345\214\226.md" "b/01.\345\205\250\346\240\210/40.\345\211\215\347\253\257\345\267\245\347\250\213/02.CSS\345\267\245\347\250\213\345\214\226.md" deleted file mode 100644 index c3581648..00000000 --- "a/01.\345\205\250\346\240\210/40.\345\211\215\347\253\257\345\267\245\347\250\213/02.CSS\345\267\245\347\250\213\345\214\226.md" +++ /dev/null @@ -1,618 +0,0 @@ ---- -url: /01.全栈/40.前端工程/02.CSS工程化.md -description: >- - 本文系统剖析主流 CSS 工程化方案的底层逻辑,提出“样式资产 ROI”评估模型,并针对 Vue/React 生态给出了面向 AI - 时代的企业级混合架构选型建议。 ---- - -# 从原子化到变体驱动:现代 CSS 工程化的架构演进与混合实践指南 - -> **摘要总结**:在前端生态日新月异的今天,CSS 工程化早已超越了“如何写样式”的范畴,演变为一场关于\*\*开发效率(Velocity)与系统韧性(Resilience)\*\*的深度博弈。本文将系统梳理从预处理器、CSS-in-JS、Scoped CSS 到原子化 CSS 的演进脉络,并首次引入 “样式资产 ROI” 模型,深入剖析为何 Tailwind 已成为 AI 时代的基石架构。针对 Vue 与 React 的不同哲学,我们总结出了一套 “原子化为主,工程化局部兜底” 的企业级混合架构方案。无论你是深耕 React 生态、追求全链路类型安全的“变体驱动”先行者,还是在 Vue 生态中寻找极致心智负担平衡的实践者,本文都将为你提供一份清晰的架构决策树,助你规避工程红线,构建真正面向未来的样式资产。 - -## 1. 引言:主流 CSS 工程化方案有哪些? - -在现代前端开发中,随着项目复杂度的急剧提升,原生 CSS 常常面临**全局污染、复用困难、层级嵌套过深以及维护成本极高**等问题。为了解决这些痛点,社区多年来不断探索,沉淀出了多种主流的 CSS 工程化方案。 - -除原生 CSS 之外,主流方案还包括预处理器、CSS-in-JS、CSS Module、Scoped CSS、原子化 CSS 等。BEM 作为一种基于命名约定来规避命名冲突的早期方案,在现代前端工程中已基本不再使用,因此本文不再对其展开详细分析。 - -> CSS 命名规范(BEM):通过严格的命名约定(如 Block\_\_Element--Modifier)来约束作用域,增强代码的可读性和可维护性。BEM 本身是一个优秀的规范,但它高度依赖开发者的自觉性,且会导致类名冗长,难以管理。 - -## 2. CSS 预处理器 - -CSS 预处理器是一种扩展了 CSS 功能的脚本语言,通过添加变量、嵌套、混入(Mixins)和函数等编程特性,让 CSS 更具结构化、可读性和可维护性。它允许开发者用特殊语法编写样式,然后编译成浏览器可读的普通 CSS 文件。 -它也是最早也是最基础的工程化方案,核心思想是通过扩展原生 CSS 的语法,赋予其“编程”能力。 - -| **维度** | **说明** | -| -------- | -------- | -| **核心思想** | 增强版 CSS 使用变量统一管理设计令牌(Design Tokens),用嵌套减少重复选择器。 | -| **代表技术** | **Sass (SCSS)**, **Less**, **Stylus** | -| **核心特点** | 提供了变量(Variables)、嵌套(Nesting)、混合(Mixins)、继承、函数等功能。 | -| **适用场景** | 几乎所有项目。**现阶段它通常不作为独立的解决方案,而是与其他方案(如 CSS Modules)结合使用。** | -| **局限性** | **编译后的产物依然是普通 CSS,无法从根本上解决全局命名冲突的问题(通常需要配合 BEM 命名规范来缓解)** | - -以 SCSS 为例,示意如下: - -```scss -/* Button.scss */ - -/* 1. 定义变量 */ -$primary-color: #3b82f6; -$default-bg: #e5e7eb; -$border-radius: 4px; - -/* 2. 嵌套与复用 */ -.btn { - padding: 8px 16px; - border-radius: $border-radius; - background-color: $default-bg; - color: #333; - border: none; - cursor: pointer; - - /* 使用 & 符号引用父选择器 */ - &:hover { - opacity: 0.8; - } - - /* 修改修饰符状态 (类似 BEM 命名) */ - &.btn-primary { - background-color: $primary-color; - color: white; - } -} -``` - -## 3. CSS-in-JS - -随着 React 等组件化框架的兴起,"将样式与逻辑写在同一个文件里"的理念应运而生。 - -CSS-in-JS 是一种将 CSS 样式直接编写在 JavaScript 文件中的技术(通常内嵌在组件内),打破了传统样式与结构分离的开发模式。它允许开发者利用 JS 变量、函数和逻辑动态生成样式,从而有效解决 CSS 全局污染、样式隔离困难以及维护成本高等问题。 - -| **维度** | **说明** | -| -------- | -------- | -| **核心思想** | 将 CSS 样式直接写在 JavaScript 文件中,为每个组件生成唯一的、带哈希值的类名,从而实现“作用域化样式”,彻底解决了全局污染问题。 | -| **代表技术** | **Styled-components**, **Emotion**, Vanilla Extract(零运行时方案)。 | -| **核心特点** | 直接在 JavaScript/TypeScript 文件中编写 CSS;它可以极其方便地读取 JS 变量和组件的 Props,从而实现极其强大的**动态样式**能力。 | -| **优势** | 完美的组件隔离;**极强的动态控制能力**;自动移除无用的 CSS 代码。 | -| **局限性** | 传统的 CSS-in-JS 库会带来一定的**运行时性能开销**(在浏览器侧动态计算和注入 ` -``` - -## 6. 原子化 CSS(Utility-First / Atomic CSS) - -原子化 CSS 是近年来最能深刻改变前端开发习惯的方案。它是**一种将 CSS 样式拆分为最小、独立、可复用的类名的架构方法**,倾向于**使用视觉效果命名**(如 `.text-red`)而非业务功能命名。通过组合这些"原子类"直接在 HTML 中构建样式,它具备无需起类名、CSS 体积小、开发效率高等优点。 - -这是一种与传统"语义化 CSS"截然不同的思路:**提供了一系列高度可组合、功能单一的"原子类"(Atomic CSS / Utility Classes)**。 - -| **维度** | **说明** | -| -------- | -------- | -| **核心思想** | 组装积木开发者不再为组件编写专门的 CSS 类,而是直接在 HTML 中组合这些原子类来构建样式 | -| **代表技术** | **Tailwind CSS****UnoCSS**Windi CSS | -| **核心特点** | **预设了成百上千个底层、单一职责的 CSS 工具类**(例如 `flex`, `pt-4`, `text-center`, `bg-blue-500`)开发者几乎不需要写 CSS 代码,而是直接在 HTML 或 JSX/Template 中拼装类名 | -| **优势** | **开发效率极高:** 省去了在 HTML 和 CSS 文件之间反复横跳、绞尽脑汁起类名的烦恼 **产物体积极小:** **按需编译**(Purge),只打包项目中真正用到的类名,不管项目多大,CSS 产物通常能保持在 10KB 左右 **高度一致性:** 团队使用同一套 Design System 设计令牌,来自预设的 `design tokens` (在 `tailwind.config.js` 中定义),保证了整个项目视觉上的一致性。 | -| **局限性** | 学习和记忆类名需要一定时间HTML 代码容易变得非常长(虽然可以通过组件化提取来缓解) | - -代码示例: - -```typescript -// Button.jsx (React/Vue/HTML 通用思路) - -function Button({ isPrimary, children }) { - // baseClasses: 预设基础类 (边距、圆角、字体、过渡动画) - const baseClasses = "px-4 py-2 rounded font-medium transition-opacity hover:opacity-80"; - - // colorClasses: 根据状态赋予不同的原子类 - const colorClasses = isPrimary - ? "bg-blue-500 text-white" - : "bg-gray-200 text-gray-800"; - - return ( - - ); -} - -``` - -tailwind.config.js 配置示意如下(更多配置选项请参考 [Tailwind 官方文档](https://tailwindcss.com/docs/theme)): - -```javascript -export default { - /** - * ============================================ - * Content 配置 (Content Paths) - * ============================================ - * content 数组告诉 Tailwind 在哪些文件中查找类名, - * 以便它能够正确生成所需的 CSS。 - * - * 注意: Tailwind 扫描所有 content 路径中的文件, - * 只保留实际使用的 CSS 类(Tree-shaking) - */ - content: [ - "./index.html", - "./src/**/*.{js,ts,jsx,tsx}", - ], - theme: { - extend: { - /** - * Tailwind 的颜色系统采用 "语义化命名" + "数值阶梯" 策略: - * - 品牌色 (brand): 模拟 CSS HSL 色阶,从 50(最浅) 到 900(最深) - * 选择 sky blue (#0ea5e9) 作为主品牌色,传达科技、专业感 - * - 强调色 (accent): 用于 CTA 按钮、重要操作提示 - * 选择 amber (#d97706),暖色调形成与品牌色的视觉对比 - * - * 使用方式: bg-brand-500, text-accent, border-accent-light - */ - colors: { - brand: { - // 这里引用了 CSS 自定义变量来定义品牌阶梯色的 design tokens - 50: 'var(--color-brand-50)', - 100: 'var(--color-brand-100)', - 200: 'var(--color-brand-200)', - 300: 'var(--color-brand-300)', - 400: 'var(--color-brand-400)', - 500: 'var(--color-brand-500)', // 主品牌色 - 600: 'var(--color-brand-600)', - 700: 'var(--color-brand-700)', - 800: 'var(--color-brand-800)', - 900: 'var(--color-brand-900)', - }, - // ... - }, - // ... - }, - // ... - }, -} -``` - -### 为什么 AI 应用产品都在拥抱 Tailwind ? - -> AI 产品的核心在模型与算法,Tailwind 让团队从 CSS 架构中解放,专注功能实现而非样式细节。 - -Tailwind 已从"样式工具"演变为 AI 产品的"基础设施",核心原因可归纳为以下四点: - -| 核心驱动力 | 关键要点 | -|-----------|---------| -| **极速迭代** | AI 赛道"一天一个样",Tailwind 让开发者像搭积木一样直接在组件中堆砌样式,省去起名和文件切换时间,实现"快速验证想法并上线" | -| **降低门槛** | 后端/算法工程师无需精通 CSS 底层原理,通过 `flex`、`p-4`、`text-center` 等直观类名即可拼凑出专业界面 | -| **视觉标准化** | 热门组件库 shadcn/ui 直接复制 Tailwind 源码到项目,定义了 AI 产品"极简、黑白灰、精致阴影"的标准审美 | -| **性能与工程** | Tree-shaking 保证 CSS 体积与组件数量无关;组件内聚性消除"僵尸样式",契合 React/Vue 现代框架 | - -## 7. 变体驱动的原子化 (Variants-Driven Atomic CSS):CVA + Tailwind - -如果说普通的 Tailwind 是“用拼积木的方式写 CSS”,那么 `CVA + Tailwind` 就是\*\*“用写 TypeScript 接口的方式来管理积木”\*\*。 - -* **核心思想:** **状态机与类型安全**,彻底抛弃传统的 CSS/SCSS 文件,将样式的“组合逻辑”全部抽象为 JavaScript/TypeScript 中的纯函数。**UI 组件的不同状态(大小、颜色、禁用等)被视为不同的“变体(Variants)”,通过配置对象来映射对应的 Tailwind 原子类**。 -* **代表技术:** **CVA (Class Variance Authority)** + **tailwind-merge** + **clsx**,这三者也是目前顶级 UI 库 shadcn/ui 的底层核心基石。 -* **核心特点:** - * 使用 `cva()` 函数预先定义组件的“基础类名”和各种“状态变体类名”。 - * 结合 TypeScript,组件的 Props 可以直接从 CVA 的配置中推导出来,实现**完全的类型安全**。 - * **配合 `tailwind-merge` 智能解决 Tailwind 类名冲突**(比如传了 `p-4` 又传了 `p-8`,自动保留后者)。 -* **优势:** - * **极致的 JSX 整洁度:** 告别长串的嵌套三元运算符(`isPrimary ? 'bg-blue' : 'bg-red'`),模板代码极其清爽。 - * **完美的 TS 类型提示:** 你敲下 `variant=` 时,IDE 会自动提示你只有 `primary` 和 `secondary` 可选,杜绝拼写错误。 - * **绝对的组件封装:** 样式逻辑和业务逻辑高度内聚在一个 `.tsx` 文件中,迁移和复用成本极低。 -* **局限性:** - * **JS/TS 强绑定:** 它完全依赖 JavaScript 运行时来拼接字符串,不适合纯 HTML 或对 JS 极度精简的场景。 - * **学习曲线:** 需要同时掌握 Tailwind 的类名、TypeScript 的类型推导,以及 CVA 的 API,对新手的综合要求较高。 -* **适用场景:** 现代 **React/Next.js** 项目的终极形态,特别是当你需要从零搭建一套属于自己团队的 \*\*Design System(设计系统)\*\*或复杂 UI 组件库时,这是目前的最优解。 - -```typescript -import { cva, type VariantProps } from "class-variance-authority"; -import { twMerge } from "tailwind-merge"; -import { clsx, type ClassValue } from "clsx"; - -// 1. 核心工具函数:完美合并类名并解决冲突 -export function cn(...inputs: ClassValue[]) { - return twMerge(clsx(inputs)); -} - -// 2. 使用 CVA 定义所有的变体状态 -const buttonVariants = cva( - // 基础样式:所有按钮都有的属性 - "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2", - { - variants: { - variant: { - default: "bg-blue-600 text-white hover:bg-blue-700", - destructive: "bg-red-500 text-white hover:bg-red-600", - outline: "border border-gray-300 bg-transparent hover:bg-gray-100 text-gray-900", - }, - size: { - default: "h-10 px-4 py-2", - sm: "h-9 rounded-md px-3", - lg: "h-11 rounded-md px-8", - }, - disabled: { - true: "opacity-50 cursor-not-allowed pointer-events-none", - } - }, - // 默认状态 - defaultVariants: { - variant: "default", - size: "default", - }, - } -); - -// 3. 极其优雅的 TS 类型推导:直接提取 CVA 配置作为 Props 的一部分 -export interface ButtonProps - extends React.ButtonHTMLAttributes, - VariantProps {} - -// 4. 组件渲染:干净得不可思议 -export function Button({ className, variant, size, disabled, ...props }: ButtonProps) { - return ( - -// 甚至支持外部传入 className 覆盖: -// -``` - -## 8. 实践指南:如何构建可扩展的样式工程化体系? - -样式方案的选择本质上是对\*\*开发效率(Velocity)与长期维护成本(Maintenance Cost)\*\*的博弈。面对前端生态中百花齐放的 CSS 工程化解决方案,我们在做技术选型时,往往难以在开发效率、可维护性和运行时性能之间找到完美平衡,常陷入"既要、又要、还要"的两难境地。 - -为便于指导日常的技术选型与工程实践,本文对六大主流方案进行了系统梳理: - -| **方案分类** | **代表技术** | **核心隔离原理** | **开发体验 / 心智负担** | **样式与逻辑解耦度** | **核心优势** | -| ------- | ------- | ------- | ------ | --------- | ------------ | -| **1. 预处理器** | Sass, Less | 无 (需依赖命名规范) | 极好 / 很低 | **极高** (独立文件) | 语法强大,最接近原生,易学易用。 | -| **2. 传统 CSS-in-JS** | Styled-components | JS 动态生成 Hash 类名 | 良好 / 较高 | **极低** (CSS 变成 JS 组件) | 完美的运行时动态能力,变量跨端共享。| -| **3. 模块化** | CSS Modules | 改写类名 (生成 Hash 类名) | 良好 / 中等 | **高** (需 JS 导入) | 100% 杜绝污染,严谨安全,适合底层 UI。| -| **4. 框架级 Scoped CSS** | Vue / Svelte `")}catch(d){console&&console.log(d)}}s=function(){var d,h=document.createElement("div");h.innerHTML=e._iconfont_svg_string_4999519,(h=h.getElementsByTagName("svg")[0])&&(h.setAttribute("aria-hidden","true"),h.style.position="absolute",h.style.width=0,h.style.height=0,h.style.overflow="hidden",h=h,(d=document.body).firstChild?c(h,d.firstChild):d.appendChild(h))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(s,0):(o=function(){document.removeEventListener("DOMContentLoaded",o,!1),s()},document.addEventListener("DOMContentLoaded",o,!1)):document.attachEvent&&(i=s,r=e.document,a=!1,f(),r.onreadystatechange=function(){r.readyState=="complete"&&(r.onreadystatechange=null,u())})}function u(){a||(a=!0,i())}function f(){try{r.documentElement.doScroll("left")}catch{return void setTimeout(f,50)}u()}})(window));var Eh=` + + `,xh=` + + `,Yi=` + + + + `,Jc=` + + `,j7=` + + `,zf=` + + + + + + + + + + + + + + `,U7=` + + `,jf=` + + + + + `,W7=` + ICP备案号 + + + `,q7=` + + `,K7=` + + `,Uf=` + + `,Gi=` + + + + + `,Y7=` + 主题 + + `,Wf=` + + + + + + + + + + + + + + + + + + + `,Ah=` + + + `,G7=` + + + + `,J7=` + + `,X7=` + + `,Xc=` + + `,Qc=` + + `,Q7=` + + `,qf=` + + + `,$h=` + +`,Z7=` + +`,e9=` + + `,t9=` + + `,Lh=` + + `,n9=` + + `,s9=` + + `,o9=` + + `,i9=` + + `,Ih=` + + `,Kf=``,Yf=``,r9=` + + `,a9=` + + `,l9=` + + `,Gf=` + + `,Ph=` + + `,c9=` + + `,Mh=` + + `,u9=` + + `,f9=` + + `,d9=` + + `,h9=` + + `,p9=` + + `,Fh=` + + `,Bh=` + + `,m9=` + + `,g9=` + + + `,v9=` + + + `,Vr=` + + + + + + `,Nh=` + + + + + + `,y9=` + + `,b9=` + + `,k9=` + + + + + `,w9=` + + `,C9=` + + + + + + `,_9=` + + + + + `,Vh=` + + + + + `,S9=` + + `;const jn=e=>Ci()?(uc(e),!0):!1,Ve=(e,t,n,s)=>{const o=[],i=()=>{o.forEach(f=>f()),o.length=0},r=(f,d,h,m)=>(f.addEventListener(d,h,m),()=>f.removeEventListener(d,h,m)),a=F(()=>{if(!me)return;const f=Se(e)||window;return f?.$el??f}),c=te(a,f=>{i(),f&&o.push(r(f,t,n,s))},{flush:"post",immediate:!0}),u=()=>{c(),i()};return jn(i),u};let Jf=!1;const T9=(e,t,n={})=>{const{ignore:s=[],capture:o=!0,detectIframe:i=!1,controls:r=!1}=n;if(!me)return r?{stop:()=>{},cancel:()=>{},trigger:()=>{}}:()=>{};if(M7()&&!Jf){Jf=!0;const v={passive:!0};Array.from(window.document.body.children).forEach(k=>Ve(k,"click",()=>{},v)),Ve(window.document.documentElement,"click",()=>{},v)}let a=!0;const c=v=>Se(s).some(k=>{if(typeof k=="string")return Array.from(window.document.querySelectorAll(k)).some(b=>b===v.target||v.composedPath().includes(b));{const b=Se(k);return b&&(v.target===b||v.composedPath().includes(b))}});function u(v){const k=Se(v);return k&&k.$.subTree.shapeFlag===16}function f(v,k){const b=Se(v),C=b.$.subTree&&b.$.subTree.children;return C==null||!Array.isArray(C)?!1:C.some(y=>y.el===k.target||k.composedPath().includes(y.el))}const d=v=>{const k=Se(e),b=k?.$el??k;if(v.target!=null&&!(!(b instanceof Element)&&u(e)&&f(e,v))&&!(!b||b===v.target||v.composedPath().includes(b))){if("detail"in v&&v.detail===0&&(a=!c(v)),!a){a=!0;return}t(v)}};let h=!1;const m=[Ve(window,"click",v=>{h||(h=!0,setTimeout(()=>{h=!1},0),d(v))},{passive:!0,capture:o}),Ve(window,"pointerdown",v=>{const k=Se(e),b=k?.$el??k;a=!c(v)&&!!(b&&!v.composedPath().includes(b))},{passive:!0}),i&&Ve(window,"blur",v=>{setTimeout(()=>{const k=Se(e),b=k?.$el??k;window.document.activeElement?.tagName==="IFRAME"&&!b?.contains(window.document.activeElement)&&t(v)},0)},{passive:!0})].filter(Boolean),g=()=>m.forEach(v=>v());return r?{stop:g,cancel:()=>{a=!1},trigger:v=>{a=!0,d(v),a=!1}}:g},Bo=(e,t={})=>{const{sync:n=!1,nexTick:s=!0}=t,o=He(!1),i=dt();return i?be(()=>{o.value=!0,e?.()},i):n?e?.():s&&ze(()=>e?.()),o},E9=()=>{const{theme:e}=Ae(),t=Dn({id:"",top:-1}),n=()=>{const o=document.querySelectorAll(".content-container .main :is(h1, h2, h3, h4, h5, h6)");for(let i=0;i{Ve(window,"scroll",n)}),{startWatch:()=>{e.value.anchorScroll!==!1&&te(()=>t.id,o=>{!me||!o||window.history.replaceState(history.state||null,"",`#${o}`)})}}},x9=9999,A9=9999,$9=9999,L9=9999,I9={site_pv:9999,site_uv:9999,page_pv:9999,page_uv:9999},P9={site_pv:9999,site_uv:9999,page_pv:9999,page_uv:9999},Oh=(e=!1,t={})=>{const{url:n,provider:s="busuanzi",tryRequest:o=!1,tryCount:i=5,tryIterationTime:r=2e3,requestFn:a}=t,c=j(0),u=j(0),f=j(0),d=j(0),h=j({site_pv:0,site_uv:0,page_pv:0,page_uv:0}),m=j({site_pv:0,site_uv:0,page_pv:0,page_uv:0}),g=j(!0),v=()=>{if(!me||g.value===!1)return;g.value=!1,(async b=>{if(a){const C=await a(b,Zc);return window.dispatchEvent(new CustomEvent("views",{detail:C})),Promise.resolve(C)}switch(s){case"busuanzi":return Xf(b);case"vercount":return M9(b);default:return Xf(b)}})(n||void 0).then(b=>{c.value=b.site_pv||x9,u.value=b.site_uv||A9,f.value=b.page_pv||$9,d.value=b.page_uv||L9,h.value=b.today||I9,m.value=b.yesterday||P9,g.value=!0,window.dispatchEvent(new CustomEvent("views",{detail:b}))})};if(e&&ze(v),o){let k=0;const b=y=>{y&&(clearInterval(y),y=null)},C=setInterval(()=>{if(g.value)return b(C);v(),k+=r,k>r*i&&b(C)},r);jn(()=>b(C))}return{sitePv:It(c),siteUv:It(u),pagePv:It(f),pageUv:It(d),today:It(h),yesterday:It(m),isGet:It(g),request:v}},Zc=(e,t=!0)=>{const n=document.createElement("script");return n.type="text/javascript",n.defer=!0,n.src=e,t&&document.body.appendChild(n),n},Xf=(e="//busuanzi.ibruce.info/busuanzi?jsonpCallback=BusuanziCallback")=>{const t="BusuanziCallback_"+Math.floor(1099511627776*Math.random());e=e.replace("=BusuanziCallback","="+t);const n=Zc(e);n.referrerPolicy="no-referrer-when-downgrade";let s;return window[t]=o=>s=o,new Promise((o,i)=>{n.onload=()=>{o(s),setTimeout(()=>{document.body.removeChild(n)},10)},n.onerror=()=>i("Error Loading "+e)})},M9=async(e="//events.vercount.one/js",t=5e3)=>{localStorage.removeItem("visitorCountData");const n=Zc(e);return new Promise((s,o)=>{n.onload=()=>{let r=t/500;const a=setInterval(()=>{r--,r<=0&&(clearInterval(a),s({}));const c=localStorage.getItem("visitorCountData");c&&(clearInterval(a),s(JSON.parse(c)))},500);setTimeout(()=>{document.body.removeChild(n)},10)},n.onerror=()=>o("Error Loading "+e)})},Dh=(e=1500)=>{const t=j(!1),n=j(""),s=j(!1);me&&navigator.clipboard&&document.execCommand,s.value=!0;const o=async(r,a=-1)=>{if(!me)return;if(navigator.clipboard)return await navigator.clipboard.writeText(r).then(()=>{n.value=r,t.value=!0,i()});const c=document.createElement("input");c.setAttribute("readonly","readonly"),c.setAttribute("value",r),document.body.appendChild(c),c.select(),a>0&&c.setSelectionRange(0,a),document.execCommand("copy")&&(n.value=r,document.execCommand("copy"),t.value=!0,i()),document.body.removeChild(c)},i=()=>{setTimeout(()=>{t.value=!1},e)};return{copy:o,text:n,copied:t,isSupported:s}};var Ya={namespace:"tk"};const ie=(e="",t)=>{const n=Ya.namespace,s=b=>h(n,e,b),o=b=>h(n,e,"",b),i=b=>h(n,e,"","",b),r=(b,C)=>h(n,e,b,C),a=(b,C)=>h(n,e,b,"",C),c=(b,C)=>h(n,e,"",b,C),u=(b,C,y)=>h(n,e,b,C,y),f=(b,C=!0)=>C?`is-${b}`:"",d=(b,C=!0)=>C?`has-${b}`:"",h=(b,C,y,_,x)=>{let P=`${b}-${C}`;return y&&(P+=`-${y}`),_&&(P+=`__${_}`),x&&(P+=`--${x}`),P},m=b=>`${n}-${b}`,g=b=>`var(--${n}-${b})`,v=b=>`--${n}-${b}`,k=(...b)=>`${n}:${b.join(":")}`;return{namespaceModule:Ya,namespace:Ya.namespace,b:s,e:o,m:i,be:r,bm:a,em:c,bem:u,is:f,has:d,createBem:h,join:m,cssVar:g,cssVarName:v,storageKey:k}},es=(e,t=0,n=!1)=>{let s;return(...o)=>{n&&!s&&e(...o);const r=()=>{s&&(clearTimeout(s),s=null)},a=()=>{r(),n||e(...o)};r(),s=setTimeout(a,t)}},Pl=(e,t={})=>{const{delayEnter:n=0,delayLeave:s=0}=t,o=He(!1);let i;const r=a=>{const c=a?n:s;i&&(clearTimeout(i),i=null),c?i=setTimeout(()=>o.value=a,c):o.value=a};return me&&(Ve(e,"mouseenter",()=>r(!0),{passive:!0}),Ve(e,"mouseleave",()=>r(!1),{passive:!0})),o};var F9={lang:"zh-CN",tk:{archives:{label:"归档页",title:"归档",totalCount:"总共 {count} 篇文章",year:"年",month:"月",count:"篇",notFound:"未指定"},articleAnalyze:{label:"文章分析",wordCount:"文章字数",readingTime:"预计阅读时长",pageView:"浏览量"},articleAppreciation:{label:"文章赞赏",contentLabel:"赞赏方式"},articleBreadcrumb:{label:"文章面包屑",home:"首页"},breadcrumb:{label:"面包屑"},articleInfo:{label:"文章信息",author:"作者",createTime:"创建时间",updateTime:"更新时间",category:"分类",tag:"标签"},articleOverview:{label:"文章清单",overview:" 清单",category:" 目录",name:"文章目录",title:"文章标题",date:"发布时间",wordCount:"文章字数",readingTime:"预阅读时长"},articleShare:{label:"文章分享",text:"分享此页面",copiedText:"链接已复制"},articleTitle:{label:"文章标题"},articleUpdate:{label:"最近更新"},catalogue:{label:"目录页",title:"目录"},demoCode:{playground:"在 Playground 中编辑",github:"在 Github 中编辑",copy:"复制代码",collapseSource:"查看源代码",expandSource:"隐藏源代码",notSupport:"浏览器不支持复制",copySuccess:"复制成功",copyFail:"复制失败"},footerInfo:{label:"页脚信息",socialLabel:"社交媒体",infoLabel:"页脚内容"},home:{label:"首页",postLabel:"文章列表",cardLabel:"侧边卡片栏"},homeBanner:{label:"首页横幅",wavesLabel:"首页横幅波浪",bgImgLabel:"首页横幅背景图",maskLabel:"首页横幅遮罩层",bgPureLabel:"首页横幅背景色",contentLabel:"首页横幅内容",titleLabel:"首页横幅标题",descLabel:"首页横幅描述",descSwitchLabel:"描述动态切换",descTypedLabel:"描述打字机效果",featureLabel:"首页横幅功能特性"},homePost:{label:"文章列表",emptyLabel:"暂无文章",pageLabel:"分页导航",moreLabel:"阅读全文 >",pin:"置顶:{sticky}",pinLabel:"置顶标志",excerptLabel:"文章摘要",infoLabel:"文章信息",coverImgLabel:"文章封面图"},pageCard:{label:"首页卡片",prev:"上一页",next:"下一页"},categoryCard:{pageTitle:"{icon}全部分类",homeTitle:"{icon}文章分类",label:"首页分类卡片",emptyLabel:"暂无文章分类",listLabel:"分类列表",moreLabel:"更多 ..."},docAnalysisCard:{title:"{icon}站点信息",totalPosts:"文章数目",weekAddNum:"近一周新增",monthAddNum:"近一月新增",runtime:"已运行时间",totalWordCount:"本站总字数",lastActiveTime:"最后活动时间",viewCount:"本站被访问了",visitCount:"本站曾来访过",fileUnit:"篇",runtimeLess:"不到一天",runtimeUnit:"天",wordCountUnit:"字",viewCountUnit:"次",visitCountUnit:"人",label:"首页站点分析卡片"},friendLinkCard:{title:"{icon}友情链接",emptyLabel:"暂无友情链接",label:"首页友情链接卡片",listLabel:"友情链接列表"},myCard:{label:"我的信息卡片",avatarAlt:"博主头像",avatarTitle:"我好看吗",socialLabel:"社交链接",bloggerLabel:"博主信息"},tagCard:{pageTitle:"{icon}全部标签",homeTitle:"{icon}热门标签",label:"首页标签卡片",emptyLabel:"暂无标签",listLabel:"标签列表",moreLabel:"更多 ..."},topArticleCard:{title:"{icon}精选文章",label:"首页精选文章卡片",emptyLabel:"暂无精选文章",listLabel:"精选文章列表"},image:{error:"加载失败"},notice:{label:"公告栏",title:"公告",openLabel:"打开公告弹窗",closeLabel:"关闭公告弹窗",headLabel:"公告头部区域",contentLabel:"公告内容"},pagination:{goto:"前往",pagesize:"条/页",total:"共 {total} 条",pageClassifier:"页",page:"页",prev:"上一页",next:"下一页",currentPage:"第 {pager} 页",prevPages:"向前 {pager} 页",nextPages:"向后 {pager} 页"},rightBottomButton:{backTopTitle:"返回顶部",themeSizeTitle:"主题尺寸切换",themeStyleTitle:"主题风格切换",toComment:"前往评论"},themeEnhance:{title:"布局增强",layoutSwitch:{title:"布局切换",helpDesc:"调整 VitePress 的布局样式,以适配不同的阅读习惯和屏幕环境。",fullWidthTipTitle:"全部展开",fullWidthHelpTipContent:"使侧边栏和内容区域占据整个屏幕的全部宽度。",sidebarWidthAdjustableOnlyTipTitle:"全部展开,但侧边栏宽度可调",sidebarWidthAdjustableOnlyHelpTipContent:"侧边栏宽度可调,但内容区域宽度不变,调整后的侧边栏将可以占据整个屏幕的最大宽度。",bothWidthAdjustableTipTitle:"全部展开,且侧边栏和内容区域宽度均可调",bothWidthAdjustableHelpTipContent:"侧边栏和内容区域宽度均可调,调整后的侧边栏和内容区域将可以占据整个屏幕的最大宽度。",originalWidthTipTitle:"原始宽度",originalWidthHelpTipContent:"原始的 VitePress 默认布局宽度"},docLayoutMaxWidth:{title:"文档内容最大宽度",helpDesc:"调整 VitePress 布局中文档内容区域的宽度,以适配不同的阅读习惯和屏幕环境。",helpTipTitle:"调整文档内容最大宽度",helpTipContent:"一个可调整的滑块,用于选择和自定义文档内容最大宽度。"},pageLayoutMaxWidth:{title:"页面最大宽度",helpDesc:"调整 VitePress 布局中页面的宽度,以适配不同的阅读习惯和屏幕环境。",helpTipTitle:"调整页面最大宽度",helpTipContent:"一个可调整的滑块,用于选择和自定义页面最大宽度。"},themeColor:{title:"主题色",speedLabel:"扩散",vpLabel:"VitePress 主题",epLabel:"ElementPlus 主题",vpTip:"VitePress 主题",epTip:"ElementPlus 主题",defaultLabel:"预设",blueLabel:"蓝色",greenLabel:"绿色",yellowLabel:"黄色",redLabel:"红色",helpDesc:"提供 VitePress 的基础色板和 ElementPlus 的基础色板进行选择,通过扩散开关可以将主题色扩散至其他元素,如侧边栏背景色、字体色等",vpHelpTipTitle:"VitePress 基础色板",vpHelpTipContent:"提供蓝(预设)、绿、黄、红 4 种 VitePress 基础色板",epHelpTipTitle:"ElementPlus 基础色板",epHelpTipContent:"提供蓝、绿、黄、红 4 种 ElementPlus 基础色板"},spotlight:{title:"聚光灯",helpDesc:"支持在正文中高亮当前鼠标悬停的行和元素,以优化阅读和专注困难的用户的阅读体验。",onTipTitle:"开启",onHelpTipContent:"开启聚光灯。",offTipTitle:"关闭",offHelpTipContent:"关闭聚光灯。"},spotlightStyles:{title:"聚光灯样式",helpDesc:"调整聚光灯的样式。",asideTipTitle:"置于侧边",asideHelpTipContent:"在当前鼠标悬停的元素旁边添加一条固定的纯色线以突出显示当前鼠标悬停的位置。",underTipTitle:"置于底部",underHelpTipContent:"在当前鼠标悬停的元素下方添加一个纯色背景以突出显示当前鼠标悬停的位置。"}},login:{label:"登录页",reset:"重置",login:"登录",loginSuccess:"登录成功!",loginError:"用户名或者密码错误!",loginInfoNonNull:"请输入用户名和密码!",usernamePlaceholder:"请输入用户名",passwordPlaceholder:"请输入密码",verifyCodePlaceholder:"请输入验证码",verifyCodeNonNull:"请输入验证码",verifyCodeError:"请输入正确的验证码"},riskLink:{label:"风险链接提示页",title:"即将离开 {name},请注意财产安全",linkIllegal:"链接安全性校验中,请稍后 ...",confirmButtonText:"继续访问"},sidebarTrigger:{label:"侧边栏展开/折叠"}}};const Rh=Symbol("localeContextKey"),ge=e=>{const t=qe(Rh,j()),n=F(()=>t?.value||F9),s=F(()=>n.value.lang),o=Ye(n)?n:j(n),i=(r,a,c)=>O7(c,r,r).replace(/\{(\w+)\}/g,(u,f)=>`${a?.[f]??`{${f}}`}`);return{lang:s,locale:o,t:(r,a)=>i(r,a,n.value),translate:i}},Xt=(e,t=!0)=>{const n=He(!1);Bo(()=>{n.value=window&&"matchMedia"in window&&typeof window.matchMedia=="function"});const s=He(),o=He(!1),i=r=>{o.value=r.matches};return zn(()=>{n.value&&(s.value=window.matchMedia(Se(e)),o.value=s.value.matches)}),Ve(s,"change",i,{passive:!0}),F(()=>t?o.value:!o.value)},eu=(e,t={})=>{const{initialWidth:n=Number.POSITIVE_INFINITY,initialHeight:s=Number.POSITIVE_INFINITY,includeScrollbar:o=!0,type:i="inner"}=t,r=He(n),a=He(s);let c=()=>{};const u=es(()=>{if(me){if(i==="outer")r.value=window.outerWidth,a.value=window.outerHeight;else if(i==="visual"&&window.visualViewport){const{width:f,height:d,scale:h}=window.visualViewport;r.value=Math.round(f*h),a.value=Math.round(d*h)}else o?(r.value=window.innerWidth,a.value=window.innerHeight):(r.value=window.document.documentElement.clientWidth,a.value=window.document.documentElement.clientHeight);e?.(r.value,a.value)}},100);return u(),Bo(u),c=Ve(()=>window,"resize",u,{passive:!0}),me&&i==="visual"&&window.visualViewport&&(c=Ve(window.visualViewport,"resize",u,{passive:!0})),{width:r,height:a,update:u,stop:c}},B9=()=>{const e=j(0),t=j(0);let n=null;const s=()=>n||(document.querySelector("#measure-element")?.remove(),n=document.createElement("div"),n.id="measure-element",n.style.cssText=` + position: fixed; + top: -9999px; + left: 0; + width: 100px; + height: 100px; + overflow: scroll; + visibility: hidden; + `,document.body.appendChild(n),n),o=()=>{n&&document.body.contains(n)&&(document.body.removeChild(n),n=null)},i=()=>{if(!me)return;const a=document.documentElement,c=document.compatMode==="BackCompat",u=c?document.body.scrollHeight>document.body.clientHeight:a.scrollHeight>a.clientHeight,f=c?document.body.scrollWidth>document.body.clientWidth:a.scrollWidth>a.clientWidth;if(!u&&!f){e.value=0,t.value=0;return}const d=s();e.value=u?d.offsetWidth-d.clientWidth:0,t.value=f?d.offsetHeight-d.clientHeight:0},r=()=>{i()};return Ve(()=>window,"resize",r),Bo(()=>{s(),i()}),i(),jn(o),{width:e,height:t,update:r}},xt="auto",fs=10,N9=(e,t,n={})=>{const{placement:s="bottom",offset:o=0,xOffset:i=0,yOffset:r=0}=n,a=j(xt),c=j(xt),u=j(xt),f=j(xt),{width:d,height:h}=eu(),{width:m,height:g}=B9(),v=F(()=>{const y=Se(e);return y?.$el??y}),k=F(()=>{const y=Se(t);return y?.$el??y}),b=async()=>{if(!me||!v.value||!k.value)return;await ze();const{top:y,right:_,bottom:x,left:P,width:V,height:E}=v.value.getBoundingClientRect(),L=d.value-_,I=h.value-x,N=k.value.offsetWidth,$=k.value.offsetHeight,U=window.scrollX+(o||i),q=window.scrollY+(o||r);let J=xt,G=xt,ae=xt,ne=xt;const he=["top","bottom"].some(gt=>s.startsWith(gt)),st=["left","right"].some(gt=>s.startsWith(gt)),je=()=>y+E+q,yt=()=>L+V-U-m.value,Un=()=>I+E-q-g.value,cs=()=>P+V+U;he?s.endsWith("start")?ne=cs()-V:s.endsWith("end")?G=yt()-V:ne=P+V/2-N/2+U:st&&(s.endsWith("start")?J=je()-E:s.endsWith("end")?ae=Un()-E:J=y+E/2-$/2+q),s.startsWith("top")?ae=Un()+fs:s.startsWith("right")?ne=cs()+fs:s.startsWith("bottom")?J=je()+fs:s.startsWith("left")&&(G=yt()+fs);const Zs=()=>!Je(ae)&&ae+$>h.value-q,we=()=>!Je(ne)&&ne+N>d.value+U,Ne=()=>!Je(J)&&J+$>h.value+q,Ke=()=>!Je(G)&&G+N>d.value-U;Zs()&&(J=(st?je()-E:je())+fs,Ne()?J=xt:ae=xt),Ne()&&(ae=(st?Un()-E:Un())+fs,Zs()?ae=xt:J=xt),we()&&(G=(he?yt()-V:yt())+fs,Ke()?G=xt:ne=xt),Ke()&&(ne=(he?cs()-V:cs())+fs,we()?ne=xt:G=xt),a.value=J,c.value=G,u.value=ae,f.value=ne};b();const C=()=>{b()};return Ve(()=>window,"scroll",C),Ve(()=>window,"resize",C),{top:a,right:c,bottom:u,left:f,update:C}},V9=(e,t,n={})=>{const{intervalTime:s=3e3,reloadWhenDataChanged:o=!1}=n,i=F(()=>Se(e)||[]),r=j(i.value.slice(0,t));let a=t,c=null;const u=()=>{const m=(a+1)%i.value.length;r.value.push(i.value[m]),r.value.shift(),a=m},f=()=>{u(),c=setInterval(()=>{u()},s)},d=(m=!1)=>{c&&(clearInterval(c),c=null),m&&(r.value=i.value.slice(0,t),a=t)},h=()=>{d(!0),f()};return o&&te(i,()=>h()),jn(d),{data:r,start:f,stop:d,restart:h}},O9={boolean:{read:e=>e==="true",write:e=>String(e)},object:{read:e=>JSON.parse(e),write:e=>JSON.stringify(e)},number:{read:e=>Number.parseFloat(e),write:e=>String(e)},any:{read:e=>e,write:e=>String(e)},string:{read:e=>e,write:e=>String(e)},map:{read:e=>new Map(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e.entries()))},set:{read:e=>new Set(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e))},date:{read:e=>new Date(e),write:e=>e.toISOString()}},D9=e=>e==null?"any":e instanceof Set?"set":e instanceof Map?"map":e instanceof Date?"date":typeof e=="boolean"?"boolean":typeof e=="string"?"string":typeof e=="number"?"number":typeof e=="object"?"object":"any",bn=(e,t,n="localStorage",s={})=>{const{flush:o="pre",deep:i=!0,writeDefaults:r=!0,mergeDefaults:a=!1,initOnMounted:c}=s,u=Se(t),f=j(u);if(!me)return f;const d=D9(u),h=O9[d],m=F(()=>Se(e)),g=n==="localStorage"?localStorage:sessionStorage;te(m,()=>C(),{flush:o}),te(f,()=>k(f.value),{flush:o,deep:i}),Bo(()=>{c&&C()});const v=(y,_)=>{if(window){const x={key:m.value,oldValue:y,newValue:_,storageArea:g};window.dispatchEvent(new StorageEvent("storage",x))}},k=y=>{const _=g.getItem(m.value);if(y==null)v(_,null),g.removeItem(m.value);else{const x=h.write(y);_!==x&&(g.setItem(m.value,x),v(_,x))}},b=y=>{const _=y?y.newValue:g.getItem(m.value);if(_==null)return r&&u!=null&&g.setItem(m.value,h.write(u)),u;if(!y&&a){const x=h.read(_);return typeof a=="function"?a(x,u):d==="object"&&!Array.isArray(x)?{...u,...x}:x}return typeof _!="string"?_:h.read(_)},C=y=>{if(!(y&&y.storageArea!==g)){if(y&&y.key==null){f.value=u;return}y&&y.key!==m.value||y?.newValue!==h.write(f.value)&&(f.value=b(y))}};return c||C(),Ve(()=>window,"storage",C,{passive:!0}),f},tu=(e,t={})=>{const{timeout:n=4e3,shuffle:s=!1,reloadWhenDataChanged:o=!1,onBeforeUpdate:i,onUpdate:r,onAfterUpdate:a}=t,c=F(()=>Se(e)||[]),u=j(-1);let f;const d=y=>{let _;do _=Math.floor(Math.random()*y.length);while(_===u.value);return u.value=_,y[_]},h=j(s?d(c.value):c.value[0]),m=y=>(u.value=(u.value+1)%y.length,y[u.value]),g=()=>{f&&(clearTimeout(f),f=null)},v=()=>{g(),n>0&&(f=setTimeout(k,n))},k=()=>{const y=c.value;if(y.length<1)return;if(y.length===1){h.value=y[0];return}v();let _;if(s?_=d(y):_=m(y),_!==h.value){if(i?.(_),r)return r(h,_);h.value=_,a?.(_)}},b=(y=!1)=>{g(),y&&(u.value=-1)},C=()=>{b(!0),k()};return o&&te(c,()=>C()),jn(b),{data:h,index:u,start:k,stop:b,restart:C}},R9=(e,t={})=>{const{inputTime:n=200,outputTime:s=100,nextTime:o=800,shuffle:i=!1,reloadWhenDataChanged:r=!1}=t,a=F(()=>Se(e)||[]),c=j(""),u=j(!1);let f="",d,h,m=0,g=0;const v=()=>{d&&(clearInterval(d),d=null)},k=()=>{h&&(clearInterval(h),h=null)},b=()=>{if(u.value=!1,f=a.value[g],!f)return _();c.value=f.substring(0,m++),m>f.length&&(v(),u.value=!0,setTimeout(()=>{h=setInterval(()=>{C()},s)},o))},C=()=>{m>=0?(u.value=!1,c.value=f.substring(0,m--)):(k(),u.value=!0,setTimeout(()=>{if(i){let P;do P=Math.floor(Math.random()*a.value.length);while(P===g);g=P}else g=(g+1)%a.value.length;d=setInterval(()=>{b()},n)},o))},y=()=>{u.value=!1,d=setInterval(()=>{b()},n)},_=(P=!1)=>{v(),k(),u.value=!1,P&&(c.value="",f="",m=0,g=0)},x=()=>{_(!0),y()};return r&&te(a,()=>x()),jn(_),{text:c,isFinished:u,start:y,stop:_,restart:x}},Ml="--vp-c-brand-1",Fl="--vp-c-brand-2",Bl="--vp-c-brand-3",Nl="--vp-c-brand-soft",Vl="--vp-c-bg",Ol="--vp-c-bg-alt",Dl="--vp-c-bg-soft",Rl="--vp-c-bg-elv",Hl="--vp-c-text-1",Hh="--vp-c-text-2",zh="--vp-c-text-3",zl="--tk-bg-color-elm",jl="--tk-bg-color-mute",on={vpBrand1:Ml,vpBrand2:Fl,vpBrand3:Bl,vpBrandSoft:Nl,vpBg:Vl,vpBgAlt:Ol,vpBgSoft:Dl,vpBgElv:Rl,vpText1:Hl,vpText2:Hh,vpText3:zh,tkBgColorElm:zl,tkBgColorMute:jl},jh=(e,t)=>{const n=j(!1),{isDark:s}=Ae(),o=(v,k)=>{me&&document.documentElement.style.setProperty(v,k)},i=v=>{me&&document.documentElement.style.removeProperty(v)},r=F(()=>Se(e)),a=()=>{Object.values(on).forEach(v=>{i(v)})},c=()=>{if(!me)return;const v=r.value;if(!v)return;const k={[Ml]:v,[Fl]:_n(v,.1),[Bl]:_n(v,.2),[Nl]:_n(v,.85)},b={[Vl]:_n(v,.96),[Ol]:_n(v,.93),[Rl]:_n(v,.945),[Dl]:_n(v,.93),[Hl]:Cn(v,.6),[Hh]:Cn(v,.7),[zh]:_n(v,.6),[zl]:_n(v,.945),[jl]:_n(v,.91)},C=ht(t)?t():t||[];Object.keys(k).forEach(y=>{C?.includes(y)||o(y,k[y])}),n.value&&Object.keys(b).forEach(y=>{C?.includes(y)||o(y,b[y])})},u=()=>{if(!me)return;const v=r.value;if(!v)return;const k={[Ml]:v,[Fl]:Cn(v,.1),[Bl]:Cn(v,.2),[Nl]:Cn(v,.85)},b={[Vl]:Cn(v,.92),[Ol]:Cn(v,.94),[Rl]:Cn(v,.92),[Dl]:Cn(v,.94),[Hl]:_n(v,.9),[zl]:Cn(v,.92),[jl]:Cn(v,.91)},C=ht(t)?t():t||[];Object.keys(k).forEach(y=>{C?.includes(y)||o(y,k[y])}),n.value&&Object.keys(b).forEach(y=>{C?.includes(y)||o(y,b[y])})},f=He(!1);let d=null;const h=()=>{!f.value||d||(f.value=!1,m(),d=te(s,m,{flush:"post"}))},m=()=>{f.value||(a(),s.value?u():c())},g=()=>{d?.(),d=null,f.value=!0,a()};return h(),te(r,m),te(n,()=>{g(),h()}),{isSpread:It(n),start:h,stop:g,update:m,clear:a,updateSpread:v=>n.value=v}},H9=e=>{if(!me)return;const{enabled:t=!0,mode:n="out-in",duration:s=e.mode==="out-in"?300:600,easing:o="ease-in"}=e;if(!t)return;const i=n==="out-in",{isDark:r}=Ae();document.documentElement.setAttribute("view-transition",n);const a=()=>"startViewTransition"in document&&window.matchMedia("(prefers-reduced-motion: no-preference)").matches;In("toggle-appearance",async({clientX:c,clientY:u})=>{if(!a()){r.value=!r.value;return}const f=[`circle(0px at ${c}px ${u}px)`,`circle(${Math.hypot(Math.max(c,innerWidth-c),Math.max(u,innerHeight-u))}px at ${c}px ${u}px)`];await document.startViewTransition(async()=>{r.value=!r.value,await ze()}).ready;const d=i?r.value:!1;document.documentElement.animate({clipPath:d?f.reverse():f},{duration:s,easing:o,fill:"forwards",pseudoElement:`::view-transition-${d?"old":"new"}(root)`})})},Is=()=>{const e=Ls(),t=(r,a,c="after")=>{const{state:u={},onBeforeRouteChange:f}=e;if(u[r])return;const d=c==="before"?a:f,h=c==="after"?a:f;e.onBeforeRouteChange=async m=>await d?.(m)===!1?!1:await h?.(m),e.state={...u,[r]:!0}},n=(r,a,c="after")=>{const{state:u={},onBeforePageLoad:f}=e;if(u[r])return;const d=c==="before"?a:f,h=c==="after"?a:f;e.onBeforePageLoad=async m=>await d?.(m)===!1?!1:await h?.(m),e.state={...u,[r]:!0}},s=(r,a,c="after")=>{const{state:u={},onAfterPageLoad:f}=e;if(u[r])return;const d=c==="before"?a:f,h=c==="after"?a:f;e.onAfterPageLoad=async m=>{await d?.(m),await h?.(m)},e.state={...u,[r]:!0}},o=(r,a,c="after")=>{const{state:u={},onAfterRouteChange:f}=e;if(u[r])return;const d=c==="before"?a:f,h=c==="after"?a:f;e.onAfterRouteChange=async m=>{await d?.(m),await h?.(m)},e.state={...u,[r]:!0}},i=(r,a)=>{const{state:c={}}=e;c[r]||(a(e),e.state={...c,[r]:!0})};return{router:e,route:e.route,bindBeforeRouteChange:t,bindBeforePageLoad:n,bindAfterPageLoad:s,bindAfterRouteChange:o,bindRouterFn:i}},Ca=(e,t=!0)=>{let n=!1;const s=[],o=()=>{const c=l(e);c&&(P7(c)?c.forEach(u=>i(u)):i(c))},i=c=>{c.classList.add("scroll__animate");const{create:u,clean:f}=z9(c,d=>{d.forEach(h=>{h.isIntersecting&&requestAnimationFrame(()=>{try{c.classList.add("visible"),f()}catch(m){console.error("初始化动画失败:",m)}})})},.1);u(),s.push(f)},r=()=>{s.forEach(c=>c())},a=()=>{r(),o()};return te(()=>l(e),()=>{!n&&a()},{deep:!0}),Bo(async()=>{n=!0,t&&a(),await ze(),n=!1}),jn(r),{start:o,stop:r,restart:a}},z9=(e,t,n)=>{let s=null;const o=()=>{const r=l(e);s||!r||(s=new IntersectionObserver(t,{threshold:n}),s.observe(r))},i=()=>{s&&(s.disconnect(),s=null)};return jn(i),{create:o,clean:i}},Qf={current:0},Zf=j(0),j9=2e3,ed=Symbol("tkZIndexContextKey"),U9=Symbol("zIndexContextKey"),nu=e=>{const t=dt()?qe(ed,Qf):Qf,n=dt()?qe(U9,void 0):void 0,s=F(()=>{const r=n?.value;return Gc(r)?r:j9}),o=F(()=>s.value+Zf.value),i=()=>(t.current++,Zf.value=t.current,o.value);return qe(ed,void 0)&&console.warn("ZIndexInjection",`Looks like you are using server rendering, you must provide a z-index provider to ensure the hydration process to be succeed +usage: app.provide(ZINDEX_INJECTION_KEY, { current: 0 })`),{initialZIndex:s,currentZIndex:o,nextZIndex:i}};function Uh(e){return typeof e>"u"||e===null}function W9(e){return typeof e=="object"&&e!==null}function q9(e){return Array.isArray(e)?e:Uh(e)?[]:[e]}function K9(e,t){var n,s,o,i;if(t)for(i=Object.keys(t),n=0,s=i.length;n=0?"0b"+e.toString(2):"-0b"+e.toString(2).slice(1)},octal:function(e){return e>=0?"0o"+e.toString(8):"-0o"+e.toString(8).slice(1)},decimal:function(e){return e.toString(10)},hexadecimal:function(e){return e>=0?"0x"+e.toString(16).toUpperCase():"-0x"+e.toString(16).toUpperCase().slice(1)}},defaultStyle:"decimal",styleAliases:{binary:[2,"bin"],octal:[8,"oct"],decimal:[10,"dec"],hexadecimal:[16,"hex"]}}),xy=new RegExp("^(?:[-+]?(?:[0-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?|\\.[0-9_]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$");function Ay(e){return!(e===null||!xy.test(e)||e[e.length-1]==="_")}function $y(e){var t,n;return t=e.replace(/_/g,"").toLowerCase(),n=t[0]==="-"?-1:1,"+-".indexOf(t[0])>=0&&(t=t.slice(1)),t===".inf"?n===1?Number.POSITIVE_INFINITY:Number.NEGATIVE_INFINITY:t===".nan"?NaN:n*parseFloat(t,10)}var Ly=/^[-+]?[0-9]+e/;function Iy(e,t){var n;if(isNaN(e))switch(t){case"lowercase":return".nan";case"uppercase":return".NAN";case"camelcase":return".NaN"}else if(Number.POSITIVE_INFINITY===e)switch(t){case"lowercase":return".inf";case"uppercase":return".INF";case"camelcase":return".Inf"}else if(Number.NEGATIVE_INFINITY===e)switch(t){case"lowercase":return"-.inf";case"uppercase":return"-.INF";case"camelcase":return"-.Inf"}else if(su.isNegativeZero(e))return"-0.0";return n=e.toString(10),Ly.test(n)?n.replace("e",".e"):n}function Py(e){return Object.prototype.toString.call(e)==="[object Number]"&&(e%1!==0||su.isNegativeZero(e))}var My=new Ft("tag:yaml.org,2002:float",{kind:"scalar",resolve:Ay,construct:$y,predicate:Py,represent:Iy,defaultStyle:"lowercase"}),Fy=fy.extend({implicit:[my,by,Ey,My]}),By=Fy,qh=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"),Kh=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$");function Ny(e){return e===null?!1:qh.exec(e)!==null||Kh.exec(e)!==null}function Vy(e){var t,n,s,o,i,r,a,c=0,u=null,f,d,h;if(t=qh.exec(e),t===null&&(t=Kh.exec(e)),t===null)throw new Error("Date resolve error");if(n=+t[1],s=+t[2]-1,o=+t[3],!t[4])return new Date(Date.UTC(n,s,o));if(i=+t[4],r=+t[5],a=+t[6],t[7]){for(c=t[7].slice(0,3);c.length<3;)c+="0";c=+c}return t[9]&&(f=+t[10],d=+(t[11]||0),u=(f*60+d)*6e4,t[9]==="-"&&(u=-u)),h=new Date(Date.UTC(n,s,o,i,r,a,c)),u&&h.setTime(h.getTime()-u),h}function Oy(e){return e.toISOString()}var Dy=new Ft("tag:yaml.org,2002:timestamp",{kind:"scalar",resolve:Ny,construct:Vy,instanceOf:Date,represent:Oy});function Ry(e){return e==="<<"||e===null}var Hy=new Ft("tag:yaml.org,2002:merge",{kind:"scalar",resolve:Ry}),ou=`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/= +\r`;function zy(e){if(e===null)return!1;var t,n,s=0,o=e.length,i=ou;for(n=0;n64)){if(t<0)return!1;s+=6}return s%8===0}function jy(e){var t,n,s=e.replace(/[\r\n=]/g,""),o=s.length,i=ou,r=0,a=[];for(t=0;t>16&255),a.push(r>>8&255),a.push(r&255)),r=r<<6|i.indexOf(s.charAt(t));return n=o%4*6,n===0?(a.push(r>>16&255),a.push(r>>8&255),a.push(r&255)):n===18?(a.push(r>>10&255),a.push(r>>2&255)):n===12&&a.push(r>>4&255),new Uint8Array(a)}function Uy(e){var t="",n=0,s,o,i=e.length,r=ou;for(s=0;s>18&63],t+=r[n>>12&63],t+=r[n>>6&63],t+=r[n&63]),n=(n<<8)+e[s];return o=i%3,o===0?(t+=r[n>>18&63],t+=r[n>>12&63],t+=r[n>>6&63],t+=r[n&63]):o===2?(t+=r[n>>10&63],t+=r[n>>4&63],t+=r[n<<2&63],t+=r[64]):o===1&&(t+=r[n>>2&63],t+=r[n<<4&63],t+=r[64],t+=r[64]),t}function Wy(e){return Object.prototype.toString.call(e)==="[object Uint8Array]"}var qy=new Ft("tag:yaml.org,2002:binary",{kind:"scalar",resolve:zy,construct:jy,predicate:Wy,represent:Uy}),Ky=Object.prototype.hasOwnProperty,Yy=Object.prototype.toString;function Gy(e){if(e===null)return!0;var t=[],n,s,o,i,r,a=e;for(n=0,s=a.length;nz({name:"TeekConfigProvider",setup(t,{slots:n}){In(cb,Yh()),E9().startWatch();const{getTeekConfig:s}=fe(),o=s("viewTransition",{enabled:!0,mode:"out-in",easing:"ease-in"});return o.enabled&&H9(o),()=>nn(e,null,n)}}),fe=()=>{const{theme:e,frontmatter:t}=Ae(),n=qe(ub,{}),s=(i,r)=>{let a=r;if(ht(r)&&(a=r()),!i)return{...a,...e.value,...t.value,...t.value.tk,...l(n)};const c=e.value[i],u=t.value.tk?.[i]??t.value[i],f=l(n)?.[i];return ei(c)||ei(u)||ei(f)?{...a,...c,...u,...f}:f??u??c??a};return{getTeekConfig:s,getTeekConfigRef:(i,r)=>F(()=>s(i,r))}},iu=()=>{const{frontmatter:e}=Ae(),t=F(()=>!n.value&&!s.value&&e.value.layout==="home"),n=F(()=>!!e.value.categoriesPage),s=F(()=>!!e.value.tagsPage),o=F(()=>!!e.value.archivesPage),i=F(()=>!!e.value.catalogue),r=F(()=>!!e.value.articleOverviewPage),a=F(()=>!!e.value.loginPage),c=F(()=>!!e.value.riskLinkPage);return{isHomePage:t,isCategoriesPage:n,isTagsPage:s,isArchivesPage:o,isCataloguePage:i,isArticleOverviewPage:r,isLoginUrl:a,isRiskLinkPage:c}},$i=()=>{const{getTeekConfigRef:e}=fe(),{localeIndex:t,site:n}=Ae(),s=Pn(),o=e("category",{path:"/categories"}),i=e("tag",{path:"/tags"}),r=F(()=>{const u=t.value;return`${u!=="root"?`/${u}`:""}${o.value.path}${n.value.cleanUrls?"":".html"}`}),a=F(()=>{const u=t.value;return`${u!=="root"?`/${u}`:""}${i.value.path}${n.value.cleanUrls?"":".html"}`}),c=F(()=>{let u="",f="",d="",h="";return s.value.allPosts.forEach(m=>{const{frontmatter:{layout:g,archivesPage:v,articleOverviewPage:k,loginPage:b,riskLinkPage:C},url:y}=m,_=g==="page";(g==="TkCataloguePage"||_&&v===!0)&&(u=y),(g==="TkArticleOverviewPage"||_&&k===!0)&&(f=y),g===!1&&b===!0&&(d=y),g===!1&&C===!0&&(h=y)}),{archivesUrl:u,articleOverviewUrl:f,loginUrl:d,riskLinkUrl:h}});return{categoryPath:r,tagPath:a,archivesPath:F(()=>c.value.archivesUrl),articleOverviewPath:F(()=>c.value.articleOverviewUrl),loginPath:F(()=>c.value.loginUrl),riskLinkPath:F(()=>c.value.riskLinkUrl)}},Yh=()=>{const{theme:e}=Ae();return e.value.posts||lb},Pn=()=>{const{localeIndex:e}=Ae(),t=Yh();return F(()=>t.locales?.[e.value]||t)},Gh=()=>{const{getTeekConfigRef:e}=fe();return e("tagColor",[{border:"#bfdbfe",bg:"#eff6ff",text:"#2563eb"},{border:"#e9d5ff",bg:"#faf5ff",text:"#9333ea"},{border:"#fbcfe8",bg:"#fdf2f8",text:"#db2777"},{border:"#a7f3d0",bg:"#ecfdf5",text:"#059669"},{border:"#fde68a",bg:"#fffbeb",text:"#d97706"},{border:"#a5f3fc",bg:"#ecfeff",text:"#0891b2"},{border:"#c7d2fe",bg:"#eef2ff",text:"#4f46e5"}])},_a=e=>{const{getTeekConfigRef:t}=fe(),n=t("windowTransition",!0);return F(()=>{const s=n.value;return s===void 0?!0:ei(s)?e?.(s)??!0:s!==!1})},Jh=()=>({isMobile:Xt("(max-width: 768px)")}),Xh=()=>{const e=j(!0),t=kn();return te(()=>t.path,async()=>{if(!me)return;await ze(),document.querySelector(".VPSidebar")?e.value=!0:e.value=!1},{immediate:!0,flush:"post"}),{hasSidebar:e}},db=/\b(?:VPBadge|header-anchor|footnote-ref|ignore-header)\b/,Wl=[];function hb(e){return typeof e.outline=="object"&&!Array.isArray(e.outline)&&e.outline.label||"On this page"}function sd(e){const t=ie(),n=[...document.querySelectorAll(`.${t.join("article-page")} :where(h1,h2,h3,h4,h5,h6)`)].filter(s=>s.id&&s.hasChildNodes()).map(s=>{const o=Number(s.tagName[1]);return{element:s,title:pb(s),link:"#"+s.id,level:o}});return mb(n,e)}function pb(e){let t="";for(const n of e.childNodes)if(n.nodeType===1){if(db.test(n.className))continue;t+=n.textContent}else n.nodeType===3&&(t+=n.textContent);return t.trim()}function mb(e,t){if(t===!1)return[];const n=(typeof t=="object"&&!Array.isArray(t)?t.level:t)||2,[s,o]=typeof n=="number"?[n,n]:n==="deep"?[2,6]:n;return yb(e,s,o)}const gb=(e,t)=>{const n=Xt("(min-width: 1280px)"),s=es(i,100);let o=null;be(()=>{requestAnimationFrame(i),window.addEventListener("scroll",s)}),Mo(()=>{r(location.hash)}),cn(()=>{window.removeEventListener("scroll",s)});function i(){if(!n.value)return;const a=window.scrollY,c=window.innerHeight,u=document.body.offsetHeight,f=Math.abs(a+c-u)<1,d=Wl.map(({element:m,link:g})=>({link:g,top:vb(m)})).filter(({top:m})=>!Number.isNaN(m)).sort((m,g)=>m.top-g.top);if(!d.length){r(null);return}if(a<1){r(null);return}if(f){r(d[d.length-1].link);return}let h=null;for(const{link:m,top:g}of d){if(g>a+Hc()+4)break;h=m}r(h)}function r(a){o&&o.classList.remove("active"),a==null?o=null:o=e.value.querySelector(`a[href="${decodeURIComponent(a)}"]`);const c=o;c?(c.classList.add("active"),t.value.style.top=c.offsetTop+39+"px",t.value.style.opacity="1"):(t.value.style.top="33px",t.value.style.opacity="0")}};function vb(e){let t=0;for(;e!==document.body;){if(e===null)return NaN;t+=e.offsetTop,e=e.offsetParent}return t}function yb(e,t,n){Wl.length=0;const s=[],o=[];return e.forEach(i=>{const r={...i,children:[]};let a=o[o.length-1];for(;a&&a.level>=r.level;)o.pop(),a=o[o.length-1];if(r.element.classList.contains("ignore-header")||a&&"shouldIgnore"in a){o.push({level:r.level,shouldIgnore:!0});return}r.level>n||r.level{const i=un("DocAsideOutlineItem",!0);return p(),w("ul",{class:T([l(t).b(),e.root?l(t).is("root"):l(t).is("nested")])},[(p(!0),w(Y,null,le(e.headers,({children:r,link:a,title:c})=>(p(),w("li",{key:a},[S("a",{class:T(l(t).m("link")),href:a,onClick:n,title:c},W(c),11,bb),r?.length?(p(),D(i,{key:0,headers:r},null,8,["headers"])):A("v-if",!0)]))),128))],2)}}}),wb=z({name:"DocAsideOutline",__name:"DocAsideOutline",setup(e){const t=ie("aside-outline"),{frontmatter:n,theme:s}=Ae(),o=He([]);xi(()=>{o.value=sd(n.value.outline??s.value.outline)}),be(()=>{o.value?.length||(o.value=sd(n.value.outline??s.value.outline))});const i=j(),r=j();return gb(i,r),(a,c)=>(p(),w("nav",{"aria-labelledby":"doc-outline-aria-label",class:T([l(t).b(),{"has-outline":o.value.length>0}]),ref_key:"container",ref:i},[S("div",{class:T(l(t).e("content"))},[S("div",{class:T(l(t).m("marker")),ref_key:"marker",ref:r},null,2),S("div",{id:"doc-outline-aria-label","aria-level":"2",class:T(l(t).m("title")),role:"heading"},W(l(hb)(l(s))),3),H(kb,{headers:o.value,root:!0},null,8,["headers"])],2)],2))}}),ru=z({name:"ArticlePage",__name:"index",props:{doc:{type:Boolean},aside:{type:Boolean}},setup(e){const t=ie("article-page");return(n,s)=>(p(),w("div",{class:T([l(t).b(),l(t).is("aside",e.aside)])},[e.aside?(p(),w("div",{key:0,class:T(l(t).e("aside"))},[S("div",{class:T(l(t).e("aside__container"))},[H(wb)],2)],2)):A("v-if",!0),S("div",{class:T([l(t).join("doc"),{"vp-doc":e.doc}])},[S("div",null,[M(n.$slots,"default")])],2)],2))}}),Or=z({name:"TitleTag",__name:"index",props:{text:{},type:{},position:{},size:{}},setup(e){const t=ie("title-tag");return(n,s)=>e.text||n.$slots.default?(p(),w("span",{key:0,class:T([l(t).b(),e.type&&l(t).m(e.type),e.position&&l(t).m(e.position),e.size&&l(t).m(e.size)])},[M(n.$slots,"default",{},()=>[rt(W(e.text),1)])],2)):A("v-if",!0)}});const Cb=["href","aria-label"],_b=["innerHTML"],Sb=["id","aria-labelledby"],Tb=["href","aria-label"],Eb=["id"],xb=["aria-label"];var Ab=z({name:"CatalogueItem",__name:"CatalogueItem",props:{item:{},index:{}},setup(e){const t=ie("sub-catalogue"),n=ie("catalogue-item");return(s,o)=>{const i=un("CatalogueItem",!0);return p(),w("li",{class:T(e.item.children?l(t).b():l(n).b())},[e.item.children?e.item.children.length?(p(),w(Y,{key:1},[S("div",{id:e.item.title,class:T(l(t).e("title")),role:"group","aria-labelledby":`${e.item.title}-label`},[S("a",{href:`#${e.item.title}`,class:"anchor","aria-label":e.item.title},"#",8,Tb),S("span",{id:`${e.item.title}-label`},W(`${e.index}. ${e.item.title}`),9,Eb)],10,Sb),e.item.children?(p(),w("ul",{key:0,class:T(`${l(t).e("inline")} flx-wrap-between`),"aria-label":e.item.title},[A(" 递归自己 "),(p(!0),w(Y,null,le(e.item.children,(r,a)=>(p(),D(i,{key:a,item:r,index:`${e.index}-${a+1}`},null,8,["item","index"]))),128))],10,xb)):A("v-if",!0)],64)):A("v-if",!0):(p(),w("a",{key:0,href:e.item.url&&l(Ee)(e.item.url),"aria-label":`${e.index}. ${e.item.title}`},[rt(W(e.index)+". ",1),S("span",{innerHTML:e.item.title},null,8,_b),e.item.frontmatter?.titleTag?(p(),D(l(Or),{key:0,text:e.item.frontmatter?.titleTag,position:"right",size:"small","aria-label":e.item.frontmatter?.titleTag},null,8,["text","aria-label"])):A("v-if",!0)],8,Cb))],2)}}});const $b={id:"catalogue-header-title"},Lb={class:"description"},Ib={id:"catalogue-list-title",class:"title"},Pb={class:"flx-wrap-between"},Mb={class:"vp-doc"};var Qh=z({name:"CataloguePage",__name:"index",setup(e){const t=ie("catalogue"),{t:n}=ge(),{theme:s,frontmatter:o}=Ae(),i=F(()=>s.value.catalogues?.inv[o.value.path]?.catalogues);return(r,a)=>{const c=un("Content");return p(),D(l(ru),{class:T(l(t).b()),"aria-label":l(n)("tk.catalogue.label")},{default:O(()=>[M(r.$slots,"teek-catalogue-top-before"),S("div",{class:T(l(t).e("header")),role:"group","aria-labelledby":"catalogue-header-title"},[S("h2",$b,W(l(o).title),1),S("div",Lb,W(l(o).desc||l(o).description),1)],2),M(r.$slots,"teek-catalogue-top-after"),S("div",{class:T(l(t).e("wrapper")),"aria-labelledby":"catalogue-list-title"},[S("div",Ib,W(l(o).pageTitle||l(n)("tk.catalogue.title")),1),S("ul",Pb,[(p(!0),w(Y,null,le(i.value,(u,f)=>(p(),D(Ab,{key:f,item:u,index:f+1},null,8,["item","index"]))),128))])],2),S("div",Mb,[H(c)])]),_:3},8,["class","aria-label"])}}});const mi=Symbol(""),ti=Symbol(""),au=Symbol(""),Dr=Symbol(""),Zh=Symbol(""),Ks=Symbol(""),ep=Symbol(""),tp=Symbol(""),lu=Symbol(""),cu=Symbol(""),Li=Symbol(""),uu=Symbol(""),np=Symbol(""),fu=Symbol(""),du=Symbol(""),hu=Symbol(""),pu=Symbol(""),mu=Symbol(""),gu=Symbol(""),sp=Symbol(""),op=Symbol(""),Sa=Symbol(""),Rr=Symbol(""),vu=Symbol(""),yu=Symbol(""),gi=Symbol(""),Ii=Symbol(""),bu=Symbol(""),ql=Symbol(""),Fb=Symbol(""),Kl=Symbol(""),Hr=Symbol(""),Bb=Symbol(""),Nb=Symbol(""),ku=Symbol(""),Vb=Symbol(""),Ob=Symbol(""),wu=Symbol(""),ip=Symbol(""),Eo={[mi]:"Fragment",[ti]:"Teleport",[au]:"Suspense",[Dr]:"KeepAlive",[Zh]:"BaseTransition",[Ks]:"openBlock",[ep]:"createBlock",[tp]:"createElementBlock",[lu]:"createVNode",[cu]:"createElementVNode",[Li]:"createCommentVNode",[uu]:"createTextVNode",[np]:"createStaticVNode",[fu]:"resolveComponent",[du]:"resolveDynamicComponent",[hu]:"resolveDirective",[pu]:"resolveFilter",[mu]:"withDirectives",[gu]:"renderList",[sp]:"renderSlot",[op]:"createSlots",[Sa]:"toDisplayString",[Rr]:"mergeProps",[vu]:"normalizeClass",[yu]:"normalizeStyle",[gi]:"normalizeProps",[Ii]:"guardReactiveProps",[bu]:"toHandlers",[ql]:"camelize",[Fb]:"capitalize",[Kl]:"toHandlerKey",[Hr]:"setBlockTracking",[Bb]:"pushScopeId",[Nb]:"popScopeId",[ku]:"withCtx",[Vb]:"unref",[Ob]:"isRef",[wu]:"withMemo",[ip]:"isMemoSame"};function Db(e){Object.getOwnPropertySymbols(e).forEach(t=>{Eo[t]=e[t]})}const fn={start:{line:1,column:1,offset:0},end:{line:1,column:1,offset:0},source:""};function Rb(e,t=""){return{type:0,source:t,children:e,helpers:new Set,components:[],directives:[],hoists:[],imports:[],cached:[],temps:0,codegenNode:void 0,loc:fn}}function vi(e,t,n,s,o,i,r,a=!1,c=!1,u=!1,f=fn){return e&&(a?(e.helper(Ks),e.helper($o(e.inSSR,u))):e.helper(Ao(e.inSSR,u)),r&&e.helper(mu)),{type:13,tag:t,props:n,children:s,patchFlag:o,dynamicProps:i,directives:r,isBlock:a,disableTracking:c,isComponent:u,loc:f}}function Hs(e,t=fn){return{type:17,loc:t,elements:e}}function mn(e,t=fn){return{type:15,loc:t,properties:e}}function ft(e,t){return{type:16,loc:fn,key:_e(e)?Te(e,!0):e,value:t}}function Te(e,t=!1,n=fn,s=0){return{type:4,loc:n,content:e,isStatic:t,constType:t?3:s}}function An(e,t=fn){return{type:8,loc:t,children:e}}function mt(e,t=[],n=fn){return{type:14,loc:n,callee:e,arguments:t}}function xo(e,t=void 0,n=!1,s=!1,o=fn){return{type:18,params:e,returns:t,newline:n,isSlot:s,loc:o}}function Yl(e,t,n,s=!0){return{type:19,test:e,consequent:t,alternate:n,newline:s,loc:fn}}function Hb(e,t,n=!1,s=!1){return{type:20,index:e,value:t,needPauseTracking:n,inVOnce:s,needArraySpread:!1,loc:fn}}function zb(e){return{type:21,body:e,loc:fn}}function Ao(e,t){return e||t?lu:cu}function $o(e,t){return e||t?ep:tp}function Cu(e,{helper:t,removeHelper:n,inSSR:s}){e.isBlock||(e.isBlock=!0,n(Ao(s,e.isComponent)),t(Ks),t($o(s,e.isComponent)))}const od=new Uint8Array([123,123]),id=new Uint8Array([125,125]);function rd(e){return e>=97&&e<=122||e>=65&&e<=90}function tn(e){return e===32||e===10||e===9||e===12||e===13}function ds(e){return e===47||e===62||tn(e)}function zr(e){const t=new Uint8Array(e.length);for(let n=0;n=0;o--){const i=this.newlines[o];if(t>i){n=o+2,s=t-i;break}}return{column:s,line:n,offset:t}}peek(){return this.buffer.charCodeAt(this.index+1)}stateText(t){t===60?(this.index>this.sectionStart&&this.cbs.ontext(this.sectionStart,this.index),this.state=5,this.sectionStart=this.index):!this.inVPre&&t===this.delimiterOpen[0]&&(this.state=2,this.delimiterIndex=0,this.stateInterpolationOpen(t))}stateInterpolationOpen(t){if(t===this.delimiterOpen[this.delimiterIndex])if(this.delimiterIndex===this.delimiterOpen.length-1){const n=this.index+1-this.delimiterOpen.length;n>this.sectionStart&&this.cbs.ontext(this.sectionStart,n),this.state=3,this.sectionStart=n}else this.delimiterIndex++;else this.inRCDATA?(this.state=32,this.stateInRCDATA(t)):(this.state=1,this.stateText(t))}stateInterpolation(t){t===this.delimiterClose[0]&&(this.state=4,this.delimiterIndex=0,this.stateInterpolationClose(t))}stateInterpolationClose(t){t===this.delimiterClose[this.delimiterIndex]?this.delimiterIndex===this.delimiterClose.length-1?(this.cbs.oninterpolation(this.sectionStart,this.index+1),this.inRCDATA?this.state=32:this.state=1,this.sectionStart=this.index+1):this.delimiterIndex++:(this.state=3,this.stateInterpolation(t))}stateSpecialStartSequence(t){const n=this.sequenceIndex===this.currentSequence.length;if(!(n?ds(t):(t|32)===this.currentSequence[this.sequenceIndex]))this.inRCDATA=!1;else if(!n){this.sequenceIndex++;return}this.sequenceIndex=0,this.state=6,this.stateInTagName(t)}stateInRCDATA(t){if(this.sequenceIndex===this.currentSequence.length){if(t===62||tn(t)){const n=this.index-this.currentSequence.length;if(this.sectionStart=t||(this.state===28?this.currentSequence===At.CdataEnd?this.cbs.oncdata(this.sectionStart,t):this.cbs.oncomment(this.sectionStart,t):this.state===6||this.state===11||this.state===18||this.state===17||this.state===12||this.state===13||this.state===14||this.state===15||this.state===16||this.state===20||this.state===19||this.state===21||this.state===9||this.cbs.ontext(this.sectionStart,t))}emitCodePoint(t,n){}}function ad(e,{compatConfig:t}){const n=t&&t[e];return e==="MODE"?n||3:n}function zs(e,t){const n=ad("MODE",t),s=ad(e,t);return n===3?s===!0:s!==!1}function yi(e,t,n,...s){return zs(e,t)}function _u(e){throw e}function rp(e){}function it(e,t,n,s){const o=`https://vuejs.org/error-reference/#compiler-${e}`,i=new SyntaxError(String(o));return i.code=e,i.loc=t,i}const Yt=e=>e.type===4&&e.isStatic;function ap(e){switch(e){case"Teleport":case"teleport":return ti;case"Suspense":case"suspense":return au;case"KeepAlive":case"keep-alive":return Dr;case"BaseTransition":case"base-transition":return Zh}}const Ub=/^$|^\d|[^\$\w\xA0-\uFFFF]/,Su=e=>!Ub.test(e),lp=/[A-Za-z_$\xA0-\uFFFF]/,Wb=/[\.\?\w$\xA0-\uFFFF]/,qb=/\s+[.[]\s*|\s*[.[]\s+/g,cp=e=>e.type===4?e.content:e.loc.source,Kb=e=>{const t=cp(e).trim().replace(qb,a=>a.trim());let n=0,s=[],o=0,i=0,r=null;for(let a=0;a|^\s*(?:async\s+)?function(?:\s+[\w$]+)?\s*\(/,Gb=e=>Yb.test(cp(e)),Jb=Gb;function pn(e,t,n=!1){for(let s=0;st.type===7&&t.name==="bind"&&(!t.arg||t.arg.type!==4||!t.arg.isStatic))}function Ga(e){return e.type===5||e.type===2}function ld(e){return e.type===7&&e.name==="pre"}function Qb(e){return e.type===7&&e.name==="slot"}function jr(e){return e.type===1&&e.tagType===3}function Ur(e){return e.type===1&&e.tagType===2}const Zb=new Set([gi,Ii]);function fp(e,t=[]){if(e&&!_e(e)&&e.type===14){const n=e.callee;if(!_e(n)&&Zb.has(n))return fp(e.arguments[0],t.concat(e))}return[e,t]}function Wr(e,t,n){let s,o=e.type===13?e.props:e.arguments[2],i=[],r;if(o&&!_e(o)&&o.type===14){const a=fp(o);o=a[0],i=a[1],r=i[i.length-1]}if(o==null||_e(o))s=mn([t]);else if(o.type===14){const a=o.arguments[0];!_e(a)&&a.type===15?cd(t,a)||a.properties.unshift(t):o.callee===bu?s=mt(n.helper(Rr),[mn([t]),o]):o.arguments.unshift(mn([t])),!s&&(s=o)}else o.type===15?(cd(t,o)||o.properties.unshift(t),s=o):(s=mt(n.helper(Rr),[mn([t]),o]),r&&r.callee===Ii&&(r=i[i.length-2]));e.type===13?r?r.arguments[0]=s:e.props=s:r?r.arguments[0]=s:e.arguments[2]=s}function cd(e,t){let n=!1;if(e.key.type===4){const s=e.key.content;n=t.properties.some(o=>o.key.type===4&&o.key.content===s)}return n}function bi(e,t){return`_${t}_${e.replace(/[^\w]/g,(n,s)=>n==="-"?"_":e.charCodeAt(s).toString())}`}function ek(e){return e.type===14&&e.callee===wu?e.arguments[1].returns:e}const tk=/([\s\S]*?)\s+(?:in|of)\s+(\S[\s\S]*)/,dp={parseMode:"base",ns:0,delimiters:["{{","}}"],getNamespace:()=>0,isVoidTag:ao,isPreTag:ao,isIgnoreNewlineTag:ao,isCustomElement:ao,onError:_u,onWarn:rp,comments:!1,prefixIdentifiers:!1};let De=dp,ki=null,ts="",Lt=null,$e=null,jt="",Kn=-1,Fs=-1,Tu=0,ys=!1,Gl=null;const ot=[],lt=new jb(ot,{onerr:qn,ontext(e,t){Ji(kt(e,t),e,t)},ontextentity(e,t,n){Ji(e,t,n)},oninterpolation(e,t){if(ys)return Ji(kt(e,t),e,t);let n=e+lt.delimiterOpen.length,s=t-lt.delimiterClose.length;for(;tn(ts.charCodeAt(n));)n++;for(;tn(ts.charCodeAt(s-1));)s--;let o=kt(n,s);o.includes("&")&&(o=De.decodeEntities(o,!1)),Jl({type:5,content:hr(o,!1,ct(n,s)),loc:ct(e,t)})},onopentagname(e,t){const n=kt(e,t);Lt={type:1,tag:n,ns:De.getNamespace(n,ot[0],De.ns),tagType:0,props:[],children:[],loc:ct(e-1,t),codegenNode:void 0}},onopentagend(e){fd(e)},onclosetag(e,t){const n=kt(e,t);if(!De.isVoidTag(n)){let s=!1;for(let o=0;o0&&qn(24,ot[0].loc.start.offset);for(let r=0;r<=o;r++){const a=ot.shift();dr(a,t,r(s.type===7?s.rawName:s.name)===n)&&qn(2,t)},onattribend(e,t){if(Lt&&$e){if(Vs($e.loc,t),e!==0)if(jt.includes("&")&&(jt=De.decodeEntities(jt,!0)),$e.type===6)$e.name==="class"&&(jt=mp(jt).trim()),e===1&&!jt&&qn(13,t),$e.value={type:2,content:jt,loc:e===1?ct(Kn,Fs):ct(Kn-1,Fs+1)},lt.inSFCRoot&&Lt.tag==="template"&&$e.name==="lang"&&jt&&jt!=="html"&<.enterRCDATA(zr("o.content==="sync"))>-1&&yi("COMPILER_V_BIND_SYNC",De,$e.loc,$e.arg.loc.source)&&($e.name="model",$e.modifiers.splice(s,1))}($e.type!==7||$e.name!=="pre")&&Lt.props.push($e)}jt="",Kn=Fs=-1},oncomment(e,t){De.comments&&Jl({type:3,content:kt(e,t),loc:ct(e-4,t+3)})},onend(){const e=ts.length;for(let t=0;t{const g=t.start.offset+h,v=g+d.length;return hr(d,!1,ct(g,v),0,m?1:0)},a={source:r(i.trim(),n.indexOf(i,o.length)),value:void 0,key:void 0,index:void 0,finalized:!1};let c=o.trim().replace(nk,"").trim();const u=o.indexOf(c),f=c.match(ud);if(f){c=c.replace(ud,"").trim();const d=f[1].trim();let h;if(d&&(h=n.indexOf(d,u+c.length),a.key=r(d,h,!0)),f[2]){const m=f[2].trim();m&&(a.index=r(m,n.indexOf(m,a.key?h+d.length:u+c.length),!0))}}return c&&(a.value=r(c,u,!0)),a}function kt(e,t){return ts.slice(e,t)}function fd(e){lt.inSFCRoot&&(Lt.innerLoc=ct(e+1,e+1)),Jl(Lt);const{tag:t,ns:n}=Lt;n===0&&De.isPreTag(t)&&Tu++,De.isVoidTag(t)?dr(Lt,e):(ot.unshift(Lt),(n===1||n===2)&&(lt.inXML=!0)),Lt=null}function Ji(e,t,n){{const i=ot[0]&&ot[0].tag;i!=="script"&&i!=="style"&&e.includes("&")&&(e=De.decodeEntities(e,!1))}const s=ot[0]||ki,o=s.children[s.children.length-1];o&&o.type===2?(o.content+=e,Vs(o.loc,n)):s.children.push({type:2,content:e,loc:ct(t,n)})}function dr(e,t,n=!1){n?Vs(e.loc,hp(t,60)):Vs(e.loc,ok(t,62)+1),lt.inSFCRoot&&(e.children.length?e.innerLoc.end=Ie({},e.children[e.children.length-1].loc.end):e.innerLoc.end=Ie({},e.innerLoc.start),e.innerLoc.source=kt(e.innerLoc.start.offset,e.innerLoc.end.offset));const{tag:s,ns:o,children:i}=e;if(ys||(s==="slot"?e.tagType=2:dd(e)?e.tagType=3:rk(e)&&(e.tagType=1)),lt.inRCDATA||(e.children=pp(i)),o===0&&De.isIgnoreNewlineTag(s)){const r=i[0];r&&r.type===2&&(r.content=r.content.replace(/^\r?\n/,""))}o===0&&De.isPreTag(s)&&Tu--,Gl===e&&(ys=lt.inVPre=!1,Gl=null),lt.inXML&&(ot[0]?ot[0].ns:De.ns)===0&&(lt.inXML=!1);{const r=e.props;if(!lt.inSFCRoot&&zs("COMPILER_NATIVE_TEMPLATE",De)&&e.tag==="template"&&!dd(e)){const c=ot[0]||ki,u=c.children.indexOf(e);c.children.splice(u,1,...e.children)}const a=r.find(c=>c.type===6&&c.name==="inline-template");a&&yi("COMPILER_INLINE_TEMPLATE",De,a.loc)&&e.children.length&&(a.value={type:2,content:kt(e.children[0].loc.start.offset,e.children[e.children.length-1].loc.end.offset),loc:a.loc})}}function ok(e,t){let n=e;for(;ts.charCodeAt(n)!==t&&n=0;)n--;return n}const ik=new Set(["if","else","else-if","for","slot"]);function dd({tag:e,props:t}){if(e==="template"){for(let n=0;n64&&e<91}const lk=/\r\n/g;function pp(e){const t=De.whitespace!=="preserve";let n=!1;for(let s=0;sn.type!==3);return t.length===1&&t[0].type===1&&!Ur(t[0])?t[0]:null}function pr(e,t,n,s=!1,o=!1){const{children:i}=e,r=[];for(let f=0;f0){if(h>=2){d.codegenNode.patchFlag=-1,r.push(d);continue}}else{const m=d.codegenNode;if(m.type===13){const g=m.patchFlag;if((g===void 0||g===512||g===1)&&yp(d,n)>=2){const v=bp(d);v&&(m.props=n.hoist(v))}m.dynamicProps&&(m.dynamicProps=n.hoist(m.dynamicProps))}}}else if(d.type===12&&(s?0:rn(d,n))>=2){d.codegenNode.type===14&&d.codegenNode.arguments.length>0&&d.codegenNode.arguments.push("-1"),r.push(d);continue}if(d.type===1){const h=d.tagType===1;h&&n.scopes.vSlot++,pr(d,e,n,!1,o),h&&n.scopes.vSlot--}else if(d.type===11)pr(d,e,n,d.children.length===1,!0);else if(d.type===9)for(let h=0;hm.key===d||m.key.content===d);return h&&h.value}}r.length&&n.transformHoist&&n.transformHoist(i,n,e)}function rn(e,t){const{constantCache:n}=t;switch(e.type){case 1:if(e.tagType!==0)return 0;const s=n.get(e);if(s!==void 0)return s;const o=e.codegenNode;if(o.type!==13||o.isBlock&&e.tag!=="svg"&&e.tag!=="foreignObject"&&e.tag!=="math")return 0;if(o.patchFlag===void 0){let r=3;const a=yp(e,t);if(a===0)return n.set(e,0),0;a1)for(let c=0;cN&&(E.childIndex--,E.onNodeRemoved()),E.parent.children.splice(N,1)},onNodeRemoved:Ht,addIdentifiers(L){},removeIdentifiers(L){},hoist(L){_e(L)&&(L=Te(L)),E.hoists.push(L);const I=Te(`_hoisted_${E.hoists.length}`,!1,L.loc,2);return I.hoisted=L,I},cache(L,I=!1,N=!1){const $=Hb(E.cached.length,L,I,N);return E.cached.push($),$}};return E.filters=new Set,E}function yk(e,t){const n=vk(e,t);Ea(e,n),t.hoistStatic&&mk(e,n),t.ssr||bk(e,n),e.helpers=new Set([...n.helpers.keys()]),e.components=[...n.components],e.directives=[...n.directives],e.imports=n.imports,e.hoists=n.hoists,e.temps=n.temps,e.cached=n.cached,e.transformed=!0,e.filters=[...n.filters]}function bk(e,t){const{helper:n}=t,{children:s}=e;if(s.length===1){const o=gp(e);if(o&&o.codegenNode){const i=o.codegenNode;i.type===13&&Cu(i,t),e.codegenNode=i}else e.codegenNode=s[0]}else if(s.length>1){let o=64;e.codegenNode=vi(t,n(mi),void 0,e.children,o,void 0,void 0,!0,void 0,!1)}}function kk(e,t){let n=0;const s=()=>{n--};for(;ns===e:s=>e.test(s);return(s,o)=>{if(s.type===1){const{props:i}=s;if(s.tagType===3&&i.some(Qb))return;const r=[];for(let a=0;a`${Eo[e]}: _${Eo[e]}`;function wk(e,{mode:t="function",prefixIdentifiers:n=t==="module",sourceMap:s=!1,filename:o="template.vue.html",scopeId:i=null,optimizeImports:r=!1,runtimeGlobalName:a="Vue",runtimeModuleName:c="vue",ssrRuntimeModuleName:u="vue/server-renderer",ssr:f=!1,isTS:d=!1,inSSR:h=!1}){const m={mode:t,prefixIdentifiers:n,sourceMap:s,filename:o,scopeId:i,optimizeImports:r,runtimeGlobalName:a,runtimeModuleName:c,ssrRuntimeModuleName:u,ssr:f,isTS:d,inSSR:h,source:e.source,code:"",column:1,line:1,offset:0,indentLevel:0,pure:!1,map:void 0,helper(v){return`_${Eo[v]}`},push(v,k=-2,b){m.code+=v},indent(){g(++m.indentLevel)},deindent(v=!1){v?--m.indentLevel:g(--m.indentLevel)},newline(){g(m.indentLevel)}};function g(v){m.push(` +`+" ".repeat(v),0)}return m}function Ck(e,t={}){const n=wk(e,t);t.onContextCreated&&t.onContextCreated(n);const{mode:s,push:o,prefixIdentifiers:i,indent:r,deindent:a,newline:c,scopeId:u,ssr:f}=n,d=Array.from(e.helpers),h=d.length>0,m=!i&&s!=="module";_k(e,n);const v=f?"ssrRender":"render",b=(f?["_ctx","_push","_parent","_attrs"]:["_ctx","_cache"]).join(", ");if(o(`function ${v}(${b}) {`),r(),m&&(o("with (_ctx) {"),r(),h&&(o(`const { ${d.map(wp).join(", ")} } = _Vue +`,-1),c())),e.components.length&&(Ja(e.components,"component",n),(e.directives.length||e.temps>0)&&c()),e.directives.length&&(Ja(e.directives,"directive",n),e.temps>0&&c()),e.filters&&e.filters.length&&(c(),Ja(e.filters,"filter",n),c()),e.temps>0){o("let ");for(let C=0;C0?", ":""}_temp${C}`)}return(e.components.length||e.directives.length||e.temps)&&(o(` +`,0),c()),f||o("return "),e.codegenNode?Bt(e.codegenNode,n):o("null"),m&&(a(),o("}")),a(),o("}"),{ast:e,code:n.code,preamble:"",map:n.map?n.map.toJSON():void 0}}function _k(e,t){const{ssr:n,prefixIdentifiers:s,push:o,newline:i,runtimeModuleName:r,runtimeGlobalName:a,ssrRuntimeModuleName:c}=t,u=a,f=Array.from(e.helpers);if(f.length>0&&(o(`const _Vue = ${u} +`,-1),e.hoists.length)){const d=[lu,cu,Li,uu,np].filter(h=>f.includes(h)).map(wp).join(", ");o(`const { ${d} } = _Vue +`,-1)}Sk(e.hoists,t),i(),o("return ")}function Ja(e,t,{helper:n,push:s,newline:o,isTS:i}){const r=n(t==="filter"?pu:t==="component"?fu:hu);for(let a=0;a3||!1;t.push("["),n&&t.indent(),Pi(e,t,n),n&&t.deindent(),t.push("]")}function Pi(e,t,n=!1,s=!0){const{push:o,newline:i}=t;for(let r=0;rn||"null")}function Ik(e,t){const{push:n,helper:s,pure:o}=t,i=_e(e.callee)?e.callee:s(e.callee);o&&n(xa),n(i+"(",-2,e),Pi(e.arguments,t),n(")")}function Pk(e,t){const{push:n,indent:s,deindent:o,newline:i}=t,{properties:r}=e;if(!r.length){n("{}",-2,e);return}const a=r.length>1||!1;n(a?"{":"{ "),a&&s();for(let c=0;c "),(c||a)&&(n("{"),s()),r?(c&&n("return "),ce(r)?Eu(r,t):Bt(r,t)):a&&Bt(a,t),(c||a)&&(o(),n("}")),u&&(e.isNonScopedSlot&&n(", undefined, true"),n(")"))}function Bk(e,t){const{test:n,consequent:s,alternate:o,newline:i}=e,{push:r,indent:a,deindent:c,newline:u}=t;if(n.type===4){const d=!Su(n.content);d&&r("("),Cp(n,t),d&&r(")")}else r("("),Bt(n,t),r(")");i&&a(),t.indentLevel++,i||r(" "),r("? "),Bt(s,t),t.indentLevel--,i&&u(),i||r(" "),r(": ");const f=o.type===19;f||t.indentLevel++,Bt(o,t),f||t.indentLevel--,i&&c(!0)}function Nk(e,t){const{push:n,helper:s,indent:o,deindent:i,newline:r}=t,{needPauseTracking:a,needArraySpread:c}=e;c&&n("[...("),n(`_cache[${e.index}] || (`),a&&(o(),n(`${s(Hr)}(-1`),e.inVOnce&&n(", true"),n("),"),r(),n("(")),n(`_cache[${e.index}] = `),Bt(e.value,t),a&&(n(`).cacheIndex = ${e.index},`),r(),n(`${s(Hr)}(1),`),r(),n(`_cache[${e.index}]`),i()),n(")"),c&&n(")]")}new RegExp("\\b"+"arguments,await,break,case,catch,class,const,continue,debugger,default,delete,do,else,export,extends,finally,for,function,if,import,let,new,return,super,switch,throw,try,var,void,while,with,yield".split(",").join("\\b|\\b")+"\\b");const Vk=kp(/^(?:if|else|else-if)$/,(e,t,n)=>Ok(e,t,n,(s,o,i)=>{const r=n.parent.children;let a=r.indexOf(s),c=0;for(;a-->=0;){const u=r[a];u&&u.type===9&&(c+=u.branches.length)}return()=>{if(i)s.codegenNode=pd(o,c,n);else{const u=Dk(s.codegenNode);u.alternate=pd(o,c+s.branches.length-1,n)}}}));function Ok(e,t,n,s){if(t.name!=="else"&&(!t.exp||!t.exp.content.trim())){const o=t.exp?t.exp.loc:e.loc;n.onError(it(28,t.loc)),t.exp=Te("true",!1,o)}if(t.name==="if"){const o=hd(e,t),i={type:9,loc:fk(e.loc),branches:[o]};if(n.replaceNode(i),s)return s(i,o,!0)}else{const o=n.parent.children;let i=o.indexOf(e);for(;i-->=-1;){const r=o[i];if(r&&r.type===3){n.removeNode(r);continue}if(r&&r.type===2&&!r.content.trim().length){n.removeNode(r);continue}if(r&&r.type===9){(t.name==="else-if"||t.name==="else")&&r.branches[r.branches.length-1].condition===void 0&&n.onError(it(30,e.loc)),n.removeNode();const a=hd(e,t);r.branches.push(a);const c=s&&s(r,a,!1);Ea(a,n),c&&c(),n.currentNode=null}else n.onError(it(30,e.loc));break}}}function hd(e,t){const n=e.tagType===3;return{type:10,loc:e.loc,condition:t.name==="else"?void 0:t.exp,children:n&&!pn(e,"for")?e.children:[e],userKey:Ta(e,"key"),isTemplateIf:n}}function pd(e,t,n){return e.condition?Yl(e.condition,md(e,t,n),mt(n.helper(Li),['""',"true"])):md(e,t,n)}function md(e,t,n){const{helper:s}=n,o=ft("key",Te(`${t}`,!1,fn,2)),{children:i}=e,r=i[0];if(i.length!==1||r.type!==1)if(i.length===1&&r.type===11){const c=r.codegenNode;return Wr(c,o,n),c}else return vi(n,s(mi),mn([o]),i,64,void 0,void 0,!0,!1,!1,e.loc);else{const c=r.codegenNode,u=ek(c);return u.type===13&&Cu(u,n),Wr(u,o,n),c}}function Dk(e){for(;;)if(e.type===19)if(e.alternate.type===19)e=e.alternate;else return e;else e.type===20&&(e=e.value)}const Rk=kp("for",(e,t,n)=>{const{helper:s,removeHelper:o}=n;return Hk(e,t,n,i=>{const r=mt(s(gu),[i.source]),a=jr(e),c=pn(e,"memo"),u=Ta(e,"key",!1,!0);u&&u.type;let f=u&&(u.type===6?u.value?Te(u.value.content,!0):void 0:u.exp);const d=u&&f?ft("key",f):null,h=i.source.type===4&&i.source.constType>0,m=h?64:u?128:256;return i.codegenNode=vi(n,s(mi),void 0,r,m,void 0,void 0,!0,!h,!1,e.loc),()=>{let g;const{children:v}=i,k=v.length!==1||v[0].type!==1,b=Ur(e)?e:a&&e.children.length===1&&Ur(e.children[0])?e.children[0]:null;if(b?(g=b.codegenNode,a&&d&&Wr(g,d,n)):k?g=vi(n,s(mi),d?mn([d]):void 0,e.children,64,void 0,void 0,!0,void 0,!1):(g=v[0].codegenNode,a&&d&&Wr(g,d,n),g.isBlock!==!h&&(g.isBlock?(o(Ks),o($o(n.inSSR,g.isComponent))):o(Ao(n.inSSR,g.isComponent))),g.isBlock=!h,g.isBlock?(s(Ks),s($o(n.inSSR,g.isComponent))):s(Ao(n.inSSR,g.isComponent))),c){const C=xo(Xl(i.parseResult,[Te("_cached")]));C.body=zb([An(["const _memo = (",c.exp,")"]),An(["if (_cached",...f?[" && _cached.key === ",f]:[],` && ${n.helperString(ip)}(_cached, _memo)) return _cached`]),An(["const _item = ",g]),Te("_item.memo = _memo"),Te("return _item")]),r.arguments.push(C,Te("_cache"),Te(String(n.cached.length))),n.cached.push(null)}else r.arguments.push(xo(Xl(i.parseResult),g,!0))}})});function Hk(e,t,n,s){if(!t.exp){n.onError(it(31,t.loc));return}const o=t.forParseResult;if(!o){n.onError(it(32,t.loc));return}Sp(o);const{addIdentifiers:i,removeIdentifiers:r,scopes:a}=n,{source:c,value:u,key:f,index:d}=o,h={type:11,loc:t.loc,source:c,valueAlias:u,keyAlias:f,objectIndexAlias:d,parseResult:o,children:jr(e)?e.children:[e]};n.replaceNode(h),a.vFor++;const m=s&&s(h);return()=>{a.vFor--,m&&m()}}function Sp(e,t){e.finalized||(e.finalized=!0)}function Xl({value:e,key:t,index:n},s=[]){return zk([e,t,n,...s])}function zk(e){let t=e.length;for(;t--&&!e[t];);return e.slice(0,t+1).map((n,s)=>n||Te("_".repeat(s+1),!1))}const gd=Te("undefined",!1),jk=(e,t)=>{if(e.type===1&&(e.tagType===1||e.tagType===3)){const n=pn(e,"slot");if(n)return n.exp,t.scopes.vSlot++,()=>{t.scopes.vSlot--}}},Uk=(e,t,n,s)=>xo(e,n,!1,!0,n.length?n[0].loc:s);function Wk(e,t,n=Uk){t.helper(ku);const{children:s,loc:o}=e,i=[],r=[];let a=t.scopes.vSlot>0||t.scopes.vFor>0;const c=pn(e,"slot",!0);if(c){const{arg:k,exp:b}=c;k&&!Yt(k)&&(a=!0),i.push(ft(k||Te("default",!0),n(b,void 0,s,o)))}let u=!1,f=!1;const d=[],h=new Set;let m=0;for(let k=0;k{const y=n(b,void 0,C,o);return t.compatConfig&&(y.isNonScopedSlot=!0),ft("default",y)};u?d.length&&d.some(b=>Ql(b))&&(f?t.onError(it(39,d[0].loc)):i.push(k(void 0,d))):i.push(k(void 0,s))}const g=a?2:mr(e.children)?3:1;let v=mn(i.concat(ft("_",Te(g+"",!1))),o);return r.length&&(v=mt(t.helper(op),[v,Hs(r)])),{slots:v,hasDynamicSlots:a}}function Xi(e,t,n){const s=[ft("name",e),ft("fn",t)];return n!=null&&s.push(ft("key",Te(String(n),!0))),mn(s)}function mr(e){for(let t=0;tfunction(){if(e=t.currentNode,!(e.type===1&&(e.tagType===0||e.tagType===1)))return;const{tag:s,props:o}=e,i=e.tagType===1;let r=i?Kk(e,t):`"${s}"`;const a=Ue(r)&&r.callee===du;let c,u,f=0,d,h,m,g=a||r===ti||r===au||!i&&(s==="svg"||s==="foreignObject"||s==="math");if(o.length>0){const v=Ep(e,t,void 0,i,a);c=v.props,f=v.patchFlag,h=v.dynamicPropNames;const k=v.directives;m=k&&k.length?Hs(k.map(b=>Gk(b,t))):void 0,v.shouldUseBlock&&(g=!0)}if(e.children.length>0)if(r===Dr&&(g=!0,f|=1024),i&&r!==ti&&r!==Dr){const{slots:k,hasDynamicSlots:b}=Wk(e,t);u=k,b&&(f|=1024)}else if(e.children.length===1&&r!==ti){const k=e.children[0],b=k.type,C=b===5||b===8;C&&rn(k,t)===0&&(f|=1),C||b===2?u=k:u=e.children}else u=e.children;h&&h.length&&(d=Jk(h)),e.codegenNode=vi(t,r,c,u,f===0?void 0:f,d,m,!!g,!1,i,e.loc)};function Kk(e,t,n=!1){let{tag:s}=e;const o=Zl(s),i=Ta(e,"is",!1,!0);if(i)if(o||zs("COMPILER_IS_ON_ELEMENT",t)){let a;if(i.type===6?a=i.value&&Te(i.value.content,!0):(a=i.exp,a||(a=Te("is",!1,i.arg.loc))),a)return mt(t.helper(du),[a])}else i.type===6&&i.value.content.startsWith("vue:")&&(s=i.value.content.slice(4));const r=ap(s)||t.isBuiltInComponent(s);return r?(n||t.helper(r),r):(t.helper(fu),t.components.add(s),bi(s,"component"))}function Ep(e,t,n=e.props,s,o,i=!1){const{tag:r,loc:a,children:c}=e;let u=[];const f=[],d=[],h=c.length>0;let m=!1,g=0,v=!1,k=!1,b=!1,C=!1,y=!1,_=!1;const x=[],P=I=>{u.length&&(f.push(mn(vd(u),a)),u=[]),I&&f.push(I)},V=()=>{t.scopes.vFor>0&&u.push(ft(Te("ref_for",!0),Te("true")))},E=({key:I,value:N})=>{if(Yt(I)){const $=I.content,U=Ys($);if(U&&(!s||o)&&$.toLowerCase()!=="onclick"&&$!=="onUpdate:modelValue"&&!ws($)&&(C=!0),U&&ws($)&&(_=!0),U&&N.type===14&&(N=N.arguments[0]),N.type===20||(N.type===4||N.type===8)&&rn(N,t)>0)return;$==="ref"?v=!0:$==="class"?k=!0:$==="style"?b=!0:$!=="key"&&!x.includes($)&&x.push($),s&&($==="class"||$==="style")&&!x.includes($)&&x.push($)}else y=!0};for(let I=0;Ist.content==="prop")&&(g|=32);const he=t.directiveTransforms[$];if(he){const{props:st,needRuntime:je}=he(N,e,t);!i&&st.forEach(E),ne&&U&&!Yt(U)?P(mn(st,a)):u.push(...st),je&&(d.push(N),Gt(je)&&Tp.set(N,je))}else $2($)||(d.push(N),h&&(m=!0))}}let L;if(f.length?(P(),f.length>1?L=mt(t.helper(Rr),f,a):L=f[0]):u.length&&(L=mn(vd(u),a)),y?g|=16:(k&&!s&&(g|=2),b&&!s&&(g|=4),x.length&&(g|=8),C&&(g|=32)),!m&&(g===0||g===32)&&(v||_||d.length>0)&&(g|=512),!t.inSSR&&L)switch(L.type){case 15:let I=-1,N=-1,$=!1;for(let J=0;Jft(r,i)),o))}return Hs(n,e.loc)}function Jk(e){let t="[";for(let n=0,s=e.length;n{if(Ur(e)){const{children:n,loc:s}=e,{slotName:o,slotProps:i}=Qk(e,t),r=[t.prefixIdentifiers?"_ctx.$slots":"$slots",o,"{}","undefined","true"];let a=2;i&&(r[2]=i,a=3),n.length&&(r[3]=xo([],n,!1,!1,s),a=4),t.scopeId&&!t.slotted&&(a=5),r.splice(a),e.codegenNode=mt(t.helper(sp),r,s)}};function Qk(e,t){let n='"default"',s;const o=[];for(let i=0;i0){const{props:i,directives:r}=Ep(e,t,o,!1,!1);s=i,r.length&&t.onError(it(36,r[0].loc))}return{slotName:n,slotProps:s}}const xp=(e,t,n,s)=>{const{loc:o,modifiers:i,arg:r}=e;!e.exp&&!i.length&&n.onError(it(35,o));let a;if(r.type===4)if(r.isStatic){let d=r.content;d.startsWith("vue:")&&(d=`vnode-${d.slice(4)}`);const h=t.tagType!==0||d.startsWith("vnode")||!/[A-Z]/.test(d)?po(tt(d)):`on:${d}`;a=Te(h,!0,r.loc)}else a=An([`${n.helperString(Kl)}(`,r,")"]);else a=r,a.children.unshift(`${n.helperString(Kl)}(`),a.children.push(")");let c=e.exp;c&&!c.content.trim()&&(c=void 0);let u=n.cacheHandlers&&!c&&!n.inVOnce;if(c){const d=up(c),h=!(d||Jb(c)),m=c.content.includes(";");(h||u&&d)&&(c=An([`${h?"$event":"(...args)"} => ${m?"{":"("}`,c,m?"}":")"]))}let f={props:[ft(a,c||Te("() => {}",!1,o))]};return s&&(f=s(f)),u&&(f.props[0].value=n.cache(f.props[0].value)),f.props.forEach(d=>d.key.isHandlerKey=!0),f},Zk=(e,t,n)=>{const{modifiers:s,loc:o}=e,i=e.arg;let{exp:r}=e;return r&&r.type===4&&!r.content.trim()&&(r=void 0),i.type!==4?(i.children.unshift("("),i.children.push(') || ""')):i.isStatic||(i.content=i.content?`${i.content} || ""`:'""'),s.some(a=>a.content==="camel")&&(i.type===4?i.isStatic?i.content=tt(i.content):i.content=`${n.helperString(ql)}(${i.content})`:(i.children.unshift(`${n.helperString(ql)}(`),i.children.push(")"))),n.inSSR||(s.some(a=>a.content==="prop")&&yd(i,"."),s.some(a=>a.content==="attr")&&yd(i,"^")),{props:[ft(i,r)]}},yd=(e,t)=>{e.type===4?e.isStatic?e.content=t+e.content:e.content=`\`${t}\${${e.content}}\``:(e.children.unshift(`'${t}' + (`),e.children.push(")"))},ew=(e,t)=>{if(e.type===0||e.type===1||e.type===11||e.type===10)return()=>{const n=e.children;let s,o=!1;for(let i=0;ii.type===7&&!t.directiveTransforms[i.name])&&e.tag!=="template")))for(let i=0;i{if(e.type===1&&pn(e,"once",!0))return bd.has(e)||t.inVOnce||t.inSSR?void 0:(bd.add(e),t.inVOnce=!0,t.helper(Hr),()=>{t.inVOnce=!1;const n=t.currentNode;n.codegenNode&&(n.codegenNode=t.cache(n.codegenNode,!0,!0))})},Ap=(e,t,n)=>{const{exp:s,arg:o}=e;if(!s)return n.onError(it(41,e.loc)),Qi();const i=s.loc.source.trim(),r=s.type===4?s.content:i,a=n.bindingMetadata[i];if(a==="props"||a==="props-aliased")return n.onError(it(44,s.loc)),Qi();if(!r.trim()||!up(s))return n.onError(it(42,s.loc)),Qi();const c=o||Te("modelValue",!0),u=o?Yt(o)?`onUpdate:${tt(o.content)}`:An(['"onUpdate:" + ',o]):"onUpdate:modelValue";let f;const d=n.isTS?"($event: any)":"$event";f=An([`${d} => ((`,s,") = $event)"]);const h=[ft(c,e.exp),ft(u,f)];if(e.modifiers.length&&t.tagType===1){const m=e.modifiers.map(v=>v.content).map(v=>(Su(v)?v:JSON.stringify(v))+": true").join(", "),g=o?Yt(o)?`${o.content}Modifiers`:An([o,' + "Modifiers"']):"modelModifiers";h.push(ft(g,Te(`{ ${m} }`,!1,e.loc,2)))}return Qi(h)};function Qi(e=[]){return{props:e}}const nw=/[\w).+\-_$\]]/,sw=(e,t)=>{zs("COMPILER_FILTERS",t)&&(e.type===5?qr(e.content,t):e.type===1&&e.props.forEach(n=>{n.type===7&&n.name!=="for"&&n.exp&&qr(n.exp,t)}))};function qr(e,t){if(e.type===4)kd(e,t);else for(let n=0;n=0&&(C=n.charAt(b),C===" ");b--);(!C||!nw.test(C))&&(r=!0)}}g===void 0?g=n.slice(0,m).trim():f!==0&&k();function k(){v.push(n.slice(f,m).trim()),f=m+1}if(v.length){for(m=0;m{if(e.type===1){const n=pn(e,"memo");return!n||wd.has(e)||t.inSSR?void 0:(wd.add(e),()=>{const s=e.codegenNode||t.currentNode.codegenNode;s&&s.type===13&&(e.tagType!==1&&Cu(s,t),e.codegenNode=mt(t.helper(wu),[n.exp,xo(void 0,s),"_cache",String(t.cached.length)]),t.cached.push(null))})}},rw=(e,t)=>{if(e.type===1){for(const n of e.props)if(n.type===7&&n.name==="bind"&&(!n.exp||n.exp.type===4&&!n.exp.content.trim())&&n.arg){const s=n.arg;if(s.type!==4||!s.isStatic)t.onError(it(52,s.loc)),n.exp=Te("",!0,s.loc);else{const o=tt(s.content);(lp.test(o[0])||o[0]==="-")&&(n.exp=Te(o,!1,s.loc))}}}};function aw(e){return[[rw,tw,Vk,iw,Rk,sw,Xk,qk,jk,ew],{on:xp,bind:Zk,model:Ap}]}function lw(e,t={}){const n=t.onError||_u,s=t.mode==="module";t.prefixIdentifiers===!0?n(it(47)):s&&n(it(48));const o=!1;t.cacheHandlers&&n(it(49)),t.scopeId&&!s&&n(it(50));const i=Ie({},t,{prefixIdentifiers:o}),r=_e(e)?pk(e,i):e,[a,c]=aw();return yk(r,Ie({},i,{nodeTransforms:[...a,...t.nodeTransforms||[]],directiveTransforms:Ie({},c,t.directiveTransforms||{})})),Ck(r,i)}const cw=()=>({props:[]});const $p=Symbol(""),Lp=Symbol(""),Ip=Symbol(""),Pp=Symbol(""),ec=Symbol(""),Mp=Symbol(""),Fp=Symbol(""),Bp=Symbol(""),Np=Symbol(""),Vp=Symbol("");Db({[$p]:"vModelRadio",[Lp]:"vModelCheckbox",[Ip]:"vModelText",[Pp]:"vModelSelect",[ec]:"vModelDynamic",[Mp]:"withModifiers",[Fp]:"withKeys",[Bp]:"vShow",[Np]:"Transition",[Vp]:"TransitionGroup"});let so;function uw(e,t=!1){return so||(so=document.createElement("div")),t?(so.innerHTML=`
`,so.children[0].getAttribute("foo")):(so.innerHTML=e,so.textContent)}const fw={parseMode:"html",isVoidTag:U2,isNativeTag:e=>H2(e)||z2(e)||j2(e),isPreTag:e=>e==="pre",isIgnoreNewlineTag:e=>e==="pre"||e==="textarea",decodeEntities:uw,isBuiltInComponent:e=>{if(e==="Transition"||e==="transition")return Np;if(e==="TransitionGroup"||e==="transition-group")return Vp},getNamespace(e,t,n){let s=t?t.ns:n;if(t&&s===2)if(t.tag==="annotation-xml"){if(e==="svg")return 1;t.props.some(o=>o.type===6&&o.name==="encoding"&&o.value!=null&&(o.value.content==="text/html"||o.value.content==="application/xhtml+xml"))&&(s=0)}else/^m(?:[ions]|text)$/.test(t.tag)&&e!=="mglyph"&&e!=="malignmark"&&(s=0);else t&&s===1&&(t.tag==="foreignObject"||t.tag==="desc"||t.tag==="title")&&(s=0);if(s===0){if(e==="svg")return 1;if(e==="math")return 2}return s}},dw=e=>{e.type===1&&e.props.forEach((t,n)=>{t.type===6&&t.name==="style"&&t.value&&(e.props[n]={type:7,name:"bind",arg:Te("style",!0,t.loc),exp:hw(t.value.content,t.loc),modifiers:[],loc:t.loc})})},hw=(e,t)=>{const n=o1(e);return Te(JSON.stringify(n),!1,t,3)};function Ts(e,t){return it(e,t)}const pw=(e,t,n)=>{const{exp:s,loc:o}=e;return s||n.onError(Ts(53,o)),t.children.length&&(n.onError(Ts(54,o)),t.children.length=0),{props:[ft(Te("innerHTML",!0,o),s||Te("",!0))]}},mw=(e,t,n)=>{const{exp:s,loc:o}=e;return s||n.onError(Ts(55,o)),t.children.length&&(n.onError(Ts(56,o)),t.children.length=0),{props:[ft(Te("textContent",!0),s?rn(s,n)>0?s:mt(n.helperString(Sa),[s],o):Te("",!0))]}},gw=(e,t,n)=>{const s=Ap(e,t,n);if(!s.props.length||t.tagType===1)return s;e.arg&&n.onError(Ts(58,e.arg.loc));const{tag:o}=t,i=n.isCustomElement(o);if(o==="input"||o==="textarea"||o==="select"||i){let r=Ip,a=!1;if(o==="input"||i){const c=Ta(t,"type");if(c){if(c.type===7)r=ec;else if(c.value)switch(c.value.content){case"radio":r=$p;break;case"checkbox":r=Lp;break;case"file":a=!0,n.onError(Ts(59,e.loc));break}}else Xb(t)&&(r=ec)}else o==="select"&&(r=Pp);a||(s.needRuntime=n.helper(r))}else n.onError(Ts(57,e.loc));return s.props=s.props.filter(r=>!(r.key.type===4&&r.key.content==="modelValue")),s},vw=ln("passive,once,capture"),yw=ln("stop,prevent,self,ctrl,shift,alt,meta,exact,middle"),bw=ln("left,right"),Op=ln("onkeyup,onkeydown,onkeypress"),kw=(e,t,n,s)=>{const o=[],i=[],r=[];for(let a=0;aYt(e)&&e.content.toLowerCase()==="onclick"?Te(t,!0):e.type!==4?An(["(",e,`) === "onClick" ? "${t}" : (`,e,")"]):e,ww=(e,t,n)=>xp(e,t,n,s=>{const{modifiers:o}=e;if(!o.length)return s;let{key:i,value:r}=s.props[0];const{keyModifiers:a,nonKeyModifiers:c,eventOptionModifiers:u}=kw(i,o,n,e.loc);if(c.includes("right")&&(i=Cd(i,"onContextmenu")),c.includes("middle")&&(i=Cd(i,"onMouseup")),c.length&&(r=mt(n.helper(Mp),[r,JSON.stringify(c)])),a.length&&(!Yt(i)||Op(i.content.toLowerCase()))&&(r=mt(n.helper(Fp),[r,JSON.stringify(a)])),u.length){const f=u.map(Js).join("");i=Yt(i)?Te(`${i.content}${f}`,!0):An(["(",i,`) + "${f}"`])}return{props:[ft(i,r)]}}),Cw=(e,t,n)=>{const{exp:s,loc:o}=e;return s||n.onError(Ts(61,o)),{props:[],needRuntime:n.helper(Bp)}},_w=(e,t)=>{e.type===1&&e.tagType===0&&(e.tag==="script"||e.tag==="style")&&t.removeNode()},Sw=[dw],Tw={cloak:cw,html:pw,text:mw,model:gw,on:ww,show:Cw};function Ew(e,t={}){return lw(e,Ie({},fw,t,{nodeTransforms:[_w,...Sw,...t.nodeTransforms||[]],directiveTransforms:Ie({},Tw,t.directiveTransforms||{}),transformHoist:null}))}const Dp=e=>{const{code:t}=Ew(e),n=new Function("Vue",t)(Kv);return z({render:n})},xw=["aria-label"],Aw={key:1};var Mi=z({name:"ArticleTitle",__name:"index",props:{post:{},titleTagProps:{}},setup(e){const t=ie("article-title"),{t:n}=ge();return(s,o)=>(p(),w("span",{class:T(l(t).b()),"aria-label":l(n)("tk.articleTitle.label")},[e.post.frontmatter.titleTag&&e.titleTagProps?.position==="left"?(p(),D(l(Or),nt({key:0,text:e.post.frontmatter.titleTag},e.titleTagProps,{"aria-label":e.post.frontmatter.titleTag}),null,16,["text","aria-label"])):A("v-if",!0),M(s.$slots,"default",{},()=>[e.post.title?(p(),w(Y,{key:0},[!e.post.title.includes("`<")&&!e.post.title.includes(">`")?(p(),D(Be(l(Dp)(e.post.title)),{key:0})):(p(),w("span",Aw,W(e.post.title),1))],64)):A("v-if",!0)]),e.post.frontmatter.titleTag&&e.titleTagProps?.position==="right"?(p(),D(l(Or),nt({key:1,text:e.post.frontmatter.titleTag},e.titleTagProps,{"aria-label":e.post.frontmatter.titleTag}),null,16,["text","aria-label"])):A("v-if",!0)],10,xw))}});const $w={class:"count"},Lw={class:"vp-doc"},Iw={class:"year"},Pw={class:"count"},Mw={class:"month"},Fw={class:"count"},Bw=["href","aria-label"],Nw={class:"date"};var Rp=z({name:"ArchivesPage",__name:"index",setup(e){const t=ie("archives"),{t:n}=ge(),{frontmatter:s}=Ae(),o=Pn(),i=F(()=>{const u=s.value;return{title:u.title??n("tk.archives.title"),totalCount:u.totalCount??n("tk.archives.totalCount"),year:u.year??n("tk.archives.year"),month:u.month??n("tk.archives.month"),count:u.count??n("tk.archives.count"),notFound:u.notFound??n("tk.archives.notFound")}}),r=_a(u=>u.archives),a=j(null),{start:c}=Ca(a,!1);return be(()=>{r.value&&c()}),(u,f)=>{const d=un("Content");return p(),D(l(ru),{class:T(l(t).b()),"aria-label":l(n)("tk.archives.label")},{default:O(()=>[M(u.$slots,"teek-archives-top-before"),S("div",{class:T(`${l(t).e("header")} flx-justify-between`)},[S("h1",null,W(i.value.title),1),S("div",$w,W(i.value.totalCount.replace("{count}",l(o).sortPostsByDate.length)),1)],2),M(u.$slots,"teek-archives-top-after"),S("div",Lw,[H(d)]),S("div",{class:T(l(t).e("timeline"))},[(p(!0),w(Y,null,le(l(o).groupPostsByYearMonth,(h,m)=>(p(),w(Y,{key:m},[S("div",{class:T(`${l(t).em("timeline","year")} flx-justify-between`)},[S("div",Iw,W(String(m).trim()==="NaN"?i.value.notFound:String(m).trim()+i.value.year),1),S("div",Pw,W(l(o).groupPostsByYear[m].length+i.value.count),1)],2),S("div",{class:T(l(t).e("timeline__m"))},[(p(!0),w(Y,null,le(h,(g,v)=>(p(),w(Y,{key:v},[S("div",{class:T(`${l(t).em("timeline__m","month")} flx-justify-between`)},[S("div",Mw,W(String(v)==="NaN"?i.value.notFound:v+i.value.month),1),S("div",Fw,W(g.length+i.value.count),1)],2),S("ul",null,[(p(!0),w(Y,null,le(g,k=>(p(),w("li",{ref_for:!0,ref_key:"timelineItemListInstance",ref:a,key:k.url},[S("a",{href:k.url&&l(Ee)(k.url),"aria-label":`${k.title}`},[S("span",Nw,W(k.date?.slice(5,10)),1),H(l(Mi),{post:k,"title-tag-props":{position:"right",size:"small"}},null,8,["post"])],8,Bw)]))),128))])],64))),128))],2)],64))),128))],2)]),_:3},8,["class","aria-label"])}}});const Vw={key:0},Ow=["href","aria-label"],Dw=["id"],Rw=["href","aria-label"],Hw=["href"],zw={"aria-describedby":"overview-title"},jw=["href","aria-label"];var Hp=z({name:"ArticleOverviewPage",__name:"index",setup(e){const t=ie("article-overview"),{t:n}=ge(),s=Pn(),{localeIndex:o,site:i,theme:r,frontmatter:a}=Ae(),{getTeekConfigRef:c}=fe(),u=c("category",{path:"/categories"}),f=F(()=>s.value.groupPosts.categories),d=F(()=>r.value.docAnalysisInfo?.eachFileWords||[]),h=F(()=>{const k=o.value;return`${k!=="root"?`/${k}`:""}${u.value.path}${i.value.cleanUrls?"":".html"}`}),m=k=>d.value.filter(b=>{const C="/"+b.fileInfo.relativePath.replace(".md","");return[C,`${C}.html`].includes(k)})[0],g=F(()=>Object.entries(f.value).map(([k,b])=>({name:k,data:b.map(C=>{const y=m(C.url);return{...C,wordCount:y?.wordCount||"-",readingTime:y?.readingTime||"-"}})||[]})).sort((k,b)=>new Date(b.data[b.data.length-1].date).getTime()-new Date(k.data[k.data.length-1].date).getTime())),v=k=>{const b=a.value.publishDateFormat;return b?hi(k||new Date,b):k};return(k,b)=>{const C=un("Content");return p(),D(l(ru),{doc:"",aside:"",class:T(l(t).b())},{default:O(()=>[l(a).title?(p(),w("h1",Vw,[rt(W(l(a).title)+" ",1),S("a",{class:"header-anchor",href:`#${l(a).title}`,"aria-label":`Permalink to '${l(a).title}'`},null,8,Ow)])):A("v-if",!0),H(C),(p(!0),w(Y,null,le(g.value,y=>(p(),w(Y,{key:y.name},[S("h2",{id:`${y.name}-${l(n)("tk.articleOverview.overview")}`},[rt(W(y.name)+" "+W(l(n)("tk.articleOverview.overview"))+" ",1),S("a",{class:"header-anchor",href:`#${y.name}-${l(n)("tk.articleOverview.overview")}`,"aria-label":`Permalink to '${y.name}-${l(n)("tk.articleOverview.overview")}'`},null,8,Rw)],8,Dw),S("a",{href:`${h.value}?category=${y.name}`,"aria-describedby":"overview-title"},W(y.name)+" "+W(l(n)("tk.articleOverview.category")),9,Hw),S("table",zw,[S("thead",null,[S("tr",null,[S("th",null,W(l(n)("tk.articleOverview.name")),1),S("th",null,W(l(n)("tk.articleOverview.title")),1),S("th",null,W(l(n)("tk.articleOverview.date")),1),S("th",null,W(l(n)("tk.articleOverview.wordCount")),1),S("th",null,W(l(n)("tk.articleOverview.readingTime")),1)])]),S("tbody",null,[(p(!0),w(Y,null,le(y.data,_=>(p(),w("tr",{key:_.url},[S("td",null,W(y.name),1),S("td",null,[S("a",{href:_.url&&l(Ee)(_.url),"aria-label":_.title},[_.title?(p(),D(Be(l(Dp)(_.title)),{key:0})):A("v-if",!0)],8,jw)]),S("td",null,W(v(_.date)),1),S("td",null,W(_.wordCount),1),S("td",null,W(_.readingTime),1)]))),128))])])],64))),128))]),_:1},8,["class"])}}});const Uw=["innerHTML"];var Ww=z({name:"SvgIcon",__name:"SvgIcon",props:{icon:{}},setup(e){return(t,n)=>(p(),w("i",{innerHTML:e.icon},null,8,Uw))}});const qw={key:0,class:"iconfont"},Kw={key:2,class:"icon-svg","aria-hidden":"true"},Yw=["xlink:href"];var Gw=z({name:"FontIcon",__name:"FontIcon",props:{icon:{},iconType:{}},setup(e){return(t,n)=>e.iconType==="unicode"?(p(),w("i",qw,W(e.icon),1)):e.iconType==="iconfont"?(p(),w("i",{key:1,class:T(`iconfont ${e.icon}`)},null,2)):e.iconType==="symbol"?(p(),w("svg",Kw,[S("use",{"xlink:href":`#${e.icon}`},null,8,Yw)])):A("v-if",!0)}});const zp=/^[a-z0-9]+(-[a-z0-9]+)*$/,Aa=(e,t,n,s="")=>{const o=e.split(":");if(e.slice(0,1)==="@"){if(o.length<2||o.length>3)return null;s=o.shift().slice(1)}if(o.length>3||!o.length)return null;if(o.length>1){const a=o.pop(),c=o.pop(),u={provider:o.length>0?o[0]:s,prefix:c,name:a};return t&&!gr(u)?null:u}const i=o[0],r=i.split("-");if(r.length>1){const a={provider:s,prefix:r.shift(),name:r.join("-")};return t&&!gr(a)?null:a}if(n&&s===""){const a={provider:s,prefix:"",name:i};return t&&!gr(a,n)?null:a}return null},gr=(e,t)=>e?!!((t&&e.prefix===""||e.prefix)&&e.name):!1,jp=Object.freeze({left:0,top:0,width:16,height:16}),Kr=Object.freeze({rotate:0,vFlip:!1,hFlip:!1}),$a=Object.freeze({...jp,...Kr}),tc=Object.freeze({...$a,body:"",hidden:!1});function Jw(e,t){const n={};!e.hFlip!=!t.hFlip&&(n.hFlip=!0),!e.vFlip!=!t.vFlip&&(n.vFlip=!0);const s=((e.rotate||0)+(t.rotate||0))%4;return s&&(n.rotate=s),n}function _d(e,t){const n=Jw(e,t);for(const s in tc)s in Kr?s in e&&!(s in n)&&(n[s]=Kr[s]):s in t?n[s]=t[s]:s in e&&(n[s]=e[s]);return n}function Xw(e,t){const n=e.icons,s=e.aliases||Object.create(null),o=Object.create(null);function i(r){if(n[r])return o[r]=[];if(!(r in o)){o[r]=null;const a=s[r]&&s[r].parent,c=a&&i(a);c&&(o[r]=[a].concat(c))}return o[r]}return Object.keys(n).concat(Object.keys(s)).forEach(i),o}function Qw(e,t,n){const s=e.icons,o=e.aliases||Object.create(null);let i={};function r(a){i=_d(s[a]||o[a],i)}return r(t),n.forEach(r),_d(e,i)}function Up(e,t){const n=[];if(typeof e!="object"||typeof e.icons!="object")return n;e.not_found instanceof Array&&e.not_found.forEach(o=>{t(o,null),n.push(o)});const s=Xw(e);for(const o in s){const i=s[o];i&&(t(o,Qw(e,o,i)),n.push(o))}return n}const Zw={provider:"",aliases:{},not_found:{},...jp};function Xa(e,t){for(const n in t)if(n in e&&typeof e[n]!=typeof t[n])return!1;return!0}function Wp(e){if(typeof e!="object"||e===null)return null;const t=e;if(typeof t.prefix!="string"||!e.icons||typeof e.icons!="object"||!Xa(e,Zw))return null;const n=t.icons;for(const o in n){const i=n[o];if(!o||typeof i.body!="string"||!Xa(i,tc))return null}const s=t.aliases||Object.create(null);for(const o in s){const i=s[o],r=i.parent;if(!o||typeof r!="string"||!n[r]&&!s[r]||!Xa(i,tc))return null}return t}const Sd=Object.create(null);function eC(e,t){return{provider:e,prefix:t,icons:Object.create(null),missing:new Set}}function Lo(e,t){const n=Sd[e]||(Sd[e]=Object.create(null));return n[t]||(n[t]=eC(e,t))}function qp(e,t){return Wp(t)?Up(t,(n,s)=>{s?e.icons[n]=s:e.missing.add(n)}):[]}function tC(e,t,n){try{if(typeof n.body=="string")return e.icons[t]={...n},!0}catch{}return!1}let wi=!1;function Kp(e){return typeof e=="boolean"&&(wi=e),wi}function nC(e){const t=typeof e=="string"?Aa(e,!0,wi):e;if(t){const n=Lo(t.provider,t.prefix),s=t.name;return n.icons[s]||(n.missing.has(s)?null:void 0)}}function Yp(e,t){const n=Aa(e,!0,wi);if(!n)return!1;const s=Lo(n.provider,n.prefix);return t?tC(s,n.name,t):(s.missing.add(n.name),!0)}function sC(e,t){if(typeof e!="object")return!1;if(typeof t!="string"&&(t=e.provider||""),wi&&!t&&!e.prefix){let o=!1;return Wp(e)&&(e.prefix="",Up(e,(i,r)=>{Yp(i,r)&&(o=!0)})),o}const n=e.prefix;if(!gr({prefix:n,name:"a"}))return!1;const s=Lo(t,n);return!!qp(s,e)}const Gp=Object.freeze({width:null,height:null}),Jp=Object.freeze({...Gp,...Kr}),oC=/(-?[0-9.]*[0-9]+[0-9.]*)/g,iC=/^-?[0-9.]*[0-9]+[0-9.]*$/g;function Td(e,t,n){if(t===1)return e;if(n=n||100,typeof e=="number")return Math.ceil(e*t*n)/n;if(typeof e!="string")return e;const s=e.split(oC);if(s===null||!s.length)return e;const o=[];let i=s.shift(),r=iC.test(i);for(;;){if(r){const a=parseFloat(i);isNaN(a)?o.push(i):o.push(Math.ceil(a*t*n)/n)}else o.push(i);if(i=s.shift(),i===void 0)return o.join("");r=!r}}function rC(e,t="defs"){let n="";const s=e.indexOf("<"+t);for(;s>=0;){const o=e.indexOf(">",s),i=e.indexOf("",i);if(r===-1)break;n+=e.slice(o+1,i).trim(),e=e.slice(0,s).trim()+e.slice(r+1)}return{defs:n,content:e}}function aC(e,t){return e?""+e+""+t:t}function lC(e,t,n){const s=rC(e);return aC(s.defs,t+s.content+n)}const cC=e=>e==="unset"||e==="undefined"||e==="none";function uC(e,t){const n={...$a,...e},s={...Jp,...t},o={left:n.left,top:n.top,width:n.width,height:n.height};let i=n.body;[n,s].forEach(v=>{const k=[],b=v.hFlip,C=v.vFlip;let y=v.rotate;b?C?y+=2:(k.push("translate("+(o.width+o.left).toString()+" "+(0-o.top).toString()+")"),k.push("scale(-1 1)"),o.top=o.left=0):C&&(k.push("translate("+(0-o.left).toString()+" "+(o.height+o.top).toString()+")"),k.push("scale(1 -1)"),o.top=o.left=0);let _;switch(y<0&&(y-=Math.floor(y/4)*4),y=y%4,y){case 1:_=o.height/2+o.top,k.unshift("rotate(90 "+_.toString()+" "+_.toString()+")");break;case 2:k.unshift("rotate(180 "+(o.width/2+o.left).toString()+" "+(o.height/2+o.top).toString()+")");break;case 3:_=o.width/2+o.left,k.unshift("rotate(-90 "+_.toString()+" "+_.toString()+")");break}y%2===1&&(o.left!==o.top&&(_=o.left,o.left=o.top,o.top=_),o.width!==o.height&&(_=o.width,o.width=o.height,o.height=_)),k.length&&(i=lC(i,'',""))});const r=s.width,a=s.height,c=o.width,u=o.height;let f,d;r===null?(d=a===null?"1em":a==="auto"?u:a,f=Td(d,c/u)):(f=r==="auto"?c:r,d=a===null?Td(f,u/c):a==="auto"?u:a);const h={},m=(v,k)=>{cC(k)||(h[v]=k.toString())};m("width",f),m("height",d);const g=[o.left,o.top,c,u];return h.viewBox=g.join(" "),{attributes:h,viewBox:g,body:i}}const fC=/\sid="(\S+)"/g,dC="IconifyId"+Date.now().toString(16)+(Math.random()*16777216|0).toString(16);let hC=0;function pC(e,t=dC){const n=[];let s;for(;s=fC.exec(e);)n.push(s[1]);if(!n.length)return e;const o="suffix"+(Math.random()*16777216|Date.now()).toString(16);return n.forEach(i=>{const r=typeof t=="function"?t(i):t+(hC++).toString(),a=i.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");e=e.replace(new RegExp('([#;"])('+a+')([")]|\\.[a-z])',"g"),"$1"+r+o+"$3")}),e=e.replace(new RegExp(o,"g"),""),e}const nc=Object.create(null);function mC(e,t){nc[e]=t}function sc(e){return nc[e]||nc[""]}function xu(e){let t;if(typeof e.resources=="string")t=[e.resources];else if(t=e.resources,!(t instanceof Array)||!t.length)return null;return{resources:t,path:e.path||"/",maxURL:e.maxURL||500,rotate:e.rotate||750,timeout:e.timeout||5e3,random:e.random===!0,index:e.index||0,dataAfterTimeout:e.dataAfterTimeout!==!1}}const Au=Object.create(null),jo=["https://api.simplesvg.com","https://api.unisvg.com"],vr=[];for(;jo.length>0;)jo.length===1||Math.random()>.5?vr.push(jo.shift()):vr.push(jo.pop());Au[""]=xu({resources:["https://api.iconify.design"].concat(vr)});function gC(e,t){const n=xu(t);return n===null?!1:(Au[e]=n,!0)}function $u(e){return Au[e]}const vC=()=>{let e;try{if(e=fetch,typeof e=="function")return e}catch{}};let Ed=vC();function yC(e,t){const n=$u(e);if(!n)return 0;let s;if(!n.maxURL)s=0;else{let o=0;n.resources.forEach(r=>{o=Math.max(o,r.length)});const i=t+".json?icons=";s=n.maxURL-o-n.path.length-i.length}return s}function bC(e){return e===404}const kC=(e,t,n)=>{const s=[],o=yC(e,t),i="icons";let r={type:i,provider:e,prefix:t,icons:[]},a=0;return n.forEach((c,u)=>{a+=c.length+1,a>=o&&u>0&&(s.push(r),r={type:i,provider:e,prefix:t,icons:[]},a=c.length),r.icons.push(c)}),s.push(r),s};function wC(e){if(typeof e=="string"){const t=$u(e);if(t)return t.path}return"/"}const CC=(e,t,n)=>{if(!Ed){n("abort",424);return}let s=wC(t.provider);switch(t.type){case"icons":{const i=t.prefix,a=t.icons.join(","),c=new URLSearchParams({icons:a});s+=i+".json?"+c.toString();break}case"custom":{const i=t.uri;s+=i.slice(0,1)==="/"?i.slice(1):i;break}default:n("abort",400);return}let o=503;Ed(e+s).then(i=>{const r=i.status;if(r!==200){setTimeout(()=>{n(bC(r)?"abort":"next",r)});return}return o=501,i.json()}).then(i=>{if(typeof i!="object"||i===null){setTimeout(()=>{i===404?n("abort",i):n("next",o)});return}setTimeout(()=>{n("success",i)})}).catch(()=>{n("next",o)})},_C={prepare:kC,send:CC};function SC(e){const t={loaded:[],missing:[],pending:[]},n=Object.create(null);e.sort((o,i)=>o.provider!==i.provider?o.provider.localeCompare(i.provider):o.prefix!==i.prefix?o.prefix.localeCompare(i.prefix):o.name.localeCompare(i.name));let s={provider:"",prefix:"",name:""};return e.forEach(o=>{if(s.name===o.name&&s.prefix===o.prefix&&s.provider===o.provider)return;s=o;const i=o.provider,r=o.prefix,a=o.name,c=n[i]||(n[i]=Object.create(null)),u=c[r]||(c[r]=Lo(i,r));let f;a in u.icons?f=t.loaded:r===""||u.missing.has(a)?f=t.missing:f=t.pending;const d={provider:i,prefix:r,name:a};f.push(d)}),t}function Xp(e,t){e.forEach(n=>{const s=n.loaderCallbacks;s&&(n.loaderCallbacks=s.filter(o=>o.id!==t))})}function TC(e){e.pendingCallbacksFlag||(e.pendingCallbacksFlag=!0,setTimeout(()=>{e.pendingCallbacksFlag=!1;const t=e.loaderCallbacks?e.loaderCallbacks.slice(0):[];if(!t.length)return;let n=!1;const s=e.provider,o=e.prefix;t.forEach(i=>{const r=i.icons,a=r.pending.length;r.pending=r.pending.filter(c=>{if(c.prefix!==o)return!0;const u=c.name;if(e.icons[u])r.loaded.push({provider:s,prefix:o,name:u});else if(e.missing.has(u))r.missing.push({provider:s,prefix:o,name:u});else return n=!0,!0;return!1}),r.pending.length!==a&&(n||Xp([e],i.id),i.callback(r.loaded.slice(0),r.missing.slice(0),r.pending.slice(0),i.abort))})}))}let EC=0;function xC(e,t,n){const s=EC++,o=Xp.bind(null,n,s);if(!t.pending.length)return o;const i={id:s,icons:t,callback:e,abort:o};return n.forEach(r=>{(r.loaderCallbacks||(r.loaderCallbacks=[])).push(i)}),o}function AC(e,t=!0,n=!1){const s=[];return e.forEach(o=>{const i=typeof o=="string"?Aa(o,t,n):o;i&&s.push(i)}),s}var $C={resources:[],index:0,timeout:2e3,rotate:750,random:!1,dataAfterTimeout:!1};function LC(e,t,n,s){const o=e.resources.length,i=e.random?Math.floor(Math.random()*o):e.index;let r;if(e.random){let P=e.resources.slice(0);for(r=[];P.length>1;){const V=Math.floor(Math.random()*P.length);r.push(P[V]),P=P.slice(0,V).concat(P.slice(V+1))}r=r.concat(P)}else r=e.resources.slice(i).concat(e.resources.slice(0,i));const a=Date.now();let c="pending",u=0,f,d=null,h=[],m=[];typeof s=="function"&&m.push(s);function g(){d&&(clearTimeout(d),d=null)}function v(){c==="pending"&&(c="aborted"),g(),h.forEach(P=>{P.status==="pending"&&(P.status="aborted")}),h=[]}function k(P,V){V&&(m=[]),typeof P=="function"&&m.push(P)}function b(){return{startTime:a,payload:t,status:c,queriesSent:u,queriesPending:h.length,subscribe:k,abort:v}}function C(){c="failed",m.forEach(P=>{P(void 0,f)})}function y(){h.forEach(P=>{P.status==="pending"&&(P.status="aborted")}),h=[]}function _(P,V,E){const L=V!=="success";switch(h=h.filter(I=>I!==P),c){case"pending":break;case"failed":if(L||!e.dataAfterTimeout)return;break;default:return}if(V==="abort"){f=E,C();return}if(L){f=E,h.length||(r.length?x():C());return}if(g(),y(),!e.random){const I=e.resources.indexOf(P.resource);I!==-1&&I!==e.index&&(e.index=I)}c="completed",m.forEach(I=>{I(E)})}function x(){if(c!=="pending")return;g();const P=r.shift();if(P===void 0){if(h.length){d=setTimeout(()=>{g(),c==="pending"&&(y(),C())},e.timeout);return}C();return}const V={status:"pending",resource:P,callback:(E,L)=>{_(V,E,L)}};h.push(V),u++,d=setTimeout(x,e.rotate),n(P,t,V.callback)}return setTimeout(x),b}function Qp(e){const t={...$C,...e};let n=[];function s(){n=n.filter(a=>a().status==="pending")}function o(a,c,u){const f=LC(t,a,c,(d,h)=>{s(),u&&u(d,h)});return n.push(f),f}function i(a){return n.find(c=>a(c))||null}return{query:o,find:i,setIndex:a=>{t.index=a},getIndex:()=>t.index,cleanup:s}}function xd(){}const Qa=Object.create(null);function IC(e){if(!Qa[e]){const t=$u(e);if(!t)return;const n=Qp(t),s={config:t,redundancy:n};Qa[e]=s}return Qa[e]}function PC(e,t,n){let s,o;if(typeof e=="string"){const i=sc(e);if(!i)return n(void 0,424),xd;o=i.send;const r=IC(e);r&&(s=r.redundancy)}else{const i=xu(e);if(i){s=Qp(i);const r=e.resources?e.resources[0]:"",a=sc(r);a&&(o=a.send)}}return!s||!o?(n(void 0,424),xd):s.query(t,o,n)().abort}function Ad(){}function MC(e){e.iconsLoaderFlag||(e.iconsLoaderFlag=!0,setTimeout(()=>{e.iconsLoaderFlag=!1,TC(e)}))}function FC(e){const t=[],n=[];return e.forEach(s=>{(s.match(zp)?t:n).push(s)}),{valid:t,invalid:n}}function Uo(e,t,n){function s(){const o=e.pendingIcons;t.forEach(i=>{o&&o.delete(i),e.icons[i]||e.missing.add(i)})}if(n&&typeof n=="object")try{if(!qp(e,n).length){s();return}}catch(o){console.error(o)}s(),MC(e)}function $d(e,t){e instanceof Promise?e.then(n=>{t(n)}).catch(()=>{t(null)}):t(e)}function BC(e,t){e.iconsToLoad?e.iconsToLoad=e.iconsToLoad.concat(t).sort():e.iconsToLoad=t,e.iconsQueueFlag||(e.iconsQueueFlag=!0,setTimeout(()=>{e.iconsQueueFlag=!1;const{provider:n,prefix:s}=e,o=e.iconsToLoad;if(delete e.iconsToLoad,!o||!o.length)return;const i=e.loadIcon;if(e.loadIcons&&(o.length>1||!i)){$d(e.loadIcons(o,s,n),f=>{Uo(e,o,f)});return}if(i){o.forEach(f=>{const d=i(f,s,n);$d(d,h=>{const m=h?{prefix:s,icons:{[f]:h}}:null;Uo(e,[f],m)})});return}const{valid:r,invalid:a}=FC(o);if(a.length&&Uo(e,a,null),!r.length)return;const c=s.match(zp)?sc(n):null;if(!c){Uo(e,r,null);return}c.prepare(n,s,r).forEach(f=>{PC(n,f,d=>{Uo(e,f.icons,d)})})}))}const NC=(e,t)=>{const n=AC(e,!0,Kp()),s=SC(n);if(!s.pending.length){let c=!0;return t&&setTimeout(()=>{c&&t(s.loaded,s.missing,s.pending,Ad)}),()=>{c=!1}}const o=Object.create(null),i=[];let r,a;return s.pending.forEach(c=>{const{provider:u,prefix:f}=c;if(f===a&&u===r)return;r=u,a=f,i.push(Lo(u,f));const d=o[u]||(o[u]=Object.create(null));d[f]||(d[f]=[])}),s.pending.forEach(c=>{const{provider:u,prefix:f,name:d}=c,h=Lo(u,f),m=h.pendingIcons||(h.pendingIcons=new Set);m.has(d)||(m.add(d),o[u][f].push(d))}),i.forEach(c=>{const u=o[c.provider][c.prefix];u.length&&BC(c,u)}),t?xC(t,s,i):Ad};function VC(e,t){const n={...e};for(const s in t){const o=t[s],i=typeof o;s in Gp?(o===null||o&&(i==="string"||i==="number"))&&(n[s]=o):i===typeof n[s]&&(n[s]=s==="rotate"?o%4:o)}return n}const OC=/[\s,]+/;function DC(e,t){t.split(OC).forEach(n=>{switch(n.trim()){case"horizontal":e.hFlip=!0;break;case"vertical":e.vFlip=!0;break}})}function RC(e,t=0){const n=e.replace(/^-?[0-9.]*/,"");function s(o){for(;o<0;)o+=4;return o%4}if(n===""){const o=parseInt(e);return isNaN(o)?0:s(o)}else if(n!==e){let o=0;switch(n){case"%":o=25;break;case"deg":o=90}if(o){let i=parseFloat(e.slice(0,e.length-n.length));return isNaN(i)?0:(i=i/o,i%1===0?s(i):0)}}return t}function HC(e,t){let n=e.indexOf("xlink:")===-1?"":' xmlns:xlink="http://www.w3.org/1999/xlink"';for(const s in t)n+=" "+s+'="'+t[s]+'"';return'"+e+""}function zC(e){return e.replace(/"/g,"'").replace(/%/g,"%25").replace(/#/g,"%23").replace(//g,"%3E").replace(/\s+/g," ")}function jC(e){return"data:image/svg+xml,"+zC(e)}function UC(e){return'url("'+jC(e)+'")'}const Ld={...Jp,inline:!1},WC={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink","aria-hidden":!0,role:"img"},qC={display:"inline-block"},oc={backgroundColor:"currentColor"},Zp={backgroundColor:"transparent"},Id={Image:"var(--svg)",Repeat:"no-repeat",Size:"100% 100%"},Pd={webkitMask:oc,mask:oc,background:Zp};for(const e in Pd){const t=Pd[e];for(const n in Id)t[e+n]=Id[n]}const yr={};["horizontal","vertical"].forEach(e=>{const t=e.slice(0,1)+"Flip";yr[e+"-flip"]=t,yr[e.slice(0,1)+"-flip"]=t,yr[e+"Flip"]=t});function Md(e){return e+(e.match(/^[-0-9.]+$/)?"px":"")}const Fd=(e,t)=>{const n=VC(Ld,t),s={...WC},o=t.mode||"svg",i={},r=t.style,a=typeof r=="object"&&!(r instanceof Array)?r:{};for(let v in t){const k=t[v];if(k!==void 0)switch(v){case"icon":case"style":case"onLoad":case"mode":case"ssr":break;case"inline":case"hFlip":case"vFlip":n[v]=k===!0||k==="true"||k===1;break;case"flip":typeof k=="string"&&DC(n,k);break;case"color":i.color=k;break;case"rotate":typeof k=="string"?n[v]=RC(k):typeof k=="number"&&(n[v]=k);break;case"ariaHidden":case"aria-hidden":k!==!0&&k!=="true"&&delete s["aria-hidden"];break;default:{const b=yr[v];b?(k===!0||k==="true"||k===1)&&(n[b]=!0):Ld[v]===void 0&&(s[v]=k)}}}const c=uC(e,n),u=c.attributes;if(n.inline&&(i.verticalAlign="-0.125em"),o==="svg"){s.style={...i,...a},Object.assign(s,u);let v=0,k=t.id;return typeof k=="string"&&(k=k.replace(/-/g,"_")),s.innerHTML=pC(c.body,k?()=>k+"ID"+v++:"iconifyVue"),nn("svg",s)}const{body:f,width:d,height:h}=e,m=o==="mask"||(o==="bg"?!1:f.indexOf("currentColor")!==-1),g=HC(f,{...u,width:d+"",height:h+""});return s.style={...i,"--svg":UC(g),width:Md(u.width),height:Md(u.height),...qC,...m?oc:Zp,...a},nn("span",s)};Kp(!0);mC("",_C);if(typeof document<"u"&&typeof window<"u"){const e=window;if(e.IconifyPreload!==void 0){const t=e.IconifyPreload,n="Invalid IconifyPreload syntax.";typeof t=="object"&&t!==null&&(t instanceof Array?t:[t]).forEach(s=>{try{(typeof s!="object"||s===null||s instanceof Array||typeof s.icons!="object"||typeof s.prefix!="string"||!sC(s))&&console.error(n)}catch{console.error(n)}})}if(e.IconifyProviders!==void 0){const t=e.IconifyProviders;if(typeof t=="object"&&t!==null)for(let n in t){const s="IconifyProviders["+n+"] is invalid.";try{const o=t[n];if(typeof o!="object"||!o||o.resources===void 0)continue;gC(n,o)||console.error(s)}catch{console.error(s)}}}}const KC={...$a,body:""},e2=z({inheritAttrs:!1,data(){return{_name:"",_loadingIcon:null,iconMounted:!1,counter:0}},mounted(){this.iconMounted=!0},unmounted(){this.abortLoading()},methods:{abortLoading(){this._loadingIcon&&(this._loadingIcon.abort(),this._loadingIcon=null)},getIcon(e,t,n){if(typeof e=="object"&&e!==null&&typeof e.body=="string")return this._name="",this.abortLoading(),{data:e};let s;if(typeof e!="string"||(s=Aa(e,!1,!0))===null)return this.abortLoading(),null;let o=nC(s);if(!o)return(!this._loadingIcon||this._loadingIcon.name!==e)&&(this.abortLoading(),this._name="",o!==null&&(this._loadingIcon={name:e,abort:NC([s],()=>{this.counter++})})),null;if(this.abortLoading(),this._name!==e&&(this._name=e,t&&t(e)),n){o=Object.assign({},o);const r=n(o.body,s.name,s.prefix,s.provider);typeof r=="string"&&(o.body=r)}const i=["iconify"];return s.prefix!==""&&i.push("iconify--"+s.prefix),s.provider!==""&&i.push("iconify--"+s.provider),{data:o,classes:i}}},render(){this.counter;const e=this.$attrs,t=this.iconMounted||e.ssr?this.getIcon(e.icon,e.onLoad,e.customise):null;if(!t)return Fd(KC,e);let n=e;return t.classes&&(n={...e,class:(typeof e.class=="string"?e.class+" ":"")+t.classes.join(" ")}),Fd({...$a,...t.data},n)}});var YC=z({name:"IconifyOffline",__name:"IconifyOffline",props:{icon:{}},setup(e){const t=e;return be(()=>{const n=H1();Yp(`iconify-${n}`,t.icon)}),(n,s)=>(p(),D(l(e2),{icon:e.icon,style:{outline:"none"}},null,8,["icon"]))}}),GC=z({name:"IconifyOnline",__name:"IconifyOnline",props:{icon:{}},setup(e){return(t,n)=>(p(),D(l(e2),{icon:e.icon,style:{outline:"none"}},null,8,["icon"]))}});const JC=["innerHTML"],XC=["src","alt"];var de=z({name:"Icon",__name:"index",props:{icon:{default:""},iconType:{},size:{},color:{},hover:{type:Boolean,default:!1},hoverColor:{},imgAlt:{},pointer:{type:Boolean,default:!1},style:{}},setup(e){const t=ie("icon"),n=Z1(e,["icon","iconType","color","hover","hoverColor","pointer"]),s=Si(),o=()=>({...n.style,...e.pointer?{cursor:"pointer"}:void 0,"--icon-color":e.color,"--icon-size":n.size&&sn(n.size),"--icon-color-hover":e.hoverColor||t.cssVar("theme-color")}),i=F(()=>Je(e.icon)?e.icon.replace(/^(svg-|if-|uni-|sym-|img-)/i,""):Pe(e.icon)),r=F(()=>{if(e.iconType&&["unicode","iconfont","symbol"].includes(e.iconType))return e.iconType;if(!Je(e.icon))return"";const g=e.icon.toLowerCase();return g.startsWith("if-")||g.startsWith("iconfont")||i.value.startsWith("icon-")?"iconfont":g.startsWith("uni-")||/^&#x[\da-f]+/i.test(e.icon)||e.icon.length===1&&e.icon.charCodeAt(0)>=57344&&e.icon.charCodeAt(0)<=63743?"unicode":g.startsWith("sym-")?"symbol":""}),a=F(()=>Je(e.icon)&&(e.iconType==="svg"||e.icon.startsWith("svg-")||Je(e.icon))),c=F(()=>Je(e.icon)&&e.icon?.includes("Je(e.icon)&&r.value),f=F(()=>!Je(e.icon)&&(e.iconType==="component"||ei(e.icon)&&("setup"in e.icon||"render"in e.icon)||typeof e.icon=="function")),d=F(()=>!Je(e.icon)&&(e.iconType==="iconifyOffline"||"body"in e.icon)),h=F(()=>Je(e.icon)&&(e.iconType==="iconifyOnline"||e.icon.includes(":"))),m=F(()=>Je(e.icon)&&(e.iconType==="img"||e.icon.toLowerCase().startsWith("img-")||[".png",".jpg",".jpeg",".gif",".bmp",".webp",".svg"].some(g=>e.icon.endsWith(g))));return(g,v)=>!u.value&&!m.value&&!c.value?(p(),w("i",{key:0,class:T([l(t).b(),l(t).is("hover",e.hover)]),style:Fe(o())},[l(s).default?M(g.$slots,"default",{key:0}):f.value?(p(),D(Be(i.value),{key:1,size:e.size},null,8,["size"])):d.value?(p(),D(YC,{key:2,icon:i.value},null,8,["icon"])):h.value?(p(),D(GC,{key:3,icon:i.value},null,8,["icon"])):a.value?(p(),D(Ww,{key:4,icon:i.value},null,8,["icon"])):A("v-if",!0)],6)):c.value?(p(),w("i",{key:1,innerHTML:e.icon,class:T([l(t).b(),l(t).is("hover",e.hover)]),style:Fe(o())},null,14,JC)):u.value&&r.value?(p(),D(Gw,{key:2,icon:i.value,iconType:r.value,class:T([l(t).b(),l(t).is("hover",e.hover)]),style:Fe(o())},null,8,["icon","iconType","class","style"])):m.value?(p(),w("img",{key:3,src:i.value,alt:e.imgAlt,class:T([l(t).b(),l(t).is("hover",e.hover)]),style:Fe(o())},null,14,XC)):A("v-if",!0)}});const QC=["primary","success","info","warning","error"],t2={customClass:"",center:!1,dangerouslyUseHTMLString:!1,duration:3e3,icon:void 0,id:"",message:"",onClose:void 0,showClose:!1,type:"info",plain:!1,offset:16,zIndex:0,grouping:!1,repeatNum:1},ZC={...t2,appendTo:me?document.body:void 0},On=pc([]),e_=e=>{const t=On.findIndex(o=>o.id===e),n=On[t];let s;return t>0&&(s=On[t-1]),{current:n,prev:s}},t_=e=>{const{prev:t}=e_(e);return t?t.vm.exposed.bottom.value:0},n_=(e,t)=>On.findIndex(s=>s.id===e)>0?16:t,s_=["id"],o_=["innerHTML"];var i_=z({name:"Message",__name:"index",props:Q1({customClass:{},center:{type:Boolean},dangerouslyUseHTMLString:{type:Boolean},duration:{},icon:{},id:{},message:{type:[String,Object,Function]},onClose:{type:Function},showClose:{type:Boolean},type:{},plain:{type:Boolean},offset:{},zIndex:{},grouping:{type:Boolean},repeatNum:{}},t2),emits:["destroy"],setup(e,{expose:t,emit:n}){const s=e,o=n,i={success:Fh,warning:Bh,error:h9,info:p9},r=j(!1),a=ie("message"),{currentZIndex:c,nextZIndex:u}=nu(),f=j(),d=j(!1),h=j(0),m={info:"info",primary:"primary",success:"success",warning:"warning",error:"danger"},g=F(()=>s.type?m[s.type]:"info"),v=F(()=>{const N=s.type;return{[a.bm("icon",N)]:N&&i[N]}}),k=F(()=>s.icon||i[s.type]||""),b=F(()=>t_(s.id)),C=F(()=>n_(s.id,s.offset)+b.value),y=F(()=>h.value+C.value),_=F(()=>({top:`${C.value}px`,zIndex:c.value}));let x;const P=()=>{x&&(clearTimeout(x),x=null)},V=()=>{s.duration!==0&&(P(),x=setTimeout(()=>{E()},s.duration))},E=()=>{d.value=!1,ze(()=>{r.value||(s.onClose?.(),o("destroy"))})},L=({code:N})=>{N==="Space"&&E()};let I;return be(()=>{V(),u(),d.value=!0,I=new ResizeObserver(()=>{f.value&&(h.value=f.value.getBoundingClientRect().height)}),f.value&&I.observe(f.value)}),cn(()=>{I&&f.value&&I.unobserve(f.value)}),te(()=>s.repeatNum,()=>{P(),V()}),Ve(document,"keydown",L),t({visible:d,bottom:y,close:E}),(N,$)=>(p(),D(vt,{name:l(a).b("fade"),onBeforeEnter:$[0]||($[0]=U=>r.value=!0),onBeforeLeave:e.onClose,onAfterLeave:$[1]||($[1]=U=>N.$emit("destroy")),persisted:""},{default:O(()=>[et(S("div",{id:e.id,ref_key:"messageRef",ref:f,class:T([l(a).b(),{[l(a).m(e.type)]:e.type},l(a).is("center",e.center),l(a).is("closable",e.showClose),l(a).is("plain",e.plain),e.customClass]),style:Fe(_.value),role:"alert",onMouseenter:P,onMouseleave:V},[e.repeatNum>1?(p(),D(l(eh),{key:0,text:e.repeatNum,type:g.value,class:T(l(a).e("badge"))},null,8,["text","type","class"])):A("v-if",!0),k.value?(p(),D(l(de),{key:1,icon:k.value,class:T([l(a).e("icon"),v.value])},null,8,["icon","class"])):A("v-if",!0),M(N.$slots,"default",{},()=>[e.dangerouslyUseHTMLString?(p(),w("p",{key:1,class:T(l(a).e("content")),innerHTML:e.message},null,10,o_)):(p(),w("p",{key:0,class:T(l(a).e("content"))},W(e.message),3))]),e.showClose?(p(),D(l(de),{key:2,icon:l(Jc),class:T(l(a).e("closeBtn")),onClick:To(E,["stop"])},null,8,["icon","class"])):A("v-if",!0)],46,s_),[[at,d.value]])]),_:3},8,["name","onBeforeLeave"]))}});let r_=1;const n2=e=>{const t=!e||Je(e)||Ln(e)||ht(e)?{message:e}:e,n={...ZC,...t};if(!n.appendTo)n.appendTo=document.body;else if(Je(n.appendTo)){let s=document.querySelector(n.appendTo);Il(s)||(console.warn("Message","the appendTo option is not an HTMLElement. Falling back to document.body."),s=document.body),n.appendTo=s}return n},a_=e=>{const t=On.indexOf(e);if(t===-1)return;On.splice(t,1);const{handler:n}=e;n.close()},l_=({appendTo:e,...t},n)=>{const s=`message_${r_++}`,o=t.onClose,i=document.createElement("div"),r={...t,id:s,onClose:()=>{o?.(),a_(f)},onDestroy:()=>{di(null,i)}},a=H(i_,r,ht(r.message)||Ln(r.message)?{default:ht(r.message)?r.message:()=>r.message}:null);a.appContext=n||Ct._context,di(a,i),e.appendChild(i.firstElementChild);const c=a.component,f={id:s,vnode:a,vm:c,handler:{close:()=>{c.exposed.close()}},props:a.component.props};return f},Ct=(e={},t)=>{if(!me)return{close:()=>{}};const n=n2(e);if(n.grouping&&On.length){const o=On.find(({vnode:i})=>i.props?.message===n.message);if(o)return o.props.repeatNum+=1,o.props.type=n.type,o.handler}const s=l_(n,t);return On.push(s),s.handler};QC.forEach(e=>{Ct[e]=(t={},n)=>{const s=n2(t);return Ct({...s,type:e},n)}});function c_(e){const t=[...On];for(const n of t)(!e||e===n.props.type)&&n.handler.close()}Ct.closeAll=c_;Ct._context=null;const u_=(e=120,t=40)=>{const n=j(),s=j("");function o(r){s.value=r}function i(){n.value&&(s.value=f_(n.value,e,t))}return be(()=>{i()}),{domRef:n,imgCode:s,setImgCode:o,getImgCode:i}};function hn(e,t){return Math.floor(Math.random()*(t-e)+e)}function Zi(e,t){const n=hn(e,t),s=hn(e,t),o=hn(e,t);return`rgb(${n},${s},${o})`}function f_(e,t,n){let s="";const o="0123456789",i=e.getContext("2d");if(!i)return s;i.fillStyle=Zi(180,230),i.fillRect(0,0,t,n);for(let r=0;r<4;r+=1){const a=o[hn(0,o.length)];s+=a;const c=hn(18,41),u=hn(-30,30);i.font=`${c}px Simhei`,i.textBaseline="top",i.fillStyle=Zi(80,150),i.save(),i.translate(30*r+15,15),i.rotate(u*Math.PI/180),i.fillText(a,-10,-15),i.restore()}for(let r=0;r<5;r+=1)i.beginPath(),i.moveTo(hn(0,t),hn(0,n)),i.lineTo(hn(0,t),hn(0,n)),i.strokeStyle=Zi(180,230),i.closePath(),i.stroke();for(let r=0;r<41;r+=1)i.beginPath(),i.arc(hn(0,t),hn(0,n),1,0,2*Math.PI),i.closePath(),i.fillStyle=Zi(150,200),i.fill();return s}var d_=z({name:"ImageVerifyCode",__name:"index",props:{modelValue:{required:!0},modelModifiers:{}},emits:["update:modelValue"],setup(e,{expose:t}){const{domRef:n,imgCode:s,setImgCode:o,getImgCode:i}=u_(),r=Jt(e,"modelValue");return te(r,a=>{o(a)}),te(s,a=>{r.value=a}),t({getImgCode:i}),(a,c)=>(p(),w("canvas",{ref_key:"domRef",ref:n,width:"120",height:"40",class:"cursor-pointer",onClick:c[0]||(c[0]=(...u)=>l(i)&&l(i)(...u))},null,512))}});const s2=()=>{if(!me)return{siteLoginKey:"",pagesLoginKey:"",pageLoginKey:"",realmLoginKey:""};const e=ie(),t=e.storageKey("private","site",window.location.hostname),n=e.storageKey("private","pages",window.location.hostname),s=e.storageKey("private","page",window.location.hostname),o=e.storageKey("private","realm",window.location.hostname);return{siteLoginKey:t,pagesLoginKey:n,pageLoginKey:s,realmLoginKey:o}},uo={realm:"realm",toPath:"toPath",verifyMode:"verifyMode"},ks={site:"site",pages:"pages",page:"page",realm:"realm"},o2={enabled:!1,expire:"1d",session:!1,siteLogin:!1,site:[],pages:[],realm:{}},h_=["aria-label"],p_=["src"],m_=["src"],g_={class:"title"},v_={class:"flx-space-y-20 login-form"},y_=["for"],b_=["onUpdate:modelValue","type","placeholder","onFocus","onBlur"],k_=["aria-label"],w_=["aria-label"];var i2=z({name:"LoginPage",__name:"index",setup(e){const t=ie("login"),n=Ls(),{frontmatter:s}=Ae(),o=Pn(),{t:i}=ge(),{getTeekConfigRef:r}=fe(),a=r("private",o2),{siteLoginKey:c,pagesLoginKey:u,pageLoginKey:f,realmLoginKey:d}=s2(),h=j(""),m=Dn({username:{model:"",focusModel:!1,errorModel:!1,icon:$h,placeholder:i("tk.login.usernamePlaceholder"),type:"text"},password:{model:"",focusModel:!1,errorModel:!1,icon:v9,placeholder:i("tk.login.passwordPlaceholder"),type:"password"},verifyCode:{model:"",focusModel:!1,errorModel:!1,icon:Bh,placeholder:i("tk.login.verifyCodePlaceholder"),type:"text",append:go(d_),appendModel:h}}),g=()=>m.verifyCode.model===""?(m.verifyCode.errorModel=!0,Ct.warning({message:i("tk.login.verifyCodeNonNull"),plain:!0}),!1):m.verifyCode.model!==h.value?(m.verifyCode.errorModel=!0,Ct.error({message:i("tk.login.verifyCodeError"),plain:!0}),!1):m.username.model===""||m.password.model===""?(m.username.errorModel=!0,Ct.warning({message:i("tk.login.loginInfoNonNull"),plain:!0}),!1):m.password.model===""?(m.password.errorModel=!0,Ct.warning({message:i("tk.login.loginInfoNonNull"),plain:!0}),!1):!0,v=E=>E?E.indexOf("d")!==-1?parseInt(E.replace("d",""))*24*60*60*1e3:E.indexOf("h")!==-1?parseInt(E.replace("h",""))*60*60*1e3:parseInt(E)*1e3:864e5,k=()=>{Object.values(m).forEach(E=>{E.model="",E.focusModel=!1})},b=()=>{const{searchParams:E}=new URL(window.location.href),L=E.get(uo.verifyMode),I=E.get(uo.toPath),N=E.get(uo.realm),{site:$=[],pages:U=[],realm:q={}}=a.value;return[{condition:()=>L===ks.page&&I,handle:()=>y([],f,{toPath:I})},{condition:()=>L===ks.realm&&N,handle:()=>y(q[N]||[],d,{isRealm:!0,realm:N})},{condition:()=>L===ks.pages,handle:()=>y(U,u)},{condition:()=>L===ks.site,handle:()=>y($,c,{isSite:!0})}].find(J=>J.condition())},C=()=>{if(!me)return;const{enabled:E=!1}=a.value;if(!E)return Ct.success({message:i("tk.login.loginSuccess"),plain:!0}),n.go("/");if(!g())return;const{searchParams:L}=new URL(window.location.href),I=L.get(uo.toPath);let N=!1;const $=b();if($){const{doLogin:U}=a.value,q={username:m.username.model,password:m.password.model},J=$.handle;N=U?U(q,"page",J):J()}N!==void 0&&(N?(Ct.success({message:i("tk.login.loginSuccess"),plain:!0}),I&&n.go(I)):Ct.error({message:i("tk.login.loginError"),plain:!0}))},y=(E,L,I={})=>{const{toPath:N}=I;if(N)return _(N,L);const $=E.find(U=>U.username===m.username.model&&U.password===m.password.model);return $?x($,L,I):!1},_=(E,L)=>{const I=o.value.originPosts.find(he=>[he.frontmatter.permalink,he.url].includes(E));if(!I)return!1;const{username:N,password:$,session:U,expire:q,strategy:J,realm:G}=I.frontmatter||{},ne=[...I.frontmatter.loginInfo||[],{username:N,password:$,session:U,expire:q,strategy:J,realm:G}].filter(he=>![void 0,""].includes(he.username)&&![void 0,""].includes(he.password)).find(he=>he.username===m.username.model&&he.password===m.password.model);if(ne)return x({...ne},L+I.url);if(G&&a.value.realm){const he=()=>y(a.value.realm[G],d,{isRealm:!0,realm:G});return a.value.doLogin?a.value.doLogin({username:N,password:$},"realm",he):he()}return!1},x=(E,L,I={})=>{const{session:N,expire:$,strategy:U="once",role:q="common"}=E,{isSite:J=!1,isRealm:G=!1,realm:ae}=I,ne=N||a.value.session?sessionStorage:localStorage,he=G?`${L}${ae}`:L,st=a.value.encrypt;try{return ne.setItem(he,JSON.stringify({username:m.username.model,password:st?st(m.password.model,s):m.password.model,loginTime:new Date().getTime(),expire:U==="always"?new Date().getTime()+30*1e3:v($||a.value.expire),strategy:U||"once",...J&&{role:q}})),!0}catch(je){return console.error("[Teek Error] Failed to store credentials:",je),!1}},P=(E,L)=>{E.focusModel=!0,E.errorModel=!1,a.value.onFocus?.(E.model,L)},V=(E,L)=>{E.focusModel=!1,E.model===""&&(E.errorModel=!0),a.value.onBlur?.(E.model,L)};return(E,L)=>(p(),w("div",{class:T(l(t).b()),"aria-label":l(i)("tk.login.label")},[S("div",{class:T(l(t).e("wrapper"))},[l(s).leftImg?(p(),w("div",{key:0,class:T(l(t).e("left"))},[S("img",{src:l(Ee)(l(s).leftImg),alt:"login"},null,8,p_)],2)):A("v-if",!0),S("div",{class:T(l(t).e("right"))},[S("div",{class:T([l(t).e("right__header"),"flx-center"])},[l(s).logo?(p(),w("img",{key:0,src:l(s).logo,alt:"logo"},null,8,m_)):A("v-if",!0),S("span",g_,W(l(s).name??"VitePress Theme Teek"),1)],2),S("form",v_,[(p(!0),w(Y,null,le(m,(I,N)=>(p(),w("div",{key:N,class:"flx login-form-item"},[S("div",{class:T([l(t).e("right__form"),l(t).is("focus",I.focusModel),l(t).is("error",I.errorModel)])},[H(l(de),{icon:I.icon},null,8,["icon"]),S("label",{for:"input-"+N,class:"sr-only"},W(I.placeholder),9,y_),et(S("input",{"onUpdate:modelValue":$=>I.model=$,type:I.type,class:T(l(t).em("right__form","control")),placeholder:I.placeholder,onFocus:$=>P(I,N),onBlur:$=>V(I,N),onKeydown:va(C,["enter"])},null,42,b_),[[Fc,I.model]])],2),I.append?(p(),D(Be(I.append),{key:0,modelValue:I.appendModel,"onUpdate:modelValue":$=>I.appendModel=$},null,8,["modelValue","onUpdate:modelValue"])):A("v-if",!0)]))),128)),S("div",{class:T(l(t).e("right__form__btn"))},[S("button",{type:"button",onClick:L[0]||(L[0]=I=>k()),class:"flx-center","aria-label":l(i)("tk.login.reset")},[H(l(de),{icon:l(Mh)},null,8,["icon"]),S("span",null,W(l(i)("tk.login.reset")),1)],8,k_),S("button",{type:"button",onClick:L[1]||(L[1]=I=>C()),class:"flx-center primary","aria-label":l(i)("tk.login.login")},[H(l(de),{icon:l(Fh)},null,8,["icon"]),S("span",null,W(l(i)("tk.login.login")),1)],8,w_)],2)])],2)],2)],10,h_))}});const C_=()=>{const e=Ls(),{frontmatter:t}=Ae(),{loginPath:n}=$i(),{siteLoginKey:s,pagesLoginKey:o,pageLoginKey:i,realmLoginKey:r}=s2(),{getTeekConfigRef:a}=fe(),c=a("private",o2),u=v=>{const k=localStorage.getItem(v)||sessionStorage.getItem(v);return k?JSON.parse(k):null},f=(v,k)=>{const b=c.value.decrypt;return v.some(C=>C.username===k.username&&C.password===(b?b(k.password,t):k.password))},d=(v,k)=>{const{expire:b,loginTime:C,strategy:y}=v;return y==="always"&&(sessionStorage.removeItem(k),localStorage.removeItem(k)),b&&C&&new Date().getTime()-C>b},h=(v,k,b)=>{const C=()=>{const y=u(v);return!!(y&&f(k,y)&&!d(y,v))};return c.value.doValidate?c.value.doValidate(b,t.value,C):C()};return{watchSite:()=>{if(!me||!c.value.enabled||!c.value.siteLogin||!n.value||e.route.data.frontmatter.loginPage)return;const{verifyMode:v,toPath:k}=uo,b=`${n.value}?${v}=${ks.site}&${k}=${window.location.href}`;h(s,c.value.site||[],"site")||e.go(b)},watchPages:()=>{me&&c.value.enabled&&te(e.route,v=>{if(!c.value.enabled||!t.value.private||!n.value||v.data.frontmatter.loginPage||h(s,c.value.site||[],"site")&&u(s).role==="admin")return;const{verifyMode:k,toPath:b,realm:C}=uo,y=`${n.value}?${k}={verifyMode}&${b}=${v.path}`,_=t.value.privateRealm,x=[...t.value.loginInfo||[],{username:t.value.username,password:t.value.password}].filter(E=>![void 0,""].includes(E.username)&&![void 0,""].includes(E.password));if(x.length){const E="/"+v.data.filePath.replace(".md",""),L=i+E;if(h(L,x,"page")||h(`${L}.html`,x,"page"))return}if(_){const E=y.replace("{verifyMode}",ks.realm)+`&${C}=${_}`;h(r+_,c.value.realm[_]||[],"realm")||e.go(E);return}if(x.length){const E=y.replace("{verifyMode}",ks.page);return e.go(E)}const P=y.replace("{verifyMode}",ks.pages),V=c.value.pages||[];h(o,V,"pages")||h(`${o}.html`,V,"pages")||e.go(P)},{immediate:!0})}}},__=["src"],S_={key:1};var r2=z({name:"RiskLinkPage",__name:"index",setup(e){const t=ie("risk-link"),{t:n}=ge(),{frontmatter:s}=Ae(),o=j("");be(()=>{const{searchParams:r}=new URL(window.location.href),a=r.get("target");a&&Yc(a)&&(o.value=a)});const i=()=>{window.location.href=o.value};return(r,a)=>(p(),w("div",{class:T([l(t).b(),l(t).join("center"),"flx-space-y-20"])},[S("div",{class:T([l(t).e("header"),"flx-align-center"])},[l(s).logo?(p(),w("img",{key:0,src:l(s).logo,alt:"logo"},null,8,__)):A("v-if",!0),o.value?(p(),w("p",{key:1,class:T(l(t).e("title"))},W(l(s).desc?l(s).desc:l(n)("tk.riskLink.title",{name:l(s).name||"VitePress Theme Teek"})),3)):(p(),w("p",{key:2,class:T(l(t).e("title"))},W(l(s).linkIllegal?l(s).linkIllegal:l(n)("tk.riskLink.linkIllegal")),3))],2),o.value?(p(),w("p",{key:0,class:T([l(t).e("link"),"sle"])},W(o.value),3)):A("v-if",!0),o.value?(p(),w("div",S_,[S("button",{class:"btn",onClick:i},W(l(n)("tk.riskLink.confirmButtonText")),1)])):A("v-if",!0)],2))}});const T_=(e={})=>{const t=new Set,n=[],{riskLinkPath:s}=$i(),{whitelist:o=[],blacklist:i=[]}=e,r=(d,h)=>d.some(m=>m===h||Je(m)&&h.startsWith(m)||m instanceof RegExp&&m.test(h)),a=(d,h)=>new URL(d,window.location.origin).hostname!==h&&!r(o,d),c=async()=>{await ze(),me&&document.querySelectorAll("a").forEach(d=>{const h=d.getAttribute("href"),m=window.location.hostname;if(!h||t.has(d)||i.length&&!r(i,h)||!a(h,m))return;t.add(d);const g=Ve(d,"click",v=>{v.preventDefault();const k=encodeURIComponent(h);window.open(`${s.value}?target=${k}`)});n.push(g)})},u=()=>{n.forEach(d=>d()),n.length=0,t.clear()},f=()=>{u(),c()};return jn(u),{start:c,stop:u,restart:f}};var E_=z({name:"TransitionCollapse",__name:"index",setup(e){const t=ie("collapse-transition"),n=o=>{o.style.maxHeight="",o.style.overflow=o.dataset.oldOverflow,o.style.paddingTop=o.dataset.oldPaddingTop,o.style.paddingBottom=o.dataset.oldPaddingBottom},s={beforeEnter(o){o.dataset||(o.dataset={}),o.dataset.oldPaddingTop=o.style.paddingTop,o.dataset.oldPaddingBottom=o.style.paddingBottom,o.style.height&&(o.dataset.elExistsHeight=o.style.height),o.style.maxHeight=0,o.style.paddingTop=0,o.style.paddingBottom=0},enter(o){requestAnimationFrame(()=>{o.dataset.oldOverflow=o.style.overflow,o.dataset.elExistsHeight?o.style.maxHeight=o.dataset.elExistsHeight:o.scrollHeight!==0?o.style.maxHeight=`${o.scrollHeight}px`:o.style.maxHeight=0,o.style.paddingTop=o.dataset.oldPaddingTop,o.style.paddingBottom=o.dataset.oldPaddingBottom,o.style.overflow="hidden"})},afterEnter(o){o.style.maxHeight="",o.style.overflow=o.dataset.oldOverflow},enterCancelled(o){n(o)},beforeLeave(o){o.dataset||(o.dataset={}),o.dataset.oldPaddingTop=o.style.paddingTop,o.dataset.oldPaddingBottom=o.style.paddingBottom,o.dataset.oldOverflow=o.style.overflow,o.style.maxHeight=`${o.scrollHeight}px`,o.style.overflow="hidden"},leave(o){o.scrollHeight!==0&&(o.style.maxHeight=0,o.style.paddingTop=0,o.style.paddingBottom=0)},afterLeave(o){n(o)},leaveCancelled(o){n(o)}};return(o,i)=>(p(),D(vt,nt({name:l(t).b()},Ec(s)),{default:O(()=>[M(o.$slots,"default")]),_:3},16,["name"]))}});const x_=["innerHTML"],A_=["innerHTML"];var $_=z({name:"DemoCode",__name:"index",props:{source:{},rawSource:{},path:{},description:{},options:{},effect:{}},setup(e){const t=e,n=ie("demo-code"),{t:s}=ge(),{copy:o,copied:i,isSupported:r}=Dh(),{frontmatter:a,isDark:c}=Ae(),{playgroundUrl:u="",playgroundMainFileName:f="App.vue",githubUrl:d="",playgroundButtonTip:h=s("tk.demoCode.playground"),githubButtonTip:m=s("tk.demoCode.github"),copyButtonTip:g=s("tk.demoCode.copy"),collapseSourceButtonTip:v=s("tk.demoCode.collapseSource"),expandSourceButtonTip:k=s("tk.demoCode.expandSource")}={...JSON.parse(decodeURIComponent(t.options)),...a.value.demo},b=F(()=>decodeURIComponent(t.source)),C=F(()=>decodeURIComponent(t.rawSource)),y=F(()=>decodeURIComponent(t.description)),_=F(()=>t.effect==="true"),x=Object.assign({}),P=wc(async()=>{try{const U=Object.keys(x).find(q=>q.endsWith(`/${t.path}`));return x[U]}catch(U){console.error(`[Teek Error] Failed to load component: '/${t.path}'`,U)}}),V=j(!1),E=U=>{U!==void 0?V.value=U:V.value=!V.value},L=()=>{const U=I(t.source),q=c.value?"?theme=dark":"",G=`${(u.includes("?")?`${u}${q.replace("?","&")}`:`${u}${q}`).replace(/\/$/,"")}/#${U}`;window.open(G,"_blank")},I=U=>{const q=decodeURIComponent(U),J={[f]:q};return btoa(JSON.stringify(J))},N=()=>{const U=`${d}/${t.path}`;window.open(U,"_blank")},$=async()=>{r||console.error(s("tk.demoCode.notSupport")),await o(C.value),i.value?Ct.success({message:s("tk.demoCode.copySuccess"),plain:!0}):Ct.error({message:s("tk.demoCode.copyFail"),plain:!0})};return(U,q)=>(p(),w(Y,null,[y.value?(p(),w("div",{key:0,class:T(l(n).b("description")),innerHTML:y.value},null,10,x_)):A("v-if",!0),_.value?(p(),D(Be(l(P)),{key:1})):(p(),w("div",{key:2,class:T(l(n).b())},[S("div",{class:T(l(n).e("effect"))},[(p(),D(Be(l(P))))],2),S("div",{class:T(l(n).e("button-group"))},[M(U.$slots,"teek-demo-code-button-left"),l(u)?(p(),D(l(de),{key:0,title:l(h),onClick:L,icon:l(K7),role:"link","aria-label":l(h)},null,8,["title","icon","aria-label"])):A("v-if",!0),l(d)?(p(),D(l(de),{key:1,title:l(m),onClick:N,icon:l(n9),role:"link","aria-label":l(d)},null,8,["title","icon","aria-label"])):A("v-if",!0),H(l(de),{title:l(g),icon:l(s9),onClick:$,role:"button","aria-label":l(g)},null,8,["title","icon","aria-label"]),H(l(de),{title:V.value?l(k):l(v),onClick:q[0]||(q[0]=J=>E()),icon:l(o9),role:"button","aria-label":V.value?l(k):l(v)},null,8,["title","icon","aria-label"]),M(U.$slots,"teek-demo-code-button-right")],2),H(l(E_),null,{default:O(()=>[et(S("div",{class:T(l(n).join("vp-code")),innerHTML:b.value},null,10,A_),[[at,V.value]])]),_:1}),H(vt,{name:l(n).join("fade-linear"),persisted:""},{default:O(()=>[et(S("div",{class:T(l(n).e("float-control")),onClick:q[1]||(q[1]=J=>E(!1)),role:"button"},[H(l(de),{icon:l(i9)},null,8,["icon"]),S("span",null,W(l(k)),1)],2),[[at,V.value]])]),_:1},8,["name"])],2))],64))}}),L_=z({name:"HomeFullscreenWallpaper",__name:"index",setup(e){const t=ie("fullscreen-wallpaper"),{getTeekConfigRef:n}=fe(),s=j(!1),o=n("wallpaper",{hideBanner:!1,hideMask:!1}),i=f=>{if(f.key==="F12"&&s.value||f.key==="I"&&f.ctrlKey&&f.shiftKey&&s.value)return f.preventDefault();f.key==="F11"&&(f.preventDefault(),document.documentElement.requestFullscreen?document.documentElement.requestFullscreen():document.documentElement.mozRequestFullScreen?document.documentElement.mozRequestFullScreen():document.documentElement.webkitRequestFullscreen?document.documentElement.webkitRequestFullscreen():document.documentElement.msRequestFullscreen&&document.documentElement.msRequestFullscreen())},r=()=>{const f=document.documentElement;if(f.scrollTop!==0)return;const d=document.querySelector(".vp-doc"),h=document.querySelector(`.${t.join("banner__content")}`),m=document.querySelector(`.${t.join("banner-waves")}`),g=document.querySelector(`.${t.join("body-bg-image")} .mask`),v=document.querySelector(`.${t.join("banner-bg-image")} .mask`);s.value=!!document.fullscreenElement;const{hideBanner:k,hideMask:b}=o.value,C=[{el:f,executeClass:t.b()},{el:d,executeClass:"display-none"},{el:h,executeClass:"no-feature"},{el:h,executeClass:"display-none",execute:k},{el:m,executeClass:"display-none",execute:k},{el:g,executeClass:"display-none",execute:b},{el:v,executeClass:"display-none",execute:b}];a(!!document.fullscreenElement,C)},a=(f,d)=>{if(f){d.forEach(h=>{h.execute!==!1?h.executeClass&&h.el?.classList.add(h.executeClass):h.notExecuteClass&&h.el?.classList.add(h.notExecuteClass)});return}d.forEach(h=>{h.execute!==!1?h.executeClass&&h.el?.classList.remove(h.executeClass):h.notExecuteClass&&h.el?.classList.remove(h.notExecuteClass)})},c=f=>{s.value&&f.preventDefault()},u=()=>document;return Ve(u,"keydown",i),Ve(u,"fullscreenchange",r),Ve(u,"contextmenu",c),(f,d)=>(p(),w("div",{class:T(l(t).b())},null,2))}});const a2=Symbol("paginationKey"),I_=["disabled","aria-label","aria-disabled"],P_={key:0};var M_=z({name:"PaginationPrev",__name:"prev",props:{disabled:{type:Boolean},currentPage:{},prevText:{},prevIcon:{}},emits:["click"],setup(e){const t=e,{t:n}=ge(),s=F(()=>t.disabled||t.currentPage<=1);return(o,i)=>(p(),w("button",{type:"button",class:"btn-prev",disabled:s.value,"aria-label":e.prevText||l(n)("tk.pagination.prev"),"aria-disabled":s.value,onClick:i[0]||(i[0]=r=>o.$emit("click",r))},[e.prevText?(p(),w("span",P_,W(e.prevText),1)):e.prevIcon?(p(),D(l(de),{key:1,icon:e.prevIcon},null,8,["icon"])):A("v-if",!0)],8,I_))}});const F_=["disabled","aria-label","aria-disabled"],B_={key:0};var N_=z({name:"PaginationNext",__name:"next",props:{disabled:{type:Boolean},currentPage:{},pageCount:{},nextText:{},nextIcon:{}},emits:["click"],setup(e){const t=e,{t:n}=ge(),s=F(()=>t.disabled||t.currentPage===t.pageCount||t.pageCount===0);return(o,i)=>(p(),w("button",{type:"button",class:"btn-next",disabled:s.value,"aria-label":e.nextText||l(n)("tk.pagination.next"),"aria-disabled":s.value,onClick:i[0]||(i[0]=r=>o.$emit("click",r))},[e.nextText?(p(),w("span",B_,W(e.nextText),1)):e.nextIcon?(p(),D(l(de),{key:1,icon:e.nextIcon},null,8,["icon"])):A("v-if",!0)],8,F_))}});const l2=()=>qe(a2,{}),V_=["disabled"],O_=["disabled","aria-label"];var D_=z({name:"PaginationJumper",__name:"jumper",props:{size:{default:"default"}},setup(e){const t=ie("pagination"),{t:n}=ge(),{pageCount:s,disabled:o,currentPage:i,changeEvent:r}=l2(),a=j(i?.value||1),c=u=>{let f=u.target?.value||a.value;f<1&&(f=1),s?.value&&f>s.value&&(f=s.value);const d=Math.trunc(+f);r?.(d),a.value=d};return(u,f)=>(p(),w("span",{class:T(l(t).e("jump")),disabled:l(o)},[S("span",{class:T([l(t).e("goto")])},W(l(n)("tk.pagination.goto")),3),et(S("input",{type:"number","onUpdate:modelValue":f[0]||(f[0]=d=>a.value=d),disabled:l(o),onChange:c,"aria-label":l(n)("tk.pagination.page"),class:T([l(t).e("input"),l(t).em("input",e.size)])},null,42,O_),[[_o,a.value]]),S("span",{class:T([l(t).e("classifier")])},W(l(n)("tk.pagination.pageClassifier")),3)],10,V_))}});const R_=["disabled"];var H_=z({name:"PaginationTotal",__name:"total",props:{total:{}},setup(e){const t=ie("pagination"),{t:n}=ge(),{disabled:s}=l2();return(o,i)=>(p(),w("span",{class:T(l(t).e("total")),disabled:l(s)},W(l(n)("tk.pagination.total",{total:e.total})),11,R_))}});const z_=["aria-current","aria-label","tabindex"],j_=["tabindex","aria-label"],U_=["innerHTML"],W_=["innerHTML"],q_=["aria-current","aria-label","tabindex"],K_=["tabindex","aria-label"],Y_=["innerHTML"],G_=["innerHTML"],J_=["aria-current","aria-label","tabindex"];var X_=z({name:"PaginationPager",__name:"pager",props:{currentPage:{},pageCount:{},pagerCount:{},disabled:{type:Boolean}},emits:["change"],setup(e,{emit:t}){const n=e,s=t,o=ie("pager"),i=ie("icon"),{t:r}=ge(),a=j(!1),c=j(!1),u=j(!1),f=j(!1),d=j(!1),h=j(!1),m=F(()=>{const x=n.pagerCount||7,P=(x-1)/2,V=Number(n.currentPage),E=Number(n.pageCount);let L=!1,I=!1;E>x&&(V>x-P&&(L=!0),V["more","btn-quick-prev",i.b(),o.is("disabled",n.disabled)]),v=F(()=>["more","btn-quick-next",i.b(),o.is("disabled",n.disabled)]),k=F(()=>n.disabled?-1:0);zn(()=>{const x=(n.pagerCount-1)/2;a.value=!1,c.value=!1,n.pageCount>n.pagerCount&&(n.currentPage>n.pagerCount-x&&(a.value=!0),n.currentPage{n.disabled||(x?u.value=!0:f.value=!0)},C=(x=!1)=>{x?d.value=!0:h.value=!0},y=x=>{const P=x.target;if(P.tagName.toLowerCase()==="li"&&Array.from(P.classList).includes("number")){const V=Number(P.textContent);V!==n.currentPage&&s("change",V)}else P.tagName.toLowerCase()==="li"&&Array.from(P.classList).includes("more")&&_(x)},_=x=>{const P=x.target;if(P.tagName.toLowerCase()==="ul"||n.disabled)return;let V=Number(P.textContent);const E=n.pageCount,L=n.currentPage,I=n.pagerCount-2;P.className.includes("more")&&(P.className.includes("quick-prev")?V=L-I:P.className.includes("quick-next")&&(V=L+I)),Number.isNaN(+V)||(V<1&&(V=1),V>E&&(V=E)),V!==L&&s("change",V)};return(x,P)=>(p(),w("ul",{class:T(l(o).b()),onClick:_,onKeyup:va(y,["enter"])},[e.pageCount>0?(p(),w("li",{key:0,class:T([[l(o).is("active",e.currentPage===1),l(o).is("disabled",e.disabled)],"number"]),"aria-current":e.currentPage===1,"aria-label":l(r)("tk.pagination.currentPage",{pager:1}),tabindex:k.value}," 1 ",10,z_)):A("v-if",!0),a.value?(p(),w("li",{key:1,class:T(g.value),tabindex:k.value,"aria-label":l(r)("tk.pagination.prevPages",{pager:e.pagerCount-2}),onMouseenter:P[0]||(P[0]=V=>b(!0)),onMouseleave:P[1]||(P[1]=V=>u.value=!1),onFocus:P[2]||(P[2]=V=>C(!0)),onBlur:P[3]||(P[3]=V=>d.value=!1)},[(u.value||d.value)&&!e.disabled?(p(),w("span",{key:0,innerHTML:l(l9)},null,8,U_)):(p(),w("span",{key:1,innerHTML:l(Gf)},null,8,W_))],42,j_)):A("v-if",!0),(p(!0),w(Y,null,le(m.value,V=>(p(),w("li",{key:V,class:T([[l(o).is("active",e.currentPage===V),l(o).is("disabled",e.disabled)],"number"]),"aria-current":e.currentPage===V,"aria-label":l(r)("el.pagination.currentPage",{pager:V}),tabindex:k.value},W(V),11,q_))),128)),c.value?(p(),w("li",{key:2,class:T(v.value),tabindex:k.value,"aria-label":l(r)("tk.pagination.nextPages",{pager:e.pagerCount-2}),onMouseenter:P[4]||(P[4]=V=>b()),onMouseleave:P[5]||(P[5]=V=>f.value=!1),onFocus:P[6]||(P[6]=V=>C()),onBlur:P[7]||(P[7]=V=>h.value=!1)},[(f.value||h.value)&&!e.disabled?(p(),w("span",{key:0,innerHTML:l(a9)},null,8,Y_)):(p(),w("span",{key:1,innerHTML:l(Gf)},null,8,G_))],42,K_)):A("v-if",!0),e.pageCount>1?(p(),w("li",{key:3,class:T([[l(o).is("active",e.currentPage===e.pageCount),l(o).is("disabled",e.disabled)],"number"]),"aria-current":e.currentPage===e.pageCount,"aria-label":l(r)("tk.pagination.currentPage",{pager:e.pageCount}),tabindex:k.value},W(e.pageCount),11,J_)):A("v-if",!0)],34))}}),Q_=z({name:"Pagination",__name:"index",props:$n({total:{},pageCount:{},pagerCount:{default:7},layout:{default:["prev, pager, next, jumper, ->, total"].join(", ")},prevText:{},prevIcon:{default:()=>Xc},nextText:{},nextIcon:{default:()=>Qc},size:{default:"default"},background:{type:Boolean,default:!1},disabled:{type:Boolean,default:!1},hideOnSinglePage:{type:Boolean,default:!1}},{currentPage:{type:Number,default:1},currentPageModifiers:{},pageSize:{type:Number,default:10},pageSizeModifiers:{}}),emits:$n(["size-change","change","current-change","prev-click","next-click"],["update:currentPage","update:pageSize"]),setup(e,{emit:t}){const n=e,s=t,o=ie("pagination"),i=Si(),r=Jt(e,"currentPage"),a=Jt(e,"pageSize"),c=b=>typeof b!="number",u=F(()=>{let b=0;return c(n.pageCount)?c(n.total)||(b=Math.max(1,Math.ceil(n.total/a.value))):b=n.pageCount,b});te(u,b=>{r.value>b&&(r.value=b)}),te([r,a],b=>{s("change",...b)},{flush:"post"});const f=b=>{a.value=b,s("size-change",a.value);const C=u.value;r.value>C&&(r.value=C)},d=()=>{n.disabled||(m(r.value-1),s("prev-click",r.value))},h=()=>{n.disabled||(m(r.value+1),s("next-click",r.value))},m=b=>{r.value=b;const C=u.value;r.value<1?r.value=1:r.value>C&&(r.value=C),s("current-change",r.value)},g=(b,C)=>{b&&(b.props||(b.props={}),b.props.class=[b.props.class,C].join(" "))};In(a2,{pageCount:u,disabled:F(()=>n.disabled),currentPage:r,changeEvent:m,handleSizeChange:f});const v=F(()=>{if(!n.layout)return[];if(n.hideOnSinglePage&&u.value<=1)return[];const b=n.layout.split(",").map(P=>P.trim()),C=[],y=[],_=nn("div",{class:o.e("right-wrapper")},y);let x=!1;return b.forEach(P=>{if(P==="->"){x=!0;return}x?y.push(k.value[P]):C.push(k.value[P])}),g(C[0],o.is("first")),g(C[C.length-1],o.is("last")),y.length>0&&(g(y[0],o.is("first")),g(y[y.length-1],o.is("last")),C.push(_)),C}),k=F(()=>({prev:nn(M_,{disabled:n.disabled,currentPage:r.value,prevText:n.prevText,prevIcon:n.prevIcon,onClick:d}),jumper:nn(D_,{size:n.size}),pager:nn(X_,{currentPage:r.value,pageCount:u.value,pagerCount:n.pagerCount,onChange:m,disabled:n.disabled}),next:nn(N_,{disabled:n.disabled,currentPage:r.value,pageCount:u.value,nextText:n.nextText,nextIcon:n.nextIcon,onClick:h}),slot:i?.default?.()??null,total:nn(H_,{total:c(n.total)?0:n.total})}));return(b,C)=>(p(),w("div",{class:T([l(o).b(),l(o).is("background",e.background),l(o).m(e.size)])},[(p(!0),w(Y,null,le(v.value,y=>(p(),D(Be(y),{key:y}))),128))],2))}});const js="pageNum",Z_=["aria-label"],eS=["aria-label"],tS=["title","href","target","aria-label"],nS=["title","href","aria-label"];var Lu=z({name:"ArticleInfo",__name:"index",props:{post:{},scope:{},split:{type:Boolean,default:!1}},setup(e){const t=ie("article-info"),{t:n}=ge(),{getTeekConfigRef:s}=fe(),{page:o}=Ae(),i=s("articleAnalyze",{showIcon:!0,dateFormat:"yyyy-MM-dd",showAuthor:!0,showCreateDate:!0,showUpdateDate:!1,showCategory:!1,showTag:!1}),r=Pn(),a=kn(),c=F(()=>{const h=r.value.originPosts,m=e.post.date||h.find(v=>[v.url,v.frontmatter.permalink].includes(a.path))?.date,g=i.value.dateFormat;return ht(g)?g(m||""):hi(m||new Date,g)}),u=F(()=>{const h=o.value.lastUpdated;if(!h)return"";const m=i.value.dateFormat;return ht(m)?m(h):hi(h,m)}),f=F(()=>{const{showAuthor:h,showCreateDate:m,showUpdateDate:g,showCategory:v,showTag:k}=i.value;return[{title:n("tk.articleInfo.author"),icon:$h,data:e.post.author?.name,href:e.post.author?.link,target:e.post.author?.link?"_blank":"_self",show:d(h)},{title:n("tk.articleInfo.createTime"),icon:Z7,data:c.value,show:d(m)},{title:n("tk.articleInfo.updateTime"),icon:Lh,data:u.value,show:u.value&&(e.scope==="article"&&g||e.scope==="article-banner")},{title:n("tk.articleInfo.category"),icon:e9,dataList:e.post.frontmatter?.categories||[],href:"/categories?category={data}",class:"or",show:e.scope!=="article-banner"&&(e.scope==="post"||d(v))},{title:n("tk.articleInfo.tag"),icon:t9,dataList:e.post.frontmatter?.tags||[],href:"/tags?tag={data}",class:"or",show:e.scope!=="article-banner"&&(e.scope==="post"||d(k))}]}),d=h=>{const m=[h||[]].flat();return m.includes(!0)||m.includes(e.scope)};return(h,m)=>(p(),w("div",{class:T([l(t).b(),e.scope]),role:"group","aria-label":l(n)("tk.articleInfo.label")},[(p(!0),w(Y,null,le(f.value,g=>(p(),w(Y,{key:g.title},[g.show&&(g.data||g.dataList?.length)?(p(),w("span",{key:0,class:T([l(t).e("item"),{split:e.split}]),role:"group","aria-label":g.title},[l(i).showIcon?(p(),D(l(de),{key:0,icon:g.icon,class:T(l(t).e("icon")),"aria-hidden":"true"},null,8,["icon","class"])):A("v-if",!0),g.data?(p(),w("a",{key:1,title:g.title,href:g.href&&l(Ee)(g.href),target:g.target,class:T([g.class,"hover-color"]),"aria-label":g.data},W(g.data),11,tS)):(p(!0),w(Y,{key:2},le(g.dataList,(v,k)=>(p(),w("a",{key:k,title:g.title,href:g.href&&l(Ee)(g.href.replace("{data}",encodeURIComponent(v))),class:T([g.class,"hover-color"]),"aria-label":v},W(v),11,nS))),128))],10,eS)):A("v-if",!0)],64))),128)),M(h.$slots,"default")],10,Z_))}});const sS=["title","aria-label"],oS={class:"list flx"},iS=["href","aria-label"],rS=["aria-label"],aS=["innerHTML"],lS=["href","aria-label"],cS=["aria-label"],uS=["aria-label"],fS=["innerHTML"],dS=["href","aria-label"],hS=["href","aria-label"];var Bd=z({name:"HomePostItem",__name:"HomePostItem",props:{post:{},coverImgMode:{}},setup(e){const t=ie("post-item"),{t:n}=ge(),{getTeekConfigRef:s}=fe(),o=s("post",{excerptPosition:"bottom",showMore:!0,moreLabel:n("tk.homePost.moreLabel"),showCapture:!1,splitSeparator:!1,listStyleTitleTagPosition:"right",defaultCoverImg:[]}),i=s("articleAnalyze",{showInfo:!0}),r=e.post.url&&Ee(e.post.url),a=F(()=>e.post.frontmatter.description||e.post.excerpt||o.value.showCapture&&e.post.capture),c=F(()=>[e.post.frontmatter.coverImg||o.value.defaultCoverImg||[]].flat()),u=F(()=>{const d=c.value[Math.floor(Math.random()*c.value.length)];return{default:{is:"div",props:{style:`background-image: url(${Ee(d)});`}},full:{is:"img",props:{src:Ee(d)}}}}),f=F(()=>{const d=[i.value.showInfo].flat();return d.includes(!0)||d.includes("post")});return(d,h)=>(p(),w("div",{class:T(l(t).b())},[e.post.frontmatter.sticky?(p(),w("i",{key:0,class:"pin",title:l(n)("tk.homePost.pin",{sticky:e.post.frontmatter.sticky}),"aria-label":l(n)("tk.homePost.pinLabel")},null,8,sS)):A("v-if",!0),S("div",oS,[S("div",{class:T(l(t).e("left"))},[A(" 标题 "),S("a",{class:T([l(t).e("left__title"),"hover-color","sle"]),href:l(r),"aria-label":e.post.title},[H(l(Mi),{post:e.post,"title-tag-props":{position:l(o).listStyleTitleTagPosition}},null,8,["post","title-tag-props"])],10,iS),A(" 摘要 top "),a.value&&l(o).excerptPosition==="top"?(p(),w("div",{key:0,class:T(`${l(t).e("left__excerpt")} top`),"aria-label":l(n)("tk.homePost.excerptLabel")},[S("div",{class:"excerpt",innerHTML:a.value},null,8,aS),l(o).showMore?(p(),w("a",{key:0,class:"more",href:l(r),"aria-label":l(o).moreLabel},W(l(o).moreLabel),9,lS)):A("v-if",!0)],10,rS)):A("v-if",!0),A(" 文章信息 "),S("div",{class:T(l(t).e("left__footer")),"aria-label":l(n)("tk.homePost.infoLabel")},[f.value?(p(),D(l(Lu),{key:0,post:e.post,scope:"post",split:l(o).splitSeparator},null,8,["post","split"])):A("v-if",!0)],10,cS),A(" 摘要 bottom "),a.value&&l(o).excerptPosition==="bottom"?(p(),w("div",{key:1,class:T(`${l(t).e("left__excerpt")} bottom`),"aria-label":l(n)("tk.homePost.excerptLabel")},[S("div",{class:"excerpt",innerHTML:a.value},null,8,fS),l(o).showMore?(p(),w("a",{key:0,class:"more",href:l(r),"aria-label":l(o).moreLabel},W(l(o).moreLabel),9,dS)):A("v-if",!0)],10,uS)):A("v-if",!0)],2),A(" 右侧封面图 "),S("div",{class:T(`${l(t).e("right")} flx-align-center`)},[c.value.length?(p(),w("a",{key:0,href:l(r),class:T(`${e.coverImgMode} cover`),"aria-label":l(n)("tk.homePost.coverImgLabel")},[(p(),D(Be(u.value[e.coverImgMode].is),nt(u.value[e.coverImgMode].props,{"aria-hidden":"true",class:"cover-img"}),null,16))],10,hS)):A("v-if",!0)],2)])],2))}});const pS=["href","alt"],mS=["src"],gS=["href","aria-label"],vS=["innerHTML","aria-label"];var Nd=z({name:"HomePostItemCard",__name:"HomePostItemCard",props:{post:{}},setup(e){const t=ie("post-item-card"),{t:n}=ge(),{getTeekConfigRef:s}=fe(),o=s("post",{showCapture:!1,splitSeparator:!1,cardStyleTitleTagPosition:"left",defaultCoverImg:[]}),i=s("articleAnalyze",{showInfo:!0}),r=e.post.url&&Ee(e.post.url),a=F(()=>[e.post.frontmatter.coverImg||o.value.defaultCoverImg||[]].flat()),c=F(()=>e.post.frontmatter.description||e.post.excerpt||o.value.showCapture&&e.post.capture),u=F(()=>{const f=[i.value.showInfo].flat();return f.includes(!0)||f.includes("post")});return(f,d)=>(p(),w("div",{class:T(l(t).b())},[e.post.frontmatter.sticky?(p(),D(l(de),{key:0,icon:l(g9),class:"top",size:40,title:l(n)("tk.homePost.pin",{sticky:e.post.frontmatter.sticky}),"aria-label":l(n)("tk.homePost.pinLabel")},null,8,["icon","title","aria-label"])):A("v-if",!0),a.value.length?(p(),w("div",{key:1,class:T(l(t).e("cover-img"))},[S("a",{href:l(r),alt:e.post.title},[S("img",{src:l(Ee)(a.value[0]),class:"cover-img"},null,8,mS)],8,pS)],2)):A("v-if",!0),S("div",{class:T([l(t).e("info")])},[S("a",{class:"title hover-color, sle",href:l(r),"aria-label":e.post.title},[H(l(Mi),{post:e.post,"title-tag-props":{position:l(o).cardStyleTitleTagPosition}},null,8,["post","title-tag-props"])],8,gS),c.value?(p(),w("span",{key:0,class:"excerpt mle",innerHTML:c.value,"aria-label":l(n)("tk.homePost.excerptLabel")},null,8,vS)):A("v-if",!0),u.value?(p(),D(l(Lu),{key:1,post:e.post,scope:"post",split:l(o).splitSeparator,"aria-label":l(n)("tk.homePost.infoLabel")},null,8,["post","split","aria-label"])):A("v-if",!0)],2)],2))}});const yS=["aria-label"],bS=["aria-label"],Vd="small",Od="prev, pager, next";var kS=z({name:"HomePostList",__name:"index",props:{modelValue:{default:!1},modelModifiers:{}},emits:["update:modelValue"],setup(e,{expose:t}){const n=ie("post-list"),{t:s}=ge(),{getTeekConfigRef:o}=fe(),i=Pn(),{frontmatter:r}=Ae(),a=o("post",{postStyle:"list",coverImgMode:"default",emptyLabel:s("tk.homePost.emptyLabel"),transition:!0,transitionName:n.join("slide-fade")}),c=o("page",{}),u=j(1),f=j(0),d=j(a.value.coverImgMode),h=Jt(e,"modelValue"),m=F(()=>a.value.postStyle==="list"?10:15),g=F(()=>c.value.pageSize||m.value),v=kn(),k=j([]),b=j(0);zn(()=>{d.value=a.value.coverImgMode});const C=()=>{if(!me)return;const{searchParams:I}=new URL(window.location.href),N=Number(I.get(js))||1;N!==u.value&&(u.value=N),h.value=N>1;const $=i.value,U=r.value;let q=$.sortPostsByDateAndSticky;if(U.categoriesPage){const G=I.get("category");q=G?$.groupPosts.categories[G]:q.filter(ae=>ae.frontmatter.categories)}else if(U.tagsPage){const G=I.get("tag");q=G?$.groupPosts.tags[G]:q.filter(ae=>ae.frontmatter.tags)}f.value!==q?.length&&(f.value=q?.length||0);const J=q.filter(G=>G.frontmatter.inHomePost!==!1);b.value=J.length,k.value=J.slice((u.value-1)*g.value,u.value*g.value)};te(()=>v.path,C,{immediate:!0});const y=()=>{const{searchParams:I}=new URL(window.location.href);I.delete(js),I.append(js,String(u.value)),window.history.pushState({},"",`${window.location.pathname}?${I.toString()}`),C(),ze(()=>{const N=getComputedStyle(document.documentElement),$=V7(N.getPropertyValue("--vp-c-text-1"));document.querySelector("html")?.scrollTo({top:window.innerHeight-$,behavior:"smooth"})})},_=Dn({...c.value}),{size:x="default",layout:P="prev, pager, next, jumper, ->, total"}=c.value;eu(I=>{I<=768?_.size!==Vd&&(_.size=Vd):_.size!==x&&(_.size=x),I<=960?_.layout!==Od&&(_.layout=Od):_.layout!==P&&(_.layout=P),I<=960?d.value!=="default"&&(d.value="default"):d.value!==a.value.coverImgMode&&(d.value=a.value.coverImgMode)});const V=_a(I=>I.post),E=j(null),{start:L}=Ca(E,!1);return be(()=>{V.value&&L()}),t({updateData:C}),(I,N)=>(p(),w("div",{class:T([l(n).b(),l(n).is("card",l(a).postStyle==="card")])},[k.value?(p(),w(Y,{key:0},[M(I.$slots,"teek-home-post-list",Ge(Ze({currentPosts:k.value,transitionName:l(a).transitionName})),()=>[H(Qs,{tag:"ul",name:l(a).transition?l(a).transitionName:"","aria-label":l(s)("tk.homePost.label")},{default:O(()=>[(p(!0),w(Y,null,le(k.value,$=>(p(),w("li",{key:$.url,class:T({"full-img":d.value==="full"})},[l(V)?(p(),w("div",{key:0,ref_for:!0,ref_key:"postItemListInstance",ref:E,style:{width:"100%",height:"100%"}},[l(a).postStyle==="card"?(p(),D(Nd,{key:0,post:$},null,8,["post"])):(p(),D(Bd,{key:1,post:$,coverImgMode:d.value},null,8,["post","coverImgMode"]))],512)):(p(),w(Y,{key:1},[l(a).postStyle==="card"?(p(),D(Nd,{key:0,post:$},null,8,["post"])):(p(),D(Bd,{key:1,post:$,coverImgMode:d.value},null,8,["post","coverImgMode"]))],64))],2))),128))]),_:1},8,["name","aria-label"])]),S("div",{class:T(`${l(n).e("pagination")} flx-justify-center`),"aria-label":l(s)("tk.homePost.pageLabel")},[b.value>=g.value?(p(),D(l(Q_),nt({key:0,"page-size":g.value,"onUpdate:pageSize":N[0]||(N[0]=$=>g.value=$),"current-page":u.value,"onUpdate:currentPage":N[1]||(N[1]=$=>u.value=$),total:f.value,background:"",onCurrentChange:y},{..._}),null,16,["page-size","current-page","total"])):A("v-if",!0)],10,yS)],64)):(p(),w("div",{key:1,class:T([l(n).e("empty"),"flx-column-center"]),"aria-label":l(a).emptyLabel},[H(l(de),{icon:l(U7),size:160,color:"var(--vp-c-text-3)","aria-hidden":"true"},null,8,["icon"]),S("span",{class:T(l(n).e("empty__title"))},W(l(a).emptyLabel),3)],10,bS))],2))}});const wS=["aria-label"];var CS=z({name:"HomeBannerBgPure",__name:"HomeBannerBgPure",setup(e){const t=ie("banner-bg-pure"),{t:n}=ge(),{getTeekConfig:s}=fe(),o=()=>{const{pureBgColor:i="#28282d"}=s("banner",{});return{backgroundColor:i}};return(i,r)=>(p(),w("div",{class:T(l(t).b()),style:Fe(o()),"aria-label":l(n)("tk.homeBanner.bgPureLabel")},[M(i.$slots,"default")],14,wS))}});const _S=["aria-label"],SS=["aria-label"];var Dd=z({name:"HomeBannerBgImage",__name:"HomeBannerBgImage",setup(e){const t=ie("banner-bg-image"),{t:n}=ge(),{getTeekConfigRef:s}=fe(),o=s("banner",{bgStyle:void 0,imgSrc:void 0,imgInterval:15e3,imgShuffle:!1,mask:!0,maskBg:"rgba(0, 0, 0, 0.4)"}),i=F(()=>o.value.bgStyle==="partImg"),r=F(()=>o.value.bgStyle==="fullImg"),a=F(()=>{const h=o.value.imgSrc;return[ht(h)?h():h||[]].flat().map(m=>m&&Ee(m))}),{data:c,start:u,index:f}=tu(a,{timeout:o.value.imgInterval,shuffle:o.value.imgShuffle,onAfterUpdate:()=>{const h=(f.value+1)%a.value.length,m=a.value[h];if(m){const g=new Image;g.src=m}}});be(()=>{u()});const d=()=>{const{imgSrc:h,maskBg:m,imgInterval:g}=o.value,v=t.cssVarName("banner-img-bg"),k=t.cssVarName("banner-mask-bg-color"),b=t.cssVarName("banner-img-switch-interval-s");return h?.length?{[v]:`url(${c.value}) center center / cover no-repeat`,[k]:Je(m)?m:`rgba(0, 0, 0, ${m})`,[b]:g/1e3+"s"}:{[v]:t.cssVar("bg-img-default")}};return(h,m)=>(p(),w(Y,null,[S("div",{class:T([l(t).b(),{part:i.value,full:r.value}]),style:Fe(d()),"aria-label":l(n)("tk.homeBanner.bgImgLabel")},[l(o).mask&&l(o).imgSrc?(p(),w("div",{key:0,class:"mask","aria-label":l(n)("tk.homeBanner.maskLabel")},null,8,SS)):A("v-if",!0),i.value?M(h.$slots,"default",{key:1}):A("v-if",!0)],14,_S),r.value?M(h.$slots,"default",{key:0}):A("v-if",!0)],64))}});const TS=["aria-label"],ES=["aria-label"],xS=["aria-label"],AS={key:0},$S=["aria-label"],LS=["aria-label"];var IS=z({name:"HomeBannerContent",__name:"HomeBannerContent",setup(e){const t=ie("banner-content"),{t:n}=ge(),{getTeekConfigRef:s}=fe(),{site:o,frontmatter:i}=Ae(),r=s("banner",{name:i.value.tk?.name||o.value.title||"",descStyle:"default",description:[],switchTime:4e3,switchShuffle:!1,typesInTime:200,typesOutTime:100,typesNextTime:800,typesShuffle:!1}),a=F(()=>[...new Set([i.value.tk?.description||r.value.description||[]].flat()?.filter(k=>!!k))]),c=F(()=>r.value.descStyle==="default"),u=F(()=>r.value.descStyle==="types"),f=F(()=>r.value.descStyle==="switch"),{text:d,isFinished:h,start:m}=R9(a,{inputTime:r.value.typesInTime,outputTime:r.value.typesOutTime,nextTime:r.value.typesNextTime,shuffle:r.value.typesShuffle}),{data:g,start:v}=tu(a,{timeout:r.value.switchTime,shuffle:r.value.switchShuffle,onUpdate:(k,b)=>{k.value="",setTimeout(()=>{k.value=b},20)}});return be(()=>{u.value&&m(),f.value&&v()}),(k,b)=>(p(),w("div",{class:T(l(t).b()),"aria-label":l(n)("tk.homeBanner.contentLabel")},[A(" 首页 banner 图文字插槽 "),k.$slots["teek-home-banner-name"]?M(k.$slots,"teek-home-banner-name",Ge(nt({key:0},{name:l(r).name}))):(p(),w(Y,{key:1},[A(" 如果没有传入插槽,则渲染默认的 h1 标签及内容 "),S("h1",{class:T(l(t).e("title")),"aria-label":l(n)("tk.homeBanner.titleLabel")},W(l(r).name),11,ES)],2112)),S("p",{class:T(l(t).e("desc")),"aria-label":l(n)("tk.homeBanner.descLabel")},[c.value?(p(),w("span",AS,W(a.value[0]),1)):f.value?(p(),D(vt,{key:1,name:l(t).join("fade"),mode:"out-in"},{default:O(()=>[(p(),w("span",{key:l(g)||a.value[0],onClick:b[0]||(b[0]=(...C)=>l(v)&&l(v)(...C)),class:"switch","aria-label":l(n)("tk.homeBanner.descSwitchLabel")},W(l(g)||a.value[0]),9,$S))]),_:1},8,["name"])):u.value&&a.value.length?(p(),w(Y,{key:2},[S("span",{"aria-label":l(n)("tk.homeBanner.descTypedLabel")},W(l(d)),9,LS),S("span",{class:T(["typed",{"is-animation":l(h)}])},"|",2)],64)):A("v-if",!0)],10,xS)],10,TS))}});const PS=["aria-labelledby"],MS=["src","alt","aria-label"],FS=["id"],BS={class:"feature-details"};var NS=z({name:"HomeBannerFeature",__name:"HomeBannerFeature",setup(e){const t=ie("banner-feature"),{t:n}=ge(),{getTeekConfigRef:s}=fe(),{frontmatter:o}=Ae(),i=s("banner",{features:o.value.tk?.features||[],featureCarousel:4e3}),r=s("features",[]),a=j(0),c=j(!1);let u;const f=F(()=>i.value.features||r.value||[]),d=()=>{u&&(clearTimeout(u),u=null)};return eu(h=>{const{featureCarousel:m}=i.value;h<=719?(c.value=!0,d(),u=setInterval(()=>{a.value=(a.value+1)%f.value.length},m)):(c.value=!1,d())}),as(()=>{d()}),(h,m)=>f.value.length?(p(),D(Qs,{key:0,name:l(t).join("slide-next"),tag:"div",class:T([l(t).b(),l(t).join("wallpaper-outside"),"flx-wrap-between"]),"aria-label":l(n)("tk.homeBanner.featureLabel")},{default:O(()=>[(p(!0),w(Y,null,le(l(i).features,(g,v)=>et((p(),w("div",{class:T(l(t).e("feature__item")),key:v,role:"group","aria-labelledby":`feature-title-${v}`},[(p(),D(Be(g.link?"a":"div"),{href:l(Ee)(g.link??""),class:"flx-column-center hover-color","aria-label":g.title},{default:O(()=>[g.image?(p(),w("img",{key:0,class:"feature-img",src:l(Ee)(g.image),alt:g.title,"aria-label":g.title},null,8,MS)):A("v-if",!0),S("p",{id:`feature-title-${v}`,class:"feature-title"},W(g.title),9,FS),S("p",BS,W(g.details),1)]),_:2},1032,["href","aria-label"]))],10,PS)),[[at,!c.value||a.value===v]])),128))]),_:1},8,["name","class","aria-label"])):A("v-if",!0)}}),c2=z({name:"HomeBannerWaves",__name:"HomeBannerWaves",setup(e){const t=ie("banner-waves");return(n,s)=>(p(),w("svg",{class:T(l(t).b()),xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 24 150 28",preserveAspectRatio:"none","shape-rendering":"auto"},[A("形状容器"),s[0]||(s[0]=S("defs",null,[S("path",{id:"gentle-wave",d:"M-160 44c30 0 58-18 88-18s 58 18 88 18 58-18 88-18 58 18 88 18 v44h-352z"})],-1)),A("组合波浪"),s[1]||(s[1]=E0('',1))],2))}});const VS=["aria-label"],Rd="full-img-nav-bar";var OS=z({name:"HomeBanner",__name:"index",props:{disabled:{type:Boolean,default:!1}},setup(e){const t=ie("banner"),{t:n}=ge(),{getTeekConfigRef:s}=fe(),{frontmatter:o}=Ae(),i=s("banner",{bgStyle:"pure",imgWaves:!0,textColor:"#ffffff",titleFontSize:"3.2rem",descFontSize:"1.4rem",features:o.value.tk?.features||[]}),r=s("bodyBgImg",{imgSrc:"",bannerStyle:"full"}),a=F(()=>{const{bgStyle:v}=i.value,{imgSrc:k,bannerStyle:b}=r.value,C=v==="pure",y=v==="partImg",_=v==="fullImg",x=!!k;return{isBannerPureBgStyle:C,isBannerPartImgBgStyle:y,isBannerFullImgBgStyle:_,isBodyImgBgStyle:x,isBodyPartImgBgStyle:x&&b==="part",isBodyFullImgBgStyle:x&&b==="full"}}),c=()=>{const v=t.cssVarName("banner-title-text"),k=t.cssVarName("banner-desc-text"),b=t.cssVarName("banner-text-color"),{titleFontSize:C,descFontSize:y,textColor:_}=i.value;return{[v]:C,[k]:y,[b]:_}},u=j(null),f=(v=!0)=>{const k=document.querySelector(".VPNavBar");v?k?.classList.add(Rd):k?.classList.remove(Rd)},d=async()=>{if(!u.value||e.disabled)return;const v=a.value;if(!v.isBannerFullImgBgStyle&&!v.isBodyFullImgBgStyle)return;await ze();const k=v.isBodyImgBgStyle?0:100,b=document.documentElement.scrollTop+ke.disabled,()=>f(!e.disabled)),be(()=>{(!e.disabled&&a.value.isBannerFullImgBgStyle||a.value.isBodyFullImgBgStyle)&&(d(),Ve(window,"scroll",d))}),cn(()=>{f(!1)});const h=F(()=>{const{isBannerPureBgStyle:v,isBannerPartImgBgStyle:k,isBannerFullImgBgStyle:b,isBodyPartImgBgStyle:C,isBodyFullImgBgStyle:y}=a.value;return C?t.is("part-img"):y?t.is("full-img"):v?t.is("pure"):k?t.is("part-img"):b?t.is("full-img"):""}),m={bodyPart:{el:"div",props:{class:"body-pure"}},bodyFull:{el:"div",props:{class:"body-full"}},bannerPure:{el:CS},bannerPartImg:{el:Dd},bannerFullImg:{el:Dd}},g=F(()=>{const{isBodyImgBgStyle:v}=a.value,{bgStyle:k}=i.value,{bannerStyle:b}=r.value,C=v?`body${Hf(b)}`:`banner${Hf(k)}`;return m[C]});return(v,k)=>(p(),w(Y,null,[M(v.$slots,"teek-home-banner-before"),S("div",{ref_key:"bannerRef",ref:u,class:T([l(t).b(),h.value]),style:Fe(c()),"aria-label":l(n)("tk.homeBanner.label")},[(p(),D(Be(g.value.el),Ge(Ze(g.value.props)),{default:O(()=>[S("div",{class:T([l(t).e("content"),{"no-feature":!l(i).features.length}])},[M(v.$slots,"teek-home-banner-content-before"),H(IS,null,Wt({_:2},[le(v.$slots,(b,C)=>({name:C,fn:O(y=>[M(v.$slots,C,Ge(Ze(y)))])}))]),1024),M(v.$slots,"teek-home-banner-content-after"),M(v.$slots,"teek-home-banner-feature-before"),H(NS),M(v.$slots,"teek-home-banner-feature-after")],2)]),_:3},16)),l(i).imgWaves&&a.value.isBannerFullImgBgStyle&&!a.value.isBodyImgBgStyle?(p(),D(c2,{key:0,"aria-label":l(n)("tk.homeBanner.wavesLabel")},null,8,["aria-label"])):A("v-if",!0)],14,VS),M(v.$slots,"teek-home-banner-after")],64))}});const DS=["aria-label"],RS=["href","target","aria-label"],HS=["innerHTML"],zS=["aria-label"],jS=["innerHTML"],US=["innerHTML"],WS={key:0},qS=["aria-label","aria-disabled"],KS=["aria-label","aria-disabled"];var No=z({name:"PageCard",__name:"index",props:$n({title:{default:""},titleLink:{},titleClick:{type:Function},page:{type:Boolean,default:!1},pageSize:{default:4},total:{default:0},autoPage:{type:Boolean,default:!1},pageSpeed:{default:4e3}},{modelValue:{default:1},modelModifiers:{}}),emits:$n(["pagination"],["update:modelValue"]),setup(e,{emit:t}){const n=ie("page-card"),s=n.join("pointer"),{t:o}=ge(),i=t,r=Jt(e,"modelValue"),a=Math.ceil(e.total/e.pageSize),c=e.total!==0&&a!==1,u=j(n.join("scroll")),f=(v,k)=>{i("pagination",v,k),u.value=n.join(`slide-${k}`),e.page&&e.autoPage&&h();const C=(r.value%a+v)%a;C<1?r.value=a+C:C>a?r.value=1:r.value=C};let d;const h=()=>{m(),e.pageSpeed>0&&(d=setTimeout(()=>{f(1,"next")},e.pageSpeed))},m=()=>{d&&(clearTimeout(d),d=null)};be(()=>{e.page&&e.autoPage&&h()}),cn(()=>{e.page&&e.autoPage&&m()});const g=v=>v.replace(/<[^>]*>/g,"").trim();return(v,k)=>(p(),w("div",{class:T(`${l(n).b()} card`),"aria-label":l(o)("tk.pageCard.label")},[e.title?(p(),w("div",{key:0,class:T(`${l(n).e("header")} flx-justify-between`)},[M(v.$slots,"title",{},()=>[e.titleLink?(p(),w("a",{key:0,href:l(Ee)(e.titleLink),target:l(Yc)(e.titleLink)?"_blank":"_self","aria-label":g(e.title)},[S("span",{class:"title flx-align-center",innerHTML:e.title},null,8,HS)],8,RS)):e.titleClick?(p(),w("a",{key:1,onClick:k[0]||(k[0]=()=>e.titleClick()),class:T(l(s)),"aria-label":g(e.title)},[S("span",{class:"title flx-align-center",innerHTML:e.title},null,8,jS)],10,zS)):(p(),w("span",{key:2,class:"title flx-align-center",innerHTML:e.title},null,8,US))]),M(v.$slots,"page",Ge(Ze({pagination:f})),()=>[e.page?(p(),w("div",WS,[M(v.$slots,"page-left",Ge(Ze({pagination:f})),()=>[S("span",{class:T(["page-button",l(c)?l(s):"disabled"]),onClick:k[1]||(k[1]=b=>f(-1,"prev")),role:"button","aria-label":l(o)("tk.pageCard.prev"),"aria-disabled":!l(c)},[H(l(de),{icon:l(Xc),size:14,"aria-hidden":"true"},null,8,["icon"])],10,qS)]),M(v.$slots,"page-right",Ge(Ze({pagination:f})),()=>[S("span",{class:T(["page-button",l(c)?l(s):"disabled"]),onClick:k[2]||(k[2]=b=>f(1,"next")),role:"button","aria-label":l(o)("tk.pageCard.next"),"aria-disabled":!l(c)},[H(l(de),{icon:l(Qc),size:14,"aria-hidden":"true"},null,8,["icon"])],10,KS)])])):A("v-if",!0)])],2)):A("v-if",!0),M(v.$slots,"default",Ge(Ze({transitionName:u.value,startAutoPage:h,closeAutoPage:m})))],10,DS))}});const YS=["src","alt","srcSet"],GS={key:2};var Za=z({name:"Avatar",__name:"index",props:{size:{},shape:{default:"circle"},icon:{},iconSize:{},src:{},alt:{},srcSet:{},fit:{default:"cover"},bgColor:{},textColor:{},textSize:{},text:{}},emits:["error"],setup(e,{emit:t}){const n=t,s=ie("avatar"),o=j(!1),i=F(()=>{const f=[s.b()];return Je(e.size)&&f.push(s.m(e.size)),e.icon&&f.push(s.m("icon")),e.shape&&f.push(s.m(e.shape)),f}),r=F(()=>({[s.cssVarName("avatar-size")]:sn(e.size),[s.cssVarName("avatar-bg-color")]:e.bgColor,[s.cssVarName("avatar-text-color")]:e.textColor,[s.cssVarName("avatar-text-size")]:sn(e.textSize),[s.cssVarName("avatar-icon-size")]:sn(e.iconSize)})),a=F(()=>({objectFit:e.fit}));te(()=>e.src,()=>o.value=!1);const c=f=>{o.value=!0,n("error",f)},u=f=>{if(/^[\u4e00-\u9fa5]+$/.test(f))return f.charAt(0);const h=f.split(/\s+/).filter(m=>m.length>0);return h.length>=2?h.slice(0,2).map(m=>m.charAt(0).toUpperCase()).join(""):h.length===1?f.slice(0,2).toUpperCase():""};return(f,d)=>(p(),w("span",{class:T(i.value),style:Fe(r.value)},[(e.src||e.srcSet)&&!o.value?(p(),w("img",{key:0,src:e.src,alt:e.alt,srcSet:e.srcSet,style:Fe(a.value),onError:c},null,44,YS)):e.icon?(p(),D(l(de),{key:1,icon:e.icon},null,8,["icon"])):e.text?(p(),w("span",GS,W(u(e.text)),1)):M(f.$slots,"default",{key:3})],6))}});const JS=["aria-label"],XS=["href","title","aria-label"],QS=["aria-label"],ZS={class:"name"},eT={class:"slogan"};var tT=z({name:"HomeMyCard",__name:"index",setup(e){const t=ie("my"),{t:n}=ge(),{getTeekConfigRef:s}=fe(),o=s("blogger",{shape:"square",circleBgMask:!0}),i=s("social",[]),r=F(()=>o.value.shape.replace(/-.*$/,"")),a=F(()=>r.value==="circle"&&!!o.value.circleBgImg),c=F(()=>({backgroundImage:`url(${Ee(o.value.circleBgImg)})`})),u=F(()=>({color:o.value.color})),f=F(()=>{const d=o.value.status?.icon;return d?Yc(d)||d.startsWith("/"):!1});return(d,h)=>l(o).name?(p(),D(l(No),{key:0,class:T([l(t).b(),l(t).is("circle-bg",a.value)]),style:Fe(u.value),"aria-label":l(n)("tk.myCard.label")},{default:O(()=>[a.value?(p(),w("div",{key:0,class:T([l(t).em("avatar__circle","bg"),l(t).is("mask",l(o).circleBgMask)]),style:Fe(c.value)},null,6)):A("v-if",!0),S("div",{class:T(`${l(t).e("avatar")} ${l(o).shape} flx-center`)},[S("div",null,[l(o).avatar?(p(),D(l(Za),{key:0,src:l(Ee)(l(o).avatar),size:l(o).shape==="square"?"100%":l(o).circleSize??100,shape:r.value,"bg-color":"transparent",alt:l(n)("tk.myCard.avatarAlt"),title:l(n)("tk.myCard.avatarTitle"),"aria-hidden":"true"},null,8,["src","size","shape","alt","title"])):(p(),D(l(Za),{key:1,size:l(o).circleSize??100,shape:r.value,text:l(o).name,"text-size":50,"bg-color":l(t).cssVar("theme-color"),"aria-hidden":"true"},null,8,["size","shape","text","bg-color"])),l(o).status?.icon&&r.value?.startsWith("circle")?(p(),D(l(Za),{key:2,src:f.value?l(o).status.icon:"",text:l(o).status.icon,size:l(o).status.size??26,"icon-size":l(o).status.size??26,"text-size":l(o).status.size??26,title:l(o).status.title,circle:"","bg-color":"transparent",class:"avatar-sticker","aria-hidden":"true"},null,8,["src","text","size","icon-size","text-size","title"])):A("v-if",!0)])],2),l(i).length?(p(),w("div",{key:1,class:T(`${l(t).e("icons")} flx-justify-around`),"aria-label":l(n)("tk.myCard.socialLabel")},[(p(!0),w(Y,null,le(l(i),(m,g)=>(p(),w("a",{key:g,href:m.link&&l(Ee)(m.link),title:m.name,target:"_blank","aria-label":m.name},[m.icon?(p(),D(l(de),{key:0,iconType:m.iconType,icon:m.icon,size:"20px",hover:"",imgAlt:m.imgAlt,"aria-hidden":"true"},null,8,["iconType","icon","imgAlt"])):A("v-if",!0)],8,XS))),128))],10,JS)):A("v-if",!0),S("div",{class:T(l(t).e("blogger")),"aria-label":l(n)("tk.myCard.bloggerLabel")},[S("h3",ZS,W(l(o).name),1),S("span",eT,W(l(o).slogan),1)],10,QS)]),_:1},8,["class","style","aria-label"])):A("v-if",!0)}});const nT=["aria-label"],sT=["href"],oT={class:"date"},iT=["aria-label"];var rT=z({name:"HomeTopArticleCard",__name:"index",setup(e){const t=ie("top-article"),{t:n}=ge(),{getTeekConfigRef:s}=fe(),o=Pn(),i=s("topArticle",{limit:4,title:n("tk.topArticleCard.title",{icon:Wf}),emptyLabel:n("tk.topArticleCard.emptyLabel"),autoPage:!1,pageSpeed:4e3,dateFormat:"yyyy-MM-dd hh:mm:ss"}),r=F(()=>o.value.sortPostsByDateAndSticky.filter(b=>b.frontmatter.top)?.map((b,C)=>({...b,num:C+1}))),a=j(1),c=F(()=>{const{limit:k}=i.value,b=a.value;return r.value.slice((b-1)*k,b*k)}),u=k=>{const b=i.value.dateFormat;return ht(b)?b(k||""):hi(k||new Date,b)},f=F(()=>{const{title:k}=i.value;return ht(k)?k(Wf):k}),d=Gh(),h=j([]),m=(k,b)=>({[t.cssVarName("num-bg-color")]:d.value[k%d.value.length].text,top:`calc(${b} * (calc(${t.cssVar("home-top-article-gap")} + ${h.value?.[b]?.getBoundingClientRect().height||0}px)))`}),g=Ls(),v=()=>{i.value.titleClick?.(g)};return(k,b)=>(p(),D(l(No),{page:"",modelValue:a.value,"onUpdate:modelValue":b[0]||(b[0]=C=>a.value=C),pageSize:l(i).limit,total:r.value.length,title:f.value,titleClick:l(i).titleClick?v:void 0,autoPage:l(i).autoPage,pageSpeed:l(i).pageSpeed,class:T(l(t).b()),"aria-label":l(n)("tk.topArticleCard.label")},{default:O(({transitionName:C})=>[r.value.length?(p(),D(Qs,{key:0,name:C,tag:"ul",mode:"out-in",class:T(`${l(t).e("list")} flx-column`),"aria-label":l(n)("tk.topArticleCard.listLabel")},{default:O(()=>[(p(!0),w(Y,null,le(c.value,(y,_)=>(p(),w("li",{ref_for:!0,ref_key:"itemRefs",ref:h,key:y.num,class:T(l(t).e("list__item")),style:Fe(m(y.num-1,_)),"aria-label":y.title},[S("span",{class:T(["num",{sticky:y.frontmatter.sticky}])},W(y.num),3),S("div",{class:T(l(t).e("list__item__info"))},[S("a",{href:y.url&&l(Ee)(y.url),class:"hover-color flx-align-center"},[H(l(Mi),{post:y,"title-tag-props":{position:"right",size:"mini"}},null,8,["post"])],8,sT),S("div",oT,W(u(y.date)),1)],2)],14,nT))),128))]),_:1},8,["name","class","aria-label"])):(p(),w("div",{key:1,class:T(l(t).m("empty")),"aria-label":l(i).emptyLabel},W(l(i).emptyLabel),11,iT))]),_:1},8,["modelValue","pageSize","total","title","titleClick","autoPage","pageSpeed","class","aria-label"]))}});const Iu=Symbol("postDataUpdate"),aT=["onClick","aria-label"],lT={class:"sle"},cT=["href","aria-label"],uT=["aria-label"],er="category";var fT=z({name:"HomeCategoryCard",__name:"index",props:{categoriesPage:{type:Boolean,default:!1}},setup(e){const t=ie("category"),{t:n}=ge(),{getTeekConfigRef:s}=fe(),{categoryPath:o}=$i(),i=s("category",{path:"/categories",pageTitle:n("tk.categoryCard.pageTitle",{icon:Yi}),homeTitle:n("tk.categoryCard.homeTitle",{icon:Yi}),emptyLabel:n("tk.categoryCard.emptyLabel"),moreLabel:n("tk.categoryCard.moreLabel"),limit:5,autoPage:!1,pageSpeed:4e3}),r=Pn(),a=j(1),c=F(()=>r.value.groupCards.categories),u=F(()=>{const{limit:k}=i.value,b=c.value,C=a.value;return e.categoriesPage?b:b.slice((C-1)*k,C*k)}),f=F(()=>{const{pageTitle:k,homeTitle:b}=i.value,C=ht(k)?k(Yi):k,y=ht(b)?b(Yi):b;return{pt:C,ht:y}}),d=qe(Iu,()=>{}),h=Ls(),m=j(""),g=(k="")=>{const{pathname:b,searchParams:C}=new URL(window.location.href),y=Ee(o.value),_=y===b;C.delete(js),C.append(js,"1"),C.delete(er),k&&C.append(er,k);const x=k?`?${C.toString()}`:"";if(!(_&&m.value===k)){if(m.value=k,!_)return h.go(y+x);window.history.pushState({},"",b+x),d()}};be(()=>{const{searchParams:k}=new URL(window.location.href),b=k.get(er);b&&(m.value=b)}),te(()=>e.categoriesPage,()=>{if(!e.categoriesPage){m.value="";return}const{searchParams:k}=new URL(window.location.href),b=k.get(er);b&&m.value!==b&&(m.value=b)});const v=j([]);return(k,b)=>(p(),D(l(No),{page:!e.categoriesPage,modelValue:a.value,"onUpdate:modelValue":b[0]||(b[0]=C=>a.value=C),pageSize:l(i).limit,total:c.value.length,title:f.value[e.categoriesPage?"pt":"ht"],titleClick:g,autoPage:l(i).autoPage,pageSpeed:l(i).pageSpeed,class:T([l(t).b(),l(t).is("page",e.categoriesPage)]),"aria-label":l(n)("tk.categoryCard.label")},{default:O(({transitionName:C})=>[c.value.length?(p(),D(Qs,{key:0,name:C,tag:"div",mode:"out-in",class:T(`${l(t).e("list")} flx-column`),"aria-label":l(n)("tk.categoryCard.listLabel")},{default:O(()=>[(p(!0),w(Y,null,le(u.value,(y,_)=>(p(),w("a",{ref_for:!0,ref_key:"itemRefs",ref:v,key:y.name,onClick:x=>g(y.name),class:T([{active:y.name===m.value},"hover-color"]),style:Fe(`top: ${_*v.value?.[_]?.getBoundingClientRect().height||0}px`),"aria-label":y.name},[S("span",lT,W(y.name),1),S("span",null,W(y.length),1)],14,aT))),128)),!e.categoriesPage&&l(i).limita.value.groupCards.tags),f=F(()=>{const{limit:b}=i.value,C=u.value,y=o.value;return e.tagsPage?C:C.slice((y-1)*b,y*b)}),d=F(()=>{const{pageTitle:b,homeTitle:C}=i.value,y=ht(b)?b(Gi):b,_=ht(C)?C(Gi):C;return{pt:y,ht:_}}),h=b=>{const C=c.value,y=C[b%C.length];return{[t.cssVarName("home-tag-bg-color")]:y.bg,backgroundColor:y.bg,color:y.text,borderColor:y.border}},m=qe(Iu,()=>{}),g=Ls(),v=j(""),k=(b="")=>{const{pathname:C,searchParams:y}=new URL(window.location.href),_=Ee(r.value),x=_===C;y.delete(js),y.append(js,"1"),y.delete(tr),b&&y.append(tr,b);const P=b?`?${y.toString()}`:"";if(!(x&&v.value===b)){if(v.value=b,!x)return g.go(_+P);window.history.pushState({},"",C+P),m()}};return be(()=>{const{searchParams:b}=new URL(window.location.href),C=b.get(tr);C&&(v.value=C)}),te(()=>e.tagsPage,()=>{if(!e.tagsPage){v.value="";return}const{searchParams:b}=new URL(window.location.href),C=b.get(tr);C&&v.value!==C&&(v.value=C)}),(b,C)=>(p(),D(l(No),{page:!e.tagsPage,modelValue:o.value,"onUpdate:modelValue":C[0]||(C[0]=y=>o.value=y),pageSize:l(i).limit,total:u.value.length,title:d.value[e.tagsPage?"pt":"ht"],titleClick:k,autoPage:l(i).autoPage,pageSpeed:l(i).pageSpeed,class:T([l(t).b(),l(t).is("page",e.tagsPage)]),"aria-label":l(n)("tk.tagCard.label")},{default:O(({transitionName:y})=>[u.value.length?(p(),D(Qs,{key:0,name:y,tag:"div",mode:"out-in",class:T(l(t).e("list")),"aria-label":l(n)("tk.tagCard.listLabel")},{default:O(()=>[(p(!0),w(Y,null,le(f.value,(_,x)=>(p(),w("a",{key:_.name,style:Fe(h(x)),onClick:P=>k(_.name),class:T([{active:_.name===v.value},l(t).join("pointer")]),"aria-label":_.name},[S("span",null,W(_.name),1),S("span",hT,W(_.length),1)],14,dT))),128)),!e.tagsPage&&l(i).limit(p(),w("a",{href:e.item.link&&l(Ee)(e.item.link),target:"_blank",class:"hover-color flx-align-center","aria-label":e.item.name},[S("div",yT,[S("img",{src:e.item.avatar&&l(Ee)(e.item.avatar),class:"avatar",alt:e.item.alt||e.item.name,"aria-hidden":"true",onLoad:n[0]||(n[0]=s=>s.target?.classList.add("loaded")),onError:n[1]||(n[1]=s=>s.target?.classList.add("loaded"))},null,40,bT)]),S("div",{class:T(e.ns.e("list__item__info"))},[S("div",{class:"friend-name sle",title:e.item.name},W(e.item.name),9,kT),S("div",{class:"friend-desc sle",title:e.item.desc},W(e.item.desc),9,wT)],2)],8,vT))}});const CT=["aria-label"];var _T=z({name:"HomeFriendLinkCard",__name:"index",setup(e){const t=ie("friend-link"),{t:n}=ge(),{getTeekConfigRef:s}=fe(),o=s("friendLink",{list:[],limit:4,title:n("tk.friendLinkCard.title",{icon:jf}),emptyLabel:n("tk.friendLinkCard.emptyLabel"),autoScroll:!1,scrollSpeed:2500,autoPage:!1,pageSpeed:4e3,titleClick:void 0}),{data:i,start:r,stop:a}=V9(o.value.list,5,{intervalTime:o.value.scrollSpeed}),c=j(1),u=F(()=>{const{list:v,limit:k,autoScroll:b}=o.value;if(b)return i.value;const C=c.value;return v.slice((C-1)*k,C*k)}),f=F(()=>{const{title:v}=o.value;return ht(v)?v(jf):v});be(()=>{o.value.autoScroll&&r()});const d=j([]),h=v=>{if(o.value.autoScroll)return{};const k=d.value?.[v]?.getBoundingClientRect();return{top:`calc(${v} * (calc(${t.cssVar("home-friend-link-gap")} + ${k?.height||0}px)))`}},m=Ls(),g=()=>{o.value.titleClick?.(m)};return(v,k)=>(p(),D(l(No),{page:!l(o).autoScroll,modelValue:c.value,"onUpdate:modelValue":k[0]||(k[0]=b=>c.value=b),pageSize:l(o).limit,total:l(o).list.length,title:f.value,titleClick:l(o).titleClick?g:void 0,autoPage:l(o).autoPage,pageSpeed:l(o).pageSpeed,class:T(l(t).b()),"aria-label":l(n)("tk.friendLinkCard.label")},{default:O(({transitionName:b,startAutoPage:C,closeAutoPage:y})=>[l(o).list.length?(p(),D(Qs,{key:0,name:b,tag:"ul",mode:"out-in",class:T(`${l(t).e("list")} flx-column`),onMouseenter:_=>l(o).autoScroll?l(a)():l(o).autoPage?y():()=>{},onMouseleave:_=>l(o).autoScroll?l(r)():l(o).autoPage?C():()=>{},"aria-label":l(n)("tk.friendLinkCard.listLabel")},{default:O(()=>[l(o).autoScroll?(p(!0),w(Y,{key:0},le(u.value,(_,x)=>(p(),w("li",{key:_.name,class:T(l(t).e("list__item")),style:Fe(h(x))},[H(Hd,{item:_,ns:l(t)},null,8,["item","ns"])],6))),128)):(p(!0),w(Y,{key:1},le(u.value,(_,x)=>(p(),w("li",{ref_for:!0,ref_key:"itemRefs",ref:d,key:_.name,class:T(l(t).e("list__item")),style:Fe(h(x))},[H(Hd,{item:_,ns:l(t)},null,8,["item","ns"])],6))),128))]),_:1},8,["name","class","onMouseenter","onMouseleave","aria-label"])):(p(),w("div",{key:1,class:T(l(t).m("empty")),"aria-label":l(o).emptyLabel},W(l(o).emptyLabel),11,CT))]),_:1},8,["page","modelValue","pageSize","total","title","titleClick","autoPage","pageSpeed","class","aria-label"]))}});const ST=["innerHTML"],TT=["innerHTML"];var ET=z({name:"HomeDocAnalysisCard",__name:"index",setup(e){const t=ie("doc-analysis"),{t:n}=ge(),{getTeekConfigRef:s}=fe(),{theme:o}=Ae(),i=Is(),r=s("docAnalysis",{createTime:void 0,title:n("tk.docAnalysisCard.title",{icon:zf}),statistics:{},overrideInfo:[],appendInfo:[]}),a=F(()=>o.value.docAnalysisInfo||{}),c=F(()=>{const{title:P}=r.value;return ht(P)?P(zf):P}),u=F(()=>N7(r.value.createTime||Rf())),f=Pn(),d=F(()=>{const P=f.value.sortPostsByDate;let V=0,E=0;const L=new Date(Rf());for(const I of P){if(!I.date)continue;const N=new Date(I.date);if(N.getTime()>L.getTime()-10080*60*1e3&&V++,N.getTime()>L.getTime()-720*60*60*1e3)E++;else return{weekAddNum:V,monthAddNum:E}}return{weekAddNum:V,monthAddNum:E}}),h=P=>P<1e3?P+"":P<1e6?Math.round(P/100)/10+"k":Math.round(P/1e4)/10+"w",m=F(()=>({url:"",provider:"",siteView:!0,iteration:!1,pageIteration:2e3,permalink:!0,...r.value.statistics})),g=F(()=>!!m.value.provider&&m.value.siteView),{router:v}=i,{sitePv:k,siteUv:b,isGet:C,request:y}=Oh(!1,m.value);te(g,P=>{P&&y()}),te(v.route,()=>{g.value&&(m.value.permalink&&v.state?.permalinkPlugin?ze(y):y())},{immediate:!0});const _=F(()=>{const{appendInfo:P}=r.value;return ht(P)?P():P}),x=F(()=>{const{createTime:P,overrideInfo:V}=r.value,{fileList:E=[],totalFileWords:L,lastCommitTime:I}=a.value,N=[{key:"totalPosts",label:n("tk.docAnalysisCard.totalPosts"),originValue:E.length,value:`${E.length} ${n("tk.docAnalysisCard.fileUnit")}`},{key:"weekAddNum",label:n("tk.docAnalysisCard.weekAddNum"),originValue:d.value?.weekAddNum,value:`${d.value?.weekAddNum} ${n("tk.docAnalysisCard.fileUnit")}`},{key:"monthAddNum",label:n("tk.docAnalysisCard.monthAddNum"),originValue:d.value?.monthAddNum,value:`${d.value?.monthAddNum} ${n("tk.docAnalysisCard.fileUnit")}`},{key:"runtime",label:n("tk.docAnalysisCard.runtime"),originValue:P,value:`${u.value===0?n("tk.docAnalysisCard.runtimeLess"):`${u.value} ${n("tk.docAnalysisCard.runtimeUnit")}`}`},{key:"totalWordCount",label:n("tk.docAnalysisCard.totalWordCount"),originValue:L,value:`${h(L)} ${n("tk.docAnalysisCard.wordCountUnit")}`},{key:"lastActiveTime",label:n("tk.docAnalysisCard.lastActiveTime"),originValue:I,value:B7(I)},{key:"viewCount",label:n("tk.docAnalysisCard.viewCount"),originValue:k.value,value:C.value?`${k.value} ${n("tk.docAnalysisCard.viewCountUnit")}`:"Get...",show:g.value},{key:"visitCount",label:n("tk.docAnalysisCard.visitCount"),originValue:b.value,value:C.value?`${b.value} ${n("tk.docAnalysisCard.visitCountUnit")}`:"Get...",show:g.value},..._.value];return V.length&&N.forEach($=>{const U=V.find(q=>q.key===$.key);U&&($.label=U.label||$.label,$.value=U.value?U.value($.originValue||"",$.value):$.value,$.show=U.show!==!1)}),N});return(P,V)=>(p(),D(l(No),{title:c.value,class:T(l(t).b()),"aria-label":l(n)("tk.docAnalysisCard.label")},{default:O(()=>[(p(!0),w(Y,null,le(x.value,E=>(p(),w(Y,{key:E.key},[E.show!==!1?(p(),w("div",{key:0,class:T(l(t).e("item"))},[S("span",{innerHTML:E.label},null,8,ST),S("span",{innerHTML:E.value},null,8,TT)],2)):A("v-if",!0)],64))),128))]),_:1},8,["title","class","aria-label"]))}}),xT=z({name:"HomeCardList",__name:"index",setup(e){const t=ie("home-card-list"),{getTeekConfigRef:n}=fe(),s=n(null,{}),o=F(()=>{const h=s.value.homeCardSort||[];return["my",...new Set([...h,"topArticle","category","tag","friendLink","docAnalysis"])]}),{isHomePage:i,isCategoriesPage:r,isTagsPage:a}=iu(),c=F(()=>{const{topArticle:h,category:m,tag:g,docAnalysis:v,friendLink:k}=s.value,b=i.value,C=r.value,y=a.value;return{my:{el:tT,show:b,slot:"teek-home-card-my"},topArticle:{el:rT,show:b&&h?.enabled!==!1,slot:"teek-home-card-top-article"},category:{el:fT,props:{categoriesPage:C},show:(b||C)&&m?.enabled!==!1,slot:"teek-home-card-category"},tag:{el:gT,props:{tagsPage:y},show:(b||y)&&g?.enabled!==!1,slot:"teek-home-card-tag"},docAnalysis:{el:ET,show:b&&v?.enabled!==!1,slot:"teek-home-card-doc-analysis"},friendLink:{el:_T,show:b&&k?.enabled!==!1,slot:"teek-home-card-friend-link"}}}),u=_a(h=>h.card),f=j(null),{start:d}=Ca(f,!1);return be(()=>{u.value&&d()}),(h,m)=>(p(),w("div",{class:T([l(t).b(),"flx-column"])},[M(h.$slots,"teek-home-card-before"),M(h.$slots,"teek-home-card",{homeCard:o.value},()=>[(p(!0),w(Y,null,le(o.value,g=>(p(),w(Y,{key:g},[A(" 使用淡入动画 "),l(u)?(p(),w(Y,{key:0},[h.$slots[`${c.value[g]?.slot}-before`]?(p(),w("div",{key:0,ref_for:!0,ref_key:"cardListInstance",ref:f},[M(h.$slots,`${c.value[g]?.slot}-before`)],512)):A("v-if",!0),S("div",{ref_for:!0,ref_key:"cardListInstance",ref:f},[M(h.$slots,c.value[g]?.slot,{},()=>[c.value[g]?.show?(p(),D(Be(c.value[g]?.el),nt({key:0,ref_for:!0},c.value[g]?.props),null,16)):A("v-if",!0)])],512),h.$slots[`${c.value[g]?.slot}-after`]?(p(),w("div",{key:1,ref_for:!0,ref_key:"cardListInstance",ref:f},[M(h.$slots,`${c.value[g]?.slot}-after`)],512)):A("v-if",!0)],64)):(p(),w(Y,{key:1},[A(" 不使用淡入动画 "),c.value[g]?.slot?M(h.$slots,`${c.value[g]?.slot}-before`,{key:0}):A("v-if",!0),c.value[g]?.slot?M(h.$slots,c.value[g]?.slot,{key:1},()=>[c.value[g]?.show?(p(),D(Be(c.value[g]?.el),nt({key:0,ref_for:!0},c.value[g]?.props),null,16)):A("v-if",!0)]):A("v-if",!0),c.value[g]?.slot?M(h.$slots,`${c.value[g]?.slot}-after`,{key:2}):A("v-if",!0)],64))],64))),128))]),M(h.$slots,"teek-home-card-after")],2))}});const AT=["aria-label"],$T={key:0},LT=["aria-label"],IT=["aria-label"];var PT=z({name:"Home",__name:"index",setup(e){const t=ie("home"),{t:n}=ge(),{isHomePage:s}=iu(),{getTeekConfigRef:o}=fe(),i=o(null,{teekHome:!0,homeCardListPosition:"right",banner:{},wallpaper:{},bodyBgImg:{}}),r=j(null);In(Iu,()=>r.value?.updateData());const a=j(!1);return(c,u)=>(p(),w("div",{class:T(l(t).b()),role:"main","aria-label":l(n)("tk.home.label")},[l(s)&&(l(i).banner.enabled??!0)?et((p(),w("div",$T,[H(l(OS),{disabled:a.value},Wt({_:2},[le(c.$slots,(f,d)=>({name:d,fn:O(h=>[M(c.$slots,d,Ge(Ze(h)))])}))]),1032,["disabled"])],512)),[[at,!a.value]]):A("v-if",!0),S("div",{class:T([l(t).e("content"),l(t).join("wallpaper-outside"),"flx-start-justify-center"])},[S("div",{class:T(l(t).e("content__post")),"aria-label":l(n)("tk.home.postLabel")},[M(c.$slots,"teek-home-post-before"),H(l(kS),{modelValue:a.value,"onUpdate:modelValue":u[0]||(u[0]=f=>a.value=f),ref_key:"homePostListInstance",ref:r},Wt({_:2},[le(c.$slots,(f,d)=>({name:d,fn:O(h=>[M(c.$slots,d,Ge(Ze(h)))])}))]),1032,["modelValue"]),M(c.$slots,"teek-home-post-after")],10,LT),l(i).homeCardListPosition?(p(),w("div",{key:0,class:T([l(t).e("content__info"),l(i).homeCardListPosition==="left"?l(t).is("left"):l(t).is("right")]),"aria-label":l(n)("tk.home.cardLabel")},[H(l(xT),null,Wt({_:2},[le(c.$slots,(f,d)=>({name:d,fn:O(h=>[M(c.$slots,d,Ge(Ze(h)))])}))]),1024)],10,IT)):A("v-if",!0)],2),l(i).wallpaper.enabled&&(l(i).banner.bgStyle==="fullImg"||l(i).bodyBgImg.imgSrc)?(p(),D(l(L_),{key:1})):A("v-if",!0)],10,AT))}});const MT=["src","alt"],FT=["aria-label"],BT={class:"name"},NT={class:"slogan"};var VT=z({name:"HomeMyCardScreen",__name:"HomeMyCardScreen",setup(e){const t=ie("my-screen"),{t:n}=ge(),{getTeekConfigRef:s}=fe(),o=s("blogger",{}),i=Xt("(max-width: 960px)");return(r,a)=>l(i)&&l(o).name&&l(o).avatar&&l(o).slogan?(p(),w(Y,{key:0},[M(r.$slots,"teek-home-card-my-screen-before"),M(r.$slots,"teek-home-card-my-screen",{},()=>[S("div",{class:T(l(t).b())},[S("div",{class:T(l(t).e("avatar"))},[l(o).avatar?(p(),w("img",{key:0,src:l(Ee)(l(o).avatar),alt:l(n)("tk.myCard.avatarAlt")},null,8,MT)):A("v-if",!0)],2),S("div",{class:T(l(t).e("blogger")),"aria-label":l(n)("tk.myCard.bloggerLabel")},[S("h3",BT,W(l(o).name),1),S("span",NT,W(l(o).slogan),1)],10,FT)],2)]),M(r.$slots,"teek-home-card-my-screen-after")],64)):A("v-if",!0)}});const OT={key:0,class:"mask"};var DT=z({name:"BodyBgImage",__name:"index",setup(e){const t=ie("body-bg-image"),{getTeekConfigRef:n}=fe(),s=n("bodyBgImg",{imgSrc:void 0,imgOpacity:1,imgInterval:15e3,imgShuffle:!1,mask:!1,maskBg:"rgba(0, 0, 0, 0.2)"}),o=F(()=>{const u=s.value.imgSrc;return[ht(u)?u():u||[]].flat().map(f=>f&&Ee(f))}),{data:i,start:r,index:a}=tu(o,{timeout:s.value.imgInterval,shuffle:s.value.imgShuffle,onAfterUpdate:()=>{const u=(a.value+1)%o.value.length,f=o.value[u];if(f){const d=new Image;d.src=f}}});be(()=>{r()});const c=()=>{const{imgSrc:u,imgOpacity:f,maskBg:d}=s.value,h=t.cssVarName("body-bg-img"),m=t.cssVarName("body-bg-img-opacity"),g=t.cssVarName("body-mask-bg-color");return u?.length?{[h]:`url(${i.value}) center center / cover no-repeat`,[m]:f,[g]:Je(d)?d:`rgba(0, 0, 0, ${d})`}:{[h]:t.cssVar("bg-img-default")}};return(u,f)=>(p(),w("div",{class:T(l(t).b()),style:Fe(c())},[l(s).mask?(p(),w("div",OT)):A("v-if",!0)],6))}});const RT=["name","href","title","target","aria-label","aria-describedby"],HT={class:"sle"};var zT=z({name:"FooterGroup",__name:"index",setup(e){const t=ie("footer-group"),{getTeekConfigRef:n}=fe(),s=n("footerGroup",[]);return(o,i)=>l(s).length?(p(),w("div",{key:0,class:T(l(t).b())},[(p(!0),w(Y,null,le(l(s),(r,a)=>(p(),w("div",{key:(r.title||"")+a},[S("div",{class:T([l(t).e("title"),"flx-center"])},[r.icon?(p(),D(l(de),{key:0,icon:r.icon,style:{"margin-right":"4px"},"aria-hidden":"true"},null,8,["icon"])):A("v-if",!0),rt(" "+W(r.title),1)],2),S("ul",null,[(p(!0),w(Y,null,le(r.links||[],(c,u)=>(p(),w("li",{key:(c.name||"")+u,class:T([l(t).e("link")])},[c.icon?(p(),D(l(de),{key:0,icon:c.icon,style:{"margin-right":"4px"},"aria-hidden":"true"},null,8,["icon"])):A("v-if",!0),S("a",{name:c.name,href:c.link,title:c.name,target:l(Df)(c.link||"")?"_blank":"_self",class:"hover-color","aria-label":c.name,rel:"noopener noreferrer","aria-describedby":c.name},[S("span",HT,W(c.name),1),l(Df)(c.link||"")?(p(),D(l(de),{key:0,icon:l(r9),class:T(l(t).e("link__external-icon")),"aria-hidden":"true"},null,8,["icon","class"])):A("v-if",!0)],8,RT)],2))),128))])]))),128))],2)):A("v-if",!0)}}),jT="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKTWlDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVN3WJP3Fj7f92UPVkLY8LGXbIEAIiOsCMgQWaIQkgBhhBASQMWFiApWFBURnEhVxILVCkidiOKgKLhnQYqIWotVXDjuH9yntX167+3t+9f7vOec5/zOec8PgBESJpHmomoAOVKFPDrYH49PSMTJvYACFUjgBCAQ5svCZwXFAADwA3l4fnSwP/wBr28AAgBw1S4kEsfh/4O6UCZXACCRAOAiEucLAZBSAMguVMgUAMgYALBTs2QKAJQAAGx5fEIiAKoNAOz0ST4FANipk9wXANiiHKkIAI0BAJkoRyQCQLsAYFWBUiwCwMIAoKxAIi4EwK4BgFm2MkcCgL0FAHaOWJAPQGAAgJlCLMwAIDgCAEMeE80DIEwDoDDSv+CpX3CFuEgBAMDLlc2XS9IzFLiV0Bp38vDg4iHiwmyxQmEXKRBmCeQinJebIxNI5wNMzgwAABr50cH+OD+Q5+bk4eZm52zv9MWi/mvwbyI+IfHf/ryMAgQAEE7P79pf5eXWA3DHAbB1v2upWwDaVgBo3/ldM9sJoFoK0Hr5i3k4/EAenqFQyDwdHAoLC+0lYqG9MOOLPv8z4W/gi372/EAe/tt68ABxmkCZrcCjg/1xYW52rlKO58sEQjFu9+cj/seFf/2OKdHiNLFcLBWK8ViJuFAiTcd5uVKRRCHJleIS6X8y8R+W/QmTdw0ArIZPwE62B7XLbMB+7gECiw5Y0nYAQH7zLYwaC5EAEGc0Mnn3AACTv/mPQCsBAM2XpOMAALzoGFyolBdMxggAAESggSqwQQcMwRSswA6cwR28wBcCYQZEQAwkwDwQQgbkgBwKoRiWQRlUwDrYBLWwAxqgEZrhELTBMTgN5+ASXIHrcBcGYBiewhi8hgkEQcgIE2EhOogRYo7YIs4IF5mOBCJhSDSSgKQg6YgUUSLFyHKkAqlCapFdSCPyLXIUOY1cQPqQ28ggMor8irxHMZSBslED1AJ1QLmoHxqKxqBz0XQ0D12AlqJr0Rq0Hj2AtqKn0UvodXQAfYqOY4DRMQ5mjNlhXIyHRWCJWBomxxZj5Vg1Vo81Yx1YN3YVG8CeYe8IJAKLgBPsCF6EEMJsgpCQR1hMWEOoJewjtBK6CFcJg4Qxwicik6hPtCV6EvnEeGI6sZBYRqwm7iEeIZ4lXicOE1+TSCQOyZLkTgohJZAySQtJa0jbSC2kU6Q+0hBpnEwm65Btyd7kCLKArCCXkbeQD5BPkvvJw+S3FDrFiOJMCaIkUqSUEko1ZT/lBKWfMkKZoKpRzame1AiqiDqfWkltoHZQL1OHqRM0dZolzZsWQ8ukLaPV0JppZ2n3aC/pdLoJ3YMeRZfQl9Jr6Afp5+mD9HcMDYYNg8dIYigZaxl7GacYtxkvmUymBdOXmchUMNcyG5lnmA+Yb1VYKvYqfBWRyhKVOpVWlX6V56pUVXNVP9V5qgtUq1UPq15WfaZGVbNQ46kJ1Bar1akdVbupNq7OUndSj1DPUV+jvl/9gvpjDbKGhUaghkijVGO3xhmNIRbGMmXxWELWclYD6yxrmE1iW7L57Ex2Bfsbdi97TFNDc6pmrGaRZp3mcc0BDsax4PA52ZxKziHODc57LQMtPy2x1mqtZq1+rTfaetq+2mLtcu0W7eva73VwnUCdLJ31Om0693UJuja6UbqFutt1z+o+02PreekJ9cr1Dund0Uf1bfSj9Rfq79bv0R83MDQINpAZbDE4Y/DMkGPoa5hpuNHwhOGoEctoupHEaKPRSaMnuCbuh2fjNXgXPmasbxxirDTeZdxrPGFiaTLbpMSkxeS+Kc2Ua5pmutG003TMzMgs3KzYrMnsjjnVnGueYb7ZvNv8jYWlRZzFSos2i8eW2pZ8ywWWTZb3rJhWPlZ5VvVW16xJ1lzrLOtt1ldsUBtXmwybOpvLtqitm63Edptt3xTiFI8p0in1U27aMez87ArsmuwG7Tn2YfYl9m32zx3MHBId1jt0O3xydHXMdmxwvOuk4TTDqcSpw+lXZxtnoXOd8zUXpkuQyxKXdpcXU22niqdun3rLleUa7rrStdP1o5u7m9yt2W3U3cw9xX2r+00umxvJXcM970H08PdY4nHM452nm6fC85DnL152Xlle+70eT7OcJp7WMG3I28Rb4L3Le2A6Pj1l+s7pAz7GPgKfep+Hvqa+It89viN+1n6Zfgf8nvs7+sv9j/i/4XnyFvFOBWABwQHlAb2BGoGzA2sDHwSZBKUHNQWNBbsGLww+FUIMCQ1ZH3KTb8AX8hv5YzPcZyya0RXKCJ0VWhv6MMwmTB7WEY6GzwjfEH5vpvlM6cy2CIjgR2yIuB9pGZkX+X0UKSoyqi7qUbRTdHF09yzWrORZ+2e9jvGPqYy5O9tqtnJ2Z6xqbFJsY+ybuIC4qriBeIf4RfGXEnQTJAntieTE2MQ9ieNzAudsmjOc5JpUlnRjruXcorkX5unOy553PFk1WZB8OIWYEpeyP+WDIEJQLxhP5aduTR0T8oSbhU9FvqKNolGxt7hKPJLmnVaV9jjdO31D+miGT0Z1xjMJT1IreZEZkrkj801WRNberM/ZcdktOZSclJyjUg1plrQr1zC3KLdPZisrkw3keeZtyhuTh8r35CP5c/PbFWyFTNGjtFKuUA4WTC+oK3hbGFt4uEi9SFrUM99m/ur5IwuCFny9kLBQuLCz2Lh4WfHgIr9FuxYji1MXdy4xXVK6ZHhp8NJ9y2jLspb9UOJYUlXyannc8o5Sg9KlpUMrglc0lamUycturvRauWMVYZVkVe9ql9VbVn8qF5VfrHCsqK74sEa45uJXTl/VfPV5bdra3kq3yu3rSOuk626s91m/r0q9akHV0IbwDa0b8Y3lG19tSt50oXpq9Y7NtM3KzQM1YTXtW8y2rNvyoTaj9nqdf13LVv2tq7e+2Sba1r/dd3vzDoMdFTve75TsvLUreFdrvUV99W7S7oLdjxpiG7q/5n7duEd3T8Wej3ulewf2Re/ranRvbNyvv7+yCW1SNo0eSDpw5ZuAb9qb7Zp3tXBaKg7CQeXBJ9+mfHvjUOihzsPcw83fmX+39QjrSHkr0jq/dawto22gPaG97+iMo50dXh1Hvrf/fu8x42N1xzWPV56gnSg98fnkgpPjp2Snnp1OPz3Umdx590z8mWtdUV29Z0PPnj8XdO5Mt1/3yfPe549d8Lxw9CL3Ytslt0utPa49R35w/eFIr1tv62X3y+1XPK509E3rO9Hv03/6asDVc9f41y5dn3m978bsG7duJt0cuCW69fh29u0XdwruTNxdeo94r/y+2v3qB/oP6n+0/rFlwG3g+GDAYM/DWQ/vDgmHnv6U/9OH4dJHzEfVI0YjjY+dHx8bDRq98mTOk+GnsqcTz8p+Vv9563Or59/94vtLz1j82PAL+YvPv655qfNy76uprzrHI8cfvM55PfGm/K3O233vuO+638e9H5ko/ED+UPPR+mPHp9BP9z7nfP78L/eE8/sl0p8zAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAAQjSURBVHjaVNNZbFRlGIDh95w525zpdGa6TVtbykBbyiICxQY0AhYTJUCiiYqGqEEiJhKQmBg0ESPeeCGRENEYb4jhBr0gNQrRlCBiSgyLaSlSaKEs3Wemy+xnzuqFYdD/6rt6ku/N9wue55EcPwWArCgIgkx5ZRuYVxsnJ801Z05f3jY1MRnb/HxHV+uSph9RKq4mhkdwbZVgdQ2SHkPTwgj/h1QUWWi8/tfg/hM/XN/Y2zfaZnkSnuRDtLMsXhBOvrJtya/LlrcdMs1Qb1lVRQmSAEDAsU1kxpgamXp3y+azu1esreK9dyRqs9PIjkW6OsLx7lTV1ld/237s8HRV57MbnvO8CA+e9GCQFTk6Mza+4/0P+t9a9VSEI3uyTH/eR27aB2Ed31Q/Hx1sI6BHOPT13c5Frd0HW9p3HPUQEwAigJW9RDp+bstrOy981nVGLN/7RpHUV70YfXnEAtjxFPasxPDBQXatjzNTdOQXtg983H/51AFFy1KCIg2bNIdC+8270NwmUmelsXqSqHkDK5PDl8iCW0QcnEW+lqCjvcjQuMZ4YnQRTkotQUZu4GkjcfZNv19G011kXw4vayNYNvqCCvSVTciOgABgeuhBGwhgz5zbkI2ff7HUqJiNR2QktbbSYnBYYqbMT/ilKI4SIbT/GcRylbnvLmJ2X8N7tJ7rR8OE/BbliqEYea81WIotmOs02WFpc55Lf0f5/mSI3dsamOgxSX7ZjaALuBmB6M6FnB+S+POCwmOLk1QFFAqZyQWl1YrpiRZJLvDkygyC5NJ1XCax7xYNiTQVEYVIuUulayIcGeLkpw6WK7GuPY/fb2CkhleXIFFe8XPGaKBj9QxLW1Ik0bg8EuT2zRCJYZvZIYepe0EGbvi4bQUJVZhs2phADFYj+df0lBqJUnaekS4SUHXe3jrOnoE2PhSewHfRpfZGgcryIvfHdQruQlLo7Ns6QizqkJ31CIUlqwQJXuWUpDXj6qOsW32HT3YNImll9FwJsb4jyaLmWQ4fa6a+2sQw0ry8YZSiHcPxxXBtMfCv4XkUCrfliWs/fTE31rtTVfv9vsIorvQIniMhqXM4popVcJFVMHMpfMEaLPdxR1Tnna1b1vl6tGntpAjgCTNWONZyIFBR8Ydtr6EgrCI3VySfzZPLBDHyIq5gkpmzcOUmTGMF+bh7M9LYulfWzMmHBzk7Fpq9deWEYxjrtaCMXjWfstp6BCGNXZzBdYqYhogWqkMum4+oBVD0YnP63u/fFqbv1D+M7VSlBbmmK5uYaLYLYwslfwFVAyXQiOfcx3XyyGIM8DDn0lgWyGokHogu/0UJxpL/+f2e569s/CZQZ53OpzJr0+NXludUfb5jVdf7VUGXJUPIZast1S9PeII6jFDT5xMjFwO1S4c8zwTgnwEAxufYSzA67PMAAAAASUVORK5CYII=";const UT=["aria-label"],WT=["aria-label"],qT=["href","title","aria-label"],KT={key:1},YT=["innerHTML"],GT=["aria-label"],JT=["href","aria-label"],XT={key:2},QT=["innerHTML"],ZT=["innerHTML"];var eE=z({name:"FooterInfo",__name:"index",setup(e){const t=ie("footer-info"),{t:n}=ge(),{getTeekConfigRef:s}=fe(),o=s("footerInfo",{}),i=s("social",[]),r=F(()=>{const{theme:a={},copyright:c={},icpRecord:u,securityRecord:f}=o.value||{},d=[];a.show!==!1&&d.push({name:"Theme By Teek",icon:Y7,link:"https://github.com/Kele-Bingtang/vitepress-theme-teek",...a});const{show:h=!0,createYear:m="",suffix:g=""}=c;return h&&d.push({name:`Copyright ${m?`${m}-`:""}${new Date().getFullYear()} ${g}`,icon:j7,...c}),u&&d.push({icon:W7,...u}),f&&d.push({icon:jT,iconType:"img",imgAlt:"Security Record",...f}),d});return(a,c)=>l(o)||l(i).length?(p(),w("div",{key:0,class:T([l(t).b(),l(t).join("wallpaper-outside")]),role:"contentinfo","aria-label":l(n)("tk.footerInfo.label")},[l(i).length?(p(),w("div",{key:0,class:T(`${l(t).e("icons")} flx-center`),role:"group","aria-label":l(n)("tk.footerInfo.socialLabel")},[(p(!0),w(Y,null,le(l(i),(u,f)=>(p(),w("a",{key:f,href:u.link&&l(Ee)(u.link),title:u.name,target:"_blank","aria-label":u.name},[u.icon?(p(),D(l(de),{key:0,iconType:u.iconType,icon:u.icon,size:"20px",color:"var(--vp-c-text-2)",hover:"",imgAlt:u.imgAlt,"aria-hidden":"true"},null,8,["iconType","icon","imgAlt"])):u.name?(p(),w("span",KT,W(u.name),1)):A("v-if",!0)],8,qT))),128))],10,WT)):A("v-if",!0),l(o)?(p(),w(Y,{key:1},[(p(!0),w(Y,null,le([l(o).topMessage||[]].flat(),(u,f)=>(p(),w("p",{key:f,innerHTML:u,class:"flx-wrap-justify-center"},null,8,YT))),128)),S("div",{class:T(`${l(t).e("list")} flx-wrap-justify-center`),role:"list","aria-label":l(n)("tk.footerInfo.infoLabel")},[(p(!0),w(Y,null,le(r.value,u=>(p(),w("div",{key:u.name,class:T(`${l(t).e("list__item")} flx-align-center`),role:"listitem"},[u.icon?(p(),D(l(de),{key:0,iconType:u.iconType,icon:u.icon,size:"16px",color:"var(--vp-c-text-2)",imgAlt:u.imgAlt,"aria-hidden":"true"},null,8,["iconType","icon","imgAlt"])):A("v-if",!0),u.link?(p(),w("a",{key:1,href:l(Ee)(u.link),target:"_blank","aria-label":u.name},W(u.name),9,JT)):(p(),w("span",XT,W(u.name),1))],2))),128)),l(o).customHtml?(p(),w("span",{key:0,innerHTML:l(o).customHtml},null,8,QT)):A("v-if",!0)],10,GT),(p(!0),w(Y,null,le([l(o).bottomMessage||[]].flat(),(u,f)=>(p(),w("p",{key:f,innerHTML:u,class:"flx-wrap-justify-center"},null,8,ZT))),128))],64)):A("v-if",!0)],10,UT)):A("v-if",!0)}});let ro=[];const zd=e=>{e.code==="Escape"&&ro.forEach(t=>t(e))},tE=e=>{be(()=>{ro.length===0&&document.addEventListener("keydown",zd),me&&ro.push(e)}),as(()=>{ro=ro.filter(t=>t!==e),ro.length===0&&me&&document.removeEventListener("keydown",zd)})},el="focus-trap.focus-after-trapped",tl="focus-trap.focus-after-released",nE="focus-trap.focusout-prevented",jd={cancelable:!0,bubbles:!1},sE={cancelable:!0,bubbles:!1},Ud="focusAfterTrapped",Wd="focusAfterReleased",oE=Symbol("focusTrap"),Pu=j(),La=j(0),Mu=j(0);let nr=0;const u2=e=>{const t=[],n=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT,{acceptNode:s=>{const o=s.tagName==="INPUT"&&s.type==="hidden";return s.disabled||s.hidden||o?NodeFilter.FILTER_SKIP:s.tabIndex>=0||s===document.activeElement?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP}});for(;n.nextNode();)t.push(n.currentNode);return t},qd=(e,t)=>{for(const n of e)if(!iE(n,t))return n},iE=(e,t)=>{if(getComputedStyle(e).visibility==="hidden")return!0;for(;e;){if(t&&e===t)return!1;if(getComputedStyle(e).display==="none")return!0;e=e.parentElement}return!1},rE=e=>{const t=u2(e),n=qd(t,e),s=qd(t.reverse(),e);return[n,s]},aE=e=>e instanceof HTMLInputElement&&"select"in e,ps=(e,t)=>{if(e&&e.focus){const n=document.activeElement;let s=!1;Il(e)&&!F7(e)&&!e.getAttribute("tabindex")&&(e.setAttribute("tabindex","-1"),s=!0),e.focus({preventScroll:!0}),Mu.value=window.performance.now(),e!==n&&aE(e)&&t&&e.select(),Il(e)&&s&&e.removeAttribute("tabindex")}};function Kd(e,t){const n=[...e],s=e.indexOf(t);return s!==-1&&n.splice(s,1),n}const lE=()=>{let e=[];return{push:s=>{const o=e[0];o&&s!==o&&o.pause(),e=Kd(e,s),e.unshift(s)},remove:s=>{e=Kd(e,s),e[0]?.resume?.()}}},cE=(e,t=!1)=>{const n=document.activeElement;for(const s of e)if(ps(s,t),document.activeElement!==n)return},Yd=lE(),uE=()=>La.value>Mu.value,sr=()=>{Pu.value="pointer",La.value=window.performance.now()},Gd=()=>{Pu.value="keyboard",La.value=window.performance.now()},fE=()=>(be(()=>{nr===0&&(document.addEventListener("mousedown",sr),document.addEventListener("touchstart",sr),document.addEventListener("keydown",Gd)),nr++}),as(()=>{nr--,nr<=0&&(document.removeEventListener("mousedown",sr),document.removeEventListener("touchstart",sr),document.removeEventListener("keydown",Gd))}),{focusReason:Pu,lastUserFocusTimestamp:La,lastAutomatedFocusTimestamp:Mu}),or=e=>new CustomEvent(nE,{...sE,detail:e});var dE=z({name:"FocusTrap",inheritAttrs:!1,props:{loop:Boolean,trapped:Boolean,focusTrapEl:Object,focusStartEl:{type:[Object,String],default:"first"}},emits:[Ud,Wd,"focusin","focusout","focusout-prevented","release-requested"],setup(e,{emit:t}){const n=j();let s,o;const{focusReason:i}=fE();tE(g=>{e.trapped&&!r.paused&&t("release-requested",g)});const r={paused:!1,pause(){this.paused=!0},resume(){this.paused=!1}},a=g=>{if(!e.loop&&!e.trapped||r.paused)return;const{code:v,altKey:k,ctrlKey:b,metaKey:C,currentTarget:y,shiftKey:_}=g,{loop:x}=e,P=v==="Tab"&&!k&&!b&&!C,V=document.activeElement;if(P&&V){const E=y,[L,I]=rE(E);if(L&&I){if(!_&&V===I){const $=or({focusReason:i.value});t("focusout-prevented",$),$.defaultPrevented||(g.preventDefault(),x&&ps(L,!0))}else if(_&&[L,E].includes(V)){const $=or({focusReason:i.value});t("focusout-prevented",$),$.defaultPrevented||(g.preventDefault(),x&&ps(I,!0))}}else if(V===E){const $=or({focusReason:i.value});t("focusout-prevented",$),$.defaultPrevented||g.preventDefault()}}};In(oE,{focusTrapRef:n,onKeydown:a}),te(()=>e.focusTrapEl,g=>{g&&(n.value=g)},{immediate:!0}),te([n],([g],[v])=>{g&&(g.addEventListener("keydown",a),g.addEventListener("focusin",f),g.addEventListener("focusout",d)),v&&(v.removeEventListener("keydown",a),v.removeEventListener("focusin",f),v.removeEventListener("focusout",d))});const c=g=>{t(Ud,g)},u=g=>t(Wd,g),f=g=>{const v=n.value;if(!v)return;const k=g.target,b=g.relatedTarget,C=k&&v.contains(k);e.trapped||b&&v.contains(b)||(s=b),C&&t("focusin",g),!r.paused&&e.trapped&&(C?o=k:ps(o,!0))},d=g=>{const v=n.value;if(!(r.paused||!v))if(e.trapped){const k=g.relatedTarget;!k&&!v.contains(k)&&setTimeout(()=>{if(!r.paused&&e.trapped){const b=or({focusReason:i.value});t("focusout-prevented",b),b.defaultPrevented||ps(o,!0)}},0)}else{const k=g.target;k&&v.contains(k)||t("focusout",g)}};async function h(){await ze();const g=n.value;if(g){Yd.push(r);const v=g.contains(document.activeElement)?s:document.activeElement;if(s=v,!g.contains(v)){const b=new Event(el,jd);g.addEventListener(el,c),g.dispatchEvent(b),b.defaultPrevented||ze(()=>{let C=e.focusStartEl;Je(C)||(ps(C),document.activeElement!==C&&(C="first")),C==="first"&&cE(u2(g),!0),(document.activeElement===v||C==="container")&&ps(g)})}}}function m(){const g=n.value;if(g){g.removeEventListener(el,c);const v=new CustomEvent(tl,{...jd,detail:{focusReason:i.value}});g.addEventListener(tl,u),g.dispatchEvent(v),!v.defaultPrevented&&(i.value==="keyboard"||!uE()||g.contains(document.activeElement))&&ps(s??document.body),g.removeEventListener(tl,u),Yd.remove(r)}}return be(()=>{e.trapped&&h(),te(()=>e.trapped,g=>{g?h():m()})}),as(()=>{e.trapped&&m(),n.value&&(n.value.removeEventListener("keydown",a),n.value.removeEventListener("focusin",f),n.value.removeEventListener("focusout",d),n.value=void 0)}),{onKeydown:a}}}),hE=(e,t)=>{const n=e.__vccOpts||e;for(const[s,o]of t)n[s]=o;return n};function pE(e,t,n,s,o,i){return M(e.$slots,"default",{handleKeydown:e.onKeydown})}var f2=hE(dE,[["render",pE]]);const mE=["src","crossorigin"];var gE=z({name:"ImageViewer",__name:"ImageViewer",props:{urlList:{default:()=>[]},zIndex:{},initialIndex:{default:0},infinite:{type:Boolean,default:!0},hideOnClickModal:{type:Boolean,default:!1},teleported:{type:Boolean},closeOnPressEscape:{type:Boolean,default:!0},zoomRate:{default:1.2},minScale:{default:.2},maxScale:{default:7},showProgress:{type:Boolean,default:!1},crossorigin:{}},emits:["close","switch","rotate"],setup(e,{expose:t,emit:n}){const s={CONTAIN:{name:"contain",icon:Ph},ORIGINAL:{name:"original",icon:u9}},o=e,i=n;let r="";const a=ie("image-viewer"),{t:c}=ge(),{nextZIndex:u}=nu(),f=j(),d=j([]),h=l1(),m=j(!0),g=j(o.initialIndex),v=He(s.CONTAIN),k=j({scale:1,deg:0,offsetX:0,offsetY:0,enableTransition:!1}),b=j(o.zIndex??u()),C=F(()=>{const{urlList:we}=o;return we.length<=1}),y=F(()=>g.value===0),_=F(()=>g.value===o.urlList.length-1),x=F(()=>o.urlList[g.value]),P=F(()=>[a.e("btn"),a.e("prev"),a.is("disabled",!o.infinite&&y.value)]),V=F(()=>[a.e("btn"),a.e("next"),a.is("disabled",!o.infinite&&_.value)]),E=F(()=>{const{scale:we,deg:Ne,offsetX:Ke,offsetY:gt,enableTransition:bt}=k.value;let Nt=Ke/we,Qt=gt/we;const B=Ne*Math.PI/180,R=Math.cos(B),K=Math.sin(B);Nt=Nt*R+Qt*K,Qt=Qt*R-Ke/we*K;const ee={transform:`scale(${we}) rotate(${Ne}deg) translate(${Nt}px, ${Qt}px)`,transition:bt?"transform .3s":""};return v.value.name===s.CONTAIN.name&&(ee.maxWidth=ee.maxHeight="100%"),ee}),L=F(()=>`${g.value+1} / ${o.urlList.length}`),I=()=>{$(),Zs?.(),document.body.style.overflow=r,i("close")},N=()=>{const we=es(Ke=>{switch(Ke.code){case"Escape":o.closeOnPressEscape&&I();break;case"Space":ae();break;case"ArrowLeft":he();break;case"ArrowUp":je("zoomIn");break;case"ArrowRight":st();break;case"ArrowDown":je("zoomOut");break}}),Ne=es(Ke=>{const gt=Ke.deltaY||Ke.deltaX;je(gt<0?"zoomIn":"zoomOut",{zoomRate:o.zoomRate,enableTransition:!1})});h.run(()=>{Ve(document,"keydown",we),Ve(document,"wheel",Ne)})},$=()=>{h.stop()},U=()=>{m.value=!1},q=we=>{m.value=!1,we.target.alt=c("tk.image.error")},J=we=>{if(m.value||we.button!==0||!f.value)return;k.value.enableTransition=!1;const{offsetX:Ne,offsetY:Ke}=k.value,gt=we.pageX,bt=we.pageY,Nt=es(B=>{k.value={...k.value,offsetX:Ne+B.pageX-gt,offsetY:Ke+B.pageY-bt}}),Qt=()=>{document.removeEventListener("mousemove",Nt),document.removeEventListener("mouseup",Qt)};document.addEventListener("mousemove",Nt),document.addEventListener("mouseup",Qt),we.preventDefault()},G=()=>{k.value={scale:1,deg:0,offsetX:0,offsetY:0,enableTransition:!1}},ae=()=>{if(m.value)return;const we=Object.keys(s),Ne=Object.values(s),Ke=v.value.name,bt=(Ne.findIndex(Nt=>Nt.name===Ke)+1)%we.length;v.value=s[we[bt]],G()},ne=we=>{const Ne=o.urlList.length;g.value=(we+Ne)%Ne},he=()=>{y.value&&!o.infinite||ne(g.value-1)},st=()=>{_.value&&!o.infinite||ne(g.value+1)},je=(we,Ne={})=>{if(m.value)return;const{minScale:Ke,maxScale:gt}=o,{zoomRate:bt,rotateDeg:Nt,enableTransition:Qt}={zoomRate:o.zoomRate,rotateDeg:90,enableTransition:!0,...Ne};switch(we){case"zoomOut":k.value.scale>Ke&&(k.value.scale=Number.parseFloat((k.value.scale/bt).toFixed(3)));break;case"zoomIn":k.value.scale{we.detail?.focusReason==="pointer"&&we.preventDefault()},Un=()=>{o.closeOnPressEscape&&I()},cs=we=>{if(we.ctrlKey){if(we.deltaY<0)return we.preventDefault(),!1;if(we.deltaY>0)return we.preventDefault(),!1}};te(x,()=>{ze(()=>{d.value[0]?.complete||(m.value=!0)})}),te(g,we=>{G(),i("switch",we)}),N();const Zs=Ve(document,"wheel",cs,{passive:!1});return be(()=>{r=document.body.style.overflow,document.body.style.overflow="hidden"}),t({setActiveItem:ne}),(we,Ne)=>(p(),D(la,{disabled:!e.teleported,to:"body"},[H(vt,{name:"viewer-fade",appear:""},{default:O(()=>[S("div",{ref_key:"wrapper",ref:f,tabindex:-1,class:T(l(a).e("wrapper")),style:Fe({zIndex:b.value})},[H(l(f2),{loop:"",trapped:"","focus-trap-el":f.value,"focus-start-el":"container",onFocusoutPrevented:yt,onReleaseRequested:Un},{default:O(()=>[S("div",{class:T(l(a).e("mask")),onClick:Ne[0]||(Ne[0]=To(Ke=>e.hideOnClickModal&&I(),["self"]))},null,2),A(" CLOSE "),S("span",{class:T([l(a).e("btn"),l(a).e("close")]),onClick:I},[H(l(de),{icon:l(Jc)},null,8,["icon"])],2),A(" ARROW "),C.value?A("v-if",!0):(p(),w(Y,{key:0},[S("span",{class:T(P.value),onClick:he},[H(l(de),{icon:l(Xc)},null,8,["icon"])],2),S("span",{class:T(V.value),onClick:st},[H(l(de),{icon:l(Qc)},null,8,["icon"])],2)],64)),we.$slots.progress||e.showProgress?(p(),w("div",{key:1,class:T([l(a).e("btn"),l(a).e("progress")])},[M(we.$slots,"progress",{activeIndex:g.value,total:e.urlList.length},()=>[rt(W(L.value),1)])],2)):A("v-if",!0),A(" ACTIONS "),S("div",{class:T([l(a).e("btn"),l(a).e("actions")])},[S("div",{class:T(l(a).e("actions__inner"))},[M(we.$slots,"toolbar",{actions:je,prev:he,next:st,reset:ae,activeIndex:g.value,setActiveItem:ne},()=>[H(l(de),{icon:l(d9),onClick:Ne[1]||(Ne[1]=Ke=>je("zoomOut"))},null,8,["icon"]),H(l(de),{icon:l(f9),onClick:Ne[2]||(Ne[2]=Ke=>je("zoomIn"))},null,8,["icon"]),S("i",{class:T(l(a).e("actions__divider"))},null,2),H(l(de),{icon:v.value.icon,onClick:ae},null,8,["icon"]),S("i",{class:T(l(a).e("actions__divider"))},null,2),H(l(de),{icon:l(c9),onClick:Ne[3]||(Ne[3]=Ke=>je("anticlockwise"))},null,8,["icon"]),H(l(de),{icon:l(Mh),onClick:Ne[4]||(Ne[4]=Ke=>je("clockwise"))},null,8,["icon"])])],2)],2),A(" CANVAS "),S("div",{class:T(l(a).e("canvas"))},[(p(!0),w(Y,null,le(e.urlList,(Ke,gt)=>et((p(),w("img",{ref_for:!0,ref:bt=>d.value[gt]=bt,key:Ke,src:Ke,style:Fe(E.value),class:T([l(a).e("img"),"image-viewer__img"]),crossorigin:e.crossorigin,onLoad:U,onError:q,onMousedown:J},null,46,mE)),[[at,gt===g.value]])),128))],2),M(we.$slots,"default")]),_:3},8,["focus-trap-el"])],6)]),_:3})],8,["disabled"]))}}),vE=z({name:"ImageViewerControl",__name:"index",props:{modelValue:{default:!1},modelModifiers:{}},emits:["update:modelValue"],setup(e){const t=Jt(e,"modelValue"),n=()=>{document.body.style.overflow="",t.value=!1};return(s,o)=>t.value?(p(),D(gE,nt({key:0},s.$attrs,{onClose:n}),null,16)):A("v-if",!0)}});let Jd=null;const yE=e=>{if(typeof window>"u")return;const{modelValue:t=!0}=e;e.modelValue=t,document.body.style.overflow="hidden";const n=document.createElement("div");document.body.appendChild(n),Jd=H(vE,e),di(Jd,n)};var bE=z({__name:"index",setup(e){const{getTeekConfig:t}=fe(),n=F(()=>{const{imageViewer:o={}}=t("articleAnalyze",{});return o});return Ve(()=>document.querySelector("#VPContent"),"click",o=>{const i=o.target;if(i.tagName.toLowerCase()==="img"&&!i.className.includes("image-viewer__img")&&!i.className.includes("no-preview")){const r=i.querySelectorAll(".content-container .main img"),a=Array.from(r),c=a.map(d=>d.src);let u=a.findIndex(d=>d===i);const f=i.getAttribute("src");u===-1&&f&&(c.push(f),u=c.length-1),yE({infinite:!1,...n.value,urlList:c,initialIndex:u})}}),(o,i)=>null}});const d2=Symbol("breadcrumbKey"),ni=ie("breadcrumb"),kE=["aria-label"];var wE=z({name:"Breadcrumb",__name:"Breadcrumb",props:{separator:{default:"/"}},setup(e){const{t}=ge(),n=j();return In(d2,{separator:e.separator}),be(()=>{const s=n.value?.querySelectorAll(`.${ni.e("item")}`);s?.length&&s[s.length-1].setAttribute("aria-current","page")}),(s,o)=>(p(),w("div",{ref_key:"breadcrumb",ref:n,class:T(l(ni).b()),role:"navigation","aria-label":l(t)("tk.breadcrumb.label")},[M(s.$slots,"default")],10,kE))}}),Xd=z({name:"BreadcrumbItem",__name:"BreadcrumbItem",setup(e){const t=qe(d2,void 0);return(n,s)=>(p(),w("span",{class:T(l(ni).e("item"))},[S("span",{ref:"link",class:T(l(ni).e("inner")),role:"link"},[M(n.$slots,"default")],2),S("span",{class:T(l(ni).e("separator")),role:"presentation"},W(l(t)?.separator),3)],2))}});const CE=["aria-label"],_E=["href","title","aria-label"];var h2=z({name:"ArticleBreadcrumb",__name:"index",setup(e){const t=ie("article-breadcrumb"),{t:n}=ge(),{getTeekConfigRef:s}=fe(),{localeIndex:o,theme:i,page:r}=Ae(),a=s("breadcrumb",{enabled:!0,showCurrentName:!1,separator:"/",homeLabel:n("tk.articleBreadcrumb.home")}),c=F(()=>r.value.filePath.split("/")||[]),u=F(()=>{const f=[],d=c.value;return d.forEach((h,m)=>{const g=h.replace(/^\d+\./,"").split(".")?.[0]||"";(m!==d.length-1||a.value.showCurrentName)&&g!==o.value&&f.push({fileName:g,url:i.value.catalogues?.inv[h]?.url||""})}),f});return(f,d)=>l(a)?.enabled?(p(),w("div",{key:0,class:T(l(t).b()),role:"navigation","aria-label":l(n)("tk.articleBreadcrumb.label")},[H(l(wE),{separator:l(a).separator},{default:O(()=>[H(l(Xd),null,{default:O(()=>[S("a",{href:l(Ee)("/"),title:l(a).homeLabel,class:"home hover-color","aria-label":l(a).homeLabel},[H(l(de),{icon:l(X7),"aria-hidden":"true"},null,8,["icon"])],8,_E)]),_:1}),(p(!0),w(Y,null,le(u.value,(h,m)=>(p(),D(l(Xd),{key:m},{default:O(()=>[(p(),D(Be(h.url?"a":"span"),{href:h.url&&l(Ee)(`${h.url}`),title:h.fileName,class:T([h.url?"hover-color":""]),"aria-label":h.fileName},{default:O(()=>[rt(W(h.fileName),1)]),_:2},1032,["href","title","class","aria-label"]))]),_:2},1024))),128))]),_:1},8,["separator"])],10,CE)):A("v-if",!0)}});const SE=["aria-label"],TE={key:0,class:"flx-center"},EE=["title","aria-label"],xE={key:1,class:"flx-center"},AE=["title","aria-label"],$E={key:2,class:"flx-center"},LE=["title","aria-label"];var p2=z({name:"ArticleAnalyze",__name:"index",props:{breadcrumb:{type:Boolean,default:!0},scope:{default:"article"}},setup(e){const t=ie("article-analyze"),{t:n}=ge(),{getTeekConfig:s,getTeekConfigRef:o}=fe(),{theme:i,frontmatter:r}=Ae(),a=Is(),{router:c}=a,u=F(()=>({author:s("author",{}),date:r.value.date,frontmatter:r.value,url:"",relativePath:""})),f=F(()=>i.value.docAnalysisInfo||{}),d=F(()=>{let P={};return f.value.eachFileWords?.forEach(V=>{V.fileInfo.relativePath===c.route.data.filePath&&(P=V)}),P}),h=o("articleAnalyze",{showInfo:!0,showIcon:!0,teleport:{}}),m=F(()=>{const P=[h.value.showInfo].flat();return!!(P.includes(!0)||P.includes("article"))}),g=j(),v=()=>{const{selector:P,position:V="after",className:E="teleport"}=h.value.teleport||{},L=g.value;if(!P||!L)return;const N=document.querySelector("#VPContent")?.querySelector(P);N?.parentElement?.querySelectorAll(`.${t.e("wrapper")}`).forEach($=>$.remove()),L.classList.add(E),N?.[V]?.(L)};te(c.route,()=>ze(v),{immediate:!0,flush:"post"});const k=o("docAnalysis",{wordCount:!0,readingTime:!0,statistics:{}}),b=F(()=>({url:"",provider:"",pageView:!0,tryRequest:!1,tryCount:5,tryIterationTime:2e3,permalink:!0,...k.value.statistics})),C=F(()=>!!b.value.provider&&b.value.pageView),{pagePv:y,isGet:_,request:x}=Oh(!1,b.value);return te(C,P=>{P&&x()}),te(c.route,()=>{C.value&&(b.value.permalink&&c.state?.permalinkPlugin?ze(x):x())},{immediate:!0}),(P,V)=>(p(),w("div",{class:T(`${l(t).b()} flx-justify-between`),"aria-label":l(n)("tk.articleAnalyze.label")},[e.breadcrumb?(p(),D(l(h2),{key:0})):A("v-if",!0),m.value?(p(),w("div",{key:1,ref_key:"baseInfoRef",ref:g,class:T(`${l(t).e("wrapper")} flx-align-center`)},[H(l(Lu),{post:u.value,scope:e.scope},null,8,["post","scope"]),l(k).wordCount&&d.value.wordCount?(p(),w("div",TE,[l(h).showIcon?(p(),D(l(de),{key:0,icon:l(Ah),"aria-hidden":"true"},null,8,["icon"])):A("v-if",!0),S("a",{title:l(n)("tk.articleAnalyze.wordCount"),class:"hover-color","aria-label":l(n)("tk.articleAnalyze.wordCount")},W(d.value.wordCount),9,EE)])):A("v-if",!0),l(k).readingTime&&d.value.readingTime?(p(),w("div",xE,[l(h).showIcon?(p(),D(l(de),{key:0,icon:l(G7)},null,8,["icon"])):A("v-if",!0),S("a",{title:l(n)("tk.articleAnalyze.readingTime"),class:"hover-color","aria-label":l(n)("tk.articleAnalyze.readingTime")},W(d.value.readingTime),9,AE)])):A("v-if",!0),C.value?(p(),w("div",$E,[l(h).showIcon?(p(),D(l(de),{key:0,icon:l(J7)},null,8,["icon"])):A("v-if",!0),S("a",{title:l(n)("tk.articleAnalyze.pageView"),class:"hover-color","aria-label":l(n)("tk.articleAnalyze.pageView")},W(l(_)?l(y):"Get..."),9,LE)])):A("v-if",!0)],2)):A("v-if",!0)],10,SE))}});const IE=["aria-label"],PE={key:0,class:"flx-center"},ME={key:1,class:"flx-center"};var FE=z({name:"ArticleShare",__name:"index",setup(e){const t=ie("article-share"),{t:n}=ge(),{getTeekConfigRef:s}=fe(),o=s("articleShare",{icon:Kf,text:n("tk.articleShare.text"),copiedIcon:Yf,copiedText:n("tk.articleShare.copiedText"),query:!1,hash:!1}),i=F(()=>{const{hash:c,query:u}=o.value,{origin:f,pathname:d,search:h}=location;return`${f}${d}${u?h:""}${c?location.hash:""}`}),{copy:r,copied:a}=Dh(2e3);return(c,u)=>(p(),w("div",{class:T(l(t).b())},[S("button",{class:T([l(t).e("button"),{copied:l(a)},"flx-center"]),"aria-label":l(a)?l(o).copiedText:l(o).text,"aria-live":"polite",onClick:u[0]||(u[0]=f=>l(r)(i.value))},[l(a)?(p(),w("div",ME,[H(l(de),{icon:l(Yf),style:{"margin-right":"4px"}},null,8,["icon"]),rt(" "+W(l(o).copiedText),1)])):(p(),w("div",PE,[H(l(de),{icon:l(Kf),style:{"margin-right":"4px"}},null,8,["icon"]),rt(" "+W(l(o).text),1)]))],10,IE)],2))}});const BE=["href","aria-label"],NE={key:1},VE=["href","aria-label"];var OE=z({name:"ArticleUpdate",__name:"index",setup(e){const t=ie("article-update"),{t:n}=ge(),s=Pn(),o=kn(),{frontmatter:i}=Ae(),{getTeekConfigRef:r}=fe(),{archivesPath:a}=$i(),c=r("articleUpdate",{limit:3}),u=F(()=>{const f="/"+o.data.filePath.replace(".md","");return[...s.value.sortPostsByDate.filter(d=>![o.path,f,`${f}.html`].includes(d.url)).slice(0,c.value.limit),{title:"更多文章 >",url:a.value,frontmatter:{},date:""}]});return(f,d)=>et((p(),w("div",{class:T(l(t).b())},[S("div",{class:T([l(t).e("title"),"flx-align-center"])},[H(l(de),{icon:l(Lh),class:"edit-icon","aria-hidden":"true"},null,8,["icon"]),l(a)?(p(),w("a",{key:0,href:l(Ee)(l(a)),class:"hover-color","aria-label":l(n)("tk.articleUpdate.label")},W(l(n)("tk.articleUpdate.label")),9,BE)):(p(),w("span",NE,W(l(n)("tk.articleUpdate.label")),1))],2),S("ul",null,[(p(!0),w(Y,null,le(u.value,(h,m)=>(p(),w("li",{key:h.url,class:"flx-center"},[S("span",{class:T(l(t).m("num")),"aria-hidden":"true"},W(m!==u.value.length-1?(m+1).toString().padStart(2,"0"):""),3),S("div",{class:T(l(t).e("content"))},[h.url?(p(),w("a",{key:0,href:l(Ee)(h.url),class:"flx-1 hover-color sle","aria-label":h.title},[H(l(Mi),{post:h,"title-tag-props":{position:"right",size:"small"}},null,8,["post"])],8,VE)):A("v-if",!0),h.date?(p(),w("span",{key:1,class:T(l(t).em("content","date"))},W(h.date),3)):A("v-if",!0)],2)]))),128))])],2)),[[at,l(i).article!==!1]])}}),DE=z({__name:"index",setup(e){const t=ie("article-heading-highlight"),n=()=>{if(!me||!window.location.hash)return;const o=decodeURIComponent(window.location.hash);if(!o)return;let i;try{i=document.querySelector(o)}catch(r){return console.error(r)}i&&(i.classList.contains(t.b())||i.classList.add(t.b()),i.classList.remove(t.b()),setTimeout(()=>{i&&i.classList.add(t.b())},10))},s=kn();return te(s,async()=>{await ze(),n()}),Ve(()=>window,"hashchange",n),(o,i)=>null}}),RE=z({__name:"index",setup(e){const t=ie(),{getTeekConfigRef:n}=fe(),s=n(null,{vpHome:!0,pageStyle:"default"}),o=async()=>{if(!me)return;await ze();const i=document.querySelector(`.${t.join("layout")}`);["default","card","card-nav","segment","segment-nav"].forEach(r=>i?.classList.remove(t.join(r))),i?.classList.add(t.join(s.value.pageStyle))};return te(()=>s.value.pageStyle,o,{immediate:!0}),te(()=>s.value.vpHome,o),(i,r)=>null}});const HE=["aria-label"],zE=["innerHTML"],jE=["innerHTML"];var UE=z({name:"AsideBottomAppreciation",__name:"AsideBottomAppreciation",setup(e){const t=ie("article-appreciation"),{t:n}=ge(),{getTeekConfigRef:s}=fe(),o=s("appreciation",{position:""}),i=F(()=>o.value.options||{});return(r,a)=>(p(),w("div",{class:T([l(t).b(),l(t).m("aside-bottom")]),"aria-label":l(n)("tk.articleAppreciation.label")},[S("span",{innerHTML:i.value.title},null,8,zE),S("div",{class:T(l(t).e("content")),innerHTML:i.value.content},null,10,jE)],10,HE))}});const WE=["aria-label"],qE=["innerHTML","aria-expanded","aria-controls"],KE=["aria-expanded","aria-controls"],YE=["innerHTML"],GE=["innerHTML"],JE=["aria-label"],XE=["innerHTML"];var QE=z({name:"DocAfterAppreciation",__name:"DocAfterAppreciation",setup(e){const t=ie("article-appreciation"),{t:n}=ge(),{getTeekConfigRef:s}=fe(),o=s("appreciation",{position:""}),i=F(()=>o.value.options||{expand:!1}),r=j(i.value.expand),a=F(()=>{const{icon:u}=i.value;return u==="aliPay"?Eh:u==="weChatPay"?Ih:u}),c=()=>{r.value=!r.value};return te(()=>i.value.expand,u=>{r.value=u}),(u,f)=>(p(),w("div",{class:T([l(t).b(),l(t).m("doc-after")]),"aria-label":l(n)("tk.articleAppreciation.label")},[i.value.buttonHtml?(p(),w("div",{key:0,innerHTML:i.value.buttonHtml,role:"button","aria-expanded":r.value,"aria-controls":`${l(t).e("content")}`},null,8,qE)):i.value.expandTitle||i.value.collapseTitle?(p(),w("button",{key:1,class:T(l(t).e("button")),onClick:c,"aria-expanded":r.value,"aria-controls":`${l(t).e("content")}`,"aria-live":"polite"},[a.value?(p(),D(l(de),{key:0,class:T(l(t).e("button__icon")),icon:a.value,size:16,"aria-hidden":"true"},null,8,["class","icon"])):A("v-if",!0),r.value?(p(),w("span",{key:1,innerHTML:i.value.collapseTitle},null,8,YE)):(p(),w("span",{key:2,innerHTML:i.value.expandTitle},null,8,GE))],10,KE)):A("v-if",!0),H(vt,{name:l(t).join("fade")},{default:O(()=>[r.value?(p(),w("div",{key:0,class:T(l(t).e("content")),"aria-label":l(n)("tk.articleAppreciation.contentLabel")},[S("div",{class:T(l(t).e("content")),innerHTML:i.value.content},null,10,XE)],10,JE)):A("v-if",!0)]),_:1},8,["name"])],10,WE))}});const ZE=(e,t)=>{const n=j();return{focusStartRef:n,onFocusAfterTrapped:()=>{t("focus")},onFocusAfterReleased:c=>{c.detail?.focusReason!=="pointer"&&(n.value="first",t("blur"))},onFocusInTrap:c=>{e.value&&c.target&&(n.value=c.target)},onFocusoutPrevented:c=>{c.detail.focusReason==="pointer"&&c.preventDefault()},onReleaseRequested:()=>{t("close")}}};var Ia=z({name:"Popover",__name:"index",props:$n({trigger:{default:"hover"},placement:{default:"bottom"},content:{default:""},width:{},height:{},offset:{default:0},xOffset:{default:0},yOffset:{default:0},disabled:{type:Boolean,default:!1},transition:{type:Boolean,default:!0},transitionName:{},triggerEl:{},zIndex:{},popperClass:{},popperStyle:{},beforePopup:{type:Function}},{modelValue:{default:!1},modelModifiers:{}}),emits:$n(["focus","blur","close"],["update:modelValue"]),setup(e,{emit:t}){const n=ie("popover"),{nextZIndex:s}=nu(),o=j(e.zIndex??s()),i=Jt(e,"modelValue"),r=j(),a=j(),c=Pl(r),u=Pl(a),f=F(()=>e.triggerEl||r.value),{top:d,right:h,left:m,bottom:g,update:v}=N9(f,a,{placement:e.placement,offset:e.offset,xOffset:e.xOffset,yOffset:e.yOffset}),k=F(()=>({zIndex:o.value,top:sn(d.value),right:sn(h.value),bottom:sn(g.value),left:sn(m.value),width:sn(e.width),height:sn(e.height),...e.popperStyle})),b=()=>{if(!r.value||!a.value){i.value=!1;return}v();const N=e.beforePopup?.({top:d.value,right:h.value,bottom:m.value,left:g.value,triggerElement:e.triggerEl||r.value,popoverElement:a.value})??{};N.top&&(d.value=N.top),N.right&&(h.value=N.right),N.bottom&&(g.value=N.bottom),N.left&&(m.value=N.left)};e.trigger==="hover"&&te(c,N=>{e.trigger==="hover"&&(i.value=N)});const C=N=>{N===e.trigger&&(i.value=!i.value)};te(i,N=>{N&&b()}),te(u,N=>{e.trigger==="hover"&&(i.value=N)}),T9(a,N=>{N.composedPath().includes(r.value)||e.trigger!=="hover"&&i.value!==!1&&(i.value=!1)});const y=n.join("popover-container");fa(()=>{if(!document.querySelector(`#${y}`)){const $=document.createElement("div");$.id=y,document.body.appendChild($)}});const _=t,{focusStartRef:x,onFocusAfterTrapped:P,onFocusAfterReleased:V,onFocusInTrap:E,onFocusoutPrevented:L,onReleaseRequested:I}=ZE(i,_);return(N,$)=>(p(),w(Y,null,[S("div",nt({ref_key:"triggerRef",ref:r,onClick:$[0]||($[0]=U=>C("click")),onContextmenu:$[1]||($[1]=U=>C("contextmenu")),onFocus:$[2]||($[2]=U=>C("focus")),onTouchstart:$[3]||($[3]=U=>i.value=!i.value)},N.$attrs),[M(N.$slots,"reference")],16),(p(),D(la,{to:`#${l(y)}`},[H(vt,{name:e.transition?e.transitionName||l(n).join("fade-linear"):""},{default:O(()=>[e.disabled?A("v-if",!0):et((p(),w("div",{key:0,ref_key:"popoverRef",ref:a,style:Fe(k.value),class:T([l(n).b(),e.popperClass]),onClick:$[4]||($[4]=To(()=>{},["stop"])),onTouchstart:$[5]||($[5]=To(()=>{},["stop"]))},[H(l(f2),{loop:"",trapped:i.value,"focus-trap-el":a.value,"focus-start-el":l(x),onFocusAfterTrapped:l(P),onFocusAfterReleased:l(V),onFocusin:l(E),onFocusoutPrevented:l(L),onReleaseRequested:l(I)},{default:O(()=>[M(N.$slots,"default",{},()=>[rt(W(e.content),1)])]),_:3},8,["trapped","focus-trap-el","focus-start-el","onFocusAfterTrapped","onFocusAfterReleased","onFocusin","onFocusoutPrevented","onReleaseRequested"])],38)),[[at,i.value]])]),_:3},8,["name"])],8,["to"]))],64))}});const ex=["aria-label"],tx=["innerHTML","aria-expanded","aria-controls"],nx=["aria-expanded","aria-controls"],sx=["innerHTML"],ox=["aria-label"],ix=["innerHTML"];var rx=z({name:"DocAfterAppreciationPopper",__name:"DocAfterAppreciationPopper",setup(e){const t=ie("article-appreciation"),{t:n}=ge(),{getTeekConfigRef:s}=fe(),o=s("appreciation",{position:""}),i=j(!1),r=F(()=>({trigger:"click",...o.value.options})),a=F(()=>{const{icon:c}=r.value;return c==="aliPay"?Eh:c==="weChatPay"?Ih:c});return(c,u)=>(p(),w("div",{class:T(l(t).b()),"aria-label":l(n)("tk.articleAppreciation.label")},[H(l(Ia),{modelValue:i.value,"onUpdate:modelValue":u[0]||(u[0]=f=>i.value=f),trigger:r.value.trigger},{reference:O(()=>[r.value.buttonHtml?(p(),w("div",{key:0,innerHTML:r.value.buttonHtml,role:"button","aria-expanded":i.value,"aria-controls":`${l(t).e("content")}`},null,8,tx)):r.value.title?(p(),w("button",{key:1,class:T(l(t).e("button")),"aria-expanded":i.value,"aria-controls":`${l(t).e("content")}`,"aria-live":"polite"},[a.value?(p(),D(l(de),{key:0,class:T(l(t).e("button__icon")),icon:a.value,size:16,"aria-hidden":"true"},null,8,["class","icon"])):A("v-if",!0),r.value.title?(p(),w("span",{key:1,innerHTML:r.value.title},null,8,sx)):A("v-if",!0)],10,nx)):A("v-if",!0)]),default:O(()=>[S("div",{class:T([l(t).e("content"),l(t).m("doc-after-popper")]),"aria-label":l(n)("tk.articleAppreciation.contentLabel")},[S("div",{class:T(l(t).e("content")),innerHTML:r.value.content},null,10,ix)],10,ox)]),_:1},8,["modelValue","trigger"])],10,ex))}});const m2=Symbol("twikoo"),ax=["href","integrity"];var lx=z({name:"CommentTwikoo",__name:"index",setup(e){const t=ie(),n=Is(),{getTeekConfig:s}=fe(),o=s("comment",{}).options,{envId:i,jsLink:r="https://cdn.jsdelivr.net/npm/twikoo@{version}/dist/twikoo.nocss.js",jsIntegrity:a,cssLink:c="https://cdn.jsdelivr.net/npm/twikoo@{version}/dist/twikoo.css",version:u="1.6.44",katex:f,timeout:d=700,...h}=o,m=()=>{if(!me)return console.error("[Teek Error] Not in a client");if(!i)return console.error("[Teek Error] Twikoo initialization failed. Please configure the 'envId'");const C=qe(m2,()=>null),y={...h,envId:i};C?C("#twikoo",y):window.twikoo&&window.twikoo.init({...y,el:"#twikoo"})},g=j(null),v=()=>{const C=g.value;C&&(C.onload=m)},k=C=>{C&&setTimeout(m,d)},b=()=>{fetch(c.replace("{version}",u)).then(C=>{if(!C.ok)throw new Error("[Teek Error] Twikoo Css Link Network response was not ok");return C.text()}).then(C=>{if(document.getElementById("twikoo-css"))return;const y=document.createElement("style");y.type="text/css",y.id="twikoo-css",y.textContent=`.${t.b("twikoo")} {${C}}`,document.head.appendChild(y)})};return be(()=>{v(),b(),g.value&&n.bindAfterRouteChange(t.join("twikoo"),C=>k(C))}),(C,y)=>(p(),w("div",{class:T(l(t).b("twikoo"))},[A(" KaTeX "),l(f)?(p(),w(Y,{key:0},[S("link",{rel:"stylesheet",href:l(f).cssLink,integrity:l(f).cssIntegrity,crossorigin:"anonymous"},null,8,ax),(p(),D(Be("script"),{defer:"",src:l(f).coreJsLink,integrity:l(f).coreJsIntegrity,crossorigin:"anonymous"},null,8,["src","integrity"])),(p(),D(Be("script"),{defer:"",src:l(f).renderJsLink,integrity:l(f).renderJsIntegrity,crossorigin:"anonymous"},null,8,["src","integrity"]))],64)):A("v-if",!0),y[0]||(y[0]=S("div",{id:"twikoo"},null,-1)),(p(),D(Be("script"),{src:l(r).replace("{version}",l(u)),integrity:l(a),crossorigin:"anonymous",ref_key:"twikooJs",ref:g},null,8,["src","integrity"]))],2))}});const g2=Symbol("artalk"),cx=["href"],nl="artalk";var ux=z({name:"CommentArtalk",__name:"index",setup(e){const t=ie(),n=Is(),{getTeekConfig:s}=fe(),{isDark:o,page:i}=Ae(),r=s("comment",{}).options,{server:a,site:c,...u}=r,f=j(null),d=j(null),h=j(),m=()=>{const C=qe(g2,()=>null),y=f.value||`#${nl}`,_=C?.(y,r);return _?(h.value=_,b(),!0):!1},g=()=>{if(!me)return console.error("[Teek Error] Not in a client");const C=window.Artalk,y=f.value||`#${nl}`;if(!C||!f.value)return console.error("[Teek Error] Artalk initialization failed. Unable to load online js file from "+a);h.value=C.init({darkMode:o.value,...u,el:y,pageKey:n.route.path,pageTitle:i.value.title,server:a,site:c}),b()},v=()=>{const C=d.value;C&&(C.onload=g)},k=()=>{const C=h.value;C?.update({pageKey:n.route.path,pageTitle:i.value.title}),C?.reload()};be(()=>{if(!m()&&a)return v(),h.value&&n.bindAfterRouteChange(t.join("artalk"),()=>k());console.error("[Teek Error] Artalk initialization failed. Please configure the 'server' and 'site' or provide the artalk instance")}),cn(()=>{const C=h.value;C&&C.destroy()});const b=()=>{setTimeout(()=>{const C=h.value;C&&C.setDarkMode(o.value)},100)};return te(o,()=>b()),(C,y)=>(p(),w("div",{class:T(l(t).b("artalk"))},[l(a)?(p(),w("link",{key:0,rel:"stylesheet",href:`${l(a)}/dist/Artalk.css`,crossorigin:"anonymous"},null,8,cx)):A("v-if",!0),S("div",{id:nl,ref_key:"artalkRef",ref:f},null,512),l(a)?(p(),D(Be("script"),{key:1,src:`${l(a)}/dist/Artalk.js`,crossorigin:"anonymous",ref_key:"artalkJs",ref:d},null,8,["src"])):A("v-if",!0)],2))}});const v2=Symbol("giscus");var fx=z({name:"CommentGiscus",__name:"index",setup(e){const t=ie(),n=Is(),{getTeekConfig:s}=fe(),{isDark:o}=Ae(),i=s("comment",{}).options,{repo:r,repoId:a,category:c,categoryId:u,mapping:f="pathname",strict:d="0",reactionsEnabled:h="1",emitMetadata:m="0",inputPosition:g="top",lang:v="zh-CN",theme:k,loading:b="eager",useOnline:C=!0,link:y="https://giscus.app/client.js",integrity:_,...x}=i,P=F(()=>ht(k)?k(o.value):k||(o.value?"dark":"light")),E=qe(v2,()=>null)?.(i),L=j(!1),I=()=>{L.value=!1,ze(()=>{L.value=!0})};return be(()=>{if(!C&&!E)return console.error("[Teek Error] Giscus initialization failed. Please configure the 'useOnline' to 'true' or provide the giscus component");I(),n.bindAfterRouteChange(t.join("giscus"),()=>{I()})}),(N,$)=>L.value?(p(),w("div",{key:0,class:T(l(t).b("giscus"))},[l(E)?(p(),D(Be(l(E)),nt({key:0,repo:l(r),"repo-id":l(a),category:l(c),"category-id":l(u),mapping:l(f),"reactions-enabled":l(h),"emit-metadata":l(m),"input-position":l(g),lang:l(v),theme:P.value,loading:l(b)},x),null,16,["repo","repo-id","category","category-id","mapping","reactions-enabled","emit-metadata","input-position","lang","theme","loading"])):l(C)?(p(),D(Be("script"),nt({key:1,defer:"",src:l(y),integrity:l(_),"data-repo":l(r),"data-repo-id":l(a),"data-category":l(c),"data-category-id":l(u),"data-mapping":l(f),"data-strict":l(d),"data-reactions-enabled":l(h),"data-emit-metadata":l(m),"data-input-position":l(g),"data-theme":P.value,"data-lang":l(v)},x,{crossorigin:"anonymous"}),null,16,["src","integrity","data-repo","data-repo-id","data-category","data-category-id","data-mapping","data-strict","data-reactions-enabled","data-emit-metadata","data-input-position","data-theme","data-lang"])):A("v-if",!0)],2)):A("v-if",!0)}});const y2=Symbol("waline"),dx=["href","integrity"],sl="waline";var hx=z({name:"CommentWaline",__name:"index",setup(e){const t=ie(),n=Is(),{getTeekConfig:s}=fe(),o=s("comment",{}).options,{serverURL:i,jsLink:r,cssLink:a,dark:c="html[class='dark']",cssIntegrity:u,...f}=o;let d=null;const h=()=>{const v=qe(y2,()=>null);return v&&(d=v?.(`#${sl}`,o)),d},m=async()=>{if(!r)return;const{init:v}=await import(r);d=v({dark:c,...f,serverURL:i,el:`#${sl}`})},g=()=>{if(!me)return;const v=document.querySelector(".wl-login-nick");v&&v.removeAttribute("href")};return be(async()=>{if(!h()&&i&&r)return await m(),g(),n.bindAfterRouteChange(t.join("waline"),()=>d?.update());console.error("[Teek Error] Waline initialization failed. Please configure the 'jsLink' and 'serverURL' or provide the waline instance")}),(v,k)=>(p(),w("div",{class:T(l(t).b("waline"))},[l(a)?(p(),w("link",{key:0,rel:"stylesheet",href:l(a),integrity:l(u),crossorigin:"anonymous"},null,8,dx)):A("v-if",!0),S("div",{id:sl})],2))}}),px=z({__name:"Overlay",emits:["click"],setup(e,{emit:t}){const n=t,s=()=>n("click");return(o,i)=>(p(),w("div",{class:"code-block-overlay",onClick:s},[i[0]||(i[0]=S("span",null,"查看更多",-1)),H(l(de),{class:"overlay-icon",icon:l(xh)},null,8,["icon"])]))}});const mx=e=>{const t=document.createDocumentFragment();return Fr(px,{onClick:e}).mount(t).$el},Qd="code-block",Zd="fold",e1="code-arrow";var gx=z({name:"CodeBlockToggle",__name:"index",setup(e){const t=ie(),{getTeekConfigRef:n}=fe(),s=n("codeBlock",{enabled:!0,collapseHeight:700,copiedDone:void 0,overlay:!1,overlayHeight:400,langTextTransform:""});te(s,a=>{if(!me)return;const{enabled:c=!0,langTextTransform:u}=a||{};if(!c)return document.documentElement.removeAttribute(Qd);document.documentElement.setAttribute(Qd,t.namespace),u&&document.documentElement.style.setProperty(t.cssVarName("code-block-lang-transform"),u),ze(()=>o())},{immediate:!0});const o=()=>{const a=document.querySelectorAll(".vp-doc div[class*='language-']");Array.from(a).forEach(c=>{c.querySelector(".copy")?.addEventListener("click",()=>{s.value.copiedDone?.(Ct)});const f=c.parentElement?.className;if(f?.includes("details")||f?.includes(t.join("vp-code"))||c.querySelector(`.${e1}`))return;const h=document.createElement("div");if(h.setAttribute("aria-hidden","true"),h.classList.add(e1),h.innerHTML=xh,s.value.overlay){const m=mx(()=>h.click());c.appendChild(m)}i(h,c),c.append(h)})},i=(a,c)=>{const u=r(c);c.style.height=sn(u);const f=c.querySelector("pre"),d=c.querySelector(".line-numbers-wrapper"),h=c.querySelector(".code-block-overlay"),m={expand:{height:sn(u),display:"block",overlayDisplay:"none",speed:80},fold:{height:s.value.overlay?sn(s.value.overlayHeight)??"400px":t.cssVar("code-block-fold-height"),display:s.value.overlay?"block":"none",overlayDisplay:"flex",speed:400}};let g;const v=()=>{g&&(clearTimeout(g),g=null)},k=()=>{const C=a.classList.contains(Zd),y=m[C?"expand":"fold"];c.style.height=y.height,v(),(f||d)&&(g=setTimeout(()=>{f&&(f.style.display=y.display),d&&(d.style.display=y.display),h&&(h.style.display=y.overlayDisplay),v()},y.speed)),a.classList.toggle(Zd)};Ve(a,"click",k);const b=s.value.collapseHeight;Zn(b)?b?k():h&&(h.style.display="none"):b&&u>b?k():h&&(h.style.display="none")},r=a=>{const c=a.parentElement?.className||"";if(!c.includes("blocks")||c.includes("blocks")&&a.className.includes("active"))return a.offsetHeight;a.style.display="block";const u=a.offsetHeight;return a.style.display="",u};return(a,c)=>null}}),En=(e=>(e.FullWidth="fullWidth",e.SidebarWidthAdjustableOnly="sidebarWidthAdjustableOnly",e.BothWidthAdjustable="bothWidthAdjustable",e.Original="original",e))(En||{}),Us=(e=>(e.Under="under",e.Aside="aside",e))(Us||{}),Sn=(e=>(e.vpDefault="vp-default",e.vpGreen="vp-green",e.vpYellow="vp-yellow",e.vpRed="vp-red",e.epBlue="ep-blue",e.epGreen="ep-green",e.epYellow="ep-yellow",e.epRed="ep-red",e))(Sn||{});const Yr=["vp-default","vp-green","vp-yellow","vp-red","ep-blue","ep-green","ep-yellow","ep-red"],Vo="(max-width: 768px)",b2="(min-width: 1440px)",k2="(pointer: coarse)",Gr="layout-mode",Jr="theme-color",gn=ie("right-bottom-button"),vx=["title","aria-label","aria-valuenow"],yx={key:0,class:"content"};var bx=z({name:"BackTop",__name:"BackTop",setup(e){const{t}=ge(),{getTeekConfigRef:n}=fe(),s=n("backTop",{enabled:!0,content:"progress"}),o=j(0),i=F(()=>o.value>100),r=j(0),a=es(()=>{me&&(document.querySelector("html")?.scrollIntoView({behavior:"smooth"}),setTimeout(()=>{s.value.done?.(Ct)},600))},500,!0),c=()=>{o.value=document.documentElement.scrollTop||document.body.scrollTop||0,u()},u=()=>{const f=window.scrollY/(document.documentElement.scrollHeight-window.innerHeight);r.value=Math.round(f*100)};return be(()=>{u()}),Ve(()=>window,"scroll",c),(f,d)=>(p(),D(vt,{name:l(gn).join("fade")},{default:O(()=>[M(f.$slots,"default",{show:i.value,progress:r.value,icon:l(Uf),scrollToTop:l(a)},()=>[et(S("div",{title:l(t)("tk.rightBottomButton.backTopTitle"),class:T([l(gn).e("button"),"back-top"]),onClick:d[0]||(d[0]=(...h)=>l(a)&&l(a)(...h)),style:Fe({[l(gn).cssVarName("progress")]:r.value}),role:"button","aria-label":l(t)("tk.rightBottomButton.backTopTitle"),"aria-valuenow":r.value,"aria-valuemin":"0","aria-valuemax":"100"},[l(s).content==="progress"?(p(),w("span",yx,W(r.value),1)):l(s).content==="icon"?(p(),D(l(de),{key:1,icon:l(Uf),"aria-hidden":"true"},null,8,["icon"])):A("v-if",!0)],14,vx),[[at,i.value]])])]),_:3},8,["name"]))}});const kx=["title","aria-label"];var wx=z({name:"ToComment",__name:"ToComment",setup(e){const{t}=ge(),{getTeekConfigRef:n}=fe(),s=n("toComment",{}),o=j(0),i=F(()=>{if(!me)return!1;const c=document.querySelector(".content-container .main")?.getBoundingClientRect().height,u=document.querySelector(".VPDocFooter")?.getBoundingClientRect().height||200;let f=0;return c&&(f=c-u-window.innerHeight/2),o.value{me&&(document.querySelector(`#${gn.join("comment")}`)?.scrollIntoView({behavior:"smooth"}),setTimeout(()=>{s.value.done?.(Ct)},600))},500,!0);return Ve(()=>window,"scroll",()=>{o.value=document.documentElement.scrollTop||document.body.scrollTop||0}),(c,u)=>(p(),D(vt,{name:l(gn).join("fade")},{default:O(()=>[M(c.$slots,"default",{show:i.value,icon:l(qf),scrollToComment:l(r)},()=>[et(S("div",{title:l(t)("tk.rightBottomButton.toComment"),class:T(l(gn).e("button")),onClick:u[0]||(u[0]=(...f)=>l(r)&&l(r)(...f)),role:"button","aria-label":l(t)("tk.rightBottomButton.toComment")},[H(l(de),{icon:l(qf),"aria-hidden":"true"},null,8,["icon"])],10,kx),[[at,i.value]])])]),_:3},8,["name"]))}});const Re=ie("theme-enhance"),Fu=Re.join("theme-enhance-slide"),Cx=Re.cssVarName("page-max-width"),_x=Re.cssVarName("doc-max-width"),Bu=Re.storageKey("layoutMode"),Sx=Re.storageKey("pageMaxWidthSlide"),Tx=Re.storageKey("docMaxWidthSlide"),w2=Re.storageKey("themeColor"),Ex=Re.storageKey("themeBgColor"),C2=Re.storageKey("spotlight"),_2=Re.storageKey("spotlightStyle"),S2=()=>{if(!me)return;const{getTeekConfigRef:e}=fe(),t=e("themeEnhance",{}),{t:n}=ge();return F(()=>{const{customize:s=!1,append:o=[]}=t.value.themeColor||{},i=Zn(s)?s===!1:s?.vitepressTheme??!0,r=Zn(s)?s===!1:s?.elementPlusTheme??!0,a=i?[{label:n("tk.themeEnhance.themeColor.vpLabel"),tip:n("tk.themeEnhance.themeColor.vpTip"),options:[{value:Sn.vpDefault,label:n("tk.themeEnhance.themeColor.defaultLabel"),title:`VitePress ${n("tk.themeEnhance.themeColor.defaultLabel")}`,ariaLabel:`VitePress ${n("tk.themeEnhance.themeColor.defaultLabel")}`,color:getComputedStyle(document.documentElement).getPropertyValue("--vp-c-indigo-1")},{value:Sn.vpGreen,label:n("tk.themeEnhance.themeColor.greenLabel"),title:`VitePress ${n("tk.themeEnhance.themeColor.greenLabel")}`,ariaLabel:`VitePress ${n("tk.themeEnhance.themeColor.greenLabel")}`,color:getComputedStyle(document.documentElement).getPropertyValue("--vp-c-green-1")},{value:Sn.vpYellow,label:n("tk.themeEnhance.themeColor.yellowLabel"),title:`VitePress ${n("tk.themeEnhance.themeColor.yellowLabel")}`,ariaLabel:`VitePress ${n("tk.themeEnhance.themeColor.yellowLabel")}`,color:getComputedStyle(document.documentElement).getPropertyValue("--vp-c-yellow-1")},{value:Sn.vpRed,label:n("tk.themeEnhance.themeColor.redLabel"),title:`VitePress ${n("tk.themeEnhance.themeColor.redLabel")}`,ariaLabel:`VitePress ${n("tk.themeEnhance.themeColor.redLabel")}`,color:getComputedStyle(document.documentElement).getPropertyValue("--vp-c-red-1")}]}]:[],c=r?[{label:n("tk.themeEnhance.themeColor.epLabel"),tip:n("tk.themeEnhance.themeColor.epTip"),options:[{value:Sn.epBlue,label:`${n("tk.themeEnhance.themeColor.blueLabel")}`,title:`ElementPlus ${n("tk.themeEnhance.themeColor.blueLabel")}`,ariaLabel:`ElementPlus ${n("tk.themeEnhance.themeColor.blueLabel")}`,color:getComputedStyle(document.documentElement).getPropertyValue("--tk-el-color-primary")},{value:Sn.epGreen,label:`${n("tk.themeEnhance.themeColor.greenLabel")}`,title:`ElementPlus ${n("tk.themeEnhance.themeColor.greenLabel")}`,ariaLabel:`ElementPlus ${n("tk.themeEnhance.themeColor.greenLabel")}`,color:getComputedStyle(document.documentElement).getPropertyValue("--tk-el-color-success")},{value:Sn.epYellow,label:`${n("tk.themeEnhance.themeColor.yellowLabel")}`,title:`ElementPlus ${n("tk.themeEnhance.themeColor.yellowLabel")}`,ariaLabel:`ElementPlus ${n("tk.themeEnhance.themeColor.yellowLabel")}`,color:getComputedStyle(document.documentElement).getPropertyValue("--tk-el-color-warning")},{value:Sn.epRed,label:`${n("tk.themeEnhance.themeColor.redLabel")}`,title:`ElementPlus ${n("tk.themeEnhance.themeColor.redLabel")}`,ariaLabel:`ElementPlus ${n("tk.themeEnhance.themeColor.redLabel")}`,color:getComputedStyle(document.documentElement).getPropertyValue("--tk-el-color-danger")}]}]:[];return[...a,...c,...o]})},xx=["title","aria-label"],Ax=["onClick","title","aria-label"];var $x=z({name:"ThemeColor",__name:"ThemeColor",setup(e){const{t}=ge(),{frontmatter:n}=Ae(),{getTeekConfigRef:s}=fe(),o=s("themeEnhance",{}),i=bn(w2,o.value.themeColor?.defaultColorName||Sn.vpDefault),r=j(i.value),a=j(""),{clear:c}=jh(a,()=>{if(Yr.includes(i.value))return[on.vpBrand1,on.vpBrand2,on.vpBrand3,on.vpBrandSoft]}),u=S2(),f=h=>{if(!me)return;const m=document.documentElement;if(i.value=h,m.getAttribute(Jr)!==h){if(m.setAttribute(Jr,h),Yr.includes(h))c(),a.value=getComputedStyle(m).getPropertyValue(on.vpBrand1);else{const k=(o.value.themeColor?.append||[]).map(b=>b.options).flat().filter(b=>b.value===h)[0]?.color;!k&&c(),a.value=k||getComputedStyle(m).getPropertyValue(on.vpBrand1)}o.value.themeColor?.switchColorDone?.(h)}};te(i,f,{immediate:!0}),te(()=>n.value.themeColorName,h=>{h?(r.value=i.value,i.value=h):i.value=r.value},{immediate:!0}),be(()=>{n.value.themeColor?f(n.value.themeColor):f(i.value)});const d=h=>{i.value=h.value};return(h,m)=>(p(),D(l(Ia),{class:T(l(gn).e("button")),"popper-class":l(gn).e("dropdown"),placement:"left-start",width:120,"x-offset":15,"transition-name":l(gn).join("fade-scale"),title:l(t)("tk.themeEnhance.themeColor.title"),role:"button","aria-label":l(t)("tk.themeEnhance.themeColor.title")},{reference:O(()=>[H(l(de),{icon:l(Q7),"aria-hidden":"true"},null,8,["icon"])]),default:O(()=>[(p(!0),w(Y,null,le(l(u),g=>(p(),w("ul",{key:g.label},[S("li",{class:T(`${l(gn).e("dropdown__title")} sle`),title:g.tip,"aria-label":g.label},W(g.label),11,xx),S("li",null,[S("ul",null,[(p(!0),w(Y,null,le(g.options,v=>(p(),w("li",{key:g.label+v.value,class:T(["dropdown-item","sle",{active:v.value===l(i)}]),onClick:k=>d(v),role:"button",title:v.title,"aria-label":v.ariaLabel??v.title??v.label},W(v.label),11,Ax))),128))])])]))),128))]),_:1},8,["class","popper-class","transition-name","title","aria-label"]))}}),Lx=z({name:"RightBottomButton",__name:"index",setup(e){const{getTeekConfigRef:t}=fe(),n=t("backTop",{enabled:!0}),s=t("toComment",{enabled:!0}),o=t("themeEnhance",{enabled:!0}),i=t(null,{comment:{provider:""}}),{frontmatter:r}=Ae(),a=F(()=>{const f=r.value.comment??i.value.comment;if(Zn(f))return{enabled:f};const d=qe(g2,null),h=qe(v2,null),m=qe(m2,null),g=qe(y2,null);return d||h||m||g?{enabled:!0}:{enabled:!0,provider:f.provider}}),c=Xt(Vo),u=F(()=>{const{enabled:f=!0,themeColor:d={},position:h="top"}=o.value,m=d.disabled??d.disabledInMobile;return f?m!==void 0?m:!c.value&&h==="top":!0});return(f,d)=>(p(),w("div",{class:T([l(gn).b(),l(gn).join("wallpaper-outside"),"flx-column"])},[M(f.$slots,"teek-right-bottom-before"),l(n).enabled?(p(),D(bx,{key:0},{default:O(h=>[M(f.$slots,"teek-back-top",Ge(Ze(h)))]),_:3})):A("v-if",!0),l(s).enabled&&(a.value.enabled||a.value.provider)?(p(),D(wx,{key:1},{default:O(h=>[M(f.$slots,"teek-to-comment",Ge(Ze(h)))]),_:3})):A("v-if",!0),u.value?A("v-if",!0):(p(),D($x,{key:2})),M(f.$slots,"teek-right-bottom-after")],2))}});const Ix=["aria-label"],Px=["aria-label"],Mx=["aria-label"],Fx={class:"flx-align-center"},Bx={id:"notice-title",class:"title sle"},Nx=["aria-label"];var Vx=z({name:"Notice",__name:"index",setup(e){const t=ie("notice"),{t:n}=ge(),{getTeekConfigRef:s}=fe(),o=Is(),{localeIndex:i}=Ae(),r=s("notice",{noticeStyle:void 0,iconStyle:{},popoverStyle:{},title:n("tk.notice.title"),initOpen:!0,duration:0,mobileMinify:!1,reopen:!0,useStorage:!0,twinkle:!1,position:"top",noticeIcon:q7,closeIcon:Jc,onAfterRouteChange:void 0}),a=j(!1),c=F(()=>!u.value&&!a.value),u=j(r.value.initOpen);te(()=>r.value.initOpen,_=>u.value=_);const f=F(()=>{const{noticeStyle:_}=r.value;return _?_.trim().startsWith(`.${t.b()}`)?_:`.${t.b()} { ${_} }`:""}),d=F(()=>{const{title:_}=r.value;return Je(_)?_:_(i.value)}),{isMobile:h}=Jh();te(()=>r.value.mobileMinify,_=>{h.value&&(a.value=_)},{immediate:!0});let m;const g=()=>{const{duration:_}=r.value;u.value&&_>0&&(m&&(clearTimeout(m),m=null),m=setTimeout(C,_))};be(()=>{o.bindAfterRouteChange(t.join("notice"),()=>r.value.onAfterRouteChange?.(o.route,c.value,u.value)),g()});const v=_=>{if(!me||r.value.position!=="center")return;const x={open:"remove",disable:"add"};document.documentElement.classList[x[_]]("disable-scroll")},k=F(()=>t.storageKey("notice",i.value,me?window.location.hostname:""));r.value.useStorage&&te(i,()=>{if(!r.value.useStorage)return;const _=localStorage.getItem(k.value);if(_){const x=_==="true";u.value=x,x&&v("disable")}},{immediate:!0});const b=()=>{u.value=!0,y("true"),g(),v("disable")},C=()=>{u.value=!1,y("false"),r.value.reopen||(a.value=!0),m&&clearTimeout(m),v("open")},y=_=>{r.value.useStorage&&localStorage.setItem(k.value,_)};return(_,x)=>(p(),w("div",{class:T([l(t).b(),l(t).join("wallpaper-outside")]),"aria-label":l(n)("tk.notice.label")},[f.value?(p(),D(Be("style"),{key:0},{default:O(()=>[rt(W(f.value),1)]),_:1})):A("v-if",!0),A(" 公告图标 "),a.value?A("v-if",!0):et((p(),w("div",{key:1,class:T([l(t).e("icon"),{twinkle:l(r).twinkle},"flx"]),style:Fe(l(r).iconStyle),onClick:b,role:"button","aria-label":l(n)("tk.notice.openLabel")},[H(l(de),{icon:l(r).noticeIcon,color:"#ffffff",size:"14px","aria-hidden":"true"},null,8,["icon"])],14,Px)),[[at,c.value]]),A(" 公告弹窗 "),et(S("div",{class:T([l(t).e("popover"),l(t).is(l(r).position)]),style:Fe(l(r).popoverStyle),role:"dialog","aria-modal":!0,"aria-labelledby":"notice-title"},[M(_.$slots,"header",{},()=>[S("div",{class:T([l(t).e("popover__header"),"flx-justify-between"]),"aria-label":l(n)("tk.notice.headLabel")},[S("div",Fx,[H(l(de),{icon:l(r).noticeIcon,color:"#ffffff",size:"20px","aria-hidden":"true"},null,8,["icon"]),S("span",Bx,W(d.value),1)]),H(l(de),{icon:l(r).closeIcon,color:"#ffffff",size:"20px",class:T(l(t).join("pointer")),onClick:C,role:"button","aria-label":l(n)("tk.notice.closeLabel")},null,8,["icon","class","aria-label"])],10,Mx)]),S("div",{class:T(l(t).e("popover__content")),"aria-label":l(n)("tk.notice.contentLabel")},[M(_.$slots,"teek-notice-content")],10,Nx)],6),[[at,u.value]]),A(" 遮罩层,与公告弹窗一起出现 "),et(S("div",{class:T(l(t).e("mask")),role:"presentation"},null,2),[[at,u.value&&l(r).position==="center"]])],10,Ix))}});const Ox=["title","disabled"],Dx=["value","name","disabled","checked","aria-checked"],Rx={key:1};var Hx=z({name:"SegmentedItem",__name:"SegmentedItem",props:$n({disabled:{type:Boolean},value:{type:[String,Number,Object,Boolean]},label:{},icon:{},title:{},name:{}},{modelValue:{type:[String,Number,Object,Boolean]},modelModifiers:{}}),emits:["update:modelValue"],setup(e){const t=ie("segmented-item"),n=Jt(e,"modelValue");return(s,o)=>(p(),w("label",{class:T([l(t).b(),l(t).is("active",n.value===e.value&&!e.disabled),l(t).is("disabled",e.disabled)]),title:e.title,disabled:e.disabled},[et(S("input",{"onUpdate:modelValue":o[0]||(o[0]=i=>n.value=i),type:"radio",value:e.value,name:e.name,disabled:e.disabled,checked:n.value===e.value,"aria-checked":n.value===e.value,role:"radio",style:{display:"none"}},null,8,Dx),[[ga,n.value]]),S("span",{class:T(l(t).e("content"))},[e.icon?(p(),D(l(de),{key:0,icon:e.icon,"aria-hidden":"true"},null,8,["icon"])):A("v-if",!0),e.label?(p(),w("span",Rx,W(e.label),1)):A("v-if",!0)],2)],10,Ox))}}),Nu=z({name:"Segmented",__name:"Segmented",props:$n({options:{},disabled:{type:Boolean}},{modelValue:{type:[String,Number,Object,Boolean]},modelModifiers:{}}),emits:["update:modelValue"],setup(e){const t=ie("segmented"),n=Jt(e,"modelValue");return(s,o)=>(p(),w("fieldset",{class:T(l(t).b())},[(p(!0),w(Y,null,le(e.options,i=>(p(),D(Hx,nt({key:i.name,modelValue:n.value,"onUpdate:modelValue":o[0]||(o[0]=r=>n.value=r)},{ref_for:!0},i,{disabled:e.disabled}),null,16,["modelValue","disabled"]))),128))],2))}});const Vu=(e=1e3,t=!1)=>{let n=null;const s=()=>{n&&(clearTimeout(n),n=null)},o=()=>{if(me){if(!t){t=!0;return}s(),document.documentElement.setAttribute(`${Gr}-animated`,"true"),n=setTimeout(()=>{document.documentElement.removeAttribute(`${Gr}-animated`)},Se(e))}};return jn(s),{start:o,stop:s}},zx={key:0};var jx=z({__name:"Title",props:{title:{},disabled:{type:Boolean},icon:{}},setup(e){return(t,n)=>(p(),w("div",{class:T([l(Re).e("title"),l(Re).is("disabled",!!e.disabled)])},[M(t.$slots,"icon",{},()=>[e.icon?(p(),D(l(de),{key:0,icon:e.icon,size:16},null,8,["icon"])):A("v-if",!0)]),M(t.$slots,"default",{},()=>[e.title?(p(),w("span",zx,W(e.title),1)):A("v-if",!0)])],2))}}),Ux=z({name:"Helper",__name:"Helper",props:$n({triggerEl:{}},{modelValue:{default:!1},modelModifiers:{}}),emits:["update:modelValue"],setup(e){const t=Jt(e,"modelValue"),n=j(t.value);return te(n,s=>{t.value=s}),(s,o)=>(p(),D(l(Ia),{class:T(l(Re).e("helper")),modelValue:n.value,"onUpdate:modelValue":o[0]||(o[0]=i=>n.value=i),"trigger-el":e.triggerEl,placement:"left-start"},{reference:O(()=>[H(l(de),{icon:l(m9),size:16},null,8,["icon"])]),default:O(()=>[S("div",{class:T(l(Re).e("helper__popup"))},[M(s.$slots,"default")],2)]),_:3},8,["class","modelValue","trigger-el"]))}}),Wx=z({name:"BorderHighlight",__name:"BorderHighlight",props:{active:{type:Boolean}},setup(e){const t=ie("border-highlight");return(n,s)=>(p(),w("div",{class:T([l(t).b(),l(t).is("active",!!e.active)])},[M(n.$slots,"default")],2))}});const qx={class:"flx-align-center",style:{"margin-bottom":"6px"}},Kx={key:1,style:{"font-weight":"600"}},Yx={key:0},Gx={key:1,style:{"margin-top":"8px"}};var Oo=z({name:"BaseTemplate",__name:"BaseTemplate",props:{title:{},helperDesc:{},icon:{},tips:{},disabled:{type:Boolean},helper:{type:Boolean},borderHighlight:{type:Boolean,default:!0}},setup(e){const t=j(!1),n=j();return(s,o)=>(p(),w("div",null,[S("div",{ref_key:"titleElementRef",ref:n,class:"flx-align-center"},[H(jx,{title:e.title,icon:e.icon,disabled:e.disabled,"aria-label":e.title},{default:O(()=>[M(s.$slots,"title")]),_:3},8,["title","icon","disabled","aria-label"]),e.helper?(p(),D(Ux,{key:0,modelValue:t.value,"onUpdate:modelValue":o[0]||(o[0]=i=>t.value=i),"trigger-el":n.value},{default:O(()=>[S("div",{class:T(l(Re).e("helper__body"))},[S("h4",{class:T(l(Re).em("helper","title"))},[M(s.$slots,"helper-title",{},()=>[rt(W(e.title),1)])],2),S("p",{class:T(l(Re).em("helper","desc"))},[M(s.$slots,"helper-desc",{},()=>[rt(W(e.helperDesc),1)])],2),(p(!0),w(Y,null,le(e.tips,(i,r)=>(p(),w("div",{key:r,class:T(l(Re).e("helper__body__tip"))},[S("div",qx,[i.icon?(p(),D(l(de),{key:0,icon:i.icon,size:16,style:{"margin-right":"4px"}},null,8,["icon"])):A("v-if",!0),i.title?(p(),w("span",Kx,W(i.title),1)):A("v-if",!0)]),i.content?(p(),w("span",Yx,W(i.content),1)):A("v-if",!0)],2))),128))],2)]),_:3},8,["modelValue","trigger-el"])):A("v-if",!0)],512),e.borderHighlight?(p(),D(Wx,{key:0,active:t.value,style:{"margin-top":"8px"}},{default:O(()=>[M(s.$slots,"default")]),_:3},8,["active"])):(p(),w("div",Gx,[M(s.$slots,"default")]))]))}}),Jx=z({name:"LayoutSwitch",__name:"LayoutSwitch",setup(e){const{getTeekConfigRef:t}=fe(),n=t("themeEnhance",{}),{t:s}=ge(),{frontmatter:o}=Ae(),i=bn(Bu,n.value.layoutSwitch?.defaultMode||En.Original),r=Xt(Vo),a=j(i.value),{start:c}=Vu();te(i,m=>{if(!me)return;const{layoutSwitch:g}=n.value;g?.disableAnimation||c();const v=document.documentElement;v.getAttribute(Gr)!==m&&(v.setAttribute(Gr,m),n.value.layoutSwitch?.switchModeDone?.(m))},{immediate:!0}),te(()=>o.value.layoutMode,m=>{m?(a.value=i.value,i.value=m):i.value=a.value},{immediate:!0}),te(()=>n.value.layoutSwitch?.defaultMode,m=>{m&&(i.value=m)});const f=F(()=>[{value:En.FullWidth,title:s("tk.themeEnhance.layoutSwitch.fullWidthTipTitle"),tipContent:s("tk.themeEnhance.layoutSwitch.fullWidthHelpTipContent"),icon:y9},{value:En.SidebarWidthAdjustableOnly,title:s("tk.themeEnhance.layoutSwitch.sidebarWidthAdjustableOnlyTipTitle"),tipContent:s("tk.themeEnhance.layoutSwitch.sidebarWidthAdjustableOnlyHelpTipContent"),icon:b9},{value:En.BothWidthAdjustable,title:s("tk.themeEnhance.layoutSwitch.bothWidthAdjustableTipTitle"),tipContent:s("tk.themeEnhance.layoutSwitch.bothWidthAdjustableHelpTipContent"),icon:Ph},{value:En.Original,title:s("tk.themeEnhance.layoutSwitch.originalWidthTipTitle"),tipContent:s("tk.themeEnhance.layoutSwitch.originalWidthHelpTipContent"),icon:w9}]),d=F(()=>f.value.map(m=>({value:m.value,title:m.title,ariaLabel:m.title,icon:m.icon}))),h=F(()=>f.value.map(m=>({title:m.title,icon:m.icon,content:m.tipContent})));return(m,g)=>(p(),D(Oo,{icon:l(k9),title:l(s)("tk.themeEnhance.layoutSwitch.title"),helper:!l(n).layoutSwitch?.disableHelp,"helper-desc":l(s)("tk.themeEnhance.layoutSwitch.helpDesc"),tips:h.value,disabled:l(r)},{default:O(()=>[H(l(Nu),{modelValue:l(i),"onUpdate:modelValue":g[0]||(g[0]=v=>Ye(i)?i.value=v:null),options:d.value,disabled:l(r)},null,8,["modelValue","options","disabled"])]),_:1},8,["icon","title","helper","helper-desc","tips","disabled"]))}});const Xx=["name","min","max","disabled","step"];var T2=z({name:"InputSlide",__name:"index",props:$n({name:{default:"Slider"},disabled:{type:Boolean},min:{default:0},max:{default:100},step:{default:1},format:{type:Function}},{modelValue:{default:0},modelModifiers:{}}),emits:["update:modelValue"],setup(e){const t=ie("input-slide"),n=Jt(e,"modelValue"),s=j(),o=j(),i=Pl(s),r=j(!1),a=t.cssVarName("slider-value"),c=t.cssVarName("slider-min"),u=t.cssVarName("slider-max");Ve(s,"input",()=>{s.value&&s.value.style.setProperty(a,s.value.value.toString())}),be(()=>{if(!s.value)return;const d=s.value.style;d.setProperty(a,n.value.toString()),d.setProperty(c,e.min?.toString()??"0"),d.setProperty(u,e.max?.toString()??"100")});const f=(d,h)=>{const m=e.max||100,g=e.min||0,v=(n.value-g)/(m-g),k=d.getBoundingClientRect(),C=(h.getBoundingClientRect().width-32)/2;h.style.setProperty("left",`${v*(k.width-32)-C}px`)};return te(i,()=>{r.value=!0,setTimeout(()=>{if(!i.value){r.value=!1;return}if(!s.value){r.value=!1;return}if(!o.value){r.value=!1;return}f(s.value,o.value),r.value=!1},50)}),te(n,d=>{de.max&&(d=e.max),!(!s.value||!o.value)&&f(s.value,o.value)}),te(()=>e.min,d=>{n.value>=d||(n.value=d)}),te(()=>e.max,d=>{n.value<=d||(n.value=d)}),(d,h)=>(p(),w("div",{class:T(l(t).b())},[S("label",{class:T(l(t).e("label"))},[et(S("input",{ref_key:"inputSliderRef",ref:s,"onUpdate:modelValue":h[0]||(h[0]=m=>n.value=m),type:"range",name:e.name,min:e.min,max:e.max,disabled:e.disabled,step:e.step,class:T([l(t).e("label__input"),l(t).e("label__input-progress"),l(t).is("disabled",e.disabled)])},null,10,Xx),[[_o,n.value,void 0,{number:!0}]]),H(vt,{name:"fade",persisted:""},{default:O(()=>[et(S("span",{ref_key:"inputSliderTooltipRef",ref:o,class:T([l(t).e("label__tooltip"),l(t).is("opacity-0",l(i)&&r.value)])},W(e.format?e.format(n.value):n.value),3),[[at,l(i)]])]),_:1})],2)],2))}}),Qx=z({name:"LayoutPageWidthSlide",__name:"LayoutPageWidthSlide",setup(e){const{getTeekConfigRef:t}=fe(),n=t("themeEnhance",{}),{t:s}=ge(),o=F(()=>6e3),i=F(()=>1e4),r=bn(Sx,(n.value.layoutSwitch?.defaultPageMaxWidth||90)*100),a=bn(Bu,n.value.layoutSwitch?.defaultMode||En.Original),{start:c}=Vu(),u=v=>{me&&(n.value.layoutSwitch?.disableAnimation||c(),document.body.style.setProperty(Cx,`${Math.ceil(v/100)}%`))},f=Xt(Vo),d=Xt(b2);te(d,()=>{u(r.value)});const h=es(u,1e3);te(r,h);const m=v=>`${Math.ceil(v/100)}%`,g=[{title:s("tk.themeEnhance.pageLayoutMaxWidth.helpTipTitle"),icon:Vh,content:s("tk.themeEnhance.pageLayoutMaxWidth.helpTipContent")}];return(v,k)=>(p(),D(vt,{name:l(Fu),persisted:""},{default:O(()=>[et(H(Oo,{icon:l(Vr),title:l(s)("tk.themeEnhance.pageLayoutMaxWidth.title"),helper:!l(n).layoutSwitch?.disablePageMaxWidthHelp,"helper-desc":l(s)("tk.themeEnhance.pageLayoutMaxWidth.helpDesc"),tips:g,disabled:l(f)},{default:O(()=>[H(l(T2),{modelValue:l(r),"onUpdate:modelValue":k[0]||(k[0]=b=>Ye(r)?r.value=b:null),disabled:l(f),min:o.value,max:i.value,format:m,class:T(l(Re).e("slide")),"aria-label":l(s)("tk.themeEnhance.pageLayoutMaxWidth.helperTipTitle")},null,8,["modelValue","disabled","min","max","class","aria-label"])]),_:1},8,["icon","title","helper","helper-desc","disabled"]),[[at,l(a)===l(En).SidebarWidthAdjustableOnly||l(a)===l(En).BothWidthAdjustable]])]),_:1},8,["name"]))}}),Zx=z({name:"LayoutDocWidthSlide",__name:"LayoutDocWidthSlide",setup(e){const{getTeekConfigRef:t}=fe(),n=t("themeEnhance",{}),{t:s}=ge(),o=F(()=>6e3),i=F(()=>1e4),r=bn(Tx,(n.value.layoutSwitch?.defaultDocMaxWidth||95)*100),a=bn(Bu,n.value.layoutSwitch?.defaultMode||En.Original),{start:c}=Vu(),u=v=>{if(!me)return;n.value.layoutSwitch?.disableAnimation||c();const k=document.body.style;d.value||k.setProperty(Re.join("page-max-width"),"100%"),k.setProperty(_x,`${Math.ceil(v/100)}%`)},f=Xt(Vo),d=Xt(b2);te(d,()=>{u(r.value)});const h=es(u,1e3);te(r,h);const m=v=>`${Math.ceil(v/100)}%`,g=[{title:s("tk.themeEnhance.docLayoutMaxWidth.helpTipTitle"),icon:Vh,content:s("tk.themeEnhance.docLayoutMaxWidth.helpTipContent")}];return(v,k)=>(p(),D(vt,{name:l(Fu),persisted:""},{default:O(()=>[et(H(Oo,{icon:l(Vr),title:l(s)("tk.themeEnhance.docLayoutMaxWidth.title"),helper:!l(n).layoutSwitch?.disableDocMaxWidthHelp,"helper-desc":l(s)("tk.themeEnhance.docLayoutMaxWidth.helpDesc"),tips:g,disabled:l(f)},{default:O(()=>[H(l(T2),{modelValue:l(r),"onUpdate:modelValue":k[0]||(k[0]=b=>Ye(r)?r.value=b:null),disabled:l(f),min:o.value,max:i.value,format:m,class:T(l(Re).e("slide")),"aria-label":l(s)("tk.themeEnhance.docLayoutMaxWidth.helperTipTitle")},null,8,["modelValue","disabled","min","max","class","aria-label"])]),_:1},8,["icon","title","helper","helper-desc","disabled"]),[[at,l(a)===l(En).BothWidthAdjustable]])]),_:1},8,["name"]))}}),eA=z({__name:"Switch",props:{modelValue:{default:!1},modelModifiers:{}},emits:["update:modelValue"],setup(e){const t=Jt(e,"modelValue"),n=()=>{t.value=!t.value};return(s,o)=>(p(),w("span",{class:T([l(Re).e("switch"),l(Re).is("checked",t.value)]),onClick:n},[...o[0]||(o[0]=[S("div",{class:"action"},null,-1)])],2))}});const tA={class:"flx-justify-between flx-1"},nA={class:"flx-align-center"},sA={class:"label"},oA=["title","aria-label"],iA={class:"color-list flx-justify-between flx-wrap"},rA=["onClick","title","aria-label"];var aA=z({name:"ThemeColor",__name:"ThemeColor",setup(e){const{getTeekConfigRef:t}=fe(),n=t("themeEnhance",{}),{t:s}=ge(),{frontmatter:o}=Ae(),i=Xt(Vo),r=bn(w2,n.value.themeColor?.defaultColorName||Sn.vpDefault),a=bn(Ex,n.value.themeColor?.defaultSpread||!1),c=j(r.value),u=j(""),{clear:f,updateSpread:d}=jh(u,()=>{if(Yr.includes(r.value))return[on.vpBrand1,on.vpBrand2,on.vpBrand3,on.vpBrandSoft]}),h=S2();te(r,b=>{if(!me)return;const C=document.documentElement;if(C.getAttribute(Jr)!==b){if(C.setAttribute(Jr,b),Yr.includes(b))f(),u.value=getComputedStyle(C).getPropertyValue(on.vpBrand1);else{const x=(n.value.themeColor?.append||[]).map(P=>P.options).flat().filter(P=>P.value===b)[0]?.color;!x&&f(),u.value=x||getComputedStyle(C).getPropertyValue(on.vpBrand1)}n.value.themeColor?.switchColorDone?.(b)}},{immediate:!0}),te(()=>o.value.themeColorName,b=>{b?(c.value=r.value,r.value=b):r.value=c.value},{immediate:!0}),te(a,d,{immediate:!0,flush:"post"});const g=[{title:s("tk.themeEnhance.themeColor.vpHelpTipTitle"),content:s("tk.themeEnhance.themeColor.vpHelpTipContent")},{title:s("tk.themeEnhance.themeColor.epHelpTipTitle"),content:s("tk.themeEnhance.themeColor.epHelpTipContent")}],v=b=>{r.value=b.value},k=b=>b?{backgroundColor:b}:{};return(b,C)=>(p(),D(Oo,{class:T(l(Re).e("theme-color")),icon:l(S9),title:l(s)("tk.themeEnhance.themeColor.title"),helper:!l(n).themeColor?.disableHelp,"helper-desc":l(s)("tk.themeEnhance.themeColor.helpDesc"),tips:g,disabled:l(i)},{title:O(()=>[S("div",tA,[rt(W(l(s)("tk.themeEnhance.themeColor.title"))+" ",1),S("div",nA,[S("span",sA,W(l(s)("tk.themeEnhance.themeColor.speedLabel")),1),H(eA,{modelValue:l(a),"onUpdate:modelValue":C[0]||(C[0]=y=>Ye(a)?a.value=y:null)},null,8,["modelValue"])])])]),default:O(()=>[(p(!0),w(Y,null,le(l(h),y=>(p(),w(Y,{key:y.label},[S("h3",{title:y.tip,"aria-label":y.label},W(y.label),9,oA),S("ul",iA,[(p(!0),w(Y,null,le(y.options,_=>(p(),w("li",{key:y.label+_.value,class:"flx-column-center",onClick:x=>v(_),title:_.title,"aria-label":_.ariaLabel??_.title??_.label},[S("div",{class:T(["color-wrapper flx-center",l(Re).is("active",_.value===l(r))])},[S("div",{class:"color-bg",style:Fe(k(_.color))},null,4)],2),S("span",null,W(_.label),1)],8,rA))),128))])],64))),128))]),_:1},8,["class","icon","title","helper","helper-desc","disabled"]))}}),lA=z({name:"SpotlightHover",__name:"SpotlightHover",props:{enabled:{type:Boolean}},setup(e){const t=e,n=j(!1),s=j({display:"none"}),o=j(),i=j(),r=bn(_2,Us.Aside),a=j({x:0,y:0}),c=h=>({display:"block",width:`${h.width+8}px`,height:`${h.height+8}px`,left:`${h.left-4}px`,top:`${h.top-4}px`,transition:"all 0.2s ease",borderRadius:"8px"}),u=h=>h===null?null:h.parentElement===document.querySelector(".VPDoc main .vp-doc > div")?h:u(h.parentElement),f=()=>{if(!me)return;const h=document.elementFromPoint(a.value.x,a.value.y);if(!(h&&o.value?.contains(h)))return;const m=u(h);if(i.value=m||void 0,i.value&&i.value.tagName==="P"){const g=i.value,v=window.getComputedStyle(g),k=Number.parseFloat(v.lineHeight),b=Math.floor(g.offsetHeight/k),C=g.getBoundingClientRect(),y=a.value.y-C.top;for(let _=0;_=x&&ydocument,"mousemove",h=>{a.value={x:h.clientX,y:h.clientY}}),Ve(()=>document,"scroll",f,!0),be(()=>{o.value=document.querySelector(".VPDoc main .vp-doc")});const d=kn();return te(d,()=>{o.value=document.querySelector(".VPDoc main .vp-doc"),n.value=!0,s.value={display:"none"},f(),n.value=!1},{flush:"post"}),te([()=>a.value.x,()=>a.value.y],()=>{t.enabled&&f()}),te(()=>t.enabled,h=>{h||(s.value={display:"none"})}),(h,m)=>(p(),D(la,{to:"body"},[t.enabled&&!n.value?(p(),w("div",{key:0,style:Fe(s.value),class:T([l(Re).join("spotlight-hover"),l(r)===l(Us).Under?l(Re).join("spotlight-hover__under"):"",l(r)===l(Us).Aside?l(Re).join("spotlight-hover__aside"):""]),"aria-hidden":"true",focusable:"false"},null,6)):A("v-if",!0)]))}}),cA=z({name:"Spotlight",__name:"Spotlight",setup(e){const{getTeekConfigRef:t}=fe(),n=t("themeEnhance",{}),{t:s}=ge(),{frontmatter:o}=Ae(),i=Xt(k2),r=bn(C2,n.value.spotlight?.defaultValue??!0),a=j(r.value);te(()=>o.value.spotlight,f=>{f!==void 0?(a.value=r.value,r.value=f):r.value=a.value},{immediate:!0});const c=F(()=>[{value:!0,label:"ON",title:s("tk.themeEnhance.spotlight.onTipTitle"),ariaLabel:s("tk.themeEnhance.spotlight.onTipTitle")},{value:!1,label:"OFF",title:s("tk.themeEnhance.spotlight.offTipTitle"),ariaLabel:s("tk.themeEnhance.spotlight.offTipTitle")}]),u=[{title:`ON ${s("tk.themeEnhance.spotlight.onTipTitle")}`,content:s("tk.themeEnhance.spotlight.onHelpTipContent")},{title:`OFF ${s("tk.themeEnhance.spotlight.offTipTitle")}`,content:s("tk.themeEnhance.spotlight.offHelpTipContent")}];return(f,d)=>(p(),w(Y,null,[H(Oo,{icon:l(Nh),title:l(s)("tk.themeEnhance.spotlight.title"),helper:!l(n).spotlight?.disableHelp,"helper-desc":l(s)("tk.themeEnhance.spotlight.helpDesc"),tips:u,disabled:l(i)},{default:O(()=>[H(l(Nu),{modelValue:l(r),"onUpdate:modelValue":d[0]||(d[0]=h=>Ye(r)?r.value=h:null),options:c.value,disabled:l(i)},null,8,["modelValue","options","disabled"])]),_:1},8,["icon","title","helper","helper-desc","disabled"]),l(r)&&!l(i)?(p(),D(lA,{key:0,enabled:l(r)&&!l(i)},null,8,["enabled"])):A("v-if",!0)],64))}}),uA=z({name:"SpotlightStyle",__name:"SpotlightStyle",setup(e){const{getTeekConfigRef:t}=fe(),n=t("themeEnhance",{}),{t:s}=ge(),o=bn(_2,n.value.spotlight?.defaultStyle||Us.Aside),i=bn(C2,n.value.spotlight?.defaultValue??!0),r=Xt(k2),a=F(()=>[{value:Us.Aside,title:s("tk.themeEnhance.spotlightStyles.asideTipTitle"),helpMessage:s("tk.themeEnhance.spotlightStyles.asideHelpTipContent"),ariaLabel:s("tk.themeEnhance.spotlightStyles.asideTipTitle"),icon:_9},{value:Us.Under,title:s("tk.themeEnhance.spotlightStyles.underTipTitle"),helpMessage:s("tk.themeEnhance.spotlightStyles.underHelpTipContent"),ariaLabel:s("tk.themeEnhance.spotlightStyles.underTipTitle"),icon:C9}]),c=F(()=>a.value.map(f=>({value:f.value,title:f.title,ariaLabel:f.ariaLabel,icon:f.icon}))),u=F(()=>a.value.map(f=>({title:f.title,icon:f.icon,content:f.helpMessage})));return(f,d)=>(p(),D(vt,{name:l(Fu)},{default:O(()=>[l(i)?(p(),D(Oo,{key:0,icon:l(Nh),title:l(s)("tk.themeEnhance.spotlightStyles.title"),helper:!l(n).spotlight?.disableHelp,"helper-desc":l(s)("tk.themeEnhance.spotlightStyles.helpDesc"),tips:u.value,disabled:l(r)},{default:O(()=>[H(l(Nu),{modelValue:l(o),"onUpdate:modelValue":d[0]||(d[0]=h=>Ye(o)?o.value=h:null),options:c.value,disabled:l(r)},null,8,["modelValue","options","disabled"])]),_:1},8,["icon","title","helper","helper-desc","tips","disabled"])):A("v-if",!0)]),_:1},8,["name"]))}}),fA=z({name:"ThemeEnhance",__name:"index",setup(e){const{getTeekConfigRef:t}=fe(),n=t("themeEnhance",{position:"top"}),s=Xt(Vo),o=F(()=>({layoutSwitch:n.value.layoutSwitch?.disabled??!1,themeColor:n.value.themeColor?.disabled??!1,spotlight:n.value.spotlight?.disabled??!1}));return(i,r)=>!l(s)&&l(n).position==="top"?(p(),D(l(Ia),{key:0,class:T([l(Re).b(),"flx-align-center"]),"popper-class":l(Re).e("popover"),"y-offset":-15},{reference:O(()=>[H(l(de),{icon:l(Ah),size:20},null,8,["icon"])]),default:O(()=>[S("div",{class:T(l(Re).e("content"))},[M(i.$slots,"teek-theme-enhance-top"),o.value.layoutSwitch?A("v-if",!0):(p(),w(Y,{key:0},[H(Jx),H(Qx),H(Zx)],64)),o.value.themeColor?A("v-if",!0):(p(),D(aA,{key:1})),o.value.spotlight?A("v-if",!0):(p(),w(Y,{key:2},[H(cA),H(uA)],64)),M(i.$slots,"teek-theme-enhance-bottom")],2)]),_:3},8,["class","popper-class"])):A("v-if",!0)}});const dA={key:0,class:"custom-block-title"},hA=["innerHTML"],pA={key:1},mA=["innerHTML"];var t1=z({name:"VpContainer",__name:"index",props:{type:{default:"tip"},title:{},text:{default:""}},setup(e){const t=ie("vp-container"),n=Si(),s=F(()=>e.title||n.title),o=F(()=>e.text||n.default);return(i,r)=>s.value||o.value?(p(),w("div",{key:0,class:T([l(t).b(),"vp-doc"])},[S("div",{class:T([e.type,"custom-block",{"no-title":!e.title}])},[s.value?(p(),w("div",dA,[M(i.$slots,"title",{},()=>[S("span",{innerHTML:e.title},null,8,hA)])])):A("v-if",!0),o.value?(p(),w("p",pA,[M(i.$slots,"default",{},()=>[S("span",{innerHTML:e.text},null,8,mA)])])):A("v-if",!0)],2)],2)):A("v-if",!0)}});const gA=["title","aria-label"];var vA=z({__name:"index",setup(e){const t=ie("sidebar-trigger"),{t:n}=ge(),s=j(!1),o=Xt("(max-width: 960px)"),i=()=>{const r=document.querySelector(`.${t.join("layout")}`);r&&r.classList.toggle(t.is("sidebar-collapse")),s.value||(s.value=!0,setTimeout(()=>{s.value=!1},300))};return be(async()=>{await ze(),document.querySelector(".VPContent.has-sidebar")?.classList.add("sidebar-trigger-transition")}),(r,a)=>l(o)?A("v-if",!0):M(r.$slots,"default",{key:0,active:s.value,icon:l(Vr),toggleSideBar:i},()=>[S("div",{class:T([l(t).b(),l(t).is("active",s.value)]),onClick:i,title:l(n)("tk.sidebarTrigger.label"),role:"button","aria-label":l(n)("tk.sidebarTrigger.label")},[S("div",{class:T([l(t).join("right-bottom-button__button")])},[H(l(de),{icon:l(Vr),"aria-hidden":"true"},null,8,["icon"])],2)],10,gA)])}});const yA=["src"],bA=["innerHTML"],kA=["innerHTML"],wA={key:0,class:"features"},CA=["innerHTML"],_A=["innerHTML"],SA=["src"],TA=["innerHTML"],EA=["innerHTML"],xA={key:0,class:"highlights"},AA=["innerHTML"],$A=["innerHTML"];var LA=z({__name:"index",setup(e){const t=ie("home-features"),{getTeekConfigRef:n}=fe(),s=n("features",[]),o=_a(a=>a.feature),i=j(null),{start:r}=Ca(i,!1);return be(()=>{o.value&&r()}),(a,c)=>l(s)?.length?(p(),w("div",{key:0,class:T([l(t).b(),"vp-doc"])},[(p(!0),w(Y,null,le(l(s),u=>(p(),w(Y,{key:u.title},[u.features?(p(),w("div",{key:0,class:T([l(t).e("feature-wrapper"),"features-wrapper"])},[S("div",{class:T(l(t).e("feature__content"))},[S("img",{src:u.image,class:"image"},null,8,yA),S("div",{class:T([l(t).e("feature__header"),"header"])},[S("h2",{ref_for:!0,ref_key:"textInstance",ref:i,innerHTML:u.title},null,8,bA),u.details?(p(),w("p",{key:0,ref_for:!0,ref_key:"textInstance",ref:i,innerHTML:u.details},null,8,kA)):A("v-if",!0)],2),u.features?.length?(p(),w("div",wA,[(p(!0),w(Y,null,le(u.features,f=>(p(),D(Be(f.link?"a":"div"),{key:f.title,href:l(Ee)(f.link??""),class:"features__item item"},{default:O(()=>[S("h3",{ref_for:!0,ref_key:"textInstance",ref:i,class:"flx-align-center"},[f.icon?(p(),D(l(de),{key:0,icon:f.icon,class:"feature-icon"},null,8,["icon"])):A("v-if",!0),S("span",{innerHTML:f.title},null,8,CA)],512),f.details?(p(),w("p",{key:0,ref_for:!0,ref_key:"textInstance",ref:i,innerHTML:f.details},null,8,_A)):A("v-if",!0)]),_:2},1032,["href"]))),128))])):A("v-if",!0)],2)],2)):u.highlights?(p(),w("div",{key:1,class:T([l(t).e("highlight-wrapper"),"features-wrapper"])},[S("div",{class:T(l(t).e("highlight"))},[S("img",{src:u.image,class:"image"},null,8,SA),S("div",{class:T(l(t).e("highlight__content"))},[S("div",{class:T([l(t).e("highlight__header"),"header"])},[S("h2",{ref_for:!0,ref_key:"textInstance",ref:i,innerHTML:u.title},null,8,TA),u.details?(p(),w("p",{key:0,ref_for:!0,ref_key:"textInstance",ref:i,innerHTML:u.details},null,8,EA)):A("v-if",!0)],2),u.highlights?.length?(p(),w("div",xA,[(p(!0),w(Y,null,le(u.highlights,f=>(p(),D(Be(f.link?"a":"div"),{key:f.title,href:l(Ee)(f.link??""),class:T([{"no-details":!f.details},"highlights__item item"])},{default:O(()=>[S("h3",{ref_for:!0,ref_key:"textInstance",ref:i},[f.icon?(p(),D(l(de),{key:0,icon:f.icon,class:"feature-icon"},null,8,["icon"])):A("v-if",!0),S("span",{innerHTML:f.title},null,8,AA)],512),f.details?(p(),w("p",{key:0,ref_for:!0,ref_key:"textInstance",ref:i,innerHTML:f.details},null,8,$A)):A("v-if",!0)]),_:2},1032,["href","class"]))),128))])):A("v-if",!0)],2)],2)],2)):A("v-if",!0)],64))),128))],2)):A("v-if",!0)}});const IA={__name:"index",props:{modelValue:{default:!0},modelModifiers:{}},emits:["update:modelValue"],setup(e){const t=Jt(e,"modelValue"),n=ie("route-loading"),s=Is(),{getTeekConfigRef:o}=fe(),i=o("loading",!1),r=()=>{t.value||(t.value=!0)},a=()=>{setTimeout(()=>{t.value&&(t.value=!1)},Math.floor(Math.random()*41)+460)};return s.bindBeforeRouteChange("routeLoadingBefore",()=>{r()},"before"),s.bindAfterRouteChange("routeLoadingAfter",()=>{a()},"before"),te(()=>s.route.path,()=>{r(),a()}),fa(r),be(a),xi(a),(c,u)=>M(c.$slots,"default",{loading:t.value},()=>[S("div",{class:T(l(n).b())},[H(vt,{name:l(n).join("fade"),mode:"out-in",persisted:""},{default:O(()=>[et(S("div",{class:T(l(n).e("mask"))},[S("div",{class:T(l(n).e("loader"))},[S("div",{class:T(l(n).e("spinner"))},null,2),S("p",null,W(l(Je)(l(i))?l(i):"Teek 拼命加载中 ..."),1)],2)],2),[[at,t.value]])]),_:1},8,["name"])],2)])}},PA=["src"],MA={key:0,class:"categories flx-center"},FA=["href","title"],BA={key:1,class:"tags flx-center"},NA=["href","title"];var VA=z({__name:"index",setup(e){const t=j(!1),n=ie("article-banner"),{frontmatter:s}=Ae(),o=kn(),{hasSidebar:i}=Xh(),{isMobile:r}=Jh(),{getTeekConfigRef:a}=fe(),c=a("articleBanner",{enabled:!1,showCategory:!0,showTag:!0,defaultCoverImg:"",defaultCoverBgColor:""}),u=a("post",{defaultCoverImg:[]}),f=F(()=>{const h=[s.value.coverImg||c.value.defaultCoverImg||u.value.defaultCoverImg||[]].flat();return h.length?h[Math.floor(Math.random()*h.length)]:""}),d=F(()=>({[n.cssVarName("article-banner-bg-color")]:s.value.coverBgColor||c.value.defaultCoverBgColor}));return te(()=>o.path,async()=>{await ze(),t.value=!0,setTimeout(()=>t.value=!1,1)}),(h,m)=>!l(i)&&l(c).enabled?et((p(),w("div",{key:0,class:T(l(n).b()),style:Fe(d.value)},[S("div",{class:T([l(n).e("wrapper"),"flx-justify-center"])},[f.value?(p(),w("div",{key:0,class:T(l(n).e("cover"))},[S("img",{src:f.value,class:"no-preview",alt:"cover"},null,8,PA)],2)):A("v-if",!0),S("div",{class:T(l(n).e("info"))},[M(h.$slots,"teek-article-banner-info-top"),l(r)?A("v-if",!0):(p(),D(l(h2),{key:0})),S("div",{class:T([l(n).e("meta"),"flx-center flx-wrap"])},[l(s).categories&&l(c).showCategory?(p(),w("div",MA,[(p(!0),w(Y,null,le(l(s).categories,g=>(p(),w("a",{key:g,href:l(Ee)(`/categories?category=${g}`),class:"meta-info category",title:g},W(g),9,FA))),128))])):A("v-if",!0),l(s).tags&&l(c).showTag?(p(),w("div",BA,[(p(!0),w(Y,null,le(l(s).tags,g=>(p(),w("a",{key:g,href:l(Ee)(`/tags?tag=${g}`),class:"meta-info tag",title:g},[m[0]||(m[0]=S("span",null,"#",-1)),S("span",null,W(g),1)],8,NA))),128))])):A("v-if",!0)],2),S("h1",null,W(l(s).title),1),H(l(p2),{breadcrumb:!1,scope:"article-banner"}),M(h.$slots,"teek-article-banner-info-bottom")],2)],2),H(l(c2))],6)),[[at,!t.value]]):A("v-if",!0)}}),OA=z({name:"TeekLayout",__name:"index",props:{locale:{}},setup(e){const t=e;In(Rh,F(()=>t.locale));const{Layout:n}=_h,s=ie("layout"),{getTeekConfigRef:o}=fe(),{isHomePage:i,isArchivesPage:r,isCataloguePage:a,isArticleOverviewPage:c}=iu(),{frontmatter:u,localeIndex:f,page:d}=Ae(),{hasSidebar:h}=Xh(),m=o(null,{teekTheme:!0,teekHome:!0,vpHome:!0,sidebarTrigger:!1,loading:!1,codeBlock:{enabled:!0},themeSize:"",bodyBgImg:{},notice:{},comment:{provider:""},articleUpdate:{enabled:!0},articleTopTip:void 0,articleBottomTip:void 0,articleShare:{},appreciation:{},riskLink:{enabled:!1},themeEnhance:{enabled:!0},articleBanner:{enabled:!1},pageStyle:"default"}),g=j(m.value.loading),v=F(()=>{const E=u.value.comment,L=m.value.comment;let I=E??L;if(Zn(E)){if(E===!1)return{enabled:!1};I=L}return{enabled:!0,components:{twikoo:lx,waline:hx,giscus:fx,artalk:ux},provider:I.provider,options:I.options}}),k=F(()=>Zn(m.value.articleTopTip)?m.value.articleTopTip:m.value.articleTopTip?.(u.value,f.value,d.value)),b=F(()=>Zn(m.value.articleBottomTip)?m.value.articleBottomTip:m.value.articleBottomTip?.(u.value,f.value,d.value)),C=F(()=>u.value.articleBanner!==!1&&m.value.articleBanner.enabled&&!h.value&&u.value.article!==!1&&(!u.value.layout||u.value.layout==="doc")&&m.value.pageStyle==="default"),y=s.join("theme-size");te(()=>m.value.themeSize,E=>{me&&(E?document.documentElement.setAttribute(y,E):document.documentElement.removeAttribute(y))},{immediate:!0,flush:"post"});const{watchSite:_,watchPages:x}=C_(),{restart:P}=T_({whitelist:m.value.riskLink.whitelist,blacklist:m.value.riskLink.blacklist});_(),x(),xi(()=>{m.value.riskLink.enabled&&P()});const V=["home-hero-before","home-features-after","nav-bar-content-after","layout-top","layout-bottom","doc-footer-before","doc-before","doc-after","aside-bottom","page-top","aside-outline-before","sidebar-nav-before"];return(E,L)=>l(m).teekTheme?(p(),w(Y,{key:0},[l(m).loading??!1?(p(),D(l(IA),{key:0,modelValue:g.value,"onUpdate:modelValue":L[0]||(L[0]=I=>g.value=I)},{default:O(I=>[M(E.$slots,"teek-loading",Ge(Ze(I)))]),_:3},8,["modelValue"])):A("v-if",!0),l(u).loginPage===!0?M(E.$slots,"teek-login-page",{key:1},()=>[et(H(l(i2),null,null,512),[[at,!g.value]])]):A("v-if",!0),l(u).riskLinkPage===!0?M(E.$slots,"teek-risk-link-page",{key:2},()=>[et(H(l(r2),null,null,512),[[at,!g.value]])]):A("v-if",!0),l(u).layout!==!1?(p(),w(Y,{key:3},[l(m).bodyBgImg?.imgSrc?(p(),D(l(DT),{key:0})):A("v-if",!0),H(l(DE)),l(m).notice?.enabled?(p(),D(l(Vx),{key:1},Wt({_:2},[le(E.$slots,(I,N)=>({name:N,fn:O($=>[M(E.$slots,N,Ge(Ze($)))])}))]),1024)):A("v-if",!0),H(l(Lx),null,Wt({_:2},[le(E.$slots,(I,N)=>({name:N,fn:O($=>[M(E.$slots,N,Ge(Ze($)))])}))]),1024)],64)):A("v-if",!0),et(H(l(n),{class:T([l(s).b(),{[l(s).m("hide-vp-home")]:!l(m).vpHome},l(s).has("sidebar-trigger",l(m).sidebarTrigger)])},Wt({"home-hero-before":O(()=>[M(E.$slots,"home-hero-before"),M(E.$slots,"teek-home-before"),A(" 自定义首页 "),l(m).teekHome?(p(),D(l(PT),{key:0},Wt({_:2},[le(E.$slots,(I,N)=>({name:N,fn:O($=>[M(E.$slots,N,Ge(Ze($)))])}))]),1024)):A("v-if",!0),M(E.$slots,"teek-home-after")]),"home-features-after":O(()=>[l(m).teekHome?A("v-if",!0):(p(),w(Y,{key:0},[M(E.$slots,"teek-home-features-before"),H(l(LA)),M(E.$slots,"teek-home-features-after")],64)),M(E.$slots,"home-features-after")]),"nav-bar-content-after":O(()=>[M(E.$slots,"nav-bar-content-after"),l(m).themeEnhance.enabled??!0?(p(),D(l(fA),{key:0},Wt({_:2},[le(E.$slots,(I,N)=>({name:N,fn:O($=>[M(E.$slots,N,Ge(Ze($)))])}))]),1024)):A("v-if",!0)]),"layout-top":O(()=>[M(E.$slots,"layout-top"),C.value?(p(),w(Y,{key:0},[M(E.$slots,"teek-article-banner-before"),H(l(VA),null,Wt({_:2},[le(E.$slots,(I,N)=>({name:N,fn:O($=>[M(E.$slots,N,Ge(Ze($)))])}))]),1024),M(E.$slots,"teek-article-banner-after")],64)):A("v-if",!0)]),"layout-bottom":O(()=>[l(i)?(p(),w(Y,{key:0},[M(E.$slots,"teek-footer-group-before"),H(l(zT)),M(E.$slots,"teek-footer-group-after"),M(E.$slots,"teek-footer-info-before"),M(E.$slots,"teek-footer-info",{},()=>[H(l(eE))]),M(E.$slots,"teek-footer-info-after")],64)):A("v-if",!0),M(E.$slots,"layout-bottom")]),"sidebar-nav-before":O(()=>[H(l(VT))]),"doc-before":O(()=>[M(E.$slots,"doc-before"),l(u).article!==!1&&!C.value?(p(),w(Y,{key:0},[M(E.$slots,"teek-article-analyze-before"),H(l(p2)),M(E.$slots,"teek-article-analyze-after")],64)):A("v-if",!0),H(l(bE)),H(l(RE)),l(m).codeBlock.enabled??!0?(p(),D(l(gx),{key:1})):A("v-if",!0),k.value?(p(),D(l(t1),Ge(nt({key:2},l(Zn)(k.value)?{}:k.value)),null,16)):A("v-if",!0),l(m).sidebarTrigger?(p(),D(l(vA),{key:3},{default:O(I=>[M(E.$slots,"teek-sidebar-trigger",Ge(Ze(I)))]),_:3})):A("v-if",!0)]),"doc-footer-before":O(()=>[M(E.$slots,"doc-footer-before"),b.value?(p(),w(Y,{key:0},[M(E.$slots,"teek-article-bottom-tip-before"),H(l(t1),Ge(Ze(l(Zn)(b.value)?{}:b.value)),null,16),M(E.$slots,"teek-article-bottom-tip-after")],64)):A("v-if",!0)]),"doc-after":O(()=>[M(E.$slots,"doc-after"),(l(m).articleUpdate.enabled??!0)&&l(u).articleUpdate!==!1?(p(),w(Y,{key:0},[M(E.$slots,"teek-doc-update-before"),H(l(OE)),M(E.$slots,"teek-doc-update-after")],64)):A("v-if",!0),["doc-after","doc-after-popper"].includes(l(m).appreciation.position)?(p(),w(Y,{key:1},[M(E.$slots,"teek-doc-after-appreciation-before"),l(m).appreciation.position==="doc-after"?(p(),D(l(QE),{key:0})):l(m).appreciation.position==="doc-after-popper"?(p(),D(l(rx),{key:1})):A("v-if",!0),M(E.$slots,"teek-doc-after-appreciation-after")],64)):A("v-if",!0),A(" 评论区 "),v.value.enabled&&v.value.provider?(p(),w(Y,{key:2},[M(E.$slots,"teek-comment-before"),v.value.provider==="render"?M(E.$slots,"teek-comment",{key:0}):(p(),D(Be(v.value.components?.[v.value.provider]),{key:1,id:`${l(s).namespace}-comment`,class:T(l(s).e("comment"))},null,8,["id","class"])),M(E.$slots,"teek-comment-after")],64)):A("v-if",!0)]),"aside-bottom":O(()=>[M(E.$slots,"aside-bottom"),l(m).appreciation.position==="aside-bottom"?(p(),w(Y,{key:0},[M(E.$slots,"teek-aside-bottom-appreciation-before"),H(l(UE)),M(E.$slots,"teek-aside-bottom-appreciation-after")],64)):A("v-if",!0)]),"page-top":O(()=>[M(E.$slots,"page-top"),l(r)||l(a)||l(c)?(p(),w(Y,{key:0},[M(E.$slots,"teek-page-top-before"),l(r)?(p(),D(l(Rp),{key:0},Wt({_:2},[le(E.$slots,(I,N)=>({name:N,fn:O($=>[M(E.$slots,N,Ge(Ze($)))])}))]),1024)):l(a)?(p(),D(l(Qh),{key:1},Wt({_:2},[le(E.$slots,(I,N)=>({name:N,fn:O($=>[M(E.$slots,N,Ge(Ze($)))])}))]),1024)):l(c)?(p(),D(l(Hp),{key:2})):A("v-if",!0),M(E.$slots,"teek-page-top-after")],64)):A("v-if",!0)]),"aside-outline-before":O(()=>[l(m).articleShare.enabled?(p(),w(Y,{key:0},[M(E.$slots,"teek-article-share-before"),H(l(FE)),M(E.$slots,"teek-article-share-after")],64)):A("v-if",!0),M(E.$slots,"aside-outline-before")]),_:2},[le(Object.keys(E.$slots).filter(I=>!V.includes(I)),I=>({name:I,fn:O(N=>[M(E.$slots,I,Ge(Ze(N)))])}))]),1032,["class"]),[[at,!g.value]])],64)):(p(),D(l(n),{key:1},Wt({_:2},[le(E.$slots,(I,N)=>({name:N,fn:O($=>[M(E.$slots,N,Ge(Ze($)))])}))]),1024))}}),XA={extends:_h,Layout:fb(OA),async enhanceApp({app:e,siteData:t,router:n}){if(e.component("TkCataloguePage",Qh),e.component("TkArchivesPage",Rp),e.component("TkArticleOverviewPage",Hp),e.component("TkLoginPage",i2),e.component("TkRiskLinkPage",r2),e.component("TkDemoCode",$_),e.component("TkTitleTag",Or),e.component("TkIcon",de),!me)return;const{themeConfig:s}=t.value;DA(s),s.permalinks&&await RA({siteData:t,router:n})}};const DA=e=>{const t=e.siteAnalytics||[],n={baidu:s=>{D7(s),me&&R7(s,window.location.href)},google:s=>H7(s),umami:s=>z7(s)};t.forEach(s=>{n[s.provider]?.(s.options)})},RA=async({siteData:e,router:t})=>{const{base:n,cleanUrls:s,themeConfig:o}=e.value;if(t.route.path===n&&t.route.data.isNotFound){const{pathname:i,search:r,hash:a}=new URL(location.href),c="/"+decodeURIComponent(i.slice(n.length)).replace(/\/$/,"").replace(/\.html/,""),u=s?c:c+".html",f=o.permalinks.inv[u];if(f){const d=n+f+r+a;await t.go(d)}}};export{He as $,XA as A,wt as B,qA as C,zn as D,N3 as E,Y as F,O3 as G,kn as H,cn as I,YA as J,KA as K,U3 as L,JA as M,bs as N,GA as O,X0 as P,nn as Q,q3 as R,rt as S,la as T,E0 as U,M as V,Fe as W,Be as X,vt as Y,u5 as Z,ke as _,Pn as a,cr as a0,Se as a1,ba as a2,Zv as a3,Bc as a4,xe as a5,zA as a6,UA as a7,jA as a8,HA as a9,_l as aa,f5 as ab,Hn as ac,ch as ad,as as ae,et as af,_o as ag,Ye as ah,go as ai,Fr as aj,WA as ak,z1 as b,F as c,z as d,z9 as e,hi as f,w as g,p as h,S as i,Ls as j,T as k,l,Ee as m,ze as n,be as o,D as p,No as q,j as r,O as s,le as t,Ae as u,To as v,te as w,W as x,A as y,H as z}; diff --git a/assets/chunks/vitepress-theme-teek.CqY1sKvl.js b/assets/chunks/vitepress-theme-teek.CqY1sKvl.js deleted file mode 100644 index 307614b6..00000000 --- a/assets/chunks/vitepress-theme-teek.CqY1sKvl.js +++ /dev/null @@ -1,647 +0,0 @@ -function ln(e){const t=Object.create(null);for(const n of e.split(","))t[n]=1;return n=>n in t}const Le={},fo=[],Ht=()=>{},ao=()=>!1,Ys=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&(e.charCodeAt(2)>122||e.charCodeAt(2)<97),ic=e=>e.startsWith("onUpdate:"),Ie=Object.assign,rc=(e,t)=>{const n=e.indexOf(t);n>-1&&e.splice(n,1)},A2=Object.prototype.hasOwnProperty,De=(e,t)=>A2.call(e,t),ce=Array.isArray,ho=e=>Io(e)==="[object Map]",Gs=e=>Io(e)==="[object Set]",Hu=e=>Io(e)==="[object Date]",$2=e=>Io(e)==="[object RegExp]",ye=e=>typeof e=="function",_e=e=>typeof e=="string",Gt=e=>typeof e=="symbol",Ue=e=>e!==null&&typeof e=="object",ac=e=>(Ue(e)||ye(e))&&ye(e.then)&&ye(e.catch),n1=Object.prototype.toString,Io=e=>n1.call(e),L2=e=>Io(e).slice(8,-1),Qr=e=>Io(e)==="[object Object]",lc=e=>_e(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e,Cs=ln(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),I2=ln("bind,cloak,else-if,else,for,html,if,model,on,once,pre,show,slot,text,memo"),Zr=e=>{const t=Object.create(null);return(n=>t[n]||(t[n]=e(n)))},P2=/-\w/g,tt=Zr(e=>e.replace(P2,t=>t.slice(1).toUpperCase())),M2=/\B([A-Z])/g,Kt=Zr(e=>e.replace(M2,"-$1").toLowerCase()),Js=Zr(e=>e.charAt(0).toUpperCase()+e.slice(1)),po=Zr(e=>e?`on${Js(e)}`:""),Ot=(e,t)=>!Object.is(e,t),mo=(e,...t)=>{for(let n=0;n{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,writable:s,value:n})},ea=e=>{const t=parseFloat(e);return isNaN(t)?e:t},kr=e=>{const t=_e(e)?Number(e):NaN;return isNaN(t)?e:t};let zu;const ta=()=>zu||(zu=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{}),F2="Infinity,undefined,NaN,isFinite,isNaN,parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt,console,Error,Symbol",B2=ln(F2);function Fe(e){if(ce(e)){const t={};for(let n=0;n{if(n){const s=n.split(V2);s.length>1&&(t[s[0].trim()]=s[1].trim())}}),t}function T(e){let t="";if(_e(e))t=e;else if(ce(e))for(let n=0;nxs(n,t))}const r1=e=>!!(e&&e.__v_isRef===!0),W=e=>_e(e)?e:e==null?"":ce(e)||Ue(e)&&(e.toString===n1||!ye(e.toString))?r1(e)?W(e.value):JSON.stringify(e,a1,2):String(e),a1=(e,t)=>r1(t)?a1(e,t.value):ho(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((n,[s,o],i)=>(n[Pa(s,i)+" =>"]=o,n),{})}:Gs(t)?{[`Set(${t.size})`]:[...t.values()].map(n=>Pa(n))}:Gt(t)?Pa(t):Ue(t)&&!ce(t)&&!Qr(t)?String(t):t,Pa=(e,t="")=>{var n;return Gt(e)?`Symbol(${(n=e.description)!=null?n:t})`:e};function J2(e){return e==null?"initial":typeof e=="string"?e===""?" ":e:String(e)}let $t;class cc{constructor(t=!1){this.detached=t,this._active=!0,this._on=0,this.effects=[],this.cleanups=[],this._isPaused=!1,this.parent=$t,!t&&$t&&(this.index=($t.scopes||($t.scopes=[])).push(this)-1)}get active(){return this._active}pause(){if(this._active){this._isPaused=!0;let t,n;if(this.scopes)for(t=0,n=this.scopes.length;t0&&--this._on===0&&($t=this.prevScope,this.prevScope=void 0)}stop(t){if(this._active){this._active=!1;let n,s;for(n=0,s=this.effects.length;n0)return;if(Go){let t=Go;for(Go=void 0;t;){const n=t.next;t.next=void 0,t.flags&=-9,t=n}}let e;for(;Yo;){let t=Yo;for(Yo=void 0;t;){const n=t.next;if(t.next=void 0,t.flags&=-9,t.flags&1)try{t.trigger()}catch(s){e||(e=s)}t=n}}if(e)throw e}function f1(e){for(let t=e.deps;t;t=t.nextDep)t.version=-1,t.prevActiveLink=t.dep.activeLink,t.dep.activeLink=t}function d1(e){let t,n=e.depsTail,s=n;for(;s;){const o=s.prevDep;s.version===-1?(s===n&&(n=o),hc(s),X2(s)):t=s,s.dep.activeLink=s.prevActiveLink,s.prevActiveLink=void 0,s=o}e.deps=t,e.depsTail=n}function ol(e){for(let t=e.deps;t;t=t.nextDep)if(t.dep.version!==t.version||t.dep.computed&&(h1(t.dep.computed)||t.dep.version!==t.version))return!0;return!!e._dirty}function h1(e){if(e.flags&4&&!(e.flags&16)||(e.flags&=-17,e.globalVersion===ii)||(e.globalVersion=ii,!e.isSSR&&e.flags&128&&(!e.deps&&!e._dirty||!ol(e))))return;e.flags|=2;const t=e.dep,n=Qe,s=xn;Qe=e,xn=!0;try{f1(e);const o=e.fn(e._value);(t.version===0||Ot(o,e._value))&&(e.flags|=128,e._value=o,t.version++)}catch(o){throw t.version++,o}finally{Qe=n,xn=s,d1(e),e.flags&=-3}}function hc(e,t=!1){const{dep:n,prevSub:s,nextSub:o}=e;if(s&&(s.nextSub=o,e.prevSub=void 0),o&&(o.prevSub=s,e.nextSub=void 0),n.subs===e&&(n.subs=s,!s&&n.computed)){n.computed.flags&=-5;for(let i=n.computed.deps;i;i=i.nextDep)hc(i,!0)}!t&&!--n.sc&&n.map&&n.map.delete(n.key)}function X2(e){const{prevDep:t,nextDep:n}=e;t&&(t.nextDep=n,e.prevDep=void 0),n&&(n.prevDep=t,e.nextDep=void 0)}function Q2(e,t){e.effect instanceof oi&&(e=e.effect.fn);const n=new oi(e);t&&Ie(n,t);try{n.run()}catch(o){throw n.stop(),o}const s=n.run.bind(n);return s.effect=n,s}function Z2(e){e.effect.stop()}let xn=!0;const p1=[];function ss(){p1.push(xn),xn=!1}function os(){const e=p1.pop();xn=e===void 0?!0:e}function ju(e){const{cleanup:t}=e;if(e.cleanup=void 0,t){const n=Qe;Qe=void 0;try{t()}finally{Qe=n}}}let ii=0;class em{constructor(t,n){this.sub=t,this.dep=n,this.version=n.version,this.nextDep=this.prevDep=this.nextSub=this.prevSub=this.prevActiveLink=void 0}}class sa{constructor(t){this.computed=t,this.version=0,this.activeLink=void 0,this.subs=void 0,this.map=void 0,this.key=void 0,this.sc=0,this.__v_skip=!0}track(t){if(!Qe||!xn||Qe===this.computed)return;let n=this.activeLink;if(n===void 0||n.sub!==Qe)n=this.activeLink=new em(Qe,this),Qe.deps?(n.prevDep=Qe.depsTail,Qe.depsTail.nextDep=n,Qe.depsTail=n):Qe.deps=Qe.depsTail=n,m1(n);else if(n.version===-1&&(n.version=this.version,n.nextDep)){const s=n.nextDep;s.prevDep=n.prevDep,n.prevDep&&(n.prevDep.nextDep=s),n.prevDep=Qe.depsTail,n.nextDep=void 0,Qe.depsTail.nextDep=n,Qe.depsTail=n,Qe.deps===n&&(Qe.deps=s)}return n}trigger(t){this.version++,ii++,this.notify(t)}notify(t){fc();try{for(let n=this.subs;n;n=n.prevSub)n.sub.notify()&&n.sub.dep.notify()}finally{dc()}}}function m1(e){if(e.dep.sc++,e.sub.flags&4){const t=e.dep.computed;if(t&&!e.dep.subs){t.flags|=20;for(let s=t.deps;s;s=s.nextDep)m1(s)}const n=e.dep.subs;n!==e&&(e.prevSub=n,n&&(n.nextSub=e)),e.dep.subs=e}}const wr=new WeakMap,Os=Symbol(""),il=Symbol(""),ri=Symbol("");function Pt(e,t,n){if(xn&&Qe){let s=wr.get(e);s||wr.set(e,s=new Map);let o=s.get(n);o||(s.set(n,o=new sa),o.map=s,o.key=n),o.track()}}function Xn(e,t,n,s,o,i){const r=wr.get(e);if(!r){ii++;return}const a=c=>{c&&c.trigger()};if(fc(),t==="clear")r.forEach(a);else{const c=ce(e),u=c&&lc(n);if(c&&n==="length"){const f=Number(s);r.forEach((d,h)=>{(h==="length"||h===ri||!Gt(h)&&h>=f)&&a(d)})}else switch((n!==void 0||r.has(void 0))&&a(r.get(n)),u&&a(r.get(ri)),t){case"add":c?u&&a(r.get("length")):(a(r.get(Os)),ho(e)&&a(r.get(il)));break;case"delete":c||(a(r.get(Os)),ho(e)&&a(r.get(il)));break;case"set":ho(e)&&a(r.get(Os));break}}dc()}function tm(e,t){const n=wr.get(e);return n&&n.get(t)}function eo(e){const t=Pe(e);return t===e?t:(Pt(t,"iterate",ri),an(e)?t:t.map(_t))}function oa(e){return Pt(e=Pe(e),"iterate",ri),e}const nm={__proto__:null,[Symbol.iterator](){return Fa(this,Symbol.iterator,_t)},concat(...e){return eo(this).concat(...e.map(t=>ce(t)?eo(t):t))},entries(){return Fa(this,"entries",e=>(e[1]=_t(e[1]),e))},every(e,t){return qn(this,"every",e,t,void 0,arguments)},filter(e,t){return qn(this,"filter",e,t,n=>n.map(_t),arguments)},find(e,t){return qn(this,"find",e,t,_t,arguments)},findIndex(e,t){return qn(this,"findIndex",e,t,void 0,arguments)},findLast(e,t){return qn(this,"findLast",e,t,_t,arguments)},findLastIndex(e,t){return qn(this,"findLastIndex",e,t,void 0,arguments)},forEach(e,t){return qn(this,"forEach",e,t,void 0,arguments)},includes(...e){return Ba(this,"includes",e)},indexOf(...e){return Ba(this,"indexOf",e)},join(e){return eo(this).join(e)},lastIndexOf(...e){return Ba(this,"lastIndexOf",e)},map(e,t){return qn(this,"map",e,t,void 0,arguments)},pop(){return Ho(this,"pop")},push(...e){return Ho(this,"push",e)},reduce(e,...t){return Uu(this,"reduce",e,t)},reduceRight(e,...t){return Uu(this,"reduceRight",e,t)},shift(){return Ho(this,"shift")},some(e,t){return qn(this,"some",e,t,void 0,arguments)},splice(...e){return Ho(this,"splice",e)},toReversed(){return eo(this).toReversed()},toSorted(e){return eo(this).toSorted(e)},toSpliced(...e){return eo(this).toSpliced(...e)},unshift(...e){return Ho(this,"unshift",e)},values(){return Fa(this,"values",_t)}};function Fa(e,t,n){const s=oa(e),o=s[t]();return s!==e&&!an(e)&&(o._next=o.next,o.next=()=>{const i=o._next();return i.done||(i.value=n(i.value)),i}),o}const sm=Array.prototype;function qn(e,t,n,s,o,i){const r=oa(e),a=r!==e&&!an(e),c=r[t];if(c!==sm[t]){const d=c.apply(e,i);return a?_t(d):d}let u=n;r!==e&&(a?u=function(d,h){return n.call(this,_t(d),h,e)}:n.length>2&&(u=function(d,h){return n.call(this,d,h,e)}));const f=c.call(r,u,s);return a&&o?o(f):f}function Uu(e,t,n,s){const o=oa(e);let i=n;return o!==e&&(an(e)?n.length>3&&(i=function(r,a,c){return n.call(this,r,a,c,e)}):i=function(r,a,c){return n.call(this,r,_t(a),c,e)}),o[t](i,...s)}function Ba(e,t,n){const s=Pe(e);Pt(s,"iterate",ri);const o=s[t](...n);return(o===-1||o===!1)&&aa(n[0])?(n[0]=Pe(n[0]),s[t](...n)):o}function Ho(e,t,n=[]){ss(),fc();const s=Pe(e)[t].apply(e,n);return dc(),os(),s}const om=ln("__proto__,__v_isRef,__isVue"),g1=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>e!=="arguments"&&e!=="caller").map(e=>Symbol[e]).filter(Gt));function im(e){Gt(e)||(e=String(e));const t=Pe(this);return Pt(t,"has",e),t.hasOwnProperty(e)}class v1{constructor(t=!1,n=!1){this._isReadonly=t,this._isShallow=n}get(t,n,s){if(n==="__v_skip")return t.__v_skip;const o=this._isReadonly,i=this._isShallow;if(n==="__v_isReactive")return!o;if(n==="__v_isReadonly")return o;if(n==="__v_isShallow")return i;if(n==="__v_raw")return s===(o?i?_1:C1:i?w1:k1).get(t)||Object.getPrototypeOf(t)===Object.getPrototypeOf(s)?t:void 0;const r=ce(t);if(!o){let c;if(r&&(c=nm[n]))return c;if(n==="hasOwnProperty")return im}const a=Reflect.get(t,n,Ye(t)?t:s);if((Gt(n)?g1.has(n):om(n))||(o||Pt(t,"get",n),i))return a;if(Ye(a)){const c=r&&lc(n)?a:a.value;return o&&Ue(c)?It(c):c}return Ue(a)?o?It(a):Dn(a):a}}class y1 extends v1{constructor(t=!1){super(!1,t)}set(t,n,s,o){let i=t[n];if(!this._isShallow){const c=is(i);if(!an(s)&&!is(s)&&(i=Pe(i),s=Pe(s)),!ce(t)&&Ye(i)&&!Ye(s))return c||(i.value=s),!0}const r=ce(t)&&lc(n)?Number(n)e,Bi=e=>Reflect.getPrototypeOf(e);function um(e,t,n){return function(...s){const o=this.__v_raw,i=Pe(o),r=ho(i),a=e==="entries"||e===Symbol.iterator&&r,c=e==="keys"&&r,u=o[e](...s),f=n?rl:t?Cr:_t;return!t&&Pt(i,"iterate",c?il:Os),{next(){const{value:d,done:h}=u.next();return h?{value:d,done:h}:{value:a?[f(d[0]),f(d[1])]:f(d),done:h}},[Symbol.iterator](){return this}}}}function Ni(e){return function(...t){return e==="delete"?!1:e==="clear"?void 0:this}}function fm(e,t){const n={get(o){const i=this.__v_raw,r=Pe(i),a=Pe(o);e||(Ot(o,a)&&Pt(r,"get",o),Pt(r,"get",a));const{has:c}=Bi(r),u=t?rl:e?Cr:_t;if(c.call(r,o))return u(i.get(o));if(c.call(r,a))return u(i.get(a));i!==r&&i.get(o)},get size(){const o=this.__v_raw;return!e&&Pt(Pe(o),"iterate",Os),o.size},has(o){const i=this.__v_raw,r=Pe(i),a=Pe(o);return e||(Ot(o,a)&&Pt(r,"has",o),Pt(r,"has",a)),o===a?i.has(o):i.has(o)||i.has(a)},forEach(o,i){const r=this,a=r.__v_raw,c=Pe(a),u=t?rl:e?Cr:_t;return!e&&Pt(c,"iterate",Os),a.forEach((f,d)=>o.call(i,u(f),u(d),r))}};return Ie(n,e?{add:Ni("add"),set:Ni("set"),delete:Ni("delete"),clear:Ni("clear")}:{add(o){!t&&!an(o)&&!is(o)&&(o=Pe(o));const i=Pe(this);return Bi(i).has.call(i,o)||(i.add(o),Xn(i,"add",o,o)),this},set(o,i){!t&&!an(i)&&!is(i)&&(i=Pe(i));const r=Pe(this),{has:a,get:c}=Bi(r);let u=a.call(r,o);u||(o=Pe(o),u=a.call(r,o));const f=c.call(r,o);return r.set(o,i),u?Ot(i,f)&&Xn(r,"set",o,i):Xn(r,"add",o,i),this},delete(o){const i=Pe(this),{has:r,get:a}=Bi(i);let c=r.call(i,o);c||(o=Pe(o),c=r.call(i,o)),a&&a.call(i,o);const u=i.delete(o);return c&&Xn(i,"delete",o,void 0),u},clear(){const o=Pe(this),i=o.size!==0,r=o.clear();return i&&Xn(o,"clear",void 0,void 0),r}}),["keys","values","entries",Symbol.iterator].forEach(o=>{n[o]=um(o,e,t)}),n}function ia(e,t){const n=fm(e,t);return(s,o,i)=>o==="__v_isReactive"?!e:o==="__v_isReadonly"?e:o==="__v_raw"?s:Reflect.get(De(n,o)&&o in s?n:s,o,i)}const dm={get:ia(!1,!1)},hm={get:ia(!1,!0)},pm={get:ia(!0,!1)},mm={get:ia(!0,!0)},k1=new WeakMap,w1=new WeakMap,C1=new WeakMap,_1=new WeakMap;function gm(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function vm(e){return e.__v_skip||!Object.isExtensible(e)?0:gm(L2(e))}function Dn(e){return is(e)?e:ra(e,!1,rm,dm,k1)}function pc(e){return ra(e,!1,lm,hm,w1)}function It(e){return ra(e,!0,am,pm,C1)}function al(e){return ra(e,!0,cm,mm,_1)}function ra(e,t,n,s,o){if(!Ue(e)||e.__v_raw&&!(t&&e.__v_isReactive))return e;const i=vm(e);if(i===0)return e;const r=o.get(e);if(r)return r;const a=new Proxy(e,i===2?s:n);return o.set(e,a),a}function _s(e){return is(e)?_s(e.__v_raw):!!(e&&e.__v_isReactive)}function is(e){return!!(e&&e.__v_isReadonly)}function an(e){return!!(e&&e.__v_isShallow)}function aa(e){return e?!!e.__v_raw:!1}function Pe(e){const t=e&&e.__v_raw;return t?Pe(t):e}function go(e){return!De(e,"__v_skip")&&Object.isExtensible(e)&&s1(e,"__v_skip",!0),e}const _t=e=>Ue(e)?Dn(e):e,Cr=e=>Ue(e)?It(e):e;function Ye(e){return e?e.__v_isRef===!0:!1}function j(e){return S1(e,!1)}function ze(e){return S1(e,!0)}function S1(e,t){return Ye(e)?e:new ym(e,t)}class ym{constructor(t,n){this.dep=new sa,this.__v_isRef=!0,this.__v_isShallow=!1,this._rawValue=n?t:Pe(t),this._value=n?t:_t(t),this.__v_isShallow=n}get value(){return this.dep.track(),this._value}set value(t){const n=this._rawValue,s=this.__v_isShallow||an(t)||is(t);t=s?t:Pe(t),Ot(t,n)&&(this._rawValue=t,this._value=s?t:_t(t),this.dep.trigger())}}function bm(e){e.dep&&e.dep.trigger()}function l(e){return Ye(e)?e.value:e}function Se(e){return ye(e)?e():l(e)}const km={get:(e,t,n)=>t==="__v_raw"?e:l(Reflect.get(e,t,n)),set:(e,t,n,s)=>{const o=e[t];return Ye(o)&&!Ye(n)?(o.value=n,!0):Reflect.set(e,t,n,s)}};function mc(e){return _s(e)?e:new Proxy(e,km)}class wm{constructor(t){this.__v_isRef=!0,this._value=void 0;const n=this.dep=new sa,{get:s,set:o}=t(n.track.bind(n),n.trigger.bind(n));this._get=s,this._set=o}get value(){return this._value=this._get()}set value(t){this._set(t)}}function gc(e){return new wm(e)}function Cm(e){const t=ce(e)?new Array(e.length):{};for(const n in e)t[n]=E1(e,n);return t}class _m{constructor(t,n,s){this._object=t,this._key=n,this._defaultValue=s,this.__v_isRef=!0,this._value=void 0}get value(){const t=this._object[this._key];return this._value=t===void 0?this._defaultValue:t}set value(t){this._object[this._key]=t}get dep(){return tm(Pe(this._object),this._key)}}class Sm{constructor(t){this._getter=t,this.__v_isRef=!0,this.__v_isReadonly=!0,this._value=void 0}get value(){return this._value=this._getter()}}function T1(e,t,n){return Ye(e)?e:ye(e)?new Sm(e):Ue(e)&&arguments.length>1?E1(e,t,n):j(e)}function E1(e,t,n){const s=e[t];return Ye(s)?s:new _m(e,t,n)}class Tm{constructor(t,n,s){this.fn=t,this.setter=n,this._value=void 0,this.dep=new sa(this),this.__v_isRef=!0,this.deps=void 0,this.depsTail=void 0,this.flags=16,this.globalVersion=ii-1,this.next=void 0,this.effect=this,this.__v_isReadonly=!n,this.isSSR=s}notify(){if(this.flags|=16,!(this.flags&8)&&Qe!==this)return u1(this,!0),!0}get value(){const t=this.dep.track();return h1(this),t&&(t.version=this.dep.version),this._value}set value(t){this.setter&&this.setter(t)}}function Em(e,t,n=!1){let s,o;return ye(e)?s=e:(s=e.get,o=e.set),new Tm(s,o,n)}const xm={GET:"get",HAS:"has",ITERATE:"iterate"},Am={SET:"set",ADD:"add",DELETE:"delete",CLEAR:"clear"},Vi={},_r=new WeakMap;let gs;function $m(){return gs}function x1(e,t=!1,n=gs){if(n){let s=_r.get(n);s||_r.set(n,s=[]),s.push(e)}}function Lm(e,t,n=Le){const{immediate:s,deep:o,once:i,scheduler:r,augmentJob:a,call:c}=n,u=_=>o?_:an(_)||o===!1||o===0?Qn(_,1):Qn(_);let f,d,h,p,g=!1,v=!1;if(Ye(e)?(d=()=>e.value,g=an(e)):_s(e)?(d=()=>u(e),g=!0):ce(e)?(v=!0,g=e.some(_=>_s(_)||an(_)),d=()=>e.map(_=>{if(Ye(_))return _.value;if(_s(_))return u(_);if(ye(_))return c?c(_,2):_()})):ye(e)?t?d=c?()=>c(e,2):e:d=()=>{if(h){ss();try{h()}finally{os()}}const _=gs;gs=f;try{return c?c(e,3,[p]):e(p)}finally{gs=_}}:d=Ht,t&&o){const _=d,x=o===!0?1/0:o;d=()=>Qn(_(),x)}const k=_i(),b=()=>{f.stop(),k&&k.active&&rc(k.effects,f)};if(i&&t){const _=t;t=(...x)=>{_(...x),b()}}let w=v?new Array(e.length).fill(Vi):Vi;const y=_=>{if(!(!(f.flags&1)||!f.dirty&&!_))if(t){const x=f.run();if(o||g||(v?x.some((L,V)=>Ot(L,w[V])):Ot(x,w))){h&&h();const L=gs;gs=f;try{const V=[x,w===Vi?void 0:v&&w[0]===Vi?[]:w,p];w=x,c?c(t,3,V):t(...V)}finally{gs=L}}}else f.run()};return a&&a(y),f=new oi(d),f.scheduler=r?()=>r(y,!1):y,p=_=>x1(_,!1,f),h=f.onStop=()=>{const _=_r.get(f);if(_){if(c)c(_,4);else for(const x of _)x();_r.delete(f)}},t?s?y(!0):w=f.run():r?r(y.bind(null,!0),!0):f.run(),b.pause=f.pause.bind(f),b.resume=f.resume.bind(f),b.stop=b,b}function Qn(e,t=1/0,n){if(t<=0||!Ue(e)||e.__v_skip||(n=n||new Map,(n.get(e)||0)>=t))return e;if(n.set(e,t),t--,Ye(e))Qn(e.value,t,n);else if(ce(e))for(let s=0;s{Qn(s,t,n)});else if(Qr(e)){for(const s in e)Qn(e[s],t,n);for(const s of Object.getOwnPropertySymbols(e))Object.prototype.propertyIsEnumerable.call(e,s)&&Qn(e[s],t,n)}return e}const A1=[];function Im(e){A1.push(e)}function Pm(){A1.pop()}function Mm(e,t){}const Fm={SETUP_FUNCTION:0,0:"SETUP_FUNCTION",RENDER_FUNCTION:1,1:"RENDER_FUNCTION",NATIVE_EVENT_HANDLER:5,5:"NATIVE_EVENT_HANDLER",COMPONENT_EVENT_HANDLER:6,6:"COMPONENT_EVENT_HANDLER",VNODE_HOOK:7,7:"VNODE_HOOK",DIRECTIVE_HOOK:8,8:"DIRECTIVE_HOOK",TRANSITION_HOOK:9,9:"TRANSITION_HOOK",APP_ERROR_HANDLER:10,10:"APP_ERROR_HANDLER",APP_WARN_HANDLER:11,11:"APP_WARN_HANDLER",FUNCTION_REF:12,12:"FUNCTION_REF",ASYNC_COMPONENT_LOADER:13,13:"ASYNC_COMPONENT_LOADER",SCHEDULER:14,14:"SCHEDULER",COMPONENT_UPDATE:15,15:"COMPONENT_UPDATE",APP_UNMOUNT_CLEANUP:16,16:"APP_UNMOUNT_CLEANUP"},Bm={sp:"serverPrefetch hook",bc:"beforeCreate hook",c:"created hook",bm:"beforeMount hook",m:"mounted hook",bu:"beforeUpdate hook",u:"updated",bum:"beforeUnmount hook",um:"unmounted hook",a:"activated hook",da:"deactivated hook",ec:"errorCaptured hook",rtc:"renderTracked hook",rtg:"renderTriggered hook",0:"setup function",1:"render function",2:"watcher getter",3:"watcher callback",4:"watcher cleanup function",5:"native event handler",6:"component event handler",7:"vnode hook",8:"directive hook",9:"transition hook",10:"app errorHandler",11:"app warnHandler",12:"ref function",13:"async component loader",14:"scheduler flush",15:"component update",16:"app unmount cleanup function"};function Po(e,t,n,s){try{return s?e(...s):e()}catch(o){Xs(o,t,n)}}function yn(e,t,n,s){if(ye(e)){const o=Po(e,t,n,s);return o&&ac(o)&&o.catch(i=>{Xs(i,t,n)}),o}if(ce(e)){const o=[];for(let i=0;i>>1,o=Dt[s],i=li(o);i=li(n)?Dt.push(e):Dt.splice(Vm(t),0,e),e.flags|=1,L1()}}function L1(){Sr||(Sr=$1.then(I1))}function ai(e){ce(e)?vo.push(...e):vs&&e.id===-1?vs.splice(oo+1,0,e):e.flags&1||(vo.push(e),e.flags|=1),L1()}function Wu(e,t,n=Bn+1){for(;nli(n)-li(s));if(vo.length=0,vs){vs.push(...t);return}for(vs=t,oo=0;ooe.id==null?e.flags&2?-1:1/0:e.id;function I1(e){try{for(Bn=0;Bnio.emit(o,...i)),Oi=[]):typeof window<"u"&&window.HTMLElement&&!((s=(n=window.navigator)==null?void 0:n.userAgent)!=null&&s.includes("jsdom"))?((t.__VUE_DEVTOOLS_HOOK_REPLAY__=t.__VUE_DEVTOOLS_HOOK_REPLAY__||[]).push(i=>{P1(i,t)}),setTimeout(()=>{io||(t.__VUE_DEVTOOLS_HOOK_REPLAY__=null,Oi=[])},3e3)):Oi=[]}let Tt=null,la=null;function ci(e){const t=Tt;return Tt=e,la=e&&e.type.__scopeId||null,t}function Om(e){la=e}function Dm(){la=null}const Rm=e=>O;function O(e,t=Tt,n){if(!t||e._n)return e;const s=(...o)=>{s._d&&di(-1);const i=ci(t);let r;try{r=e(...o)}finally{ci(i),s._d&&di(1)}return r};return s._n=!0,s._c=!0,s._d=!0,s}function et(e,t){if(Tt===null)return e;const n=xi(Tt),s=e.dirs||(e.dirs=[]);for(let o=0;oe.__isTeleport,Jo=e=>e&&(e.disabled||e.disabled===""),qu=e=>e&&(e.defer||e.defer===""),Ku=e=>typeof SVGElement<"u"&&e instanceof SVGElement,Yu=e=>typeof MathMLElement=="function"&&e instanceof MathMLElement,ll=(e,t)=>{const n=e&&e.to;return _e(n)?t?t(n):null:n},B1={name:"Teleport",__isTeleport:!0,process(e,t,n,s,o,i,r,a,c,u){const{mc:f,pc:d,pbc:h,o:{insert:p,querySelector:g,createText:v,createComment:k}}=u,b=Jo(t.props);let{shapeFlag:w,children:y,dynamicChildren:_}=t;if(e==null){const x=t.el=v(""),L=t.anchor=v("");p(x,n,s),p(L,n,s);const V=(I,P)=>{w&16&&f(y,I,P,o,i,r,a,c)},E=()=>{const I=t.target=ll(t.props,g),P=N1(I,t,v,p);I&&(r!=="svg"&&Ku(I)?r="svg":r!=="mathml"&&Yu(I)&&(r="mathml"),o&&o.isCE&&(o.ce._teleportTargets||(o.ce._teleportTargets=new Set)).add(I),b||(V(I,P),rr(t,!1)))};b&&(V(n,L),rr(t,!0)),qu(t.props)?(t.el.__isMounted=!1,pt(()=>{E(),delete t.el.__isMounted},i)):E()}else{if(qu(t.props)&&e.el.__isMounted===!1){pt(()=>{B1.process(e,t,n,s,o,i,r,a,c,u)},i);return}t.el=e.el,t.targetStart=e.targetStart;const x=t.anchor=e.anchor,L=t.target=e.target,V=t.targetAnchor=e.targetAnchor,E=Jo(e.props),I=E?n:L,P=E?x:V;if(r==="svg"||Ku(L)?r="svg":(r==="mathml"||Yu(L))&&(r="mathml"),_?(h(e.dynamicChildren,_,I,o,i,r,a),Ic(e,t,!0)):c||d(e,t,I,P,o,i,r,a,!1),b)E?t.props&&e.props&&t.props.to!==e.props.to&&(t.props.to=e.props.to):Di(t,n,x,u,1);else if((t.props&&t.props.to)!==(e.props&&e.props.to)){const N=t.target=ll(t.props,g);N&&Di(t,N,null,u,0)}else E&&Di(t,L,V,u,1);rr(t,b)}},remove(e,t,n,{um:s,o:{remove:o}},i){const{shapeFlag:r,children:a,anchor:c,targetStart:u,targetAnchor:f,target:d,props:h}=e;if(d&&(o(u),o(f)),i&&o(c),r&16){const p=i||!Jo(h);for(let g=0;g{e.isMounted=!0}),ls(()=>{e.isUnmounting=!0}),e}const dn=[Function,Array],bc={mode:String,appear:Boolean,persisted:Boolean,onBeforeEnter:dn,onEnter:dn,onAfterEnter:dn,onEnterCancelled:dn,onBeforeLeave:dn,onLeave:dn,onAfterLeave:dn,onLeaveCancelled:dn,onBeforeAppear:dn,onAppear:dn,onAfterAppear:dn,onAppearCancelled:dn},V1=e=>{const t=e.subTree;return t.component?V1(t.component):t},zm={name:"BaseTransition",props:bc,setup(e,{slots:t}){const n=dt(),s=yc();return()=>{const o=t.default&&ua(t.default(),!0);if(!o||!o.length)return;const i=O1(o),r=Pe(e),{mode:a}=r;if(s.isLeaving)return Na(i);const c=Gu(i);if(!c)return Na(i);let u=ko(c,r,s,n,d=>u=d);c.type!==ut&&rs(c,u);let f=n.subTree&&Gu(n.subTree);if(f&&f.type!==ut&&!Tn(f,c)&&V1(n).type!==ut){let d=ko(f,r,s,n);if(rs(f,d),a==="out-in"&&c.type!==ut)return s.isLeaving=!0,d.afterLeave=()=>{s.isLeaving=!1,n.job.flags&8||n.update(),delete d.afterLeave,f=void 0},Na(i);a==="in-out"&&c.type!==ut?d.delayLeave=(h,p,g)=>{const v=R1(s,f);v[String(f.key)]=f,h[Jn]=()=>{p(),h[Jn]=void 0,delete u.delayedLeave,f=void 0},u.delayedLeave=()=>{g(),delete u.delayedLeave,f=void 0}}:f=void 0}else f&&(f=void 0);return i}}};function O1(e){let t=e[0];if(e.length>1){for(const n of e)if(n.type!==ut){t=n;break}}return t}const D1=zm;function R1(e,t){const{leavingVNodes:n}=e;let s=n.get(t.type);return s||(s=Object.create(null),n.set(t.type,s)),s}function ko(e,t,n,s,o){const{appear:i,mode:r,persisted:a=!1,onBeforeEnter:c,onEnter:u,onAfterEnter:f,onEnterCancelled:d,onBeforeLeave:h,onLeave:p,onAfterLeave:g,onLeaveCancelled:v,onBeforeAppear:k,onAppear:b,onAfterAppear:w,onAppearCancelled:y}=t,_=String(e.key),x=R1(n,e),L=(I,P)=>{I&&yn(I,s,9,P)},V=(I,P)=>{const N=P[1];L(I,P),ce(I)?I.every($=>$.length<=1)&&N():I.length<=1&&N()},E={mode:r,persisted:a,beforeEnter(I){let P=c;if(!n.isMounted)if(i)P=k||c;else return;I[Jn]&&I[Jn](!0);const N=x[_];N&&Tn(e,N)&&N.el[Jn]&&N.el[Jn](),L(P,[I])},enter(I){let P=u,N=f,$=d;if(!n.isMounted)if(i)P=b||u,N=w||f,$=y||d;else return;let U=!1;const q=I[Ri]=J=>{U||(U=!0,J?L($,[I]):L(N,[I]),E.delayedLeave&&E.delayedLeave(),I[Ri]=void 0)};P?V(P,[I,q]):q()},leave(I,P){const N=String(e.key);if(I[Ri]&&I[Ri](!0),n.isUnmounting)return P();L(h,[I]);let $=!1;const U=I[Jn]=q=>{$||($=!0,P(),q?L(v,[I]):L(g,[I]),I[Jn]=void 0,x[N]===e&&delete x[N])};x[N]=e,p?V(p,[I,U]):U()},clone(I){const P=ko(I,t,n,s,o);return o&&o(P),P}};return E}function Na(e){if(Si(e))return e=Rn(e),e.children=null,e}function Gu(e){if(!Si(e))return F1(e.type)&&e.children?O1(e.children):e;if(e.component)return e.component.subTree;const{shapeFlag:t,children:n}=e;if(n){if(t&16)return n[0];if(t&32&&ye(n.default))return n.default()}}function rs(e,t){e.shapeFlag&6&&e.component?(e.transition=t,rs(e.component.subTree,t)):e.shapeFlag&128?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function ua(e,t=!1,n){let s=[],o=0;for(let i=0;i1)for(let i=0;in.value,set:i=>n.value=i})}return n}const Er=new WeakMap;function yo(e,t,n,s,o=!1){if(ce(e)){e.forEach((g,v)=>yo(g,t&&(ce(t)?t[v]:t),n,s,o));return}if(Ss(s)&&!o){s.shapeFlag&512&&s.type.__asyncResolved&&s.component.subTree.component&&yo(e,t,n,s.component.subTree);return}const i=s.shapeFlag&4?xi(s.component):s.el,r=o?null:i,{i:a,r:c}=e,u=t&&t.r,f=a.refs===Le?a.refs={}:a.refs,d=a.setupState,h=Pe(d),p=d===Le?ao:g=>De(h,g);if(u!=null&&u!==c){if(Ju(t),_e(u))f[u]=null,p(u)&&(d[u]=null);else if(Ye(u)){u.value=null;const g=t;g.k&&(f[g.k]=null)}}if(ye(c))Po(c,a,12,[r,f]);else{const g=_e(c),v=Ye(c);if(g||v){const k=()=>{if(e.f){const b=g?p(c)?d[c]:f[c]:c.value;if(o)ce(b)&&rc(b,i);else if(ce(b))b.includes(i)||b.push(i);else if(g)f[c]=[i],p(c)&&(d[c]=f[c]);else{const w=[i];c.value=w,e.k&&(f[e.k]=w)}}else g?(f[c]=r,p(c)&&(d[c]=r)):v&&(c.value=r,e.k&&(f[e.k]=r))};if(r){const b=()=>{k(),Er.delete(e)};b.id=-1,Er.set(e,b),pt(b,n)}else Ju(e),k()}}}function Ju(e){const t=Er.get(e);t&&(t.flags|=8,Er.delete(e))}let Xu=!1;const to=()=>{Xu||(console.error("Hydration completed but contains mismatches."),Xu=!0)},jm=e=>e.namespaceURI.includes("svg")&&e.tagName!=="foreignObject",Um=e=>e.namespaceURI.includes("MathML"),Hi=e=>{if(e.nodeType===1){if(jm(e))return"svg";if(Um(e))return"mathml"}},lo=e=>e.nodeType===8;function Wm(e){const{mt:t,p:n,o:{patchProp:s,createText:o,nextSibling:i,parentNode:r,remove:a,insert:c,createComment:u}}=e,f=(y,_)=>{if(!_.hasChildNodes()){n(null,y,_),Tr(),_._vnode=y;return}d(_.firstChild,y,null,null,null),Tr(),_._vnode=y},d=(y,_,x,L,V,E=!1)=>{E=E||!!_.dynamicChildren;const I=lo(y)&&y.data==="[",P=()=>v(y,_,x,L,V,I),{type:N,ref:$,shapeFlag:U,patchFlag:q}=_;let J=y.nodeType;_.el=y,q===-2&&(E=!1,_.dynamicChildren=null);let G=null;switch(N){case Ts:J!==3?_.children===""?(c(_.el=o(""),r(y),y),G=y):G=P():(y.data!==_.children&&(to(),y.data=_.children),G=i(y));break;case ut:w(y)?(G=i(y),b(_.el=y.content.firstChild,y,x)):J!==8||I?G=P():G=i(y);break;case Rs:if(I&&(y=i(y),J=y.nodeType),J===1||J===3){G=y;const ae=!_.children.length;for(let ne=0;ne<_.staticCount;ne++)ae&&(_.children+=G.nodeType===1?G.outerHTML:G.data),ne===_.staticCount-1&&(_.anchor=G),G=i(G);return I?i(G):G}else P();break;case Y:I?G=g(y,_,x,L,V,E):G=P();break;default:if(U&1)(J!==1||_.type.toLowerCase()!==y.tagName.toLowerCase())&&!w(y)?G=P():G=h(y,_,x,L,V,E);else if(U&6){_.slotScopeIds=V;const ae=r(y);if(I?G=k(y):lo(y)&&y.data==="teleport start"?G=k(y,y.data,"teleport end"):G=i(y),t(_,ae,null,x,L,Hi(ae),E),Ss(_)&&!_.type.__asyncResolved){let ne;I?(ne=H(Y),ne.anchor=G?G.previousSibling:ae.lastChild):ne=y.nodeType===3?rt(""):H("div"),ne.el=y,_.component.subTree=ne}}else U&64?J!==8?G=P():G=_.type.hydrate(y,_,x,L,V,E,e,p):U&128&&(G=_.type.hydrate(y,_,x,L,Hi(r(y)),V,E,e,d))}return $!=null&&yo($,null,L,_),G},h=(y,_,x,L,V,E)=>{E=E||!!_.dynamicChildren;const{type:I,props:P,patchFlag:N,shapeFlag:$,dirs:U,transition:q}=_,J=I==="input"||I==="option";if(J||N!==-1){U&&Nn(_,null,x,"created");let G=!1;if(w(y)){G=h0(null,q)&&x&&x.vnode.props&&x.vnode.props.appear;const ne=y.content.firstChild;if(G){const he=ne.getAttribute("class");he&&(ne.$cls=he),q.beforeEnter(ne)}b(ne,y,x),_.el=y=ne}if($&16&&!(P&&(P.innerHTML||P.textContent))){let ne=p(y.firstChild,_,y,x,L,V,E);for(;ne;){zi(y,1)||to();const he=ne;ne=ne.nextSibling,a(he)}}else if($&8){let ne=_.children;ne[0]===` -`&&(y.tagName==="PRE"||y.tagName==="TEXTAREA")&&(ne=ne.slice(1));const{textContent:he}=y;he!==ne&&he!==ne.replace(/\r\n|\r/g,` -`)&&(zi(y,0)||to(),y.textContent=_.children)}if(P){if(J||!E||N&48){const ne=y.tagName.includes("-");for(const he in P)(J&&(he.endsWith("value")||he==="indeterminate")||Ys(he)&&!Cs(he)||he[0]==="."||ne)&&s(y,he,null,P[he],void 0,x)}else if(P.onClick)s(y,"onClick",null,P.onClick,void 0,x);else if(N&4&&_s(P.style))for(const ne in P.style)P.style[ne]}let ae;(ae=P&&P.onVnodeBeforeMount)&&Ut(ae,x,_),U&&Nn(_,null,x,"beforeMount"),((ae=P&&P.onVnodeMounted)||U||G)&&C0(()=>{ae&&Ut(ae,x,_),G&&q.enter(y),U&&Nn(_,null,x,"mounted")},L)}return y.nextSibling},p=(y,_,x,L,V,E,I)=>{I=I||!!_.dynamicChildren;const P=_.children,N=P.length;for(let $=0;${const{slotScopeIds:I}=_;I&&(V=V?V.concat(I):I);const P=r(y),N=p(i(y),_,P,x,L,V,E);return N&&lo(N)&&N.data==="]"?i(_.anchor=N):(to(),c(_.anchor=u("]"),P,N),N)},v=(y,_,x,L,V,E)=>{if(zi(y.parentElement,1)||to(),_.el=null,E){const N=k(y);for(;;){const $=i(y);if($&&$!==N)a($);else break}}const I=i(y),P=r(y);return a(y),n(null,_,P,I,x,L,Hi(P),V),x&&(x.vnode.el=_.el,pa(x,_.el)),I},k=(y,_="[",x="]")=>{let L=0;for(;y;)if(y=i(y),y&&lo(y)&&(y.data===_&&L++,y.data===x)){if(L===0)return i(y);L--}return y},b=(y,_,x)=>{const L=_.parentNode;L&&L.replaceChild(y,_);let V=x;for(;V;)V.vnode.el===_&&(V.vnode.el=V.subTree.el=y),V=V.parent},w=y=>y.nodeType===1&&y.tagName==="TEMPLATE";return[f,d]}const Qu="data-allow-mismatch",qm={0:"text",1:"children",2:"class",3:"style",4:"attribute"};function zi(e,t){if(t===0||t===1)for(;e&&!e.hasAttribute(Qu);)e=e.parentElement;const n=e&&e.getAttribute(Qu);if(n==null)return!1;if(n==="")return!0;{const s=n.split(",");return t===0&&s.includes("children")?!0:s.includes(qm[t])}}const Km=ta().requestIdleCallback||(e=>setTimeout(e,1)),Ym=ta().cancelIdleCallback||(e=>clearTimeout(e)),Gm=(e=1e4)=>t=>{const n=Km(t,{timeout:e});return()=>Ym(n)};function Jm(e){const{top:t,left:n,bottom:s,right:o}=e.getBoundingClientRect(),{innerHeight:i,innerWidth:r}=window;return(t>0&&t0&&s0&&n0&&o(t,n)=>{const s=new IntersectionObserver(o=>{for(const i of o)if(i.isIntersecting){s.disconnect(),t();break}},e);return n(o=>{if(o instanceof Element){if(Jm(o))return t(),s.disconnect(),!1;s.observe(o)}}),()=>s.disconnect()},Qm=e=>t=>{if(e){const n=matchMedia(e);if(n.matches)t();else return n.addEventListener("change",t,{once:!0}),()=>n.removeEventListener("change",t)}},Zm=(e=[])=>(t,n)=>{_e(e)&&(e=[e]);let s=!1;const o=r=>{s||(s=!0,i(),t(),r.target.dispatchEvent(new r.constructor(r.type,r)))},i=()=>{n(r=>{for(const a of e)r.removeEventListener(a,o)})};return n(r=>{for(const a of e)r.addEventListener(a,o,{once:!0})}),i};function eg(e,t){if(lo(e)&&e.data==="["){let n=1,s=e.nextSibling;for(;s;){if(s.nodeType===1){if(t(s)===!1)break}else if(lo(s))if(s.data==="]"){if(--n===0)break}else s.data==="["&&n++;s=s.nextSibling}}else t(e)}const Ss=e=>!!e.type.__asyncLoader;function wc(e){ye(e)&&(e={loader:e});const{loader:t,loadingComponent:n,errorComponent:s,delay:o=200,hydrate:i,timeout:r,suspensible:a=!0,onError:c}=e;let u=null,f,d=0;const h=()=>(d++,u=null,p()),p=()=>{let g;return u||(g=u=t().catch(v=>{if(v=v instanceof Error?v:new Error(String(v)),c)return new Promise((k,b)=>{c(v,()=>k(h()),()=>b(v),d+1)});throw v}).then(v=>g!==u&&u?u:(v&&(v.__esModule||v[Symbol.toStringTag]==="Module")&&(v=v.default),f=v,v)))};return z({name:"AsyncComponentWrapper",__asyncLoader:p,__asyncHydrate(g,v,k){let b=!1;(v.bu||(v.bu=[])).push(()=>b=!0);const w=()=>{b||k()},y=i?()=>{const _=i(w,x=>eg(g,x));_&&(v.bum||(v.bum=[])).push(_)}:w;f?y():p().then(()=>!v.isUnmounted&&y())},get __asyncResolved(){return f},setup(){const g=St;if(kc(g),f)return()=>ji(f,g);const v=y=>{u=null,Xs(y,g,13,!s)};if(a&&g.suspense||wo)return p().then(y=>()=>ji(y,g)).catch(y=>(v(y),()=>s?H(s,{error:y}):null));const k=j(!1),b=j(),w=j(!!o);return o&&setTimeout(()=>{w.value=!1},o),r!=null&&setTimeout(()=>{if(!k.value&&!b.value){const y=new Error(`Async component timed out after ${r}ms.`);v(y),b.value=y}},r),p().then(()=>{k.value=!0,g.parent&&Si(g.parent.vnode)&&g.parent.update()}).catch(y=>{v(y),b.value=y}),()=>{if(k.value&&f)return ji(f,g);if(b.value&&s)return H(s,{error:b.value});if(n&&!w.value)return ji(n,g)}}})}function ji(e,t){const{ref:n,props:s,children:o,ce:i}=t.vnode,r=H(e,s,o);return r.ref=n,r.ce=i,delete t.vnode.ce,r}const Si=e=>e.type.__isKeepAlive,tg={name:"KeepAlive",__isKeepAlive:!0,props:{include:[String,RegExp,Array],exclude:[String,RegExp,Array],max:[String,Number]},setup(e,{slots:t}){const n=dt(),s=n.ctx;if(!s.renderer)return()=>{const w=t.default&&t.default();return w&&w.length===1?w[0]:w};const o=new Map,i=new Set;let r=null;const a=n.suspense,{renderer:{p:c,m:u,um:f,o:{createElement:d}}}=s,h=d("div");s.activate=(w,y,_,x,L)=>{const V=w.component;u(w,y,_,0,a),c(V.vnode,w,y,_,V,a,x,w.slotScopeIds,L),pt(()=>{V.isDeactivated=!1,V.a&&mo(V.a);const E=w.props&&w.props.onVnodeMounted;E&&Ut(E,V.parent,w)},a)},s.deactivate=w=>{const y=w.component;Ar(y.m),Ar(y.a),u(w,h,null,1,a),pt(()=>{y.da&&mo(y.da);const _=w.props&&w.props.onVnodeUnmounted;_&&Ut(_,y.parent,w),y.isDeactivated=!0},a)};function p(w){Va(w),f(w,n,a,!0)}function g(w){o.forEach((y,_)=>{const x=bl(y.type);x&&!w(x)&&v(_)})}function v(w){const y=o.get(w);y&&(!r||!Tn(y,r))?p(y):r&&Va(r),o.delete(w),i.delete(w)}te(()=>[e.include,e.exclude],([w,y])=>{w&&g(_=>qo(w,_)),y&&g(_=>!qo(y,_))},{flush:"post",deep:!0});let k=null;const b=()=>{k!=null&&($r(n.subTree.type)?pt(()=>{o.set(k,Ui(n.subTree))},n.subTree.suspense):o.set(k,Ui(n.subTree)))};return be(b),Fo(b),ls(()=>{o.forEach(w=>{const{subTree:y,suspense:_}=n,x=Ui(y);if(w.type===x.type&&w.key===x.key){Va(x);const L=x.component.da;L&&pt(L,_);return}p(w)})}),()=>{if(k=null,!t.default)return r=null;const w=t.default(),y=w[0];if(w.length>1)return r=null,w;if(!Ln(y)||!(y.shapeFlag&4)&&!(y.shapeFlag&128))return r=null,y;let _=Ui(y);if(_.type===ut)return r=null,_;const x=_.type,L=bl(Ss(_)?_.type.__asyncResolved||{}:x),{include:V,exclude:E,max:I}=e;if(V&&(!L||!qo(V,L))||E&&L&&qo(E,L))return _.shapeFlag&=-257,r=_,y;const P=_.key==null?x:_.key,N=o.get(P);return _.el&&(_=Rn(_),y.shapeFlag&128&&(y.ssContent=_)),k=P,N?(_.el=N.el,_.component=N.component,_.transition&&rs(_,_.transition),_.shapeFlag|=512,i.delete(P),i.add(P)):(i.add(P),I&&i.size>parseInt(I,10)&&v(i.values().next().value)),_.shapeFlag|=256,r=_,$r(y.type)?y:_}}},ng=tg;function qo(e,t){return ce(e)?e.some(n=>qo(n,t)):_e(e)?e.split(",").includes(t):$2(e)?(e.lastIndex=0,e.test(t)):!1}function j1(e,t){W1(e,"a",t)}function U1(e,t){W1(e,"da",t)}function W1(e,t,n=St){const s=e.__wdc||(e.__wdc=()=>{let o=n;for(;o;){if(o.isDeactivated)return;o=o.parent}return e()});if(fa(t,s,n),n){let o=n.parent;for(;o&&o.parent;)Si(o.parent.vnode)&&sg(s,t,n,o),o=o.parent}}function sg(e,t,n,s){const o=fa(t,e,s,!0);cn(()=>{rc(s[t],o)},n)}function Va(e){e.shapeFlag&=-257,e.shapeFlag&=-513}function Ui(e){return e.shapeFlag&128?e.ssContent:e}function fa(e,t,n=St,s=!1){if(n){const o=n[e]||(n[e]=[]),i=t.__weh||(t.__weh=(...r)=>{ss();const a=qs(n),c=yn(t,n,e,r);return a(),os(),c});return s?o.unshift(i):o.push(i),i}}const as=e=>(t,n=St)=>{(!wo||e==="sp")&&fa(e,(...s)=>t(...s),n)},Mo=as("bm"),be=as("m"),Cc=as("bu"),Fo=as("u"),ls=as("bum"),cn=as("um"),q1=as("sp"),K1=as("rtg"),Y1=as("rtc");function G1(e,t=St){fa("ec",e,t)}const _c="components",og="directives";function un(e,t){return Sc(_c,e,!0,t)||e}const J1=Symbol.for("v-ndc");function Be(e){return _e(e)?Sc(_c,e,!1)||e:e||J1}function ig(e){return Sc(og,e)}function Sc(e,t,n=!0,s=!1){const o=Tt||St;if(o){const i=o.type;if(e===_c){const a=bl(i,!1);if(a&&(a===t||a===tt(t)||a===Js(tt(t))))return i}const r=Zu(o[e]||i[e],t)||Zu(o.appContext[e],t);return!r&&s?i:r}}function Zu(e,t){return e&&(e[t]||e[tt(t)]||e[Js(tt(t))])}function le(e,t,n,s){let o;const i=n&&n[s],r=ce(e);if(r||_e(e)){const a=r&&_s(e);let c=!1,u=!1;a&&(c=!an(e),u=is(e),e=oa(e)),o=new Array(e.length);for(let f=0,d=e.length;ft(a,c,void 0,i&&i[c]));else{const a=Object.keys(e);o=new Array(a.length);for(let c=0,u=a.length;c{const i=s.fn(...o);return i&&(i.key=s.key),i}:s.fn)}return e}function M(e,t,n={},s,o){if(Tt.ce||Tt.parent&&Ss(Tt.parent)&&Tt.parent.ce){const u=Object.keys(n).length>0;return t!=="default"&&(n.name=t),m(),D(Y,null,[H("slot",n,s&&s())],u?-2:64)}let i=e[t];i&&i._c&&(i._d=!1),m();const r=i&&Tc(i(n)),a=n.key||r&&r.key,c=D(Y,{key:(a&&!Gt(a)?a:`_${t}`)+(!r&&s?"_fb":"")},r||(s?s():[]),r&&e._===1?64:-2);return!o&&c.scopeId&&(c.slotScopeIds=[c.scopeId+"-s"]),i&&i._c&&(i._d=!0),c}function Tc(e){return e.some(t=>Ln(t)?!(t.type===ut||t.type===Y&&!Tc(t.children)):!0)?e:null}function Ec(e,t){const n={};for(const s in e)n[t&&/[A-Z]/.test(s)?`on:${s}`:po(s)]=e[s];return n}const cl=e=>e?A0(e)?xi(e):cl(e.parent):null,Xo=Ie(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>cl(e.parent),$root:e=>cl(e.root),$host:e=>e.ce,$emit:e=>e.emit,$options:e=>xc(e),$forceUpdate:e=>e.f||(e.f=()=>{vc(e.update)}),$nextTick:e=>e.n||(e.n=Oe.bind(e.proxy)),$watch:e=>Lg.bind(e)}),Oa=(e,t)=>e!==Le&&!e.__isScriptSetup&&De(e,t),ul={get({_:e},t){if(t==="__v_skip")return!0;const{ctx:n,setupState:s,data:o,props:i,accessCache:r,type:a,appContext:c}=e;let u;if(t[0]!=="$"){const p=r[t];if(p!==void 0)switch(p){case 1:return s[t];case 2:return o[t];case 4:return n[t];case 3:return i[t]}else{if(Oa(s,t))return r[t]=1,s[t];if(o!==Le&&De(o,t))return r[t]=2,o[t];if((u=e.propsOptions[0])&&De(u,t))return r[t]=3,i[t];if(n!==Le&&De(n,t))return r[t]=4,n[t];fl&&(r[t]=0)}}const f=Xo[t];let d,h;if(f)return t==="$attrs"&&Pt(e.attrs,"get",""),f(e);if((d=a.__cssModules)&&(d=d[t]))return d;if(n!==Le&&De(n,t))return r[t]=4,n[t];if(h=c.config.globalProperties,De(h,t))return h[t]},set({_:e},t,n){const{data:s,setupState:o,ctx:i}=e;return Oa(o,t)?(o[t]=n,!0):s!==Le&&De(s,t)?(s[t]=n,!0):De(e.props,t)||t[0]==="$"&&t.slice(1)in e?!1:(i[t]=n,!0)},has({_:{data:e,setupState:t,accessCache:n,ctx:s,appContext:o,propsOptions:i,type:r}},a){let c,u;return!!(n[a]||e!==Le&&a[0]!=="$"&&De(e,a)||Oa(t,a)||(c=i[0])&&De(c,a)||De(s,a)||De(Xo,a)||De(o.config.globalProperties,a)||(u=r.__cssModules)&&u[a])},defineProperty(e,t,n){return n.get!=null?e._.accessCache[t]=0:De(n,"value")&&this.set(e,t,n.value,null),Reflect.defineProperty(e,t,n)}},rg=Ie({},ul,{get(e,t){if(t!==Symbol.unscopables)return ul.get(e,t,e)},has(e,t){return t[0]!=="_"&&!B2(t)}});function ag(){return null}function lg(){return null}function cg(e){}function ug(e){}function fg(){return null}function dg(){}function hg(e,t){return null}function Ti(){return X1().slots}function pg(){return X1().attrs}function X1(e){const t=dt();return t.setupContext||(t.setupContext=I0(t))}function ui(e){return ce(e)?e.reduce((t,n)=>(t[n]=null,t),{}):e}function Q1(e,t){const n=ui(e);for(const s in t){if(s.startsWith("__skip"))continue;let o=n[s];o?ce(o)||ye(o)?o=n[s]={type:o,default:t[s]}:o.default=t[s]:o===null&&(o=n[s]={default:t[s]}),o&&t[`__skip_${s}`]&&(o.skipFactory=!0)}return n}function $n(e,t){return!e||!t?e||t:ce(e)&&ce(t)?e.concat(t):Ie({},ui(e),ui(t))}function Z1(e,t){const n={};for(const s in e)t.includes(s)||Object.defineProperty(n,s,{enumerable:!0,get:()=>e[s]});return n}function mg(e){const t=dt();let n=e();return gl(),ac(n)&&(n=n.catch(s=>{throw qs(t),s})),[n,()=>qs(t)]}let fl=!0;function gg(e){const t=xc(e),n=e.proxy,s=e.ctx;fl=!1,t.beforeCreate&&ef(t.beforeCreate,e,"bc");const{data:o,computed:i,methods:r,watch:a,provide:c,inject:u,created:f,beforeMount:d,mounted:h,beforeUpdate:p,updated:g,activated:v,deactivated:k,beforeDestroy:b,beforeUnmount:w,destroyed:y,unmounted:_,render:x,renderTracked:L,renderTriggered:V,errorCaptured:E,serverPrefetch:I,expose:P,inheritAttrs:N,components:$,directives:U,filters:q}=t;if(u&&vg(u,s,null),r)for(const ae in r){const ne=r[ae];ye(ne)&&(s[ae]=ne.bind(n))}if(o){const ae=o.call(n,n);Ue(ae)&&(e.data=Dn(ae))}if(fl=!0,i)for(const ae in i){const ne=i[ae],he=ye(ne)?ne.bind(n,n):ye(ne.get)?ne.get.bind(n,n):Ht,st=!ye(ne)&&ye(ne.set)?ne.set.bind(n):Ht,je=F({get:he,set:st});Object.defineProperty(s,ae,{enumerable:!0,configurable:!0,get:()=>je.value,set:yt=>je.value=yt})}if(a)for(const ae in a)e0(a[ae],s,n,ae);if(c){const ae=ye(c)?c.call(n):c;Reflect.ownKeys(ae).forEach(ne=>{In(ne,ae[ne])})}f&&ef(f,e,"c");function G(ae,ne){ce(ne)?ne.forEach(he=>ae(he.bind(n))):ne&&ae(ne.bind(n))}if(G(Mo,d),G(be,h),G(Cc,p),G(Fo,g),G(j1,v),G(U1,k),G(G1,E),G(Y1,L),G(K1,V),G(ls,w),G(cn,_),G(q1,I),ce(P))if(P.length){const ae=e.exposed||(e.exposed={});P.forEach(ne=>{Object.defineProperty(ae,ne,{get:()=>n[ne],set:he=>n[ne]=he,enumerable:!0})})}else e.exposed||(e.exposed={});x&&e.render===Ht&&(e.render=x),N!=null&&(e.inheritAttrs=N),$&&(e.components=$),U&&(e.directives=U),I&&kc(e)}function vg(e,t,n=Ht){ce(e)&&(e=dl(e));for(const s in e){const o=e[s];let i;Ue(o)?"default"in o?i=qe(o.from||s,o.default,!0):i=qe(o.from||s):i=qe(o),Ye(i)?Object.defineProperty(t,s,{enumerable:!0,configurable:!0,get:()=>i.value,set:r=>i.value=r}):t[s]=i}}function ef(e,t,n){yn(ce(e)?e.map(s=>s.bind(t.proxy)):e.bind(t.proxy),t,n)}function e0(e,t,n,s){let o=s.includes(".")?y0(n,s):()=>n[s];if(_e(e)){const i=t[e];ye(i)&&te(o,i)}else if(ye(e))te(o,e.bind(n));else if(Ue(e))if(ce(e))e.forEach(i=>e0(i,t,n,s));else{const i=ye(e.handler)?e.handler.bind(n):t[e.handler];ye(i)&&te(o,i,e)}}function xc(e){const t=e.type,{mixins:n,extends:s}=t,{mixins:o,optionsCache:i,config:{optionMergeStrategies:r}}=e.appContext,a=i.get(t);let c;return a?c=a:!o.length&&!n&&!s?c=t:(c={},o.length&&o.forEach(u=>xr(c,u,r,!0)),xr(c,t,r)),Ue(t)&&i.set(t,c),c}function xr(e,t,n,s=!1){const{mixins:o,extends:i}=t;i&&xr(e,i,n,!0),o&&o.forEach(r=>xr(e,r,n,!0));for(const r in t)if(!(s&&r==="expose")){const a=yg[r]||n&&n[r];e[r]=a?a(e[r],t[r]):t[r]}return e}const yg={data:tf,props:nf,emits:nf,methods:Ko,computed:Ko,beforeCreate:Vt,created:Vt,beforeMount:Vt,mounted:Vt,beforeUpdate:Vt,updated:Vt,beforeDestroy:Vt,beforeUnmount:Vt,destroyed:Vt,unmounted:Vt,activated:Vt,deactivated:Vt,errorCaptured:Vt,serverPrefetch:Vt,components:Ko,directives:Ko,watch:kg,provide:tf,inject:bg};function tf(e,t){return t?e?function(){return Ie(ye(e)?e.call(this,this):e,ye(t)?t.call(this,this):t)}:t:e}function bg(e,t){return Ko(dl(e),dl(t))}function dl(e){if(ce(e)){const t={};for(let n=0;n1)return n&&ye(t)?t.call(s&&s.proxy):t}}function Ac(){return!!(dt()||Ds)}const n0={},s0=()=>Object.create(n0),o0=e=>Object.getPrototypeOf(e)===n0;function _g(e,t,n,s=!1){const o={},i=s0();e.propsDefaults=Object.create(null),i0(e,t,o,i);for(const r in e.propsOptions[0])r in o||(o[r]=void 0);n?e.props=s?o:pc(o):e.type.props?e.props=o:e.props=i,e.attrs=i}function Sg(e,t,n,s){const{props:o,attrs:i,vnode:{patchFlag:r}}=e,a=Pe(o),[c]=e.propsOptions;let u=!1;if((s||r>0)&&!(r&16)){if(r&8){const f=e.vnode.dynamicProps;for(let d=0;d{c=!0;const[h,p]=r0(d,t,!0);Ie(r,h),p&&a.push(...p)};!n&&t.mixins.length&&t.mixins.forEach(f),e.extends&&f(e.extends),e.mixins&&e.mixins.forEach(f)}if(!i&&!c)return Ue(e)&&s.set(e,fo),fo;if(ce(i))for(let f=0;fe==="_"||e==="_ctx"||e==="$stable",Lc=e=>ce(e)?e.map(qt):[qt(e)],Eg=(e,t,n)=>{if(t._n)return t;const s=O((...o)=>Lc(t(...o)),n);return s._c=!1,s},a0=(e,t,n)=>{const s=e._ctx;for(const o in e){if($c(o))continue;const i=e[o];if(ye(i))t[o]=Eg(o,i,s);else if(i!=null){const r=Lc(i);t[o]=()=>r}}},l0=(e,t)=>{const n=Lc(t);e.slots.default=()=>n},c0=(e,t,n)=>{for(const s in t)(n||!$c(s))&&(e[s]=t[s])},xg=(e,t,n)=>{const s=e.slots=s0();if(e.vnode.shapeFlag&32){const o=t._;o?(c0(s,t,n),n&&s1(s,"_",o,!0)):a0(t,s)}else t&&l0(e,t)},Ag=(e,t,n)=>{const{vnode:s,slots:o}=e;let i=!0,r=Le;if(s.shapeFlag&32){const a=t._;a?n&&a===1?i=!1:c0(o,t,n):(i=!t.$stable,a0(t,o)),r=t}else t&&(l0(e,t),r={default:1});if(i)for(const a in o)!$c(a)&&r[a]==null&&delete o[a]},pt=C0;function u0(e){return d0(e)}function f0(e){return d0(e,Wm)}function d0(e,t){const n=ta();n.__VUE__=!0;const{insert:s,remove:o,patchProp:i,createElement:r,createText:a,createComment:c,setText:u,setElementText:f,parentNode:d,nextSibling:h,setScopeId:p=Ht,insertStaticContent:g}=e,v=(B,R,K,ee=null,X=null,Q=null,re=void 0,oe=null,se=!!R.dynamicChildren)=>{if(B===R)return;B&&!Tn(B,R)&&(ee=Ne(B),yt(B,X,Q,!0),B=null),R.patchFlag===-2&&(se=!1,R.dynamicChildren=null);const{type:Z,ref:ve,shapeFlag:ue}=R;switch(Z){case Ts:k(B,R,K,ee);break;case ut:b(B,R,K,ee);break;case Rs:B==null&&w(R,K,ee,re);break;case Y:$(B,R,K,ee,X,Q,re,oe,se);break;default:ue&1?x(B,R,K,ee,X,Q,re,oe,se):ue&6?U(B,R,K,ee,X,Q,re,oe,se):(ue&64||ue&128)&&Z.process(B,R,K,ee,X,Q,re,oe,se,bt)}ve!=null&&X?yo(ve,B&&B.ref,Q,R||B,!R):ve==null&&B&&B.ref!=null&&yo(B.ref,null,Q,B,!0)},k=(B,R,K,ee)=>{if(B==null)s(R.el=a(R.children),K,ee);else{const X=R.el=B.el;R.children!==B.children&&u(X,R.children)}},b=(B,R,K,ee)=>{B==null?s(R.el=c(R.children||""),K,ee):R.el=B.el},w=(B,R,K,ee)=>{[B.el,B.anchor]=g(B.children,R,K,ee,B.el,B.anchor)},y=({el:B,anchor:R},K,ee)=>{let X;for(;B&&B!==R;)X=h(B),s(B,K,ee),B=X;s(R,K,ee)},_=({el:B,anchor:R})=>{let K;for(;B&&B!==R;)K=h(B),o(B),B=K;o(R)},x=(B,R,K,ee,X,Q,re,oe,se)=>{if(R.type==="svg"?re="svg":R.type==="math"&&(re="mathml"),B==null)L(R,K,ee,X,Q,re,oe,se);else{const Z=B.el&&B.el._isVueCE?B.el:null;try{Z&&Z._beginPatch(),I(B,R,X,Q,re,oe,se)}finally{Z&&Z._endPatch()}}},L=(B,R,K,ee,X,Q,re,oe)=>{let se,Z;const{props:ve,shapeFlag:ue,transition:pe,dirs:Ce}=B;if(se=B.el=r(B.type,Q,ve&&ve.is,ve),ue&8?f(se,B.children):ue&16&&E(B.children,se,null,ee,X,Da(B,Q),re,oe),Ce&&Nn(B,null,ee,"created"),V(se,B,B.scopeId,re,ee),ve){for(const Xe in ve)Xe!=="value"&&!Cs(Xe)&&i(se,Xe,null,ve[Xe],Q,ee);"value"in ve&&i(se,"value",null,ve.value,Q),(Z=ve.onVnodeBeforeMount)&&Ut(Z,ee,B)}Ce&&Nn(B,null,ee,"beforeMount");const Me=h0(X,pe);Me&&pe.beforeEnter(se),s(se,R,K),((Z=ve&&ve.onVnodeMounted)||Me||Ce)&&pt(()=>{Z&&Ut(Z,ee,B),Me&&pe.enter(se),Ce&&Nn(B,null,ee,"mounted")},X)},V=(B,R,K,ee,X)=>{if(K&&p(B,K),ee)for(let Q=0;Q{for(let Z=se;Z{const oe=R.el=B.el;let{patchFlag:se,dynamicChildren:Z,dirs:ve}=R;se|=B.patchFlag&16;const ue=B.props||Le,pe=R.props||Le;let Ce;if(K&&Ps(K,!1),(Ce=pe.onVnodeBeforeUpdate)&&Ut(Ce,K,R,B),ve&&Nn(R,B,K,"beforeUpdate"),K&&Ps(K,!0),(ue.innerHTML&&pe.innerHTML==null||ue.textContent&&pe.textContent==null)&&f(oe,""),Z?P(B.dynamicChildren,Z,oe,K,ee,Da(R,X),Q):re||ne(B,R,oe,null,K,ee,Da(R,X),Q,!1),se>0){if(se&16)N(oe,ue,pe,K,X);else if(se&2&&ue.class!==pe.class&&i(oe,"class",null,pe.class,X),se&4&&i(oe,"style",ue.style,pe.style,X),se&8){const Me=R.dynamicProps;for(let Xe=0;Xe{Ce&&Ut(Ce,K,R,B),ve&&Nn(R,B,K,"updated")},ee)},P=(B,R,K,ee,X,Q,re)=>{for(let oe=0;oe{if(R!==K){if(R!==Le)for(const Q in R)!Cs(Q)&&!(Q in K)&&i(B,Q,R[Q],null,X,ee);for(const Q in K){if(Cs(Q))continue;const re=K[Q],oe=R[Q];re!==oe&&Q!=="value"&&i(B,Q,oe,re,X,ee)}"value"in K&&i(B,"value",R.value,K.value,X)}},$=(B,R,K,ee,X,Q,re,oe,se)=>{const Z=R.el=B?B.el:a(""),ve=R.anchor=B?B.anchor:a("");let{patchFlag:ue,dynamicChildren:pe,slotScopeIds:Ce}=R;Ce&&(oe=oe?oe.concat(Ce):Ce),B==null?(s(Z,K,ee),s(ve,K,ee),E(R.children||[],K,ve,X,Q,re,oe,se)):ue>0&&ue&64&&pe&&B.dynamicChildren?(P(B.dynamicChildren,pe,K,X,Q,re,oe),(R.key!=null||X&&R===X.subTree)&&Ic(B,R,!0)):ne(B,R,K,ve,X,Q,re,oe,se)},U=(B,R,K,ee,X,Q,re,oe,se)=>{R.slotScopeIds=oe,B==null?R.shapeFlag&512?X.ctx.activate(R,K,ee,re,se):q(R,K,ee,X,Q,re,se):J(B,R,se)},q=(B,R,K,ee,X,Q,re)=>{const oe=B.component=x0(B,ee,X);if(Si(B)&&(oe.ctx.renderer=bt),$0(oe,!1,re),oe.asyncDep){if(X&&X.registerDep(oe,G,re),!B.el){const se=oe.subTree=H(ut);b(null,se,R,K),B.placeholder=se.el}}else G(oe,B,R,K,X,Q,re)},J=(B,R,K)=>{const ee=R.component=B.component;if(Ng(B,R,K))if(ee.asyncDep&&!ee.asyncResolved){ae(ee,R,K);return}else ee.next=R,ee.update();else R.el=B.el,ee.vnode=R},G=(B,R,K,ee,X,Q,re)=>{const oe=()=>{if(B.isMounted){let{next:ue,bu:pe,u:Ce,parent:Me,vnode:Xe}=B;{const Zt=p0(B);if(Zt){ue&&(ue.el=Xe.el,ae(B,ue,re)),Zt.asyncDep.then(()=>{B.isUnmounted||oe()});return}}let We=ue,zt;Ps(B,!1),ue?(ue.el=Xe.el,ae(B,ue,re)):ue=Xe,pe&&mo(pe),(zt=ue.props&&ue.props.onVnodeBeforeUpdate)&&Ut(zt,Me,ue,Xe),Ps(B,!0);const Et=ar(B),wn=B.subTree;B.subTree=Et,v(wn,Et,d(wn.el),Ne(wn),B,X,Q),ue.el=Et.el,We===null&&pa(B,Et.el),Ce&&pt(Ce,X),(zt=ue.props&&ue.props.onVnodeUpdated)&&pt(()=>Ut(zt,Me,ue,Xe),X)}else{let ue;const{el:pe,props:Ce}=R,{bm:Me,m:Xe,parent:We,root:zt,type:Et}=B,wn=Ss(R);if(Ps(B,!1),Me&&mo(Me),!wn&&(ue=Ce&&Ce.onVnodeBeforeMount)&&Ut(ue,We,R),Ps(B,!0),pe&&Qt){const Zt=()=>{B.subTree=ar(B),Qt(pe,B.subTree,B,X,null)};wn&&Et.__asyncHydrate?Et.__asyncHydrate(pe,B,Zt):Zt()}else{zt.ce&&zt.ce._def.shadowRoot!==!1&&zt.ce._injectChildStyle(Et);const Zt=B.subTree=ar(B);v(null,Zt,K,ee,B,X,Q),R.el=Zt.el}if(Xe&&pt(Xe,X),!wn&&(ue=Ce&&Ce.onVnodeMounted)){const Zt=R;pt(()=>Ut(ue,We,Zt),X)}(R.shapeFlag&256||We&&Ss(We.vnode)&&We.vnode.shapeFlag&256)&&B.a&&pt(B.a,X),B.isMounted=!0,R=K=ee=null}};B.scope.on();const se=B.effect=new oi(oe);B.scope.off();const Z=B.update=se.run.bind(se),ve=B.job=se.runIfDirty.bind(se);ve.i=B,ve.id=B.uid,se.scheduler=()=>vc(ve),Ps(B,!0),Z()},ae=(B,R,K)=>{R.component=B;const ee=B.vnode.props;B.vnode=R,B.next=null,Sg(B,R.props,ee,K),Ag(B,R.children,K),ss(),Wu(B),os()},ne=(B,R,K,ee,X,Q,re,oe,se=!1)=>{const Z=B&&B.children,ve=B?B.shapeFlag:0,ue=R.children,{patchFlag:pe,shapeFlag:Ce}=R;if(pe>0){if(pe&128){st(Z,ue,K,ee,X,Q,re,oe,se);return}else if(pe&256){he(Z,ue,K,ee,X,Q,re,oe,se);return}}Ce&8?(ve&16&&we(Z,X,Q),ue!==Z&&f(K,ue)):ve&16?Ce&16?st(Z,ue,K,ee,X,Q,re,oe,se):we(Z,X,Q,!0):(ve&8&&f(K,""),Ce&16&&E(ue,K,ee,X,Q,re,oe,se))},he=(B,R,K,ee,X,Q,re,oe,se)=>{B=B||fo,R=R||fo;const Z=B.length,ve=R.length,ue=Math.min(Z,ve);let pe;for(pe=0;peve?we(B,X,Q,!0,!1,ue):E(R,K,ee,X,Q,re,oe,se,ue)},st=(B,R,K,ee,X,Q,re,oe,se)=>{let Z=0;const ve=R.length;let ue=B.length-1,pe=ve-1;for(;Z<=ue&&Z<=pe;){const Ce=B[Z],Me=R[Z]=se?ys(R[Z]):qt(R[Z]);if(Tn(Ce,Me))v(Ce,Me,K,null,X,Q,re,oe,se);else break;Z++}for(;Z<=ue&&Z<=pe;){const Ce=B[ue],Me=R[pe]=se?ys(R[pe]):qt(R[pe]);if(Tn(Ce,Me))v(Ce,Me,K,null,X,Q,re,oe,se);else break;ue--,pe--}if(Z>ue){if(Z<=pe){const Ce=pe+1,Me=Cepe)for(;Z<=ue;)yt(B[Z],X,Q,!0),Z++;else{const Ce=Z,Me=Z,Xe=new Map;for(Z=Me;Z<=pe;Z++){const en=R[Z]=se?ys(R[Z]):qt(R[Z]);en.key!=null&&Xe.set(en.key,Z)}let We,zt=0;const Et=pe-Me+1;let wn=!1,Zt=0;const Ro=new Array(Et);for(Z=0;Z=Et){yt(en,X,Q,!0);continue}let Mn;if(en.key!=null)Mn=Xe.get(en.key);else for(We=Me;We<=pe;We++)if(Ro[We-Me]===0&&Tn(en,R[We])){Mn=We;break}Mn===void 0?yt(en,X,Q,!0):(Ro[Mn-Me]=Z+1,Mn>=Zt?Zt=Mn:wn=!0,v(en,R[Mn],K,null,X,Q,re,oe,se),zt++)}const Ou=wn?$g(Ro):fo;for(We=Ou.length-1,Z=Et-1;Z>=0;Z--){const en=Me+Z,Mn=R[en],Du=R[en+1],Ru=en+1{const{el:Q,type:re,transition:oe,children:se,shapeFlag:Z}=B;if(Z&6){je(B.component.subTree,R,K,ee);return}if(Z&128){B.suspense.move(R,K,ee);return}if(Z&64){re.move(B,R,K,bt);return}if(re===Y){s(Q,R,K);for(let ue=0;ueoe.enter(Q),X);else{const{leave:ue,delayLeave:pe,afterLeave:Ce}=oe,Me=()=>{B.ctx.isUnmounted?o(Q):s(Q,R,K)},Xe=()=>{Q._isLeaving&&Q[Jn](!0),ue(Q,()=>{Me(),Ce&&Ce()})};pe?pe(Q,Me,Xe):Xe()}else s(Q,R,K)},yt=(B,R,K,ee=!1,X=!1)=>{const{type:Q,props:re,ref:oe,children:se,dynamicChildren:Z,shapeFlag:ve,patchFlag:ue,dirs:pe,cacheIndex:Ce}=B;if(ue===-2&&(X=!1),oe!=null&&(ss(),yo(oe,null,K,B,!0),os()),Ce!=null&&(R.renderCache[Ce]=void 0),ve&256){R.ctx.deactivate(B);return}const Me=ve&1&&pe,Xe=!Ss(B);let We;if(Xe&&(We=re&&re.onVnodeBeforeUnmount)&&Ut(We,R,B),ve&6)Zs(B.component,K,ee);else{if(ve&128){B.suspense.unmount(K,ee);return}Me&&Nn(B,null,R,"beforeUnmount"),ve&64?B.type.remove(B,R,K,bt,ee):Z&&!Z.hasOnce&&(Q!==Y||ue>0&&ue&64)?we(Z,R,K,!1,!0):(Q===Y&&ue&384||!X&&ve&16)&&we(se,R,K),ee&&Wn(B)}(Xe&&(We=re&&re.onVnodeUnmounted)||Me)&&pt(()=>{We&&Ut(We,R,B),Me&&Nn(B,null,R,"unmounted")},K)},Wn=B=>{const{type:R,el:K,anchor:ee,transition:X}=B;if(R===Y){us(K,ee);return}if(R===Rs){_(B);return}const Q=()=>{o(K),X&&!X.persisted&&X.afterLeave&&X.afterLeave()};if(B.shapeFlag&1&&X&&!X.persisted){const{leave:re,delayLeave:oe}=X,se=()=>re(K,Q);oe?oe(B.el,Q,se):se()}else Q()},us=(B,R)=>{let K;for(;B!==R;)K=h(B),o(B),B=K;o(R)},Zs=(B,R,K)=>{const{bum:ee,scope:X,job:Q,subTree:re,um:oe,m:se,a:Z}=B;Ar(se),Ar(Z),ee&&mo(ee),X.stop(),Q&&(Q.flags|=8,yt(re,B,R,K)),oe&&pt(oe,R),pt(()=>{B.isUnmounted=!0},R)},we=(B,R,K,ee=!1,X=!1,Q=0)=>{for(let re=Q;re{if(B.shapeFlag&6)return Ne(B.component.subTree);if(B.shapeFlag&128)return B.suspense.next();const R=h(B.anchor||B.el),K=R&&R[M1];return K?h(K):R};let Ke=!1;const gt=(B,R,K)=>{B==null?R._vnode&&yt(R._vnode,null,null,!0):v(R._vnode||null,B,R,null,null,null,K),R._vnode=B,Ke||(Ke=!0,Wu(),Tr(),Ke=!1)},bt={p:v,um:yt,m:je,r:Wn,mt:q,mc:E,pc:ne,pbc:P,n:Ne,o:e};let Nt,Qt;return t&&([Nt,Qt]=t(bt)),{render:gt,hydrate:Nt,createApp:Cg(gt,Nt)}}function Da({type:e,props:t},n){return n==="svg"&&e==="foreignObject"||n==="mathml"&&e==="annotation-xml"&&t&&t.encoding&&t.encoding.includes("html")?void 0:n}function Ps({effect:e,job:t},n){n?(e.flags|=32,t.flags|=4):(e.flags&=-33,t.flags&=-5)}function h0(e,t){return(!e||e&&!e.pendingBranch)&&t&&!t.persisted}function Ic(e,t,n=!1){const s=e.children,o=t.children;if(ce(s)&&ce(o))for(let i=0;i>1,e[n[a]]0&&(t[s]=n[i-1]),n[i]=s)}}for(i=n.length,r=n[i-1];i-- >0;)n[i]=r,r=t[r];return n}function p0(e){const t=e.subTree.component;if(t)return t.asyncDep&&!t.asyncResolved?t:p0(t)}function Ar(e){if(e)for(let t=0;tqe(m0);function zn(e,t){return Ei(e,null,t)}function da(e,t){return Ei(e,null,{flush:"post"})}function v0(e,t){return Ei(e,null,{flush:"sync"})}function te(e,t,n){return Ei(e,t,n)}function Ei(e,t,n=Le){const{immediate:s,deep:o,flush:i,once:r}=n,a=Ie({},n),c=t&&s||!t&&i!=="post";let u;if(wo){if(i==="sync"){const p=g0();u=p.__watcherHandles||(p.__watcherHandles=[])}else if(!c){const p=()=>{};return p.stop=Ht,p.resume=Ht,p.pause=Ht,p}}const f=St;a.call=(p,g,v)=>yn(p,f,g,v);let d=!1;i==="post"?a.scheduler=p=>{pt(p,f&&f.suspense)}:i!=="sync"&&(d=!0,a.scheduler=(p,g)=>{g?p():vc(p)}),a.augmentJob=p=>{t&&(p.flags|=4),d&&(p.flags|=2,f&&(p.id=f.uid,p.i=f))};const h=Lm(e,t,a);return wo&&(u?u.push(h):c&&h()),h}function Lg(e,t,n){const s=this.proxy,o=_e(e)?e.includes(".")?y0(s,e):()=>s[e]:e.bind(s,s);let i;ye(t)?i=t:(i=t.handler,n=t);const r=qs(this),a=Ei(o,i.bind(s),n);return r(),a}function y0(e,t){const n=t.split(".");return()=>{let s=e;for(let o=0;o{let f,d=Le,h;return v0(()=>{const p=e[o];Ot(f,p)&&(f=p,u())}),{get(){return c(),n.get?n.get(f):f},set(p){const g=n.set?n.set(p):p;if(!Ot(g,f)&&!(d!==Le&&Ot(p,d)))return;const v=s.vnode.props;v&&(t in v||o in v||i in v)&&(`onUpdate:${t}`in v||`onUpdate:${o}`in v||`onUpdate:${i}`in v)||(f=p,u()),s.emit(`update:${t}`,g),Ot(p,g)&&Ot(p,d)&&!Ot(g,h)&&u(),d=p,h=g}}});return a[Symbol.iterator]=()=>{let c=0;return{next(){return c<2?{value:c++?r||Le:a,done:!1}:{done:!0}}}},a}const b0=(e,t)=>t==="modelValue"||t==="model-value"?e.modelModifiers:e[`${t}Modifiers`]||e[`${tt(t)}Modifiers`]||e[`${Kt(t)}Modifiers`];function Ig(e,t,...n){if(e.isUnmounted)return;const s=e.vnode.props||Le;let o=n;const i=t.startsWith("update:"),r=i&&b0(s,t.slice(7));r&&(r.trim&&(o=n.map(f=>_e(f)?f.trim():f)),r.number&&(o=n.map(ea)));let a,c=s[a=po(t)]||s[a=po(tt(t))];!c&&i&&(c=s[a=po(Kt(t))]),c&&yn(c,e,6,o);const u=s[a+"Once"];if(u){if(!e.emitted)e.emitted={};else if(e.emitted[a])return;e.emitted[a]=!0,yn(u,e,6,o)}}const Pg=new WeakMap;function k0(e,t,n=!1){const s=n?Pg:t.emitsCache,o=s.get(e);if(o!==void 0)return o;const i=e.emits;let r={},a=!1;if(!ye(e)){const c=u=>{const f=k0(u,t,!0);f&&(a=!0,Ie(r,f))};!n&&t.mixins.length&&t.mixins.forEach(c),e.extends&&c(e.extends),e.mixins&&e.mixins.forEach(c)}return!i&&!a?(Ue(e)&&s.set(e,null),null):(ce(i)?i.forEach(c=>r[c]=null):Ie(r,i),Ue(e)&&s.set(e,r),r)}function ha(e,t){return!e||!Ys(t)?!1:(t=t.slice(2).replace(/Once$/,""),De(e,t[0].toLowerCase()+t.slice(1))||De(e,Kt(t))||De(e,t))}function ar(e){const{type:t,vnode:n,proxy:s,withProxy:o,propsOptions:[i],slots:r,attrs:a,emit:c,render:u,renderCache:f,props:d,data:h,setupState:p,ctx:g,inheritAttrs:v}=e,k=ci(e);let b,w;try{if(n.shapeFlag&4){const _=o||s,x=_;b=qt(u.call(x,_,f,d,p,h,g)),w=a}else{const _=t;b=qt(_.length>1?_(d,{attrs:a,slots:r,emit:c}):_(d,null)),w=t.props?a:Fg(a)}}catch(_){Qo.length=0,Xs(_,e,1),b=H(ut)}let y=b;if(w&&v!==!1){const _=Object.keys(w),{shapeFlag:x}=y;_.length&&x&7&&(i&&_.some(ic)&&(w=Bg(w,i)),y=Rn(y,w,!1,!0))}return n.dirs&&(y=Rn(y,null,!1,!0),y.dirs=y.dirs?y.dirs.concat(n.dirs):n.dirs),n.transition&&rs(y,n.transition),b=y,ci(k),b}function Mg(e,t=!0){let n;for(let s=0;s{let t;for(const n in e)(n==="class"||n==="style"||Ys(n))&&((t||(t={}))[n]=e[n]);return t},Bg=(e,t)=>{const n={};for(const s in e)(!ic(s)||!(s.slice(9)in t))&&(n[s]=e[s]);return n};function Ng(e,t,n){const{props:s,children:o,component:i}=e,{props:r,children:a,patchFlag:c}=t,u=i.emitsOptions;if(t.dirs||t.transition)return!0;if(n&&c>=0){if(c&1024)return!0;if(c&16)return s?of(s,r,u):!!r;if(c&8){const f=t.dynamicProps;for(let d=0;de.__isSuspense;let pl=0;const Vg={name:"Suspense",__isSuspense:!0,process(e,t,n,s,o,i,r,a,c,u){if(e==null)Dg(t,n,s,o,i,r,a,c,u);else{if(i&&i.deps>0&&!e.suspense.isInFallback){t.suspense=e.suspense,t.suspense.vnode=t,t.el=e.el;return}Rg(e,t,n,s,o,r,a,c,u)}},hydrate:Hg,normalize:zg},Og=Vg;function fi(e,t){const n=e.props&&e.props[t];ye(n)&&n()}function Dg(e,t,n,s,o,i,r,a,c){const{p:u,o:{createElement:f}}=c,d=f("div"),h=e.suspense=w0(e,o,s,t,d,n,i,r,a,c);u(null,h.pendingBranch=e.ssContent,d,null,s,h,i,r),h.deps>0?(fi(e,"onPending"),fi(e,"onFallback"),u(null,e.ssFallback,t,n,s,null,i,r),bo(h,e.ssFallback)):h.resolve(!1,!0)}function Rg(e,t,n,s,o,i,r,a,{p:c,um:u,o:{createElement:f}}){const d=t.suspense=e.suspense;d.vnode=t,t.el=e.el;const h=t.ssContent,p=t.ssFallback,{activeBranch:g,pendingBranch:v,isInFallback:k,isHydrating:b}=d;if(v)d.pendingBranch=h,Tn(v,h)?(c(v,h,d.hiddenContainer,null,o,d,i,r,a),d.deps<=0?d.resolve():k&&(b||(c(g,p,n,s,o,null,i,r,a),bo(d,p)))):(d.pendingId=pl++,b?(d.isHydrating=!1,d.activeBranch=v):u(v,o,d),d.deps=0,d.effects.length=0,d.hiddenContainer=f("div"),k?(c(null,h,d.hiddenContainer,null,o,d,i,r,a),d.deps<=0?d.resolve():(c(g,p,n,s,o,null,i,r,a),bo(d,p))):g&&Tn(g,h)?(c(g,h,n,s,o,d,i,r,a),d.resolve(!0)):(c(null,h,d.hiddenContainer,null,o,d,i,r,a),d.deps<=0&&d.resolve()));else if(g&&Tn(g,h))c(g,h,n,s,o,d,i,r,a),bo(d,h);else if(fi(t,"onPending"),d.pendingBranch=h,h.shapeFlag&512?d.pendingId=h.component.suspenseId:d.pendingId=pl++,c(null,h,d.hiddenContainer,null,o,d,i,r,a),d.deps<=0)d.resolve();else{const{timeout:w,pendingId:y}=d;w>0?setTimeout(()=>{d.pendingId===y&&d.fallback(p)},w):w===0&&d.fallback(p)}}function w0(e,t,n,s,o,i,r,a,c,u,f=!1){const{p:d,m:h,um:p,n:g,o:{parentNode:v,remove:k}}=u;let b;const w=jg(e);w&&t&&t.pendingBranch&&(b=t.pendingId,t.deps++);const y=e.props?kr(e.props.timeout):void 0,_=i,x={vnode:e,parent:t,parentComponent:n,namespace:r,container:s,hiddenContainer:o,deps:0,pendingId:pl++,timeout:typeof y=="number"?y:-1,activeBranch:null,pendingBranch:null,isInFallback:!f,isHydrating:f,isUnmounted:!1,effects:[],resolve(L=!1,V=!1){const{vnode:E,activeBranch:I,pendingBranch:P,pendingId:N,effects:$,parentComponent:U,container:q,isInFallback:J}=x;let G=!1;x.isHydrating?x.isHydrating=!1:L||(G=I&&P.transition&&P.transition.mode==="out-in",G&&(I.transition.afterLeave=()=>{N===x.pendingId&&(h(P,q,i===_?g(I):i,0),ai($),J&&E.ssFallback&&(E.ssFallback.el=null))}),I&&(v(I.el)===q&&(i=g(I)),p(I,U,x,!0),!G&&J&&E.ssFallback&&(E.ssFallback.el=null)),G||h(P,q,i,0)),bo(x,P),x.pendingBranch=null,x.isInFallback=!1;let ae=x.parent,ne=!1;for(;ae;){if(ae.pendingBranch){ae.effects.push(...$),ne=!0;break}ae=ae.parent}!ne&&!G&&ai($),x.effects=[],w&&t&&t.pendingBranch&&b===t.pendingId&&(t.deps--,t.deps===0&&!V&&t.resolve()),fi(E,"onResolve")},fallback(L){if(!x.pendingBranch)return;const{vnode:V,activeBranch:E,parentComponent:I,container:P,namespace:N}=x;fi(V,"onFallback");const $=g(E),U=()=>{x.isInFallback&&(d(null,L,P,$,I,null,N,a,c),bo(x,L))},q=L.transition&&L.transition.mode==="out-in";q&&(E.transition.afterLeave=U),x.isInFallback=!0,p(E,I,null,!0),q||U()},move(L,V,E){x.activeBranch&&h(x.activeBranch,L,V,E),x.container=L},next(){return x.activeBranch&&g(x.activeBranch)},registerDep(L,V,E){const I=!!x.pendingBranch;I&&x.deps++;const P=L.vnode.el;L.asyncDep.catch(N=>{Xs(N,L,0)}).then(N=>{if(L.isUnmounted||x.isUnmounted||x.pendingId!==L.suspenseId)return;L.asyncResolved=!0;const{vnode:$}=L;vl(L,N,!1),P&&($.el=P);const U=!P&&L.subTree.el;V(L,$,v(P||L.subTree.el),P?null:g(L.subTree),x,r,E),U&&($.placeholder=null,k(U)),pa(L,$.el),I&&--x.deps===0&&x.resolve()})},unmount(L,V){x.isUnmounted=!0,x.activeBranch&&p(x.activeBranch,n,L,V),x.pendingBranch&&p(x.pendingBranch,n,L,V)}};return x}function Hg(e,t,n,s,o,i,r,a,c){const u=t.suspense=w0(t,s,n,e.parentNode,document.createElement("div"),null,o,i,r,a,!0),f=c(e,u.pendingBranch=t.ssContent,n,u,i,r);return u.deps===0&&u.resolve(!1,!0),f}function zg(e){const{shapeFlag:t,children:n}=e,s=t&32;e.ssContent=rf(s?n.default:n),e.ssFallback=s?rf(n.fallback):H(ut)}function rf(e){let t;if(ye(e)){const n=Ws&&e._c;n&&(e._d=!1,m()),e=e(),n&&(e._d=!0,t=Mt,_0())}return ce(e)&&(e=Mg(e)),e=qt(e),t&&!e.dynamicChildren&&(e.dynamicChildren=t.filter(n=>n!==e)),e}function C0(e,t){t&&t.pendingBranch?ce(e)?t.effects.push(...e):t.effects.push(e):ai(e)}function bo(e,t){e.activeBranch=t;const{vnode:n,parentComponent:s}=e;let o=t.el;for(;!o&&t.component;)t=t.component.subTree,o=t.el;n.el=o,s&&s.subTree===n&&(s.vnode.el=o,pa(s,o))}function jg(e){const t=e.props&&e.props.suspensible;return t!=null&&t!==!1}const Y=Symbol.for("v-fgt"),Ts=Symbol.for("v-txt"),ut=Symbol.for("v-cmt"),Rs=Symbol.for("v-stc"),Qo=[];let Mt=null;function m(e=!1){Qo.push(Mt=e?null:[])}function _0(){Qo.pop(),Mt=Qo[Qo.length-1]||null}let Ws=1;function di(e,t=!1){Ws+=e,e<0&&Mt&&t&&(Mt.hasOnce=!0)}function S0(e){return e.dynamicChildren=Ws>0?Mt||fo:null,_0(),Ws>0&&Mt&&Mt.push(e),e}function C(e,t,n,s,o,i){return S0(S(e,t,n,s,o,i,!0))}function D(e,t,n,s,o){return S0(H(e,t,n,s,o,!0))}function Ln(e){return e?e.__v_isVNode===!0:!1}function Tn(e,t){return e.type===t.type&&e.key===t.key}function Ug(e){}const T0=({key:e})=>e??null,lr=({ref:e,ref_key:t,ref_for:n})=>(typeof e=="number"&&(e=""+e),e!=null?_e(e)||Ye(e)||ye(e)?{i:Tt,r:e,k:t,f:!!n}:e:null);function S(e,t=null,n=null,s=0,o=null,i=e===Y?0:1,r=!1,a=!1){const c={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&T0(t),ref:t&&lr(t),scopeId:la,slotScopeIds:null,children:n,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetStart:null,targetAnchor:null,staticCount:0,shapeFlag:i,patchFlag:s,dynamicProps:o,dynamicChildren:null,appContext:null,ctx:Tt};return a?(Pc(c,n),i&128&&e.normalize(c)):n&&(c.shapeFlag|=_e(n)?8:16),Ws>0&&!r&&Mt&&(c.patchFlag>0||i&6)&&c.patchFlag!==32&&Mt.push(c),c}const H=Wg;function Wg(e,t=null,n=null,s=0,o=null,i=!1){if((!e||e===J1)&&(e=ut),Ln(e)){const a=Rn(e,t,!0);return n&&Pc(a,n),Ws>0&&!i&&Mt&&(a.shapeFlag&6?Mt[Mt.indexOf(e)]=a:Mt.push(a)),a.patchFlag=-2,a}if(Qg(e)&&(e=e.__vccOpts),t){t=Ze(t);let{class:a,style:c}=t;a&&!_e(a)&&(t.class=T(a)),Ue(c)&&(aa(c)&&!ce(c)&&(c=Ie({},c)),t.style=Fe(c))}const r=_e(e)?1:$r(e)?128:F1(e)?64:Ue(e)?4:ye(e)?2:0;return S(e,t,n,s,o,r,i,!0)}function Ze(e){return e?aa(e)||o0(e)?Ie({},e):e:null}function Rn(e,t,n=!1,s=!1){const{props:o,ref:i,patchFlag:r,children:a,transition:c}=e,u=t?nt(o||{},t):o,f={__v_isVNode:!0,__v_skip:!0,type:e.type,props:u,key:u&&T0(u),ref:t&&t.ref?n&&i?ce(i)?i.concat(lr(t)):[i,lr(t)]:lr(t):i,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:a,target:e.target,targetStart:e.targetStart,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==Y?r===-1?16:r|16:r,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:c,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&Rn(e.ssContent),ssFallback:e.ssFallback&&Rn(e.ssFallback),placeholder:e.placeholder,el:e.el,anchor:e.anchor,ctx:e.ctx,ce:e.ce};return c&&s&&rs(f,c.clone(f)),f}function rt(e=" ",t=0){return H(Ts,null,e,t)}function E0(e,t){const n=H(Rs,null,e);return n.staticCount=t,n}function A(e="",t=!1){return t?(m(),D(ut,null,e)):H(ut,null,e)}function qt(e){return e==null||typeof e=="boolean"?H(ut):ce(e)?H(Y,null,e.slice()):Ln(e)?ys(e):H(Ts,null,String(e))}function ys(e){return e.el===null&&e.patchFlag!==-1||e.memo?e:Rn(e)}function Pc(e,t){let n=0;const{shapeFlag:s}=e;if(t==null)t=null;else if(ce(t))n=16;else if(typeof t=="object")if(s&65){const o=t.default;o&&(o._c&&(o._d=!1),Pc(e,o()),o._c&&(o._d=!0));return}else{n=32;const o=t._;!o&&!o0(t)?t._ctx=Tt:o===3&&Tt&&(Tt.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else ye(t)?(t={default:t,_ctx:Tt},n=32):(t=String(t),s&64?(n=16,t=[rt(t)]):n=8);e.children=t,e.shapeFlag|=n}function nt(...e){const t={};for(let n=0;nSt||Tt;let Lr,ml;{const e=ta(),t=(n,s)=>{let o;return(o=e[n])||(o=e[n]=[]),o.push(s),i=>{o.length>1?o.forEach(r=>r(i)):o[0](i)}};Lr=t("__VUE_INSTANCE_SETTERS__",n=>St=n),ml=t("__VUE_SSR_SETTERS__",n=>wo=n)}const qs=e=>{const t=St;return Lr(e),e.scope.on(),()=>{e.scope.off(),Lr(t)}},gl=()=>{St&&St.scope.off(),Lr(null)};function A0(e){return e.vnode.shapeFlag&4}let wo=!1;function $0(e,t=!1,n=!1){t&&ml(t);const{props:s,children:o}=e.vnode,i=A0(e);_g(e,s,i,t),xg(e,o,n||t);const r=i?Yg(e,t):void 0;return t&&ml(!1),r}function Yg(e,t){const n=e.type;e.accessCache=Object.create(null),e.proxy=new Proxy(e.ctx,ul);const{setup:s}=n;if(s){ss();const o=e.setupContext=s.length>1?I0(e):null,i=qs(e),r=Po(s,e,0,[e.props,o]),a=ac(r);if(os(),i(),(a||e.sp)&&!Ss(e)&&kc(e),a){if(r.then(gl,gl),t)return r.then(c=>{vl(e,c,t)}).catch(c=>{Xs(c,e,0)});e.asyncDep=r}else vl(e,r,t)}else L0(e,t)}function vl(e,t,n){ye(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:Ue(t)&&(e.setupState=mc(t)),L0(e,n)}let Ir,yl;function Gg(e){Ir=e,yl=t=>{t.render._rc&&(t.withProxy=new Proxy(t.ctx,rg))}}const Jg=()=>!Ir;function L0(e,t,n){const s=e.type;if(!e.render){if(!t&&Ir&&!s.render){const o=s.template||xc(e).template;if(o){const{isCustomElement:i,compilerOptions:r}=e.appContext.config,{delimiters:a,compilerOptions:c}=s,u=Ie(Ie({isCustomElement:i,delimiters:a},r),c);s.render=Ir(o,u)}}e.render=s.render||Ht,yl&&yl(e)}{const o=qs(e);ss();try{gg(e)}finally{os(),o()}}}const Xg={get(e,t){return Pt(e,"get",""),e[t]}};function I0(e){const t=n=>{e.exposed=n||{}};return{attrs:new Proxy(e.attrs,Xg),slots:e.slots,emit:e.emit,expose:t}}function xi(e){return e.exposed?e.exposeProxy||(e.exposeProxy=new Proxy(mc(go(e.exposed)),{get(t,n){if(n in t)return t[n];if(n in Xo)return Xo[n](e)},has(t,n){return n in t||n in Xo}})):e.proxy}function bl(e,t=!0){return ye(e)?e.displayName||e.name:e.name||t&&e.__name}function Qg(e){return ye(e)&&"__vccOpts"in e}const F=(e,t)=>Em(e,t,wo);function nn(e,t,n){try{di(-1);const s=arguments.length;return s===2?Ue(t)&&!ce(t)?Ln(t)?H(e,null,[t]):H(e,t):H(e,null,t):(s>3?n=Array.prototype.slice.call(arguments,2):s===3&&Ln(n)&&(n=[n]),H(e,t,n))}finally{di(1)}}function Zg(){}function ev(e,t,n,s){const o=n[s];if(o&&P0(o,e))return o;const i=t();return i.memo=e.slice(),i.cacheIndex=s,n[s]=i}function P0(e,t){const n=e.memo;if(n.length!=t.length)return!1;for(let s=0;s0&&Mt&&Mt.push(e),!0}const M0="3.5.24",tv=Ht,nv=Bm,sv=io,ov=P1,iv={createComponentInstance:x0,setupComponent:$0,renderComponentRoot:ar,setCurrentRenderingInstance:ci,isVNode:Ln,normalizeVNode:qt,getComponentPublicInstance:xi,ensureValidVNode:Tc,pushWarningContext:Im,popWarningContext:Pm},rv=iv,av=null,lv=null,cv=null;let kl;const af=typeof window<"u"&&window.trustedTypes;if(af)try{kl=af.createPolicy("vue",{createHTML:e=>e})}catch{}const F0=kl?e=>kl.createHTML(e):e=>e,uv="http://www.w3.org/2000/svg",fv="http://www.w3.org/1998/Math/MathML",Gn=typeof document<"u"?document:null,lf=Gn&&Gn.createElement("template"),dv={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,s)=>{const o=t==="svg"?Gn.createElementNS(uv,e):t==="mathml"?Gn.createElementNS(fv,e):n?Gn.createElement(e,{is:n}):Gn.createElement(e);return e==="select"&&s&&s.multiple!=null&&o.setAttribute("multiple",s.multiple),o},createText:e=>Gn.createTextNode(e),createComment:e=>Gn.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>Gn.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,n,s,o,i){const r=n?n.previousSibling:t.lastChild;if(o&&(o===i||o.nextSibling))for(;t.insertBefore(o.cloneNode(!0),n),!(o===i||!(o=o.nextSibling)););else{lf.innerHTML=F0(s==="svg"?`${e}`:s==="mathml"?`${e}`:e);const a=lf.content;if(s==="svg"||s==="mathml"){const c=a.firstChild;for(;c.firstChild;)a.appendChild(c.firstChild);a.removeChild(c)}t.insertBefore(a,n)}return[r?r.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}},fs="transition",zo="animation",Co=Symbol("_vtc"),B0={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String},N0=Ie({},bc,B0),hv=e=>(e.displayName="Transition",e.props=N0,e),vt=hv((e,{slots:t})=>nn(D1,V0(e),t)),Ms=(e,t=[])=>{ce(e)?e.forEach(n=>n(...t)):e&&e(...t)},cf=e=>e?ce(e)?e.some(t=>t.length>1):e.length>1:!1;function V0(e){const t={};for(const $ in e)$ in B0||(t[$]=e[$]);if(e.css===!1)return t;const{name:n="v",type:s,duration:o,enterFromClass:i=`${n}-enter-from`,enterActiveClass:r=`${n}-enter-active`,enterToClass:a=`${n}-enter-to`,appearFromClass:c=i,appearActiveClass:u=r,appearToClass:f=a,leaveFromClass:d=`${n}-leave-from`,leaveActiveClass:h=`${n}-leave-active`,leaveToClass:p=`${n}-leave-to`}=e,g=pv(o),v=g&&g[0],k=g&&g[1],{onBeforeEnter:b,onEnter:w,onEnterCancelled:y,onLeave:_,onLeaveCancelled:x,onBeforeAppear:L=b,onAppear:V=w,onAppearCancelled:E=y}=t,I=($,U,q,J)=>{$._enterCancelled=J,ps($,U?f:a),ps($,U?u:r),q&&q()},P=($,U)=>{$._isLeaving=!1,ps($,d),ps($,p),ps($,h),U&&U()},N=$=>(U,q)=>{const J=$?V:w,G=()=>I(U,$,q);Ms(J,[U,G]),uf(()=>{ps(U,$?c:i),Fn(U,$?f:a),cf(J)||ff(U,s,v,G)})};return Ie(t,{onBeforeEnter($){Ms(b,[$]),Fn($,i),Fn($,r)},onBeforeAppear($){Ms(L,[$]),Fn($,c),Fn($,u)},onEnter:N(!1),onAppear:N(!0),onLeave($,U){$._isLeaving=!0;const q=()=>P($,U);Fn($,d),$._enterCancelled?(Fn($,h),wl($)):(wl($),Fn($,h)),uf(()=>{$._isLeaving&&(ps($,d),Fn($,p),cf(_)||ff($,s,k,q))}),Ms(_,[$,q])},onEnterCancelled($){I($,!1,void 0,!0),Ms(y,[$])},onAppearCancelled($){I($,!0,void 0,!0),Ms(E,[$])},onLeaveCancelled($){P($),Ms(x,[$])}})}function pv(e){if(e==null)return null;if(Ue(e))return[Ra(e.enter),Ra(e.leave)];{const t=Ra(e);return[t,t]}}function Ra(e){return kr(e)}function Fn(e,t){t.split(/\s+/).forEach(n=>n&&e.classList.add(n)),(e[Co]||(e[Co]=new Set)).add(t)}function ps(e,t){t.split(/\s+/).forEach(s=>s&&e.classList.remove(s));const n=e[Co];n&&(n.delete(t),n.size||(e[Co]=void 0))}function uf(e){requestAnimationFrame(()=>{requestAnimationFrame(e)})}let mv=0;function ff(e,t,n,s){const o=e._endId=++mv,i=()=>{o===e._endId&&s()};if(n!=null)return setTimeout(i,n);const{type:r,timeout:a,propCount:c}=O0(e,t);if(!r)return s();const u=r+"end";let f=0;const d=()=>{e.removeEventListener(u,h),i()},h=p=>{p.target===e&&++f>=c&&d()};setTimeout(()=>{f(n[g]||"").split(", "),o=s(`${fs}Delay`),i=s(`${fs}Duration`),r=df(o,i),a=s(`${zo}Delay`),c=s(`${zo}Duration`),u=df(a,c);let f=null,d=0,h=0;t===fs?r>0&&(f=fs,d=r,h=i.length):t===zo?u>0&&(f=zo,d=u,h=c.length):(d=Math.max(r,u),f=d>0?r>u?fs:zo:null,h=f?f===fs?i.length:c.length:0);const p=f===fs&&/\b(?:transform|all)(?:,|$)/.test(s(`${fs}Property`).toString());return{type:f,timeout:d,propCount:h,hasTransform:p}}function df(e,t){for(;e.lengthhf(n)+hf(e[s])))}function hf(e){return e==="auto"?0:Number(e.slice(0,-1).replace(",","."))*1e3}function wl(e){return(e?e.ownerDocument:document).body.offsetHeight}function gv(e,t,n){const s=e[Co];s&&(t=(t?[t,...s]:[...s]).join(" ")),t==null?e.removeAttribute("class"):n?e.setAttribute("class",t):e.className=t}const Pr=Symbol("_vod"),D0=Symbol("_vsh"),at={name:"show",beforeMount(e,{value:t},{transition:n}){e[Pr]=e.style.display==="none"?"":e.style.display,n&&t?n.beforeEnter(e):jo(e,t)},mounted(e,{value:t},{transition:n}){n&&t&&n.enter(e)},updated(e,{value:t,oldValue:n},{transition:s}){!t!=!n&&(s?t?(s.beforeEnter(e),jo(e,!0),s.enter(e)):s.leave(e,()=>{jo(e,!1)}):jo(e,t))},beforeUnmount(e,{value:t}){jo(e,t)}};function jo(e,t){e.style.display=t?e[Pr]:"none",e[D0]=!t}function vv(){at.getSSRProps=({value:e})=>{if(!e)return{style:{display:"none"}}}}const R0=Symbol("");function yv(e){const t=dt();if(!t)return;const n=t.ut=(o=e(t.proxy))=>{Array.from(document.querySelectorAll(`[data-v-owner="${t.uid}"]`)).forEach(i=>Mr(i,o))},s=()=>{const o=e(t.proxy);t.ce?Mr(t.ce,o):Cl(t.subTree,o),n(o)};Cc(()=>{ai(s)}),be(()=>{te(s,Ht,{flush:"post"});const o=new MutationObserver(s);o.observe(t.subTree.el.parentNode,{childList:!0}),cn(()=>o.disconnect())})}function Cl(e,t){if(e.shapeFlag&128){const n=e.suspense;e=n.activeBranch,n.pendingBranch&&!n.isHydrating&&n.effects.push(()=>{Cl(n.activeBranch,t)})}for(;e.component;)e=e.component.subTree;if(e.shapeFlag&1&&e.el)Mr(e.el,t);else if(e.type===Y)e.children.forEach(n=>Cl(n,t));else if(e.type===Rs){let{el:n,anchor:s}=e;for(;n&&(Mr(n,t),n!==s);)n=n.nextSibling}}function Mr(e,t){if(e.nodeType===1){const n=e.style;let s="";for(const o in t){const i=J2(t[o]);n.setProperty(`--${o}`,i),s+=`--${o}: ${i};`}n[R0]=s}}const bv=/(?:^|;)\s*display\s*:/;function kv(e,t,n){const s=e.style,o=_e(n);let i=!1;if(n&&!o){if(t)if(_e(t))for(const r of t.split(";")){const a=r.slice(0,r.indexOf(":")).trim();n[a]==null&&cr(s,a,"")}else for(const r in t)n[r]==null&&cr(s,r,"");for(const r in n)r==="display"&&(i=!0),cr(s,r,n[r])}else if(o){if(t!==n){const r=s[R0];r&&(n+=";"+r),s.cssText=n,i=bv.test(n)}}else t&&e.removeAttribute("style");Pr in e&&(e[Pr]=i?s.display:"",e[D0]&&(s.display="none"))}const pf=/\s*!important$/;function cr(e,t,n){if(ce(n))n.forEach(s=>cr(e,t,s));else if(n==null&&(n=""),t.startsWith("--"))e.setProperty(t,n);else{const s=wv(e,t);pf.test(n)?e.setProperty(Kt(s),n.replace(pf,""),"important"):e[s]=n}}const mf=["Webkit","Moz","ms"],Ha={};function wv(e,t){const n=Ha[t];if(n)return n;let s=tt(t);if(s!=="filter"&&s in e)return Ha[t]=s;s=Js(s);for(let o=0;oza||(Tv.then(()=>za=0),za=Date.now());function xv(e,t){const n=s=>{if(!s._vts)s._vts=Date.now();else if(s._vts<=n.attached)return;yn(Av(s,n.value),t,5,[s])};return n.value=e,n.attached=Ev(),n}function Av(e,t){if(ce(t)){const n=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{n.call(e),e._stopped=!0},t.map(s=>o=>!o._stopped&&s&&s(o))}else return t}const wf=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,$v=(e,t,n,s,o,i)=>{const r=o==="svg";t==="class"?gv(e,s,r):t==="style"?kv(e,n,s):Ys(t)?ic(t)||_v(e,t,n,s,i):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):Lv(e,t,s,r))?(yf(e,t,s),!e.tagName.includes("-")&&(t==="value"||t==="checked"||t==="selected")&&vf(e,t,s,r,i,t!=="value")):e._isVueCE&&(/[A-Z]/.test(t)||!_e(s))?yf(e,tt(t),s,i,t):(t==="true-value"?e._trueValue=s:t==="false-value"&&(e._falseValue=s),vf(e,t,s,r))};function Lv(e,t,n,s){if(s)return!!(t==="innerHTML"||t==="textContent"||t in e&&wf(t)&&ye(n));if(t==="spellcheck"||t==="draggable"||t==="translate"||t==="autocorrect"||t==="sandbox"&&e.tagName==="IFRAME"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA")return!1;if(t==="width"||t==="height"){const o=e.tagName;if(o==="IMG"||o==="VIDEO"||o==="CANVAS"||o==="SOURCE")return!1}return wf(t)&&_e(n)?!1:t in e}const Cf={};function H0(e,t,n){let s=z(e,t);Qr(s)&&(s=Ie({},s,t));class o extends ma{constructor(r){super(s,r,n)}}return o.def=s,o}const Iv=((e,t)=>H0(e,t,X0)),Pv=typeof HTMLElement<"u"?HTMLElement:class{};class ma extends Pv{constructor(t,n={},s=Br){super(),this._def=t,this._props=n,this._createApp=s,this._isVueCE=!0,this._instance=null,this._app=null,this._nonce=this._def.nonce,this._connected=!1,this._resolved=!1,this._patching=!1,this._dirty=!1,this._numberProps=null,this._styleChildren=new WeakSet,this._ob=null,this.shadowRoot&&s!==Br?this._root=this.shadowRoot:t.shadowRoot!==!1?(this.attachShadow(Ie({},t.shadowRootOptions,{mode:"open"})),this._root=this.shadowRoot):this._root=this}connectedCallback(){if(!this.isConnected)return;!this.shadowRoot&&!this._resolved&&this._parseSlots(),this._connected=!0;let t=this;for(;t=t&&(t.parentNode||t.host);)if(t instanceof ma){this._parent=t;break}this._instance||(this._resolved?this._mount(this._def):t&&t._pendingResolve?this._pendingResolve=t._pendingResolve.then(()=>{this._pendingResolve=void 0,this._resolveDef()}):this._resolveDef())}_setParent(t=this._parent){t&&(this._instance.parent=t._instance,this._inheritParentContext(t))}_inheritParentContext(t=this._parent){t&&this._app&&Object.setPrototypeOf(this._app._context.provides,t._instance.provides)}disconnectedCallback(){this._connected=!1,Oe(()=>{this._connected||(this._ob&&(this._ob.disconnect(),this._ob=null),this._app&&this._app.unmount(),this._instance&&(this._instance.ce=void 0),this._app=this._instance=null,this._teleportTargets&&(this._teleportTargets.clear(),this._teleportTargets=void 0))})}_processMutations(t){for(const n of t)this._setAttr(n.attributeName)}_resolveDef(){if(this._pendingResolve)return;for(let s=0;s{this._resolved=!0,this._pendingResolve=void 0;const{props:i,styles:r}=s;let a;if(i&&!ce(i))for(const c in i){const u=i[c];(u===Number||u&&u.type===Number)&&(c in this._props&&(this._props[c]=kr(this._props[c])),(a||(a=Object.create(null)))[tt(c)]=!0)}this._numberProps=a,this._resolveProps(s),this.shadowRoot&&this._applyStyles(r),this._mount(s)},n=this._def.__asyncLoader;n?this._pendingResolve=n().then(s=>{s.configureApp=this._def.configureApp,t(this._def=s,!0)}):t(this._def)}_mount(t){this._app=this._createApp(t),this._inheritParentContext(),t.configureApp&&t.configureApp(this._app),this._app._ceVNode=this._createVNode(),this._app.mount(this._root);const n=this._instance&&this._instance.exposed;if(n)for(const s in n)De(this,s)||Object.defineProperty(this,s,{get:()=>l(n[s])})}_resolveProps(t){const{props:n}=t,s=ce(n)?n:Object.keys(n||{});for(const o of Object.keys(this))o[0]!=="_"&&s.includes(o)&&this._setProp(o,this[o]);for(const o of s.map(tt))Object.defineProperty(this,o,{get(){return this._getProp(o)},set(i){this._setProp(o,i,!0,!this._patching)}})}_setAttr(t){if(t.startsWith("data-v-"))return;const n=this.hasAttribute(t);let s=n?this.getAttribute(t):Cf;const o=tt(t);n&&this._numberProps&&this._numberProps[o]&&(s=kr(s)),this._setProp(o,s,!1,!0)}_getProp(t){return this._props[t]}_setProp(t,n,s=!0,o=!1){if(n!==this._props[t]&&(this._dirty=!0,n===Cf?delete this._props[t]:(this._props[t]=n,t==="key"&&this._app&&(this._app._ceVNode.key=n)),o&&this._instance&&this._update(),s)){const i=this._ob;i&&(this._processMutations(i.takeRecords()),i.disconnect()),n===!0?this.setAttribute(Kt(t),""):typeof n=="string"||typeof n=="number"?this.setAttribute(Kt(t),n+""):n||this.removeAttribute(Kt(t)),i&&i.observe(this,{attributes:!0})}}_update(){const t=this._createVNode();this._app&&(t.appContext=this._app._context),hi(t,this._root)}_createVNode(){const t={};this.shadowRoot||(t.onVnodeMounted=t.onVnodeUpdated=this._renderSlots.bind(this));const n=H(this._def,Ie(t,this._props));return this._instance||(n.ce=s=>{this._instance=s,s.ce=this,s.isCE=!0;const o=(i,r)=>{this.dispatchEvent(new CustomEvent(i,Qr(r[0])?Ie({detail:r},r[0]):{detail:r}))};s.emit=(i,...r)=>{o(i,r),Kt(i)!==i&&o(Kt(i),r)},this._setParent()}),n}_applyStyles(t,n){if(!t)return;if(n){if(n===this._def||this._styleChildren.has(n))return;this._styleChildren.add(n)}const s=this._nonce;for(let o=t.length-1;o>=0;o--){const i=document.createElement("style");s&&i.setAttribute("nonce",s),i.textContent=t[o],this.shadowRoot.prepend(i)}}_parseSlots(){const t=this._slots={};let n;for(;n=this.firstChild;){const s=n.nodeType===1&&n.getAttribute("slot")||"default";(t[s]||(t[s]=[])).push(n),this.removeChild(n)}}_renderSlots(){const t=this._getSlots(),n=this._instance.type.__scopeId;for(let s=0;s(delete e.props.mode,e),Nv=Bv({name:"TransitionGroup",props:Ie({},N0,{tag:String,moveClass:String}),setup(e,{slots:t}){const n=dt(),s=yc();let o,i;return Fo(()=>{if(!o.length)return;const r=e.moveClass||`${e.name||"v"}-move`;if(!Rv(o[0].el,n.vnode.el,r)){o=[];return}o.forEach(Vv),o.forEach(Ov);const a=o.filter(Dv);wl(n.vnode.el),a.forEach(c=>{const u=c.el,f=u.style;Fn(u,r),f.transform=f.webkitTransform=f.transitionDuration="";const d=u[Fr]=h=>{h&&h.target!==u||(!h||h.propertyName.endsWith("transform"))&&(u.removeEventListener("transitionend",d),u[Fr]=null,ps(u,r))};u.addEventListener("transitionend",d)}),o=[]}),()=>{const r=Pe(e),a=V0(r);let c=r.tag||Y;if(o=[],i)for(let u=0;u{a.split(/\s+/).forEach(c=>c&&s.classList.remove(c))}),n.split(/\s+/).forEach(a=>a&&s.classList.add(a)),s.style.display="none";const i=t.nodeType===1?t:t.parentNode;i.appendChild(s);const{hasTransform:r}=O0(s);return i.removeChild(s),r}const As=e=>{const t=e.props["onUpdate:modelValue"]||!1;return ce(t)?n=>mo(t,n):t};function Hv(e){e.target.composing=!0}function Sf(e){const t=e.target;t.composing&&(t.composing=!1,t.dispatchEvent(new Event("input")))}const vn=Symbol("_assign");function Tf(e,t,n){return t&&(e=e.trim()),n&&(e=ea(e)),e}const _o={created(e,{modifiers:{lazy:t,trim:n,number:s}},o){e[vn]=As(o);const i=s||o.props&&o.props.type==="number";Zn(e,t?"change":"input",r=>{r.target.composing||e[vn](Tf(e.value,n,i))}),(n||i)&&Zn(e,"change",()=>{e.value=Tf(e.value,n,i)}),t||(Zn(e,"compositionstart",Hv),Zn(e,"compositionend",Sf),Zn(e,"change",Sf))},mounted(e,{value:t}){e.value=t??""},beforeUpdate(e,{value:t,oldValue:n,modifiers:{lazy:s,trim:o,number:i}},r){if(e[vn]=As(r),e.composing)return;const a=(i||e.type==="number")&&!/^0\d/.test(e.value)?ea(e.value):e.value,c=t??"";a!==c&&(document.activeElement===e&&e.type!=="range"&&(s&&t===n||o&&e.value.trim()===c)||(e.value=c))}},Mc={deep:!0,created(e,t,n){e[vn]=As(n),Zn(e,"change",()=>{const s=e._modelValue,o=So(e),i=e.checked,r=e[vn];if(ce(s)){const a=na(s,o),c=a!==-1;if(i&&!c)r(s.concat(o));else if(!i&&c){const u=[...s];u.splice(a,1),r(u)}}else if(Gs(s)){const a=new Set(s);i?a.add(o):a.delete(o),r(a)}else r(q0(e,i))})},mounted:Ef,beforeUpdate(e,t,n){e[vn]=As(n),Ef(e,t,n)}};function Ef(e,{value:t,oldValue:n},s){e._modelValue=t;let o;if(ce(t))o=na(t,s.props.value)>-1;else if(Gs(t))o=t.has(s.props.value);else{if(t===n)return;o=xs(t,q0(e,!0))}e.checked!==o&&(e.checked=o)}const ga={created(e,{value:t},n){e.checked=xs(t,n.props.value),e[vn]=As(n),Zn(e,"change",()=>{e[vn](So(e))})},beforeUpdate(e,{value:t,oldValue:n},s){e[vn]=As(s),t!==n&&(e.checked=xs(t,s.props.value))}},W0={deep:!0,created(e,{value:t,modifiers:{number:n}},s){const o=Gs(t);Zn(e,"change",()=>{const i=Array.prototype.filter.call(e.options,r=>r.selected).map(r=>n?ea(So(r)):So(r));e[vn](e.multiple?o?new Set(i):i:i[0]),e._assigning=!0,Oe(()=>{e._assigning=!1})}),e[vn]=As(s)},mounted(e,{value:t}){xf(e,t)},beforeUpdate(e,t,n){e[vn]=As(n)},updated(e,{value:t}){e._assigning||xf(e,t)}};function xf(e,t){const n=e.multiple,s=ce(t);if(!(n&&!s&&!Gs(t))){for(let o=0,i=e.options.length;oString(u)===String(a)):r.selected=na(t,a)>-1}else r.selected=t.has(a);else if(xs(So(r),t)){e.selectedIndex!==o&&(e.selectedIndex=o);return}}!n&&e.selectedIndex!==-1&&(e.selectedIndex=-1)}}function So(e){return"_value"in e?e._value:e.value}function q0(e,t){const n=t?"_trueValue":"_falseValue";return n in e?e[n]:t}const Fc={created(e,t,n){Wi(e,t,n,null,"created")},mounted(e,t,n){Wi(e,t,n,null,"mounted")},beforeUpdate(e,t,n,s){Wi(e,t,n,s,"beforeUpdate")},updated(e,t,n,s){Wi(e,t,n,s,"updated")}};function K0(e,t){switch(e){case"SELECT":return W0;case"TEXTAREA":return _o;default:switch(t){case"checkbox":return Mc;case"radio":return ga;default:return _o}}}function Wi(e,t,n,s,o){const r=K0(e.tagName,n.props&&n.props.type)[o];r&&r(e,t,n,s)}function zv(){_o.getSSRProps=({value:e})=>({value:e}),ga.getSSRProps=({value:e},t)=>{if(t.props&&xs(t.props.value,e))return{checked:!0}},Mc.getSSRProps=({value:e},t)=>{if(ce(e)){if(t.props&&na(e,t.props.value)>-1)return{checked:!0}}else if(Gs(e)){if(t.props&&e.has(t.props.value))return{checked:!0}}else if(e)return{checked:!0}},Fc.getSSRProps=(e,t)=>{if(typeof t.type!="string")return;const n=K0(t.type.toUpperCase(),t.props&&t.props.type);if(n.getSSRProps)return n.getSSRProps(e,t)}}const jv=["ctrl","shift","alt","meta"],Uv={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>"button"in e&&e.button!==0,middle:e=>"button"in e&&e.button!==1,right:e=>"button"in e&&e.button!==2,exact:(e,t)=>jv.some(n=>e[`${n}Key`]&&!t.includes(n))},To=(e,t)=>{const n=e._withMods||(e._withMods={}),s=t.join(".");return n[s]||(n[s]=((o,...i)=>{for(let r=0;r{const n=e._withKeys||(e._withKeys={}),s=t.join(".");return n[s]||(n[s]=(o=>{if(!("key"in o))return;const i=Kt(o.key);if(t.some(r=>r===i||Wv[r]===i))return e(o)}))},Y0=Ie({patchProp:$v},dv);let Zo,Af=!1;function G0(){return Zo||(Zo=u0(Y0))}function J0(){return Zo=Af?Zo:f0(Y0),Af=!0,Zo}const hi=((...e)=>{G0().render(...e)}),qv=((...e)=>{J0().hydrate(...e)}),Br=((...e)=>{const t=G0().createApp(...e),{mount:n}=t;return t.mount=s=>{const o=Z0(s);if(!o)return;const i=t._component;!ye(i)&&!i.render&&!i.template&&(i.template=o.innerHTML),o.nodeType===1&&(o.textContent="");const r=n(o,!1,Q0(o));return o instanceof Element&&(o.removeAttribute("v-cloak"),o.setAttribute("data-v-app","")),r},t}),X0=((...e)=>{const t=J0().createApp(...e),{mount:n}=t;return t.mount=s=>{const o=Z0(s);if(o)return n(o,!0,Q0(o))},t});function Q0(e){if(e instanceof SVGElement)return"svg";if(typeof MathMLElement=="function"&&e instanceof MathMLElement)return"mathml"}function Z0(e){return _e(e)?document.querySelector(e):e}let $f=!1;const Kv=()=>{$f||($f=!0,zv(),vv())};const Yv=()=>{},Gv=Object.freeze(Object.defineProperty({__proto__:null,BaseTransition:D1,BaseTransitionPropsValidators:bc,Comment:ut,DeprecationTypes:cv,EffectScope:cc,ErrorCodes:Fm,ErrorTypeStrings:nv,Fragment:Y,KeepAlive:ng,ReactiveEffect:oi,Static:Rs,Suspense:Og,Teleport:ca,Text:Ts,TrackOpTypes:xm,Transition:vt,TransitionGroup:Qs,TriggerOpTypes:Am,VueElement:ma,assertNumber:Mm,callWithAsyncErrorHandling:yn,callWithErrorHandling:Po,camelize:tt,capitalize:Js,cloneVNode:Rn,compatUtils:lv,compile:Yv,computed:F,createApp:Br,createBlock:D,createCommentVNode:A,createElementBlock:C,createElementVNode:S,createHydrationRenderer:f0,createPropsRestProxy:Z1,createRenderer:u0,createSSRApp:X0,createSlots:Wt,createStaticVNode:E0,createTextVNode:rt,createVNode:H,customRef:gc,defineAsyncComponent:wc,defineComponent:z,defineCustomElement:H0,defineEmits:lg,defineExpose:cg,defineModel:dg,defineOptions:ug,defineProps:ag,defineSSRCustomElement:Iv,defineSlots:fg,devtools:sv,effect:Q2,effectScope:l1,getCurrentInstance:dt,getCurrentScope:_i,getCurrentWatcher:$m,getTransitionRawChildren:ua,guardReactiveProps:Ze,h:nn,handleError:Xs,hasInjectionContext:Ac,hydrate:qv,hydrateOnIdle:Gm,hydrateOnInteraction:Zm,hydrateOnMediaQuery:Qm,hydrateOnVisible:Xm,initCustomFormatter:Zg,initDirectivesForSSR:Kv,inject:qe,isMemoSame:P0,isProxy:aa,isReactive:_s,isReadonly:is,isRef:Ye,isRuntimeOnly:Jg,isShallow:an,isVNode:Ln,markRaw:go,mergeDefaults:Q1,mergeModels:$n,mergeProps:nt,nextTick:Oe,normalizeClass:T,normalizeProps:Ge,normalizeStyle:Fe,onActivated:j1,onBeforeMount:Mo,onBeforeUnmount:ls,onBeforeUpdate:Cc,onDeactivated:U1,onErrorCaptured:G1,onMounted:be,onRenderTracked:Y1,onRenderTriggered:K1,onScopeDispose:uc,onServerPrefetch:q1,onUnmounted:cn,onUpdated:Fo,onWatcherCleanup:x1,openBlock:m,popScopeId:Dm,provide:In,proxyRefs:mc,pushScopeId:Om,queuePostFlushCb:ai,reactive:Dn,readonly:It,ref:j,registerRuntimeCompiler:Gg,render:hi,renderList:le,renderSlot:M,resolveComponent:un,resolveDirective:ig,resolveDynamicComponent:Be,resolveFilter:av,resolveTransitionHooks:ko,setBlockTracking:di,setDevtoolsHook:ov,setTransitionHooks:rs,shallowReactive:pc,shallowReadonly:al,shallowRef:ze,ssrContextKey:m0,ssrUtils:rv,stop:Z2,toDisplayString:W,toHandlerKey:po,toHandlers:Ec,toRaw:Pe,toRef:T1,toRefs:Cm,toValue:Se,transformVNodeArgs:Ug,triggerRef:bm,unref:l,useAttrs:pg,useCssModule:Fv,useCssVars:yv,useHost:z0,useId:H1,useModel:Jt,useSSRContext:g0,useShadowRoot:Mv,useSlots:Ti,useTemplateRef:z1,useTransitionState:yc,vModelCheckbox:Mc,vModelDynamic:Fc,vModelRadio:ga,vModelSelect:W0,vModelText:_o,vShow:at,version:M0,warn:tv,watch:te,watchEffect:zn,watchPostEffect:da,watchSyncEffect:v0,withAsyncContext:mg,withCtx:O,withDefaults:hg,withDirectives:et,withKeys:va,withMemo:ev,withModifiers:To,withScopeId:Rm},Symbol.toStringTag,{value:"Module"})),eh=z({__name:"VPBadge",props:{text:{},type:{default:"tip"}},setup(e){return(t,n)=>(m(),C("span",{class:T(["VPBadge",e.type])},[M(t.$slots,"default",{},()=>[rt(W(e.text),1)])],2))}}),Jv=window.__VP_SITE_DATA__;function Bc(e,t){return _i()?(uc(e,t),!0):!1}const ja=new WeakMap,Xv=(...e)=>{var t;const n=e[0],s=(t=dt())===null||t===void 0?void 0:t.proxy,o=s??_i();if(o==null&&!Ac())throw new Error("injectLocal must be called in setup");return o&&ja.has(o)&&n in ja.get(o)?ja.get(o)[n]:qe(...e)},th=typeof window<"u"&&typeof document<"u";typeof WorkerGlobalScope<"u"&&globalThis instanceof WorkerGlobalScope;const Qv=e=>e!=null,Zv=Object.prototype.toString,e3=e=>Zv.call(e)==="[object Object]",$s=()=>{},Lf=t3();function t3(){var e,t,n;return th&&((e=window)===null||e===void 0||(e=e.navigator)===null||e===void 0?void 0:e.userAgent)&&(/iP(?:ad|hone|od)/.test(window.navigator.userAgent)||((t=window)===null||t===void 0||(t=t.navigator)===null||t===void 0?void 0:t.maxTouchPoints)>2&&/iPad|Macintosh/.test((n=window)===null||n===void 0?void 0:n.navigator.userAgent))}function Nc(...e){if(e.length!==1)return T1(...e);const t=e[0];return typeof t=="function"?It(gc(()=>({get:t,set:$s}))):j(t)}function Vc(e,t){function n(...s){return new Promise((o,i)=>{Promise.resolve(e(()=>t.apply(this,s),{fn:t,thisArg:this,args:s})).then(o).catch(i)})}return n}const nh=e=>e();function sh(e,t={}){let n,s,o=$s;const i=c=>{clearTimeout(c),o(),o=$s};let r;return c=>{const u=Se(e),f=Se(t.maxWait);return n&&i(n),u<=0||f!==void 0&&f<=0?(s&&(i(s),s=void 0),Promise.resolve(c())):new Promise((d,h)=>{o=t.rejectOnCancel?h:d,r=c,f&&!s&&(s=setTimeout(()=>{n&&i(n),s=void 0,d(r())},f)),n=setTimeout(()=>{s&&i(s),s=void 0,d(c())},u)})}}function n3(...e){let t=0,n,s=!0,o=$s,i,r,a,c,u;!Ye(e[0])&&typeof e[0]=="object"?{delay:r,trailing:a=!0,leading:c=!0,rejectOnCancel:u=!1}=e[0]:[r,a=!0,c=!0,u=!1]=e;const f=()=>{n&&(clearTimeout(n),n=void 0,o(),o=$s)};return h=>{const p=Se(r),g=Date.now()-t,v=()=>i=h();return f(),p<=0?(t=Date.now(),v()):(g>p?(t=Date.now(),(c||!s)&&v()):a&&(i=new Promise((k,b)=>{o=u?b:k,n=setTimeout(()=>{t=Date.now(),s=!0,k(v()),f()},Math.max(0,p-g))})),!c&&!n&&(n=setTimeout(()=>s=!0,p)),s=!1,i)}}function s3(e=nh,t={}){const{initialState:n="active"}=t,s=Nc(n==="active");function o(){s.value=!1}function i(){s.value=!0}const r=(...a)=>{s.value&&e(...a)};return{isActive:It(s),pause:o,resume:i,eventFilter:r}}function If(e){return e.endsWith("rem")?Number.parseFloat(e)*16:Number.parseFloat(e)}function ur(e){return Array.isArray(e)?e:[e]}function oh(e){return dt()}function o3(e,t=200,n={}){return Vc(sh(t,n),e)}function i3(e,t=200,n=!1,s=!0,o=!1){return Vc(n3(t,n,s,o),e)}function ih(e,t,n={}){const{eventFilter:s=nh,...o}=n;return te(e,Vc(s,t),o)}function r3(e,t,n={}){const{eventFilter:s,initialState:o="active",...i}=n,{eventFilter:r,pause:a,resume:c,isActive:u}=s3(s,{initialState:o});return{stop:ih(e,t,{...i,eventFilter:r}),pause:a,resume:c,isActive:u}}const a3=r3;function ya(e,t=!0,n){oh()?be(e,n):t?e():Oe(e)}function l3(e,t){oh()&&cn(e,t)}function c3(e,t,n={}){const{debounce:s=0,maxWait:o=void 0,...i}=n;return ih(e,t,{...i,eventFilter:sh(s,{maxWait:o})})}const jA=c3;function u3(e,t,n){return te(e,t,{...n,immediate:!0})}function UA(e,t,n){var s;let o;Ye(n)?o={evaluating:n}:o=n||{};const{lazy:i=!1,flush:r="sync",evaluating:a=void 0,shallow:c=!0,onError:u=(s=globalThis.reportError)!==null&&s!==void 0?s:$s}=o,f=ze(!i),d=c?ze(t):j(t);let h=0;return zn(async p=>{if(!f.value)return;h++;const g=h;let v=!1;a&&Promise.resolve().then(()=>{a.value=!0});try{const k=await e(b=>{p(()=>{a&&(a.value=!1),v||b()})});g===h&&(d.value=k)}catch(k){u(k)}finally{a&&g===h&&(a.value=!1),v=!0}},{flush:r}),i?F(()=>(f.value=!0,d.value)):d}const Rt=th?window:void 0;function ba(e){var t;const n=Se(e);return(t=n?.$el)!==null&&t!==void 0?t:n}function Hn(...e){const t=[],n=()=>{t.forEach(a=>a()),t.length=0},s=(a,c,u,f)=>(a.addEventListener(c,u,f),()=>a.removeEventListener(c,u,f)),o=F(()=>{const a=ur(Se(e[0])).filter(c=>c!=null);return a.every(c=>typeof c!="string")?a:void 0}),i=u3(()=>{var a,c;return[(a=(c=o.value)===null||c===void 0?void 0:c.map(u=>ba(u)))!==null&&a!==void 0?a:[Rt].filter(u=>u!=null),ur(Se(o.value?e[1]:e[0])),ur(l(o.value?e[2]:e[1])),Se(o.value?e[3]:e[2])]},([a,c,u,f])=>{if(n(),!a?.length||!c?.length||!u?.length)return;const d=e3(f)?{...f}:f;t.push(...a.flatMap(h=>c.flatMap(p=>u.map(g=>s(h,p,g,d)))))},{flush:"post"}),r=()=>{i(),n()};return Bc(n),r}function f3(){const e=ze(!1),t=dt();return t&&be(()=>{e.value=!0},t),e}function Oc(e){const t=f3();return F(()=>(t.value,!!e()))}function d3(e,t,n={}){const{window:s=Rt,...o}=n;let i;const r=Oc(()=>s&&"MutationObserver"in s),a=()=>{i&&(i.disconnect(),i=void 0)},c=te(F(()=>{const d=ur(Se(e)).map(ba).filter(Qv);return new Set(d)}),d=>{a(),r.value&&d.size&&(i=new MutationObserver(t),d.forEach(h=>i.observe(h,o)))},{immediate:!0,flush:"post"}),u=()=>i?.takeRecords(),f=()=>{c(),a()};return Bc(f),{isSupported:r,stop:f,takeRecords:u}}function h3(e){return typeof e=="function"?e:typeof e=="string"?t=>t.key===e:Array.isArray(e)?t=>e.includes(t.key):()=>!0}function _l(...e){let t,n,s={};e.length===3?(t=e[0],n=e[1],s=e[2]):e.length===2?typeof e[1]=="object"?(t=!0,n=e[0],s=e[1]):(t=e[0],n=e[1]):(t=!0,n=e[0]);const{target:o=Rt,eventName:i="keydown",passive:r=!1,dedupe:a=!1}=s,c=h3(t);return Hn(o,i,f=>{f.repeat&&Se(a)||c(f)&&n(f)},r)}const p3=Symbol("vueuse-ssr-width");function m3(){const e=Ac()?Xv(p3,null):null;return typeof e=="number"?e:void 0}function Nr(e,t={}){const{window:n=Rt,ssrWidth:s=m3()}=t,o=Oc(()=>n&&"matchMedia"in n&&typeof n.matchMedia=="function"),i=ze(typeof s=="number"),r=ze(),a=ze(!1),c=u=>{a.value=u.matches};return zn(()=>{if(i.value){i.value=!o.value,a.value=Se(e).split(",").some(u=>{const f=u.includes("not all"),d=u.match(/\(\s*min-width:\s*(-?\d+(?:\.\d*)?[a-z]+\s*)\)/),h=u.match(/\(\s*max-width:\s*(-?\d+(?:\.\d*)?[a-z]+\s*)\)/);let p=!!(d||h);return d&&p&&(p=s>=If(d[1])),h&&p&&(p=s<=If(h[1])),f?!p:p});return}o.value&&(r.value=n.matchMedia(Se(e)),a.value=r.value.matches)}),Hn(r,"change",c,{passive:!0}),F(()=>a.value)}const qi=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{},Ki="__vueuse_ssr_handlers__",g3=v3();function v3(){return Ki in qi||(qi[Ki]=qi[Ki]||{}),qi[Ki]}function rh(e,t){return g3[e]||t}function ah(e){return Nr("(prefers-color-scheme: dark)",e)}function y3(e){return e==null?"any":e instanceof Set?"set":e instanceof Map?"map":e instanceof Date?"date":typeof e=="boolean"?"boolean":typeof e=="string"?"string":typeof e=="object"?"object":Number.isNaN(e)?"any":"number"}const b3={boolean:{read:e=>e==="true",write:e=>String(e)},object:{read:e=>JSON.parse(e),write:e=>JSON.stringify(e)},number:{read:e=>Number.parseFloat(e),write:e=>String(e)},any:{read:e=>e,write:e=>String(e)},string:{read:e=>e,write:e=>String(e)},map:{read:e=>new Map(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e.entries()))},set:{read:e=>new Set(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e))},date:{read:e=>new Date(e),write:e=>e.toISOString()}},Pf="vueuse-storage";function Dc(e,t,n,s={}){var o;const{flush:i="pre",deep:r=!0,listenToStorageChanges:a=!0,writeDefaults:c=!0,mergeDefaults:u=!1,shallow:f,window:d=Rt,eventFilter:h,onError:p=q=>{console.error(q)},initOnMounted:g}=s,v=(f?ze:j)(typeof t=="function"?t():t),k=F(()=>Se(e));if(!n)try{n=rh("getDefaultStorage",()=>Rt?.localStorage)()}catch(q){p(q)}if(!n)return v;const b=Se(t),w=y3(b),y=(o=s.serializer)!==null&&o!==void 0?o:b3[w],{pause:_,resume:x}=a3(v,q=>P(q),{flush:i,deep:r,eventFilter:h});te(k,()=>$(),{flush:i});let L=!1;const V=q=>{g&&!L||$(q)},E=q=>{g&&!L||U(q)};d&&a&&(n instanceof Storage?Hn(d,"storage",V,{passive:!0}):Hn(d,Pf,E)),g?ya(()=>{L=!0,$()}):$();function I(q,J){if(d){const G={key:k.value,oldValue:q,newValue:J,storageArea:n};d.dispatchEvent(n instanceof Storage?new StorageEvent("storage",G):new CustomEvent(Pf,{detail:G}))}}function P(q){try{const J=n.getItem(k.value);if(q==null)I(J,null),n.removeItem(k.value);else{const G=y.write(q);J!==G&&(n.setItem(k.value,G),I(J,G))}}catch(J){p(J)}}function N(q){const J=q?q.newValue:n.getItem(k.value);if(J==null)return c&&b!=null&&n.setItem(k.value,y.write(b)),b;if(!q&&u){const G=y.read(J);return typeof u=="function"?u(G,b):w==="object"&&!Array.isArray(G)?{...b,...G}:G}else return typeof J!="string"?J:y.read(J)}function $(q){if(!(q&&q.storageArea!==n)){if(q&&q.key==null){v.value=b;return}if(!(q&&q.key!==k.value)){_();try{const J=y.write(v.value);(q===void 0||q?.newValue!==J)&&(v.value=N(q))}catch(J){p(J)}finally{q?Oe(x):x()}}}}function U(q){$(q.detail)}return v}const k3="*,*::before,*::after{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}";function w3(e={}){const{selector:t="html",attribute:n="class",initialValue:s="auto",window:o=Rt,storage:i,storageKey:r="vueuse-color-scheme",listenToStorageChanges:a=!0,storageRef:c,emitAuto:u,disableTransition:f=!0}=e,d={auto:"",light:"light",dark:"dark",...e.modes||{}},h=ah({window:o}),p=F(()=>h.value?"dark":"light"),g=c||(r==null?Nc(s):Dc(r,s,i,{window:o,listenToStorageChanges:a})),v=F(()=>g.value==="auto"?p.value:g.value),k=rh("updateHTMLAttrs",(_,x,L)=>{const V=typeof _=="string"?o?.document.querySelector(_):ba(_);if(!V)return;const E=new Set,I=new Set;let P=null;if(x==="class"){const $=L.split(/\s/g);Object.values(d).flatMap(U=>(U||"").split(/\s/g)).filter(Boolean).forEach(U=>{$.includes(U)?E.add(U):I.add(U)})}else P={key:x,value:L};if(E.size===0&&I.size===0&&P===null)return;let N;f&&(N=o.document.createElement("style"),N.appendChild(document.createTextNode(k3)),o.document.head.appendChild(N));for(const $ of E)V.classList.add($);for(const $ of I)V.classList.remove($);P&&V.setAttribute(P.key,P.value),f&&(o.getComputedStyle(N).opacity,document.head.removeChild(N))});function b(_){var x;k(t,n,(x=d[_])!==null&&x!==void 0?x:_)}function w(_){e.onChanged?e.onChanged(_,b):b(_)}te(v,w,{flush:"post",immediate:!0}),ya(()=>w(v.value));const y=F({get(){return u?g.value:v.value},set(_){g.value=_}});return Object.assign(y,{store:g,system:p,state:v})}function C3(e={}){const{valueDark:t="dark",valueLight:n=""}=e,s=w3({...e,onChanged:(i,r)=>{var a;e.onChanged?(a=e.onChanged)===null||a===void 0||a.call(e,i==="dark",r,i):r(i)},modes:{dark:t,light:n}}),o=F(()=>s.system.value);return F({get(){return s.value==="dark"},set(i){const r=i?"dark":"light";o.value===r?s.value="auto":s.value=r}})}function Ua(e){return typeof Window<"u"&&e instanceof Window?e.document.documentElement:typeof Document<"u"&&e instanceof Document?e.documentElement:e}const Mf=1;function _3(e,t={}){const{throttle:n=0,idle:s=200,onStop:o=$s,onScroll:i=$s,offset:r={left:0,right:0,top:0,bottom:0},observe:a={mutation:!1},eventListenerOptions:c={capture:!1,passive:!0},behavior:u="auto",window:f=Rt,onError:d=I=>{console.error(I)}}=t,h=typeof a=="boolean"?{mutation:a}:a,p=ze(0),g=ze(0),v=F({get(){return p.value},set(I){b(I,void 0)}}),k=F({get(){return g.value},set(I){b(void 0,I)}});function b(I,P){var N,$,U,q;if(!f)return;const J=Se(e);if(!J)return;(N=J instanceof Document?f.document.body:J)===null||N===void 0||N.scrollTo({top:($=Se(P))!==null&&$!==void 0?$:k.value,left:(U=Se(I))!==null&&U!==void 0?U:v.value,behavior:Se(u)});const G=(J==null||(q=J.document)===null||q===void 0?void 0:q.documentElement)||J?.documentElement||J;v!=null&&(p.value=G.scrollLeft),k!=null&&(g.value=G.scrollTop)}const w=ze(!1),y=Dn({left:!0,right:!1,top:!0,bottom:!1}),_=Dn({left:!1,right:!1,top:!1,bottom:!1}),x=I=>{w.value&&(w.value=!1,_.left=!1,_.right=!1,_.top=!1,_.bottom=!1,o(I))},L=o3(x,n+s),V=I=>{var P;if(!f)return;const N=(I==null||(P=I.document)===null||P===void 0?void 0:P.documentElement)||I?.documentElement||ba(I),{display:$,flexDirection:U,direction:q}=getComputedStyle(N),J=q==="rtl"?-1:1,G=N.scrollLeft;_.left=Gp.value;const ae=Math.abs(G*J)<=(r.left||0),ne=Math.abs(G*J)+N.clientWidth>=N.scrollWidth-(r.right||0)-Mf;$==="flex"&&U==="row-reverse"?(y.left=ne,y.right=ae):(y.left=ae,y.right=ne),p.value=G;let he=N.scrollTop;I===f.document&&!he&&(he=f.document.body.scrollTop),_.top=heg.value;const st=Math.abs(he)<=(r.top||0),je=Math.abs(he)+N.clientHeight>=N.scrollHeight-(r.bottom||0)-Mf;$==="flex"&&U==="column-reverse"?(y.top=je,y.bottom=st):(y.top=st,y.bottom=je),g.value=he},E=I=>{var P;f&&(V((P=I.target.documentElement)!==null&&P!==void 0?P:I.target),w.value=!0,L(I),i(I))};return Hn(e,"scroll",n?i3(E,n,!0,!1):E,c),ya(()=>{try{const I=Se(e);if(!I)return;V(I)}catch(I){d(I)}}),h?.mutation&&e!=null&&e!==f&&e!==document&&d3(e,()=>{const I=Se(e);I&&V(I)},{attributes:!0,childList:!0,subtree:!0}),Hn(e,"scrollend",x,c),{x:v,y:k,isScrolling:w,arrivedState:y,directions:_,measure(){const I=Se(e);f&&I&&V(I)}}}function WA(e,t,n={}){const{window:s=Rt}=n;return Dc(e,t,s?.localStorage,n)}function S3(e={}){const{window:t=Rt}=e,n=t?.navigator,s=Oc(()=>n&&"language"in n),o=ze(n?.language);return Hn(t,"languagechange",()=>{n&&(o.value=n.language)},{passive:!0}),{isSupported:s,language:o}}function lh(e){const t=window.getComputedStyle(e);if(t.overflowX==="scroll"||t.overflowY==="scroll"||t.overflowX==="auto"&&e.clientWidth1?!0:(t.preventDefault&&t.preventDefault(),!1)}const Wa=new WeakMap;function ch(e,t=!1){const n=ze(t);let s=null,o="";te(Nc(e),a=>{const c=Ua(Se(a));if(c){const u=c;if(Wa.get(u)||Wa.set(u,u.style.overflow),u.style.overflow!=="hidden"&&(o=u.style.overflow),u.style.overflow==="hidden")return n.value=!0;if(n.value)return u.style.overflow="hidden"}},{immediate:!0});const i=()=>{const a=Ua(Se(e));!a||n.value||(Lf&&(s=Hn(a,"touchmove",c=>{T3(c)},{passive:!1})),a.style.overflow="hidden",n.value=!0)},r=()=>{const a=Ua(Se(e));!a||!n.value||(Lf&&s?.(),a.style.overflow=o,Wa.delete(a),n.value=!1)};return Bc(r),F({get(){return n.value},set(a){a?i():r()}})}function qA(e,t,n={}){const{window:s=Rt}=n;return Dc(e,t,s?.sessionStorage,n)}function uh(e={}){const{window:t=Rt,...n}=e;return _3(t,n)}function E3(e={}){const{window:t=Rt,initialWidth:n=Number.POSITIVE_INFINITY,initialHeight:s=Number.POSITIVE_INFINITY,listenOrientation:o=!0,includeScrollbar:i=!0,type:r="inner"}=e,a=ze(n),c=ze(s),u=()=>{if(t)if(r==="outer")a.value=t.outerWidth,c.value=t.outerHeight;else if(r==="visual"&&t.visualViewport){const{width:d,height:h,scale:p}=t.visualViewport;a.value=Math.round(d*p),c.value=Math.round(h*p)}else i?(a.value=t.innerWidth,c.value=t.innerHeight):(a.value=t.document.documentElement.clientWidth,c.value=t.document.documentElement.clientHeight)};u(),ya(u);const f={passive:!0};return Hn("resize",u,f),t&&r==="visual"&&t.visualViewport&&Hn(t.visualViewport,"resize",u,f),o&&te(Nr("(orientation: portrait)"),()=>u()),{width:a,height:c}}const x3={};var A3={};const ka=/^(?:[a-z]+:|\/\/)/i,$3="vitepress-theme-appearance",fh=Symbol("stack-view:unpack"),L3=/#.*$/,I3=/[?#].*$/,P3=/(?:(^|\/)index)?\.(?:md|html)$/,wt=typeof document<"u",dh={relativePath:"404.md",filePath:"",title:"404",description:"Not Found",headers:[],frontmatter:{sidebar:!1,layout:"page"},lastUpdated:0,isNotFound:!0};function Ls(e,t,n=!1){if(t===void 0)return!1;if(e=Ff(`/${e}`),n)return new RegExp(t).test(e);if(Ff(t)!==e)return!1;const s=t.match(L3);return s?(wt?location.hash:"")===s[0]:!0}function Ff(e){return decodeURI(e).replace(I3,"").replace(P3,"$1")}function hh(e){return ka.test(e)}function M3(e,t){return Object.keys(e?.locales||{}).find(n=>n!=="root"&&!hh(n)&&Ls(t,`^/${n}/`,!0))||"root"}function F3(e,t){const n=M3(e,t),{label:s,link:o,...i}=e.locales[n]??{};Object.assign(i,{localeIndex:n});const r=R3(e,t),a={head:V3(e.head??[],i.head??[],...r.map(c=>c.head??[]).reverse())};return Rc(a,...r,i,e)}function B3(e,t){const n=t.title||e.title,s=t.titleTemplate??e.titleTemplate;if(typeof s=="string"&&s.includes(":title"))return s.replace(/:title/g,n);const o=N3(e.title,s);return n===o.slice(3)?n:`${n}${o}`}function N3(e,t){return t===!1?"":t===!0||t===void 0?` | ${e}`:e===t?"":` | ${t}`}function V3(...e){const t=[],n=new Map;for(const s of e)for(const o of s){const[i,r]=o,a=Object.entries(r)[0];if(i!=="meta"||!a){t.push(o);continue}const c=`${a[0]}=${a[1]}`,u=n.get(c);u!=null?t[u]=o:(n.set(c,t.length),t.push(o))}return t}const O3=/[\u0000-\u001F"#$&*+,:;<=>?[\]^`{|}\u007F]/g,D3=/^[a-z]:/i;function Bf(e){const t=D3.exec(e),n=t?t[0]:"";return n+e.slice(n.length).replace(O3,"_").replace(/(^|\/)_+(?=[^/]*$)/,"$1")}const qa=new Set;function ph(e){if(qa.size===0){const n=typeof process=="object"&&A3?.VITE_EXTRA_EXTENSIONS||x3?.VITE_EXTRA_EXTENSIONS||"";("3g2,3gp,aac,ai,apng,au,avif,bin,bmp,cer,class,conf,crl,css,csv,dll,doc,eps,epub,exe,gif,gz,ics,ief,jar,jpe,jpeg,jpg,js,json,jsonld,m4a,man,mid,midi,mjs,mov,mp2,mp3,mp4,mpe,mpeg,mpg,mpp,oga,ogg,ogv,ogx,opus,otf,p10,p7c,p7m,p7s,pdf,png,ps,qt,roff,rtf,rtx,ser,svg,t,tif,tiff,tr,ts,tsv,ttf,txt,vtt,wav,weba,webm,webp,woff,woff2,xhtml,xml,yaml,yml,zip"+(n&&typeof n=="string"?","+n:"")).split(",").forEach(s=>qa.add(s))}const t=e.split(".").pop();return t==null||!qa.has(t.toLowerCase())}function KA(e){return e.replace(/[|\\{}()[\]^$+*?.]/g,"\\$&").replace(/-/g,"\\x2d")}function R3({additionalConfig:e},t){if(e===void 0)return[];if(typeof e=="function")return e(t)??[];const n=[],s=t.split("/").slice(0,-1);for(;s.length;){const o=`/${s.join("/")}/`;n.push(e[o]),s.pop()}return n.push(e["/"]),n.filter(o=>o!==void 0)}function Rc(...e){const t=e.filter(o=>H3(o));if(t.length<=1)return e[0];const n=new Set(t.flatMap(o=>Reflect.ownKeys(o))),s=[...n];return new Proxy({},{get(o,i){return i===fh?t:Rc(...t.map(r=>r[i]).filter(r=>r!==void 0))},set(){throw new Error("StackView is read-only and cannot be mutated.")},has(o,i){return n.has(i)},ownKeys(){return s},getOwnPropertyDescriptor(o,i){for(const r of t){const a=Object.getOwnPropertyDescriptor(r,i);if(a)return a}}})}Rc.unpack=function(e){return e?.[fh]};function H3(e){return Object.prototype.toString.call(e)==="[object Object]"}const z3=["shellscript","shell","bash","sh","zsh"];function YA(e){return z3.includes(e)}const j3=Symbol(),ks=ze(It(Jv));function GA(e){const t=F(()=>F3(ks.value,e.data.relativePath)),n=t.value.appearance,s=n==="force-dark"?j(!0):n==="force-auto"?ah():n?C3({storageKey:$3,initialValue:()=>n==="dark"?"dark":"auto",...typeof n=="object"?n:{}}):j(!1),o=j(wt?location.hash:"");return wt&&window.addEventListener("hashchange",()=>{o.value=location.hash}),te(()=>e.data,()=>{o.value=wt?location.hash:""}),{site:t,theme:F(()=>t.value.themeConfig),page:F(()=>e.data),frontmatter:F(()=>e.data.frontmatter),params:F(()=>e.data.params),lang:F(()=>t.value.lang),dir:F(()=>e.data.frontmatter.dir||t.value.dir),localeIndex:F(()=>t.value.localeIndex||"root"),title:F(()=>B3(t.value,e.data)),description:F(()=>e.data.description||t.value.description),isDark:s,hash:F(()=>o.value)}}function Ae(){const e=qe(j3);if(!e)throw new Error("vitepress data not properly injected in app");return e}function U3(e,t){return`${e}${t}`.replace(/\/+/g,"/")}function Ee(e){return ka.test(e)||!e.startsWith("/")?e:U3(ks.value.base,e)}function JA(e){let t=e.replace(/\.html$/,"");if(t=decodeURIComponent(t),t=t.replace(/\/$/,"/index"),wt){t=Bf(t.slice(1).replace(/\//g,"_")||"index")+".md";let s=__VP_HASH_MAP__[t.toLowerCase()];if(s||(t=t.endsWith("_index.md")?t.slice(0,-9)+".md":t.slice(0,-3)+"_index.md",s=__VP_HASH_MAP__[t.toLowerCase()]),!s)return null;t=`/assets/${t}.${s}.js`}else t=`./${Bf(t.slice(1).replace(/\//g,"_"))}.md.js`;return t}let fr=[];function Ai(e){fr.push(e),l3(()=>{fr=fr.filter(t=>t!==e)})}function Hc(){let e=ks.value.scrollOffset,t=0,n=24;if(typeof e=="object"&&"padding"in e&&(n=e.padding,e=e.selector),typeof e=="number")t=e;else if(typeof e=="string")t=Nf(e,n);else if(Array.isArray(e))for(const s of e){const o=Nf(s,n);if(o){t=o;break}}return t}function Nf(e,t){const n=document.querySelector(e);if(!n)return 0;const s=n.getBoundingClientRect().bottom;return s<0?0:s+t}const W3=Symbol(),mh="http://a.com",q3=()=>({path:"/",hash:"",query:"",component:null,data:dh});function XA(e,t){const n=Dn(q3()),s={route:n,async go(a,c){a=Tl(a),await s.onBeforeRouteChange?.(a)!==!1&&((!wt||await K3(a,c))&&await i(a),r(),await s.onAfterRouteChange?.(a))}};let o=null;async function i(a,c=0,u=!1){if(await s.onBeforePageLoad?.(a)===!1)return;const f=new URL(a,mh),d=o=f.pathname;try{let h=await e(d);if(!h)throw new Error(`Page not found: ${d}`);if(o===d){o=null;const{default:p,__pageData:g}=h;if(!p)throw new Error(`Invalid route component: ${p}`);await s.onAfterPageLoad?.(a),n.path=wt?d:Ee(d),n.component=go(p),n.data=go(g),r(f),wt&&Oe(()=>{let v=ks.value.base+g.relativePath.replace(/(?:(^|\/)index)?\.md$/,"$1");return!ks.value.cleanUrls&&!v.endsWith("/")&&(v+=".html"),v!==f.pathname&&(f.pathname=v,a=v+f.search+f.hash,history.replaceState({},"",a)),Sl(f.hash,!1,c)})}}catch(h){if(!/fetch|Page not found/.test(h.message)&&!/^\/404(\.html|\/)?$/.test(a)&&console.error(h),!u)try{const p=await fetch(ks.value.base+"hashmap.json");window.__VP_HASH_MAP__=await p.json(),await i(a,c,!0);return}catch{}if(o===d){o=null,n.path=wt?d:Ee(d),n.component=t?go(t):null;const p=wt?n.path.replace(/(^|\/)$/,"$1index").replace(/(\.html)?$/,".md").slice(ks.value.base.length):"404.md";n.data={...dh,relativePath:p},r(f)}}}function r(a=wt?location:{search:"",hash:""}){n.query=a.search,n.hash=decodeURIComponent(a.hash)}return wt&&(history.state===null&&history.replaceState({},""),window.addEventListener("click",a=>{if(a.defaultPrevented||!(a.target instanceof Element)||a.target.closest("button")||a.button!==0||a.ctrlKey||a.shiftKey||a.altKey||a.metaKey)return;const c=a.target.closest("a");if(!c||c.closest(".vp-raw")||c.hasAttribute("download")||c.hasAttribute("target"))return;const u=c.getAttribute("href")??(c instanceof SVGAElement?c.getAttribute("xlink:href"):null);if(u==null)return;const{href:f,origin:d,pathname:h}=new URL(u,c.baseURI),p=new URL(location.href);d===p.origin&&ph(h)&&(a.preventDefault(),s.go(f,{smoothScroll:c.classList.contains("header-anchor")}))},{capture:!0}),window.addEventListener("popstate",async a=>{if(a.state===null)return;const c=Tl(location.href);await i(c,a.state&&a.state.scrollPosition||0),r(),await s.onAfterRouteChange?.(c)}),window.addEventListener("hashchange",a=>{a.preventDefault(),r()})),s}function jn(){const e=qe(W3);if(!e)throw new Error("useRouter() is called without provider.");return e}function kn(){return jn().route}function Sl(e,t=!1,n=0){if(!e||n){window.scrollTo(0,n);return}let s=null;try{s=document.getElementById(decodeURIComponent(e).slice(1))}catch(a){console.warn(a)}if(!s)return;const o=window.scrollY+s.getBoundingClientRect().top-Hc()+Number.parseInt(window.getComputedStyle(s).paddingTop,10)||0,i=window.matchMedia("(prefers-reduced-motion)").matches?"instant":t&&Math.abs(o-window.scrollY)<=window.innerHeight?"smooth":"auto";requestAnimationFrame(()=>{if(window.scrollTo({left:0,top:o,behavior:i}),s.focus({preventScroll:!0}),document.activeElement===s||s.hasAttribute("tabindex"))return;const a=()=>{s.removeAttribute("tabindex"),s.removeEventListener("blur",a)};s.setAttribute("tabindex","-1"),s.addEventListener("blur",a),s.focus({preventScroll:!0}),document.activeElement!==s&&a()})}function Tl(e){const t=new URL(e,mh);return t.pathname=t.pathname.replace(/(^|\/)index(\.html)?$/,"$1"),ks.value.cleanUrls?t.pathname=t.pathname.replace(/\.html$/,""):!t.pathname.endsWith("/")&&!t.pathname.endsWith(".html")&&(t.pathname+=".html"),t.pathname+t.search+t.hash}async function K3(e,{smoothScroll:t=!1,initialLoad:n=!1,replace:s=!1}={}){const o=Tl(location.href),i=new URL(e,location.origin),r=new URL(o,location.origin);if(e===o){if(!n)return Sl(i.hash,t),!1}else if(s?history.replaceState({},"",e):(history.replaceState({scrollPosition:window.scrollY},""),history.pushState({},"",e)),i.pathname===r.pathname)return i.hash!==r.hash&&(window.dispatchEvent(new HashChangeEvent("hashchange",{oldURL:r.href,newURL:i.href})),Sl(i.hash,t)),!1;return!0}const Yi=()=>fr.forEach(e=>e()),QA=z({name:"VitePressContent",props:{as:{type:[Object,String],default:"div"}},setup(e){const t=kn(),{frontmatter:n,site:s}=Ae();return te(n,Yi,{deep:!0,flush:"post"}),()=>nn(e.as,s.value.contentProps??{style:{position:"relative"}},[t.component?nn(t.component,{onVnodeMounted:Yi,onVnodeUpdated:Yi,onVnodeUnmounted:Yi}):"404 Page Not Found"])}});function gh(e=!0){const t="http://a.com",n=jn(),{site:s,theme:o,localeIndex:i}=Ae(),{base:r,cleanUrls:a}=s.value,{permalinks:c={}}=o.value,u=Object.keys(c),f=async p=>{if(!u.length)return;const{pathname:g,search:v,hash:k}=new URL(p,t),b=decodeURIComponent(g.slice(r.length)),w=c.map[b.replace(/\.html/,"")];if(w==="/"+b)return;if(w)return Oe(async()=>{const _=r.replace(/\/$/,"")+w+v+k;history.replaceState(history.state||null,"",_),await n.onAfterUrlLoad?.(_)});const y=d(g);if(y){const _=r+y+v+k;history.replaceState(history.state||null,"",_),await n.go(_)}else await n.onAfterUrlLoad?.(p)};e&&Mo(async()=>{n.state.permalinkPlugin||(n.state={...n.state,permalinkPlugin:!0}),await f(window.location.href)});const d=p=>{const g="/"+decodeURIComponent(p.slice(r.length)).replace(/\/$/,"").replace(/\.html/,""),v=i.value,k=a?g:g+".html";let b="";return v!=="root"&&!k.startsWith(`/${v}/`)?b=c.inv[`/${v}${k}`]:b=c.inv[k],`/${b}`===g?"":b};return{startWatch:()=>{if(!u.length||(n.state||{}).permalinkPlugin)return;const g=n.onBeforeRouteChange;n.onBeforeRouteChange=async k=>{if(await g?.(k)===!1)return!1;if(k===r)return;const{pathname:w,search:y,hash:_}=new URL(k,t),x=d(w);if(x){const L=r+x+y+_;return await n.go(L),!1}};const v=n.onAfterRouteChange;n.onAfterRouteChange=async k=>{await f(k),await v?.(k)},n.state={...n.state,permalinkPlugin:!0}},teyGetFilePathByPermalink:d}}const xe=Ae;function Y3(e,t){let n,s=!1;return()=>{n&&clearTimeout(n),s?n=setTimeout(e,t):(e(),(s=!0)&&setTimeout(()=>s=!1,t))}}function El(e){return e.startsWith("/")?e:`/${e}`}function zc(e){const{pathname:t,search:n,hash:s,protocol:o}=new URL(e,"http://a.com");if(hh(e)||e.startsWith("#")||!o.startsWith("http")||!ph(t))return e;const{site:i}=xe(),r=t.endsWith("/")||t.endsWith(".html")?e:e.replace(/(?:(^\.+)\/)?.*$/,`$1${t.replace(/(\.md)?$/,i.value.cleanUrls?"":".html")}${n}${s}`);return Ee(r)}function $i({correspondingLink:e=!1}={}){const{site:t,localeIndex:n,page:s,theme:o,hash:i}=xe(),r=F(()=>({label:t.value.locales[n.value]?.label,link:t.value.locales[n.value]?.link||(n.value==="root"?"/":`/${n.value}/`)}));return{localeLinks:F(()=>Object.entries(t.value.locales).flatMap(([c,u])=>r.value.label===u.label?[]:{text:u.label,link:G3(u.link||(c==="root"?"/":`/${c}/`),o.value.i18nRouting!==!1&&e,s.value.relativePath.slice(r.value.link.length-1),!t.value.cleanUrls)+i.value,lang:u.lang,dir:u.dir})),currentLang:r}}function G3(e,t,n,s){return t?e.replace(/\/$/,"")+El(n.replace(/(^|\/)index\.md$/,"$1").replace(/\.md$/,s?".html":"")):e}const J3={class:"NotFound"},X3={class:"code"},Q3={class:"title"},Z3={class:"quote"},e4={class:"action"},t4=["href","aria-label"],n4=z({__name:"NotFound",setup(e){const{theme:t}=xe(),{currentLang:n}=$i();return(s,o)=>(m(),C("div",J3,[S("p",X3,W(l(t).notFound?.code??"404"),1),S("h1",Q3,W(l(t).notFound?.title??"PAGE NOT FOUND"),1),o[0]||(o[0]=S("div",{class:"divider"},null,-1)),S("blockquote",Z3,W(l(t).notFound?.quote??"But if you don't change your direction, and if you keep looking, you may end up where you are heading."),1),S("div",e4,[S("a",{class:"link",href:l(Ee)(l(t).notFound?.link??l(n).link),"aria-label":l(t).notFound?.linkLabel??"go to home"},W(l(t).notFound?.linkText??"Take me home"),9,t4)])]))}}),ke=(e,t)=>{const n=e.__vccOpts||e;for(const[s,o]of t)n[s]=o;return n},vh=ke(n4,[["__scopeId","data-v-1b32e0f1"]]),s4=z({__name:"NotFoundDelay",setup(e){const t=jn(),{site:n,theme:s}=Ae(),{teyGetFilePathByPermalink:o}=gh(!1),i=j(!0),r=()=>{i.value=!1};return Mo(async()=>{const{permalinks:a}=s.value;if(!a&&!Object.keys(a||{}).length)return r();const{search:c,hash:u}=new URL(window.location.href),f=o(t.route.path);if(f){const d=n.value.base+f+c+u;history.replaceState(history.state||null,"",d),await t.go(d),setTimeout(r,3e3)}else r()}),(a,c)=>i.value?A("",!0):M(a.$slots,"not-found",{key:0},()=>[H(vh)])}}),o4={key:0,class:"VPBackdrop"},i4=z({__name:"VPBackdrop",props:{show:{type:Boolean}},setup(e){return(t,n)=>(m(),D(vt,{name:"fade"},{default:O(()=>[e.show?(m(),C("div",o4)):A("",!0)]),_:1}))}}),r4=ke(i4,[["__scopeId","data-v-f703a812"]]);function yh(e,t){if(Array.isArray(e))return dr(e);if(e==null)return[];t=El(t);const n=Object.keys(e).sort((o,i)=>i.split("/").length-o.split("/").length).find(o=>t.startsWith(El(o))),s=n?e[n]:[];return Array.isArray(s)?dr(s):dr(s.items,s.base)}function a4(e){const t=[];let n=0;for(const s in e){const o=e[s];if(o.items){n=t.push(o);continue}t[n]||t.push({items:[]}),t[n].items.push(o)}return t}function l4(e){const t=[];function n(s){for(const o of s)o.text&&o.link&&t.push({text:o.text,link:o.link,docFooterText:o.docFooterText}),o.items&&n(o.items)}return n(e),t}function xl(e,t){return Array.isArray(t)?t.some(n=>xl(e,n)):Ls(e,t.link)?!0:t.items?xl(e,t.items):!1}function dr(e,t){return[...e].map(n=>{const s={...n},o=s.base||t;return o&&s.link&&(s.link=o+s.link.replace(/^\//,o.endsWith("/")?"":"/")),s.items&&(s.items=dr(s.items,o)),s})}function c4(){const{hasSidebar:e}=cs(),t=Nr("(min-width: 960px)"),n=Nr("(min-width: 1280px)");return{isAsideEnabled:F(()=>!n.value&&!t.value?!1:e.value?n.value:t.value)}}const u4=/\b(?:VPBadge|header-anchor|footnote-ref|ignore-header)\b/,Al=[];function bh(e){return typeof e.outline=="object"&&!Array.isArray(e.outline)&&e.outline.label||e.outlineTitle||"On this page"}function f4(e){const t=[...document.querySelectorAll(".VPDoc h1, .VPDoc h2, .VPDoc h3, .VPDoc h4, .VPDoc h5, .VPDoc h6")].filter(n=>n.id&&n.hasChildNodes()).map(n=>{const s=Number(n.tagName[1]);return{element:n,title:d4(n),link:"#"+n.id,level:s}});return h4(t,e)}function d4(e){let t="";for(const n of e.childNodes)if(n.nodeType===1){if(u4.test(n.className))continue;t+=n.textContent}else n.nodeType===3&&(t+=n.textContent);return t.trim()}function h4(e,t){if(t===!1)return[];const n=(typeof t=="object"&&!Array.isArray(t)?t.level:t)||2,[s,o]=typeof n=="number"?[n,n]:n==="deep"?[2,6]:n;return g4(e,s,o)}function p4(e,t){const{isAsideEnabled:n}=c4(),s=Y3(i,100);let o=null;be(()=>{requestAnimationFrame(i),window.addEventListener("scroll",s)}),Fo(()=>{r(location.hash)}),cn(()=>{window.removeEventListener("scroll",s)});function i(){if(!n.value)return;const a=window.scrollY,c=window.innerHeight,u=document.body.offsetHeight,f=Math.abs(a+c-u)<1,d=Al.map(({element:p,link:g})=>({link:g,top:m4(p)})).filter(({top:p})=>!Number.isNaN(p)).sort((p,g)=>p.top-g.top);if(!d.length){r(null);return}if(a<1){r(null);return}if(f){r(d[d.length-1].link);return}let h=null;for(const{link:p,top:g}of d){if(g>a+Hc()+4)break;h=p}r(h)}function r(a){o&&o.classList.remove("active"),a==null?o=null:o=e.value.querySelector(`a[href="${decodeURIComponent(a)}"]`);const c=o;c?(c.classList.add("active"),t.value.style.top=c.offsetTop+39+"px",t.value.style.opacity="1"):(t.value.style.top="33px",t.value.style.opacity="0")}}function m4(e){let t=0;for(;e!==document.body;){if(e===null)return NaN;t+=e.offsetTop,e=e.offsetParent}return t}function g4(e,t,n){Al.length=0;const s=[],o=[];return e.forEach(i=>{const r={...i,children:[]};let a=o[o.length-1];for(;a&&a.level>=r.level;)o.pop(),a=o[o.length-1];if(r.element.classList.contains("ignore-header")||a&&"shouldIgnore"in a){o.push({level:r.level,shouldIgnore:!0});return}r.level>n||r.level{t=co.value?document.activeElement:void 0}),be(()=>{window.addEventListener("keyup",n)}),cn(()=>{window.removeEventListener("keyup",n)});function n(s){s.key==="Escape"&&co.value&&(e(),t?.focus())}}function y4(){function e(){co.value=!0}function t(){co.value=!1}function n(){co.value?t():e()}return{isOpen:co,open:e,close:t,toggle:n}}function b4(e){const{page:t,hash:n}=xe(),s=j(!1),o=F(()=>e.value.collapsed!=null),i=F(()=>!!e.value.link),r=j(!1),a=()=>{r.value=Ls(t.value.relativePath,e.value.link)};te([t,e,n],a),be(a);const c=F(()=>r.value?!0:e.value.items?xl(t.value.relativePath,e.value.items):!1),u=F(()=>!!(e.value.items&&e.value.items.length));zn(()=>{s.value=!!(o.value&&e.value.collapsed)}),da(()=>{(r.value||c.value)&&(s.value=!1)});function f(){o.value&&(s.value=!s.value)}return{collapsed:s,collapsible:o,isLink:i,isActiveLink:r,hasActiveLink:c,hasChildren:u,toggle:f}}const $l=ze([]),ei=ze([]),Ll=ze(!1);function cs(){const{frontmatter:e,theme:t}=xe(),n=F(()=>!!(e.value.isHome??e.value.layout==="home")),s=F(()=>e.value.sidebar!==!1&&ei.value.length>0&&!n.value),o=F(()=>s.value&&Ll.value),i=F(()=>s.value?a4(ei.value):[]),r=F(()=>n.value?!1:e.value.aside!=null?!!e.value.aside:t.value.aside!==!1),a=F(()=>r.value?e.value.aside==null?t.value.aside==="left":e.value.aside==="left":!1),c=F(()=>$l.value.length>0);return{isHome:n,sidebar:al(ei),sidebarGroups:i,hasSidebar:s,isSidebarEnabled:o,hasAside:r,leftAside:a,headers:al($l),hasLocalNav:c}}function k4({closeSidebar:e}){const{frontmatter:t,page:n,theme:s}=xe();te(()=>[n.value.relativePath,s.value.sidebar],([i,r])=>{const a=r?yh(r,i):[];JSON.stringify(a)!==JSON.stringify(ei.value)&&(ei.value=a)},{immediate:!0,deep:!0,flush:"sync"}),Ai(()=>{$l.value=f4(t.value.outline??s.value.outline)}),wt&&(Ll.value=window.innerWidth>=960,window.addEventListener("resize",()=>{Ll.value=window.innerWidth>=960},{passive:!0}));const o=kn();te(()=>o.path,e),v4(e)}const kh=Symbol("layout-info"),w4=["href","title"],C4=z({__name:"VPDocOutlineItem",props:{headers:{},root:{type:Boolean}},setup(e){return(t,n)=>{const s=un("VPDocOutlineItem",!0);return m(),C("ul",{class:T(["VPDocOutlineItem",e.root?"root":"nested"])},[(m(!0),C(Y,null,le(e.headers,({children:o,link:i,title:r})=>(m(),C("li",null,[S("a",{class:"outline-link",href:i,title:r},W(r),9,w4),o?.length?(m(),D(s,{key:0,headers:o},null,8,["headers"])):A("",!0)]))),256))],2)}}}),wh=ke(C4,[["__scopeId","data-v-d90f9aed"]]),_4={class:"content"},S4={"aria-level":"2",class:"outline-title",id:"doc-outline-aria-label",role:"heading"},T4=z({__name:"VPDocAsideOutline",setup(e){const{theme:t}=xe(),n=j(),s=j(),{headers:o,hasLocalNav:i}=cs();return p4(n,s),(r,a)=>(m(),C("nav",{"aria-labelledby":"doc-outline-aria-label",class:T(["VPDocAsideOutline",{"has-outline":l(i)}]),ref_key:"container",ref:n},[S("div",_4,[S("div",{class:"outline-marker",ref_key:"marker",ref:s},null,512),S("div",S4,W(l(bh)(l(t))),1),H(wh,{headers:l(o),root:!0},null,8,["headers"])])],2))}}),E4=ke(T4,[["__scopeId","data-v-3f819b94"]]),x4={class:"VPDocAsideCarbonAds"},A4=z({__name:"VPDocAsideCarbonAds",props:{carbonAds:{}},setup(e){const t=()=>null;return(n,s)=>(m(),C("div",x4,[H(l(t),{"carbon-ads":e.carbonAds},null,8,["carbon-ads"])]))}}),$4={class:"VPDocAside"},L4=z({__name:"VPDocAside",setup(e){const{theme:t}=xe();return(n,s)=>(m(),C("div",$4,[M(n.$slots,"aside-top",{},void 0,!0),M(n.$slots,"aside-outline-before",{},void 0,!0),H(E4),M(n.$slots,"aside-outline-after",{},void 0,!0),s[0]||(s[0]=S("div",{class:"spacer"},null,-1)),M(n.$slots,"aside-ads-before",{},void 0,!0),l(t).carbonAds?(m(),D(A4,{key:0,"carbon-ads":l(t).carbonAds},null,8,["carbon-ads"])):A("",!0),M(n.$slots,"aside-ads-after",{},void 0,!0),M(n.$slots,"aside-bottom",{},void 0,!0)]))}}),I4=ke(L4,[["__scopeId","data-v-77a1b21d"]]);function P4(){const{theme:e,page:t}=xe();return F(()=>{const{text:n="Edit this page",pattern:s=""}=e.value.editLink||{};let o;return typeof s=="function"?o=s(t.value):o=s.replace(/:path/g,t.value.filePath),{url:o,text:n}})}function M4(){const{page:e,theme:t,frontmatter:n}=xe();return F(()=>{const s=yh(t.value.sidebar,e.value.relativePath),o=l4(s),i=F4(o,u=>u.link.replace(/[?#].*$/,"")),r=i.findIndex(u=>Ls(e.value.relativePath,u.link)),a=t.value.docFooter?.prev===!1&&!n.value.prev||n.value.prev===!1,c=t.value.docFooter?.next===!1&&!n.value.next||n.value.next===!1;return{prev:a?void 0:{text:(typeof n.value.prev=="string"?n.value.prev:typeof n.value.prev=="object"?n.value.prev.text:void 0)??i[r-1]?.docFooterText??i[r-1]?.text,link:(typeof n.value.prev=="object"?n.value.prev.link:void 0)??i[r-1]?.link},next:c?void 0:{text:(typeof n.value.next=="string"?n.value.next:typeof n.value.next=="object"?n.value.next.text:void 0)??i[r+1]?.docFooterText??i[r+1]?.text,link:(typeof n.value.next=="object"?n.value.next.link:void 0)??i[r+1]?.link}}})}function F4(e,t){const n=new Set;return e.filter(s=>{const o=t(s);return n.has(o)?!1:n.add(o)})}const Vn=z({__name:"VPLink",props:{tag:{},href:{},noIcon:{type:Boolean},target:{},rel:{}},setup(e){const t=e,n=F(()=>t.tag??(t.href?"a":"span")),s=F(()=>t.href&&ka.test(t.href)||t.target==="_blank");return(o,i)=>(m(),D(Be(n.value),{class:T(["VPLink",{link:e.href,"vp-external-link-icon":s.value,"no-icon":e.noIcon}]),href:e.href?l(zc)(e.href):void 0,target:e.target??(s.value?"_blank":void 0),rel:e.rel??(s.value?"noreferrer":void 0)},{default:O(()=>[M(o.$slots,"default")]),_:3},8,["class","href","target","rel"]))}}),B4={class:"VPLastUpdated"},N4=["datetime"],V4=z({__name:"VPDocFooterLastUpdated",setup(e){const{theme:t,page:n,lang:s}=xe(),{language:o}=S3(),i=z1("timeRef"),r=F(()=>new Date(n.value.lastUpdated)),a=F(()=>r.value.toISOString()),c=ze("");return be(()=>{zn(()=>{const u=t.value.lastUpdated?.formatOptions?.forceLocale?s.value:o.value;c.value=new Intl.DateTimeFormat(u,t.value.lastUpdated?.formatOptions??{dateStyle:"medium",timeStyle:"medium"}).format(r.value),u&&s.value!==u?i.value?.setAttribute("lang",u):i.value?.removeAttribute("lang")})}),(u,f)=>(m(),C("p",B4,[rt(W(l(t).lastUpdated?.text||l(t).lastUpdatedText||"Last updated")+": ",1),S("time",{ref_key:"timeRef",ref:i,datetime:a.value},W(c.value),9,N4)]))}}),O4=ke(V4,[["__scopeId","data-v-8f712c9b"]]),D4={key:0,class:"VPDocFooter"},R4={key:0,class:"edit-info"},H4={key:0,class:"edit-link"},z4={key:1,class:"last-updated"},j4={key:1,class:"prev-next","aria-labelledby":"doc-footer-aria-label"},U4={class:"pager"},W4=["innerHTML"],q4=["innerHTML"],K4={class:"pager"},Y4=["innerHTML"],G4=["innerHTML"],J4=z({__name:"VPDocFooter",setup(e){const{theme:t,page:n,frontmatter:s}=xe(),o=P4(),i=M4(),r=F(()=>t.value.editLink&&s.value.editLink!==!1),a=F(()=>n.value.lastUpdated),c=F(()=>r.value||a.value||i.value.prev||i.value.next);return(u,f)=>c.value?(m(),C("footer",D4,[M(u.$slots,"doc-footer-before",{},void 0,!0),r.value||a.value?(m(),C("div",R4,[r.value?(m(),C("div",H4,[H(Vn,{class:"edit-link-button",href:l(o).url,"no-icon":!0},{default:O(()=>[f[0]||(f[0]=S("span",{class:"vpi-square-pen edit-link-icon"},null,-1)),rt(" "+W(l(o).text),1)]),_:1},8,["href"])])):A("",!0),a.value?(m(),C("div",z4,[H(O4)])):A("",!0)])):A("",!0),l(i).prev?.link||l(i).next?.link?(m(),C("nav",j4,[f[1]||(f[1]=S("span",{class:"visually-hidden",id:"doc-footer-aria-label"},"Pager",-1)),S("div",U4,[l(i).prev?.link?(m(),D(Vn,{key:0,class:"pager-link prev",href:l(i).prev.link},{default:O(()=>[S("span",{class:"desc",innerHTML:l(t).docFooter?.prev||"Previous page"},null,8,W4),S("span",{class:"title",innerHTML:l(i).prev.text},null,8,q4)]),_:1},8,["href"])):A("",!0)]),S("div",K4,[l(i).next?.link?(m(),D(Vn,{key:0,class:"pager-link next",href:l(i).next.link},{default:O(()=>[S("span",{class:"desc",innerHTML:l(t).docFooter?.next||"Next page"},null,8,Y4),S("span",{class:"title",innerHTML:l(i).next.text},null,8,G4)]),_:1},8,["href"])):A("",!0)])])):A("",!0)])):A("",!0)}}),X4=ke(J4,[["__scopeId","data-v-af105c74"]]),Q4={class:"container"},Z4={class:"aside-container"},e6={class:"aside-content"},t6={class:"content"},n6={class:"content-container"},s6={class:"main"},o6=z({__name:"VPDoc",setup(e){const{theme:t}=xe(),n=kn(),{hasSidebar:s,hasAside:o,leftAside:i}=cs(),r=F(()=>n.path.replace(/[./]+/g,"_").replace(/_html$/,""));return(a,c)=>{const u=un("Content");return m(),C("div",{class:T(["VPDoc",{"has-sidebar":l(s),"has-aside":l(o)}])},[M(a.$slots,"doc-top",{},void 0,!0),S("div",Q4,[l(o)?(m(),C("div",{key:0,class:T(["aside",{"left-aside":l(i)}])},[c[0]||(c[0]=S("div",{class:"aside-curtain"},null,-1)),S("div",Z4,[S("div",e6,[H(I4,null,{"aside-top":O(()=>[M(a.$slots,"aside-top",{},void 0,!0)]),"aside-bottom":O(()=>[M(a.$slots,"aside-bottom",{},void 0,!0)]),"aside-outline-before":O(()=>[M(a.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":O(()=>[M(a.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":O(()=>[M(a.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":O(()=>[M(a.$slots,"aside-ads-after",{},void 0,!0)]),_:3})])])],2)):A("",!0),S("div",t6,[S("div",n6,[M(a.$slots,"doc-before",{},void 0,!0),S("main",s6,[H(u,{class:T(["vp-doc",[r.value,l(t).externalLinkIcon&&"external-link-icon-enabled"]])},null,8,["class"])]),H(X4,null,{"doc-footer-before":O(()=>[M(a.$slots,"doc-footer-before",{},void 0,!0)]),_:3}),M(a.$slots,"doc-after",{},void 0,!0)])])]),M(a.$slots,"doc-bottom",{},void 0,!0)],2)}}}),i6=ke(o6,[["__scopeId","data-v-256763c0"]]),r6=z({__name:"VPButton",props:{tag:{},size:{default:"medium"},theme:{default:"brand"},text:{},href:{},target:{},rel:{}},setup(e){const t=e,n=F(()=>t.href&&ka.test(t.href)),s=F(()=>t.tag||(t.href?"a":"button"));return(o,i)=>(m(),D(Be(s.value),{class:T(["VPButton",[e.size,e.theme]]),href:e.href?l(zc)(e.href):void 0,target:t.target??(n.value?"_blank":void 0),rel:t.rel??(n.value?"noreferrer":void 0)},{default:O(()=>[M(o.$slots,"default",{},()=>[rt(W(e.text),1)],!0)]),_:3},8,["class","href","target","rel"]))}}),a6=ke(r6,[["__scopeId","data-v-b44745dc"]]),l6=["src","alt"],c6=z({inheritAttrs:!1,__name:"VPImage",props:{image:{},alt:{}},setup(e){return(t,n)=>{const s=un("VPImage",!0);return e.image?(m(),C(Y,{key:0},[typeof e.image=="string"||"src"in e.image?(m(),C("img",nt({key:0,class:"VPImage"},typeof e.image=="string"?t.$attrs:{...e.image,...t.$attrs},{src:l(Ee)(typeof e.image=="string"?e.image:e.image.src),alt:e.alt??(typeof e.image=="string"?"":e.image.alt||"")}),null,16,l6)):(m(),C(Y,{key:1},[H(s,nt({class:"dark",image:e.image.dark,alt:e.image.alt},t.$attrs),null,16,["image","alt"]),H(s,nt({class:"light",image:e.image.light,alt:e.image.alt},t.$attrs),null,16,["image","alt"])],64))],64)):A("",!0)}}}),Vr=ke(c6,[["__scopeId","data-v-e0e0d586"]]),u6={class:"container"},f6={class:"main"},d6={class:"heading"},h6=["innerHTML"],p6=["innerHTML"],m6=["innerHTML"],g6={key:0,class:"actions"},v6={key:0,class:"image"},y6={class:"image-container"},b6=z({__name:"VPHero",props:{name:{},text:{},tagline:{},image:{},actions:{}},setup(e){const{heroImageSlotExists:t}=qe(kh);return(n,s)=>(m(),C("div",{class:T(["VPHero",{"has-image":e.image||l(t)}])},[S("div",u6,[S("div",f6,[M(n.$slots,"home-hero-info-before",{},void 0,!0),M(n.$slots,"home-hero-info",{},()=>[S("h1",d6,[e.name?(m(),C("span",{key:0,innerHTML:e.name,class:"name clip"},null,8,h6)):A("",!0),e.text?(m(),C("span",{key:1,innerHTML:e.text,class:"text"},null,8,p6)):A("",!0)]),e.tagline?(m(),C("p",{key:0,innerHTML:e.tagline,class:"tagline"},null,8,m6)):A("",!0)],!0),M(n.$slots,"home-hero-info-after",{},void 0,!0),e.actions?(m(),C("div",g6,[(m(!0),C(Y,null,le(e.actions,o=>(m(),C("div",{key:o.link,class:"action"},[H(a6,{tag:"a",size:"medium",theme:o.theme,text:o.text,href:o.link,target:o.target,rel:o.rel},null,8,["theme","text","href","target","rel"])]))),128))])):A("",!0),M(n.$slots,"home-hero-actions-after",{},void 0,!0)]),e.image||l(t)?(m(),C("div",v6,[S("div",y6,[s[0]||(s[0]=S("div",{class:"image-bg"},null,-1)),M(n.$slots,"home-hero-image",{},()=>[e.image?(m(),D(Vr,{key:0,class:"image-src",image:e.image},null,8,["image"])):A("",!0)],!0)])])):A("",!0)])],2))}}),k6=ke(b6,[["__scopeId","data-v-09867ed5"]]),w6=z({__name:"VPHomeHero",setup(e){const{frontmatter:t}=xe();return(n,s)=>l(t).hero?(m(),D(k6,{key:0,class:"VPHomeHero",name:l(t).hero.name,text:l(t).hero.text,tagline:l(t).hero.tagline,image:l(t).hero.image,actions:l(t).hero.actions},{"home-hero-info-before":O(()=>[M(n.$slots,"home-hero-info-before")]),"home-hero-info":O(()=>[M(n.$slots,"home-hero-info")]),"home-hero-info-after":O(()=>[M(n.$slots,"home-hero-info-after")]),"home-hero-actions-after":O(()=>[M(n.$slots,"home-hero-actions-after")]),"home-hero-image":O(()=>[M(n.$slots,"home-hero-image")]),_:3},8,["name","text","tagline","image","actions"])):A("",!0)}}),C6={class:"box"},_6={key:0,class:"icon"},S6=["innerHTML"],T6=["innerHTML"],E6=["innerHTML"],x6={key:4,class:"link-text"},A6={class:"link-text-value"},$6=z({__name:"VPFeature",props:{icon:{},title:{},details:{},link:{},linkText:{},rel:{},target:{}},setup(e){return(t,n)=>(m(),D(Vn,{class:"VPFeature",href:e.link,rel:e.rel,target:e.target,"no-icon":!0,tag:e.link?"a":"div"},{default:O(()=>[S("article",C6,[typeof e.icon=="object"&&e.icon.wrap?(m(),C("div",_6,[H(Vr,{image:e.icon,alt:e.icon.alt,height:e.icon.height||48,width:e.icon.width||48},null,8,["image","alt","height","width"])])):typeof e.icon=="object"?(m(),D(Vr,{key:1,image:e.icon,alt:e.icon.alt,height:e.icon.height||48,width:e.icon.width||48},null,8,["image","alt","height","width"])):e.icon?(m(),C("div",{key:2,class:"icon",innerHTML:e.icon},null,8,S6)):A("",!0),S("h2",{class:"title",innerHTML:e.title},null,8,T6),e.details?(m(),C("p",{key:3,class:"details",innerHTML:e.details},null,8,E6)):A("",!0),e.linkText?(m(),C("div",x6,[S("p",A6,[rt(W(e.linkText)+" ",1),n[0]||(n[0]=S("span",{class:"vpi-arrow-right link-text-icon"},null,-1))])])):A("",!0)])]),_:1},8,["href","rel","target","tag"]))}}),L6=ke($6,[["__scopeId","data-v-684de982"]]),I6={key:0,class:"VPFeatures"},P6={class:"container"},M6={class:"items"},F6=z({__name:"VPFeatures",props:{features:{}},setup(e){const t=e,n=F(()=>{const s=t.features.length;if(s){if(s===2)return"grid-2";if(s===3)return"grid-3";if(s%3===0)return"grid-6";if(s>3)return"grid-4"}else return});return(s,o)=>e.features?(m(),C("div",I6,[S("div",P6,[S("div",M6,[(m(!0),C(Y,null,le(e.features,i=>(m(),C("div",{key:i.title,class:T(["item",[n.value]])},[H(L6,{icon:i.icon,title:i.title,details:i.details,link:i.link,"link-text":i.linkText,rel:i.rel,target:i.target},null,8,["icon","title","details","link","link-text","rel","target"])],2))),128))])])])):A("",!0)}}),B6=ke(F6,[["__scopeId","data-v-4422ade5"]]),N6=z({__name:"VPHomeFeatures",setup(e){const{frontmatter:t}=xe();return(n,s)=>l(t).features?(m(),D(B6,{key:0,class:"VPHomeFeatures",features:l(t).features},null,8,["features"])):A("",!0)}}),V6=z({__name:"VPHomeContent",setup(e){const{width:t}=E3({initialWidth:0,includeScrollbar:!1});return(n,s)=>(m(),C("div",{class:"vp-doc container",style:Fe(l(t)?{"--vp-offset":`calc(50% - ${l(t)/2}px)`}:{})},[M(n.$slots,"default",{},void 0,!0)],4))}}),O6=ke(V6,[["__scopeId","data-v-1b679879"]]),D6=z({__name:"VPHome",setup(e){const{frontmatter:t,theme:n}=xe();return(s,o)=>{const i=un("Content");return m(),C("div",{class:T(["VPHome",{"external-link-icon-enabled":l(n).externalLinkIcon}])},[M(s.$slots,"home-hero-before",{},void 0,!0),H(w6,null,{"home-hero-info-before":O(()=>[M(s.$slots,"home-hero-info-before",{},void 0,!0)]),"home-hero-info":O(()=>[M(s.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-info-after":O(()=>[M(s.$slots,"home-hero-info-after",{},void 0,!0)]),"home-hero-actions-after":O(()=>[M(s.$slots,"home-hero-actions-after",{},void 0,!0)]),"home-hero-image":O(()=>[M(s.$slots,"home-hero-image",{},void 0,!0)]),_:3}),M(s.$slots,"home-hero-after",{},void 0,!0),M(s.$slots,"home-features-before",{},void 0,!0),H(N6),M(s.$slots,"home-features-after",{},void 0,!0),l(t).markdownStyles!==!1?(m(),D(O6,{key:0},{default:O(()=>[H(i)]),_:1})):(m(),D(i,{key:1}))],2)}}}),R6=ke(D6,[["__scopeId","data-v-10bb9ea0"]]),H6={},z6={class:"VPPage"};function j6(e,t){const n=un("Content");return m(),C("div",z6,[M(e.$slots,"page-top"),H(n),M(e.$slots,"page-bottom")])}const U6=ke(H6,[["render",j6]]),W6=z({__name:"VPContent",setup(e){const{page:t,frontmatter:n}=xe(),{isHome:s,hasSidebar:o}=cs();return(i,r)=>(m(),C("div",{class:T(["VPContent",{"has-sidebar":l(o),"is-home":l(s)}]),id:"VPContent"},[l(t).isNotFound?M(i.$slots,"not-found",{key:0},()=>[H(vh)],!0):l(n).layout==="page"?(m(),D(U6,{key:1},{"page-top":O(()=>[M(i.$slots,"page-top",{},void 0,!0)]),"page-bottom":O(()=>[M(i.$slots,"page-bottom",{},void 0,!0)]),_:3})):l(n).layout==="home"?(m(),D(R6,{key:2},{"home-hero-before":O(()=>[M(i.$slots,"home-hero-before",{},void 0,!0)]),"home-hero-info-before":O(()=>[M(i.$slots,"home-hero-info-before",{},void 0,!0)]),"home-hero-info":O(()=>[M(i.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-info-after":O(()=>[M(i.$slots,"home-hero-info-after",{},void 0,!0)]),"home-hero-actions-after":O(()=>[M(i.$slots,"home-hero-actions-after",{},void 0,!0)]),"home-hero-image":O(()=>[M(i.$slots,"home-hero-image",{},void 0,!0)]),"home-hero-after":O(()=>[M(i.$slots,"home-hero-after",{},void 0,!0)]),"home-features-before":O(()=>[M(i.$slots,"home-features-before",{},void 0,!0)]),"home-features-after":O(()=>[M(i.$slots,"home-features-after",{},void 0,!0)]),_:3})):l(n).layout&&l(n).layout!=="doc"?(m(),D(Be(l(n).layout),{key:3})):(m(),D(i6,{key:4},{"doc-top":O(()=>[M(i.$slots,"doc-top",{},void 0,!0)]),"doc-bottom":O(()=>[M(i.$slots,"doc-bottom",{},void 0,!0)]),"doc-footer-before":O(()=>[M(i.$slots,"doc-footer-before",{},void 0,!0)]),"doc-before":O(()=>[M(i.$slots,"doc-before",{},void 0,!0)]),"doc-after":O(()=>[M(i.$slots,"doc-after",{},void 0,!0)]),"aside-top":O(()=>[M(i.$slots,"aside-top",{},void 0,!0)]),"aside-outline-before":O(()=>[M(i.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":O(()=>[M(i.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":O(()=>[M(i.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":O(()=>[M(i.$slots,"aside-ads-after",{},void 0,!0)]),"aside-bottom":O(()=>[M(i.$slots,"aside-bottom",{},void 0,!0)]),_:3}))],2))}}),q6=ke(W6,[["__scopeId","data-v-19ca35aa"]]),K6={class:"container"},Y6=["innerHTML"],G6=["innerHTML"],J6=z({__name:"VPFooter",setup(e){const{theme:t,frontmatter:n}=xe(),{hasSidebar:s}=cs();return(o,i)=>l(t).footer&&l(n).footer!==!1?(m(),C("footer",{key:0,class:T(["VPFooter",{"has-sidebar":l(s)}])},[S("div",K6,[l(t).footer.message?(m(),C("p",{key:0,class:"message",innerHTML:l(t).footer.message},null,8,Y6)):A("",!0),l(t).footer.copyright?(m(),C("p",{key:1,class:"copyright",innerHTML:l(t).footer.copyright},null,8,G6)):A("",!0)])],2)):A("",!0)}}),X6=ke(J6,[["__scopeId","data-v-105f771f"]]),Q6={class:"menu-text"},Z6={class:"header"},e8={class:"outline"},t8=z({__name:"VPLocalNavOutlineDropdown",props:{headers:{},navHeight:{}},setup(e){const t=e,{theme:n}=xe(),s=j(!1),o=j(0),i=j(),r=j();function a(d){i.value?.contains(d.target)||(s.value=!1)}te(s,d=>{if(d){document.addEventListener("click",a);return}document.removeEventListener("click",a)}),_l("Escape",()=>{s.value=!1}),Ai(()=>{s.value=!1});function c(){s.value=!s.value,o.value=window.innerHeight+Math.min(window.scrollY-t.navHeight,0)}function u(d){d.target.classList.contains("outline-link")&&(r.value&&(r.value.style.transition="none"),Oe(()=>{s.value=!1}))}function f(){s.value=!1,window.scrollTo({top:0,left:0,behavior:"smooth"})}return(d,h)=>(m(),C("div",{class:"VPLocalNavOutlineDropdown",style:Fe({"--vp-vh":o.value+"px"}),ref_key:"main",ref:i},[e.headers.length>0?(m(),C("button",{key:0,onClick:c,class:T({open:s.value})},[S("span",Q6,W(l(bh)(l(n))),1),h[0]||(h[0]=S("span",{class:"vpi-chevron-right icon"},null,-1))],2)):(m(),C("button",{key:1,onClick:f},W(l(n).returnToTopLabel||"Return to top"),1)),H(vt,{name:"flyout"},{default:O(()=>[s.value?(m(),C("div",{key:0,ref_key:"items",ref:r,class:"items",onClick:u},[S("div",Z6,[S("a",{class:"top-link",href:"#",onClick:f},W(l(n).returnToTopLabel||"Return to top"),1)]),S("div",e8,[H(wh,{headers:e.headers},null,8,["headers"])])],512)):A("",!0)]),_:1})],4))}}),n8=ke(t8,[["__scopeId","data-v-6ab9adca"]]),s8={class:"container"},o8=["aria-expanded"],i8={class:"menu-text"},r8=z({__name:"VPLocalNav",props:{open:{type:Boolean}},emits:["open-menu"],setup(e){const{theme:t}=xe(),{isHome:n,hasSidebar:s,headers:o,hasLocalNav:i}=cs(),{y:r}=uh(),a=j(0);be(()=>{a.value=parseInt(getComputedStyle(document.documentElement).getPropertyValue("--vp-nav-height"))});const c=F(()=>({VPLocalNav:!0,"has-sidebar":s.value,empty:!i.value,fixed:!i.value&&!s.value}));return(u,f)=>!l(n)&&(l(i)||l(s)||l(r)>=a.value)?(m(),C("div",{key:0,class:T(c.value)},[S("div",s8,[l(s)?(m(),C("button",{key:0,class:"menu","aria-expanded":e.open,"aria-controls":"VPSidebarNav",onClick:f[0]||(f[0]=d=>u.$emit("open-menu"))},[f[1]||(f[1]=S("span",{class:"vpi-align-left menu-icon"},null,-1)),S("span",i8,W(l(t).sidebarMenuLabel||"Menu"),1)],8,o8)):A("",!0),H(n8,{headers:l(o),navHeight:a.value},null,8,["headers","navHeight"])])],2)):A("",!0)}}),a8=ke(r8,[["__scopeId","data-v-8f018525"]]);function l8(){const e=j(!1);function t(){e.value=!0,window.addEventListener("resize",o)}function n(){e.value=!1,window.removeEventListener("resize",o)}function s(){e.value?n():t()}function o(){window.outerWidth>=768&&n()}const i=kn();return te(()=>i.path,n),{isScreenOpen:e,openScreen:t,closeScreen:n,toggleScreen:s}}const jc=Symbol("nav"),c8={},u8={class:"VPSwitch",type:"button",role:"switch"},f8={class:"check"},d8={key:0,class:"icon"};function h8(e,t){return m(),C("button",u8,[S("span",f8,[e.$slots.default?(m(),C("span",d8,[M(e.$slots,"default",{},void 0,!0)])):A("",!0)])])}const p8=ke(c8,[["render",h8],["__scopeId","data-v-5fd96198"]]),m8=z({__name:"VPSwitchAppearance",setup(e){const{isDark:t,theme:n}=xe(),s=qe("toggle-appearance",()=>{t.value=!t.value}),o=j("");return da(()=>{o.value=t.value?n.value.lightModeSwitchTitle||"Switch to light theme":n.value.darkModeSwitchTitle||"Switch to dark theme"}),(i,r)=>(m(),D(p8,{title:o.value,class:"VPSwitchAppearance","aria-checked":l(t),onClick:l(s)},{default:O(()=>[...r[0]||(r[0]=[S("span",{class:"vpi-sun sun"},null,-1),S("span",{class:"vpi-moon moon"},null,-1)])]),_:1},8,["title","aria-checked","onClick"]))}}),Uc=ke(m8,[["__scopeId","data-v-fd2b5f2c"]]),g8={key:0,class:"VPNavBarAppearance"},v8=z({__name:"VPNavBarAppearance",setup(e){const{site:t}=xe();return(n,s)=>l(t).appearance&&l(t).appearance!=="force-dark"&&l(t).appearance!=="force-auto"?(m(),C("div",g8,[H(Uc)])):A("",!0)}}),y8=ke(v8,[["__scopeId","data-v-0fac236d"]]),Wc=j();let Ch=!1,Ka=0;function b8(e){const t=j(!1);if(wt){!Ch&&k8(),Ka++;const n=te(Wc,s=>{s===e.el.value||e.el.value?.contains(s)?(t.value=!0,e.onFocus?.()):(t.value=!1,e.onBlur?.())});cn(()=>{n(),Ka--,Ka||w8()})}return It(t)}function k8(){document.addEventListener("focusin",_h),Ch=!0,Wc.value=document.activeElement}function w8(){document.removeEventListener("focusin",_h)}function _h(){Wc.value=document.activeElement}const C8={class:"VPMenuLink"},_8=["innerHTML"],S8=z({inheritAttrs:!1,__name:"VPMenuLink",props:{item:{}},setup(e){const t=e,{page:n}=xe(),s=F(()=>typeof t.item.link=="function"?t.item.link(n.value):t.item.link);return(o,i)=>(m(),C("div",C8,[H(Vn,nt(o.$attrs,{class:{active:l(Ls)(l(n).relativePath,e.item.activeMatch||s.value,!!e.item.activeMatch)},href:s.value,target:e.item.target,rel:e.item.rel,"no-icon":e.item.noIcon}),{default:O(()=>[S("span",{innerHTML:e.item.text},null,8,_8)]),_:1},16,["class","href","target","rel","no-icon"])]))}}),wa=ke(S8,[["__scopeId","data-v-c995c7e2"]]),T8={class:"VPMenuGroup"},E8={key:0,class:"title"},x8=z({__name:"VPMenuGroup",props:{text:{},items:{}},setup(e){return(t,n)=>(m(),C("div",T8,[e.text?(m(),C("p",E8,W(e.text),1)):A("",!0),(m(!0),C(Y,null,le(e.items,s=>(m(),C(Y,{key:JSON.stringify(s)},["link"in s?(m(),D(wa,{key:0,item:s},null,8,["item"])):A("",!0)],64))),128))]))}}),A8=ke(x8,[["__scopeId","data-v-0d91e4ea"]]),$8={class:"VPMenu"},L8={key:0,class:"items"},I8=z({__name:"VPMenu",props:{items:{}},setup(e){return(t,n)=>(m(),C("div",$8,[e.items?(m(),C("div",L8,[(m(!0),C(Y,null,le(e.items,s=>(m(),C(Y,{key:JSON.stringify(s)},["link"in s?(m(),D(wa,{key:0,item:s},null,8,["item"])):"component"in s?(m(),D(Be(s.component),nt({key:1,ref_for:!0},s.props),null,16)):(m(),D(A8,{key:2,text:s.text,items:s.items},null,8,["text","items"]))],64))),128))])):A("",!0),M(t.$slots,"default",{},void 0,!0)]))}}),P8=ke(I8,[["__scopeId","data-v-62da9740"]]),M8=["aria-expanded","aria-label"],F8={key:0,class:"text"},B8=["innerHTML"],N8={key:1,class:"vpi-more-horizontal icon"},V8={class:"menu"},O8=z({__name:"VPFlyout",props:{icon:{},button:{},label:{},items:{}},setup(e){const t=j(!1),n=j();b8({el:n,onBlur:s});function s(){t.value=!1}return(o,i)=>(m(),C("div",{class:"VPFlyout",ref_key:"el",ref:n,onMouseenter:i[1]||(i[1]=r=>t.value=!0),onMouseleave:i[2]||(i[2]=r=>t.value=!1)},[S("button",{type:"button",class:"button","aria-haspopup":"true","aria-expanded":t.value,"aria-label":e.label,onClick:i[0]||(i[0]=r=>t.value=!t.value)},[e.button||e.icon?(m(),C("span",F8,[e.icon?(m(),C("span",{key:0,class:T([e.icon,"option-icon"])},null,2)):A("",!0),e.button?(m(),C("span",{key:1,innerHTML:e.button},null,8,B8)):A("",!0),i[3]||(i[3]=S("span",{class:"vpi-chevron-down text-icon"},null,-1))])):(m(),C("span",N8))],8,M8),S("div",V8,[H(P8,{items:e.items},{default:O(()=>[M(o.$slots,"default",{},void 0,!0)]),_:3},8,["items"])])],544))}}),qc=ke(O8,[["__scopeId","data-v-c0d6c551"]]),D8=["href","aria-label","rel","innerHTML"],R8=z({__name:"VPSocialLink",props:{icon:{},link:{},ariaLabel:{},me:{type:Boolean}},setup(e){const t=e,n=j();be(async()=>{await Oe();const o=n.value?.children[0];o instanceof HTMLElement&&o.className.startsWith("vpi-social-")&&(getComputedStyle(o).maskImage||getComputedStyle(o).webkitMaskImage)==="none"&&o.style.setProperty("--icon",`url('https://api.iconify.design/simple-icons/${t.icon}.svg')`)});const s=F(()=>typeof t.icon=="object"?t.icon.svg:``);return(o,i)=>(m(),C("a",{ref_key:"el",ref:n,class:"VPSocialLink no-icon",href:e.link,"aria-label":e.ariaLabel??(typeof e.icon=="string"?e.icon:""),target:"_blank",rel:e.me?"me noopener":"noopener",innerHTML:s.value},null,8,D8))}}),H8=ke(R8,[["__scopeId","data-v-94c580ff"]]),z8={class:"VPSocialLinks"},j8=z({__name:"VPSocialLinks",props:{links:{},me:{type:Boolean,default:!0}},setup(e){return(t,n)=>(m(),C("div",z8,[(m(!0),C(Y,null,le(e.links,({link:s,icon:o,ariaLabel:i})=>(m(),D(H8,{key:s,icon:o,link:s,ariaLabel:i,me:e.me},null,8,["icon","link","ariaLabel","me"]))),128))]))}}),Kc=ke(j8,[["__scopeId","data-v-0f495aab"]]),U8={key:0,class:"group translations"},W8={class:"trans-title"},q8={key:1,class:"group"},K8={class:"item appearance"},Y8={class:"label"},G8={class:"appearance-action"},J8={key:2,class:"group"},X8={class:"item social-links"},Q8=z({__name:"VPNavBarExtra",setup(e){const{site:t,theme:n}=xe(),{localeLinks:s,currentLang:o}=$i({correspondingLink:!0}),i=F(()=>s.value.length&&o.value.label||t.value.appearance||n.value.socialLinks);return(r,a)=>i.value?(m(),D(qc,{key:0,class:"VPNavBarExtra",label:"extra navigation"},{default:O(()=>[l(s).length&&l(o).label?(m(),C("div",U8,[S("p",W8,W(l(o).label),1),(m(!0),C(Y,null,le(l(s),c=>(m(),D(wa,{key:c.link,item:c,lang:c.lang,dir:c.dir},null,8,["item","lang","dir"]))),128))])):A("",!0),l(t).appearance&&l(t).appearance!=="force-dark"&&l(t).appearance!=="force-auto"?(m(),C("div",q8,[S("div",K8,[S("p",Y8,W(l(n).darkModeSwitchLabel||"Appearance"),1),S("div",G8,[H(Uc)])])])):A("",!0),l(n).socialLinks?(m(),C("div",J8,[S("div",X8,[H(Kc,{class:"social-links-list",links:l(n).socialLinks},null,8,["links"])])])):A("",!0)]),_:1})):A("",!0)}}),Z8=ke(Q8,[["__scopeId","data-v-cf5e177b"]]),e5=["aria-expanded"],t5=z({__name:"VPNavBarHamburger",props:{active:{type:Boolean}},emits:["click"],setup(e){return(t,n)=>(m(),C("button",{type:"button",class:T(["VPNavBarHamburger",{active:e.active}]),"aria-label":"mobile navigation","aria-expanded":e.active,"aria-controls":"VPNavScreen",onClick:n[0]||(n[0]=s=>t.$emit("click"))},[...n[1]||(n[1]=[S("span",{class:"container"},[S("span",{class:"top"}),S("span",{class:"middle"}),S("span",{class:"bottom"})],-1)])],10,e5))}}),n5=ke(t5,[["__scopeId","data-v-1d142719"]]),s5=["innerHTML"],o5=z({__name:"VPNavBarMenuLink",props:{item:{}},setup(e){const t=e,{page:n}=xe(),s=F(()=>typeof t.item.link=="function"?t.item.link(n.value):t.item.link);return(o,i)=>(m(),D(Vn,{class:T({VPNavBarMenuLink:!0,active:l(Ls)(l(n).relativePath,e.item.activeMatch||s.value,!!e.item.activeMatch)}),href:s.value,target:e.item.target,rel:e.item.rel,"no-icon":e.item.noIcon,tabindex:"0"},{default:O(()=>[S("span",{innerHTML:e.item.text},null,8,s5)]),_:1},8,["class","href","target","rel","no-icon"]))}}),i5=ke(o5,[["__scopeId","data-v-bf8a0d28"]]),r5=z({__name:"VPNavBarMenuGroup",props:{item:{}},setup(e){const t=e,{page:n}=xe(),s=i=>"component"in i?!1:"link"in i?Ls(n.value.relativePath,typeof i.link=="function"?i.link(n.value):i.link,!!t.item.activeMatch):i.items.some(s),o=F(()=>s(t.item));return(i,r)=>(m(),D(qc,{class:T({VPNavBarMenuGroup:!0,active:l(Ls)(l(n).relativePath,e.item.activeMatch,!!e.item.activeMatch)||o.value}),button:e.item.text,items:e.item.items},null,8,["class","button","items"]))}}),a5={key:0,"aria-labelledby":"main-nav-aria-label",class:"VPNavBarMenu"},l5=z({__name:"VPNavBarMenu",setup(e){const{theme:t}=xe();return(n,s)=>l(t).nav?(m(),C("nav",a5,[s[0]||(s[0]=S("span",{id:"main-nav-aria-label",class:"visually-hidden"}," Main Navigation ",-1)),(m(!0),C(Y,null,le(l(t).nav,o=>(m(),C(Y,{key:JSON.stringify(o)},["link"in o?(m(),D(i5,{key:0,item:o},null,8,["item"])):"component"in o?(m(),D(Be(o.component),nt({key:1,ref_for:!0},o.props),null,16)):(m(),D(r5,{key:2,item:o},null,8,["item"]))],64))),128))])):A("",!0)}}),c5=ke(l5,[["__scopeId","data-v-39023d39"]]),u5="modulepreload",f5=function(e){return"/"+e},Vf={},d5=function(t,n,s){let o=Promise.resolve();if(n&&n.length>0){let c=function(u){return Promise.all(u.map(f=>Promise.resolve(f).then(d=>({status:"fulfilled",value:d}),d=>({status:"rejected",reason:d}))))};document.getElementsByTagName("link");const r=document.querySelector("meta[property=csp-nonce]"),a=r?.nonce||r?.getAttribute("nonce");o=c(n.map(u=>{if(u=f5(u),u in Vf)return;Vf[u]=!0;const f=u.endsWith(".css"),d=f?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${u}"]${d}`))return;const h=document.createElement("link");if(h.rel=f?"stylesheet":u5,f||(h.as="script"),h.crossOrigin="",h.href=u,a&&h.setAttribute("nonce",a),document.head.appendChild(h),f)return new Promise((p,g)=>{h.addEventListener("load",p),h.addEventListener("error",()=>g(new Error(`Unable to preload CSS for ${u}`)))})}))}function i(r){const a=new Event("vite:preloadError",{cancelable:!0});if(a.payload=r,window.dispatchEvent(a),!a.defaultPrevented)throw r}return o.then(r=>{for(const a of r||[])a.status==="rejected"&&i(a.reason);return t().catch(i)})};function h5(e){const{localeIndex:t,theme:n}=xe();function s(o){const i=o.split("."),r=n.value.search?.options,a=r&&typeof r=="object",c=a&&r.locales?.[t.value]?.translations||null,u=a&&r.translations||null;let f=c,d=u,h=e;const p=i.pop();for(const g of i){let v=null;const k=h?.[g];k&&(v=h=k);const b=d?.[g];b&&(v=d=b);const w=f?.[g];w&&(v=f=w),k||(h=v),b||(d=v),w||(f=v)}return f?.[p]??d?.[p]??h?.[p]??""}return s}const p5=["aria-label"],m5={class:"DocSearch-Button-Container"},g5={class:"DocSearch-Button-Placeholder"},Of=z({__name:"VPNavBarSearchButton",setup(e){const n=h5({button:{buttonText:"Search",buttonAriaLabel:"Search"}});return(s,o)=>(m(),C("button",{type:"button","aria-label":l(n)("button.buttonAriaLabel"),"aria-keyshortcuts":"/ control+k meta+k",class:"DocSearch DocSearch-Button"},[S("span",m5,[o[0]||(o[0]=S("span",{class:"vpi-search DocSearch-Search-Icon"},null,-1)),S("span",g5,W(l(n)("button.buttonText")),1)]),o[1]||(o[1]=S("span",{class:"DocSearch-Button-Keys"},[S("kbd",{class:"DocSearch-Button-Key"}),S("kbd",{class:"DocSearch-Button-Key"})],-1))],8,p5))}}),v5={class:"VPNavBarSearch"},y5={id:"local-search"},b5={key:1,id:"docsearch"},k5=z({__name:"VPNavBarSearch",setup(e){const t=wc(()=>d5(()=>import("./VPLocalSearchBox.WaTilTWb.js"),[])),n=()=>null,{theme:s}=xe(),o=j(!1),i=j(!1);be(()=>{});function r(){o.value||(o.value=!0,setTimeout(a,16))}function a(){const d=new Event("keydown");d.key="k",d.metaKey=!0,window.dispatchEvent(d),setTimeout(()=>{document.querySelector(".DocSearch-Modal")||a()},16)}function c(d){const h=d.target,p=h.tagName;return h.isContentEditable||p==="INPUT"||p==="SELECT"||p==="TEXTAREA"}const u=j(!1);_l("k",d=>{(d.ctrlKey||d.metaKey)&&(d.preventDefault(),u.value=!0)}),_l("/",d=>{c(d)||(d.preventDefault(),u.value=!0)});const f="local";return(d,h)=>(m(),C("div",v5,[l(f)==="local"?(m(),C(Y,{key:0},[u.value?(m(),D(l(t),{key:0,onClose:h[0]||(h[0]=p=>u.value=!1)})):A("",!0),S("div",y5,[H(Of,{onClick:h[1]||(h[1]=p=>u.value=!0)})])],64)):l(f)==="algolia"?(m(),C(Y,{key:1},[o.value?(m(),D(l(n),{key:0,algolia:l(s).search?.options??l(s).algolia,onVnodeBeforeMount:h[2]||(h[2]=p=>i.value=!0)},null,8,["algolia"])):A("",!0),i.value?A("",!0):(m(),C("div",b5,[H(Of,{onClick:r})]))],64)):A("",!0)]))}}),w5=z({__name:"VPNavBarSocialLinks",setup(e){const{theme:t}=xe();return(n,s)=>l(t).socialLinks?(m(),D(Kc,{key:0,class:"VPNavBarSocialLinks",links:l(t).socialLinks},null,8,["links"])):A("",!0)}}),C5=ke(w5,[["__scopeId","data-v-cd4c0ab6"]]),_5=["href","rel","target"],S5=["innerHTML"],T5={key:2},E5=z({__name:"VPNavBarTitle",setup(e){const{site:t,theme:n}=xe(),{hasSidebar:s}=cs(),{currentLang:o}=$i(),i=F(()=>typeof n.value.logoLink=="string"?n.value.logoLink:n.value.logoLink?.link),r=F(()=>typeof n.value.logoLink=="string"?void 0:n.value.logoLink?.rel),a=F(()=>typeof n.value.logoLink=="string"?void 0:n.value.logoLink?.target);return(c,u)=>(m(),C("div",{class:T(["VPNavBarTitle",{"has-sidebar":l(s)}])},[S("a",{class:"title",href:i.value??l(zc)(l(o).link),rel:r.value,target:a.value},[M(c.$slots,"nav-bar-title-before",{},void 0,!0),l(n).logo?(m(),D(Vr,{key:0,class:"logo",image:l(n).logo},null,8,["image"])):A("",!0),l(n).siteTitle?(m(),C("span",{key:1,innerHTML:l(n).siteTitle},null,8,S5)):l(n).siteTitle===void 0?(m(),C("span",T5,W(l(t).title),1)):A("",!0),M(c.$slots,"nav-bar-title-after",{},void 0,!0)],8,_5)],2))}}),x5=ke(E5,[["__scopeId","data-v-e5d5fdf8"]]),A5={class:"items"},$5={class:"title"},L5=z({__name:"VPNavBarTranslations",setup(e){const{theme:t}=xe(),{localeLinks:n,currentLang:s}=$i({correspondingLink:!0});return(o,i)=>l(n).length&&l(s).label?(m(),D(qc,{key:0,class:"VPNavBarTranslations",icon:"vpi-languages",label:l(t).langMenuLabel||"Change language"},{default:O(()=>[S("div",A5,[S("p",$5,W(l(s).label),1),(m(!0),C(Y,null,le(l(n),r=>(m(),D(wa,{key:r.link,item:r,lang:r.lang,dir:r.dir},null,8,["item","lang","dir"]))),128))])]),_:1},8,["label"])):A("",!0)}}),I5=ke(L5,[["__scopeId","data-v-1c347a57"]]),P5={class:"wrapper"},M5={class:"container"},F5={class:"title"},B5={class:"content"},N5={class:"content-body"},V5=z({__name:"VPNavBar",props:{isScreenOpen:{type:Boolean}},emits:["toggle-screen"],setup(e){const t=e,{y:n}=uh(),{isHome:s,hasSidebar:o}=cs(),i=j({});return da(()=>{i.value={"has-sidebar":o.value,home:s.value,top:n.value===0,"screen-open":t.isScreenOpen}}),(r,a)=>(m(),C("div",{class:T(["VPNavBar",i.value])},[S("div",P5,[S("div",M5,[S("div",F5,[H(x5,null,{"nav-bar-title-before":O(()=>[M(r.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":O(()=>[M(r.$slots,"nav-bar-title-after",{},void 0,!0)]),_:3})]),S("div",B5,[S("div",N5,[M(r.$slots,"nav-bar-content-before",{},void 0,!0),H(k5,{class:"search"}),H(c5,{class:"menu"}),H(I5,{class:"translations"}),H(y8,{class:"appearance"}),H(C5,{class:"social-links"}),H(Z8,{class:"extra"}),M(r.$slots,"nav-bar-content-after",{},void 0,!0),H(n5,{class:"hamburger",active:e.isScreenOpen,onClick:a[0]||(a[0]=c=>r.$emit("toggle-screen"))},null,8,["active"])])])])]),a[1]||(a[1]=S("div",{class:"divider"},[S("div",{class:"divider-line"})],-1))],2))}}),O5=ke(V5,[["__scopeId","data-v-a10c09a7"]]),D5={key:0,class:"VPNavScreenAppearance"},R5={class:"text"},H5=z({__name:"VPNavScreenAppearance",setup(e){const{site:t,theme:n}=xe();return(s,o)=>l(t).appearance&&l(t).appearance!=="force-dark"&&l(t).appearance!=="force-auto"?(m(),C("div",D5,[S("p",R5,W(l(n).darkModeSwitchLabel||"Appearance"),1),H(Uc)])):A("",!0)}}),z5=ke(H5,[["__scopeId","data-v-0c49eb9f"]]),j5=["innerHTML"],U5=z({__name:"VPNavScreenMenuLink",props:{item:{}},setup(e){const t=e,{page:n}=xe(),s=F(()=>typeof t.item.link=="function"?t.item.link(n.value):t.item.link),{closeScreen:o}=qe(jc);return(i,r)=>(m(),D(Vn,{class:"VPNavScreenMenuLink",href:s.value,target:e.item.target,rel:e.item.rel,"no-icon":e.item.noIcon,onClick:l(o)},{default:O(()=>[S("span",{innerHTML:e.item.text},null,8,j5)]),_:1},8,["href","target","rel","no-icon","onClick"]))}}),W5=ke(U5,[["__scopeId","data-v-f0c07abe"]]),q5=["innerHTML"],K5=z({__name:"VPNavScreenMenuGroupLink",props:{item:{}},setup(e){const t=e,{page:n}=xe(),s=F(()=>typeof t.item.link=="function"?t.item.link(n.value):t.item.link),{closeScreen:o}=qe(jc);return(i,r)=>(m(),D(Vn,{class:"VPNavScreenMenuGroupLink",href:s.value,target:e.item.target,rel:e.item.rel,"no-icon":e.item.noIcon,onClick:l(o)},{default:O(()=>[S("span",{innerHTML:e.item.text},null,8,q5)]),_:1},8,["href","target","rel","no-icon","onClick"]))}}),Sh=ke(K5,[["__scopeId","data-v-1c460cf9"]]),Y5={class:"VPNavScreenMenuGroupSection"},G5={key:0,class:"title"},J5=z({__name:"VPNavScreenMenuGroupSection",props:{text:{},items:{}},setup(e){return(t,n)=>(m(),C("div",Y5,[e.text?(m(),C("p",G5,W(e.text),1)):A("",!0),(m(!0),C(Y,null,le(e.items,s=>(m(),D(Sh,{key:s.text,item:s},null,8,["item"]))),128))]))}}),X5=ke(J5,[["__scopeId","data-v-b9d15d51"]]),Q5=["aria-controls","aria-expanded"],Z5=["innerHTML"],e7=["id"],t7={key:0,class:"item"},n7={key:1,class:"item"},s7={key:2,class:"group"},o7=z({__name:"VPNavScreenMenuGroup",props:{text:{},items:{}},setup(e){const t=e,n=j(!1),s=F(()=>`NavScreenGroup-${t.text.replace(" ","-").toLowerCase()}`);function o(){n.value=!n.value}return(i,r)=>(m(),C("div",{class:T(["VPNavScreenMenuGroup",{open:n.value}])},[S("button",{class:"button","aria-controls":s.value,"aria-expanded":n.value,onClick:o},[S("span",{class:"button-text",innerHTML:e.text},null,8,Z5),r[0]||(r[0]=S("span",{class:"vpi-plus button-icon"},null,-1))],8,Q5),S("div",{id:s.value,class:"items"},[(m(!0),C(Y,null,le(e.items,a=>(m(),C(Y,{key:JSON.stringify(a)},["link"in a?(m(),C("div",t7,[H(Sh,{item:a},null,8,["item"])])):"component"in a?(m(),C("div",n7,[(m(),D(Be(a.component),nt({ref_for:!0},a.props,{"screen-menu":""}),null,16))])):(m(),C("div",s7,[H(X5,{text:a.text,items:a.items},null,8,["text","items"])]))],64))),128))],8,e7)],2))}}),i7=ke(o7,[["__scopeId","data-v-8ab0c53a"]]),r7={key:0,class:"VPNavScreenMenu"},a7=z({__name:"VPNavScreenMenu",setup(e){const{theme:t}=xe();return(n,s)=>l(t).nav?(m(),C("nav",r7,[(m(!0),C(Y,null,le(l(t).nav,o=>(m(),C(Y,{key:JSON.stringify(o)},["link"in o?(m(),D(W5,{key:0,item:o},null,8,["item"])):"component"in o?(m(),D(Be(o.component),nt({key:1,ref_for:!0},o.props,{"screen-menu":""}),null,16)):(m(),D(i7,{key:2,text:o.text||"",items:o.items},null,8,["text","items"]))],64))),128))])):A("",!0)}}),l7=z({__name:"VPNavScreenSocialLinks",setup(e){const{theme:t}=xe();return(n,s)=>l(t).socialLinks?(m(),D(Kc,{key:0,class:"VPNavScreenSocialLinks",links:l(t).socialLinks},null,8,["links"])):A("",!0)}}),c7={class:"list"},u7=z({__name:"VPNavScreenTranslations",setup(e){const{localeLinks:t,currentLang:n}=$i({correspondingLink:!0}),s=j(!1);function o(){s.value=!s.value}return(i,r)=>l(t).length&&l(n).label?(m(),C("div",{key:0,class:T(["VPNavScreenTranslations",{open:s.value}])},[S("button",{class:"title",onClick:o},[r[0]||(r[0]=S("span",{class:"vpi-languages icon lang"},null,-1)),rt(" "+W(l(n).label)+" ",1),r[1]||(r[1]=S("span",{class:"vpi-chevron-down icon chevron"},null,-1))]),S("ul",c7,[(m(!0),C(Y,null,le(l(t),a=>(m(),C("li",{key:a.link,class:"item"},[H(Vn,{class:"link",href:a.link,lang:a.lang,dir:a.dir},{default:O(()=>[rt(W(a.text),1)]),_:2},1032,["href","lang","dir"])]))),128))])],2)):A("",!0)}}),f7=ke(u7,[["__scopeId","data-v-85de7b6f"]]),d7={class:"container"},h7=z({__name:"VPNavScreen",props:{open:{type:Boolean}},setup(e){const t=j(null),n=ch(wt?document.body:null);return(s,o)=>(m(),D(vt,{name:"fade",onEnter:o[0]||(o[0]=i=>n.value=!0),onAfterLeave:o[1]||(o[1]=i=>n.value=!1)},{default:O(()=>[e.open?(m(),C("div",{key:0,class:"VPNavScreen",ref_key:"screen",ref:t,id:"VPNavScreen"},[S("div",d7,[M(s.$slots,"nav-screen-content-before",{},void 0,!0),H(a7,{class:"menu"}),H(f7,{class:"translations"}),H(z5,{class:"appearance"}),H(l7,{class:"social-links"}),M(s.$slots,"nav-screen-content-after",{},void 0,!0)])],512)):A("",!0)]),_:3}))}}),p7=ke(h7,[["__scopeId","data-v-e0c26501"]]),m7={key:0,class:"VPNav"},g7=z({__name:"VPNav",setup(e){const{isScreenOpen:t,closeScreen:n,toggleScreen:s}=l8(),{frontmatter:o}=xe(),i=F(()=>o.value.navbar!==!1);return In(jc,{closeScreen:n}),zn(()=>{wt&&document.documentElement.classList.toggle("hide-nav",!i.value)}),(r,a)=>i.value?(m(),C("header",m7,[H(O5,{"is-screen-open":l(t),onToggleScreen:l(s)},{"nav-bar-title-before":O(()=>[M(r.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":O(()=>[M(r.$slots,"nav-bar-title-after",{},void 0,!0)]),"nav-bar-content-before":O(()=>[M(r.$slots,"nav-bar-content-before",{},void 0,!0)]),"nav-bar-content-after":O(()=>[M(r.$slots,"nav-bar-content-after",{},void 0,!0)]),_:3},8,["is-screen-open","onToggleScreen"]),H(p7,{open:l(t)},{"nav-screen-content-before":O(()=>[M(r.$slots,"nav-screen-content-before",{},void 0,!0)]),"nav-screen-content-after":O(()=>[M(r.$slots,"nav-screen-content-after",{},void 0,!0)]),_:3},8,["open"])])):A("",!0)}}),v7=ke(g7,[["__scopeId","data-v-d78ad477"]]),y7=["role","tabindex"],b7={key:1,class:"items"},k7=z({__name:"VPSidebarItem",props:{item:{},depth:{}},setup(e){const t=e,{collapsed:n,collapsible:s,isLink:o,isActiveLink:i,hasActiveLink:r,hasChildren:a,toggle:c}=b4(F(()=>t.item)),u=F(()=>a.value?"section":"div"),f=F(()=>o.value?"a":"div"),d=F(()=>a.value?t.depth+2===7?"p":`h${t.depth+2}`:"p"),h=F(()=>o.value?void 0:"button"),p=F(()=>[[`level-${t.depth}`],{collapsible:s.value},{collapsed:n.value},{"is-link":o.value},{"is-active":i.value},{"has-active":r.value}]);function g(k){"key"in k&&k.key!=="Enter"||!t.item.link&&c()}function v(){t.item.link&&c()}return(k,b)=>{const w=un("VPSidebarItem",!0);return m(),D(Be(u.value),{class:T(["VPSidebarItem",p.value])},{default:O(()=>[e.item.text?(m(),C("div",nt({key:0,class:"item",role:h.value},Ec(e.item.items?{click:g,keydown:g}:{},!0),{tabindex:e.item.items&&0}),[b[1]||(b[1]=S("div",{class:"indicator"},null,-1)),e.item.link?(m(),D(Vn,{key:0,tag:f.value,class:"link",href:e.item.link,rel:e.item.rel,target:e.item.target},{default:O(()=>[(m(),D(Be(d.value),{class:"text",innerHTML:e.item.text},null,8,["innerHTML"]))]),_:1},8,["tag","href","rel","target"])):(m(),D(Be(d.value),{key:1,class:"text",innerHTML:e.item.text},null,8,["innerHTML"])),e.item.collapsed!=null&&e.item.items&&e.item.items.length?(m(),C("div",{key:2,class:"caret",role:"button","aria-label":"toggle section",onClick:v,onKeydown:va(v,["enter"]),tabindex:"0"},[...b[0]||(b[0]=[S("span",{class:"vpi-chevron-right caret-icon"},null,-1)])],32)):A("",!0)],16,y7)):A("",!0),e.item.items&&e.item.items.length?(m(),C("div",b7,[e.depth<5?(m(!0),C(Y,{key:0},le(e.item.items,y=>(m(),D(w,{key:y.text,item:y,depth:e.depth+1},null,8,["item","depth"]))),128)):A("",!0)])):A("",!0)]),_:1},8,["class"])}}}),w7=ke(k7,[["__scopeId","data-v-c0d2b08d"]]),C7=z({__name:"VPSidebarGroup",props:{items:{}},setup(e){const t=j(!0);let n=null;return be(()=>{n=setTimeout(()=>{n=null,t.value=!1},300)}),ls(()=>{n!=null&&(clearTimeout(n),n=null)}),(s,o)=>(m(!0),C(Y,null,le(e.items,i=>(m(),C("div",{key:i.text,class:T(["group",{"no-transition":t.value}])},[H(w7,{item:i,depth:0},null,8,["item"])],2))),128))}}),_7=ke(C7,[["__scopeId","data-v-3423a55b"]]),S7={class:"nav",id:"VPSidebarNav","aria-labelledby":"sidebar-aria-label",tabindex:"-1"},T7=z({__name:"VPSidebar",props:{open:{type:Boolean}},setup(e){const{sidebarGroups:t,hasSidebar:n}=cs(),s=e,o=j(null),i=ch(wt?document.body:null);te([s,o],()=>{s.open?(i.value=!0,o.value?.focus()):i.value=!1},{immediate:!0,flush:"post"});const r=j(0);return te(t,()=>{r.value+=1},{deep:!0}),(a,c)=>l(n)?(m(),C("aside",{key:0,class:T(["VPSidebar",{open:e.open}]),ref_key:"navEl",ref:o,onClick:c[0]||(c[0]=To(()=>{},["stop"]))},[c[2]||(c[2]=S("div",{class:"curtain"},null,-1)),S("nav",S7,[c[1]||(c[1]=S("span",{class:"visually-hidden",id:"sidebar-aria-label"}," Sidebar Navigation ",-1)),M(a.$slots,"sidebar-nav-before",{},void 0,!0),(m(),D(_7,{items:l(t),key:r.value},null,8,["items"])),M(a.$slots,"sidebar-nav-after",{},void 0,!0)])],2)):A("",!0)}}),E7=ke(T7,[["__scopeId","data-v-3ad41a46"]]),x7={href:"#VPContent",class:"VPSkipLink visually-hidden"},A7=z({__name:"VPSkipLink",setup(e){const{theme:t}=xe(),n=kn(),s=j();return te(()=>n.path,()=>s.value.focus()),(o,i)=>(m(),C(Y,null,[S("span",{ref_key:"backToTop",ref:s,tabindex:"-1"},null,512),S("a",x7,W(l(t).skipToContentLabel||"Skip to content"),1)],64))}}),$7=ke(A7,[["__scopeId","data-v-84877a60"]]),L7=z({__name:"Layout",setup(e){const{isOpen:t,open:n,close:s}=y4();k4({closeSidebar:s});const{frontmatter:o}=xe(),i=Ti(),r=F(()=>!!i["home-hero-image"]);return In(kh,{heroImageSlotExists:r}),gh().startWatch(),(a,c)=>{const u=un("Content");return l(o).layout!==!1?(m(),C("div",{key:0,class:T(["Layout",l(o).pageClass])},[M(a.$slots,"layout-top",{},void 0,!0),H($7),H(r4,{class:"backdrop",show:l(t),onClick:l(s)},null,8,["show","onClick"]),H(v7,null,{"nav-bar-title-before":O(()=>[M(a.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":O(()=>[M(a.$slots,"nav-bar-title-after",{},void 0,!0)]),"nav-bar-content-before":O(()=>[M(a.$slots,"nav-bar-content-before",{},void 0,!0)]),"nav-bar-content-after":O(()=>[M(a.$slots,"nav-bar-content-after",{},void 0,!0)]),"nav-screen-content-before":O(()=>[M(a.$slots,"nav-screen-content-before",{},void 0,!0)]),"nav-screen-content-after":O(()=>[M(a.$slots,"nav-screen-content-after",{},void 0,!0)]),_:3}),H(a8,{open:l(t),onOpenMenu:l(n)},null,8,["open","onOpenMenu"]),H(E7,{open:l(t)},{"sidebar-nav-before":O(()=>[M(a.$slots,"sidebar-nav-before",{},void 0,!0)]),"sidebar-nav-after":O(()=>[M(a.$slots,"sidebar-nav-after",{},void 0,!0)]),_:3},8,["open"]),H(q6,null,{"page-top":O(()=>[M(a.$slots,"page-top",{},void 0,!0)]),"page-bottom":O(()=>[M(a.$slots,"page-bottom",{},void 0,!0)]),"not-found":O(()=>[H(s4,null,{"not-found":O(()=>[M(a.$slots,"not-found",{},void 0,!0)]),_:3})]),"home-hero-before":O(()=>[M(a.$slots,"home-hero-before",{},void 0,!0)]),"home-hero-info-before":O(()=>[M(a.$slots,"home-hero-info-before",{},void 0,!0)]),"home-hero-info":O(()=>[M(a.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-info-after":O(()=>[M(a.$slots,"home-hero-info-after",{},void 0,!0)]),"home-hero-actions-after":O(()=>[M(a.$slots,"home-hero-actions-after",{},void 0,!0)]),"home-hero-image":O(()=>[M(a.$slots,"home-hero-image",{},void 0,!0)]),"home-hero-after":O(()=>[M(a.$slots,"home-hero-after",{},void 0,!0)]),"home-features-before":O(()=>[M(a.$slots,"home-features-before",{},void 0,!0)]),"home-features-after":O(()=>[M(a.$slots,"home-features-after",{},void 0,!0)]),"doc-footer-before":O(()=>[M(a.$slots,"doc-footer-before",{},void 0,!0)]),"doc-before":O(()=>[M(a.$slots,"doc-before",{},void 0,!0)]),"doc-after":O(()=>[M(a.$slots,"doc-after",{},void 0,!0)]),"doc-top":O(()=>[M(a.$slots,"doc-top",{},void 0,!0)]),"doc-bottom":O(()=>[M(a.$slots,"doc-bottom",{},void 0,!0)]),"aside-top":O(()=>[M(a.$slots,"aside-top",{},void 0,!0)]),"aside-bottom":O(()=>[M(a.$slots,"aside-bottom",{},void 0,!0)]),"aside-outline-before":O(()=>[M(a.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":O(()=>[M(a.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":O(()=>[M(a.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":O(()=>[M(a.$slots,"aside-ads-after",{},void 0,!0)]),_:3}),H(X6),M(a.$slots,"layout-bottom",{},void 0,!0)],2)):(m(),D(u,{key:1}))}}}),I7=ke(L7,[["__scopeId","data-v-17498edd"]]),Th={Layout:I7,enhanceApp:({app:e})=>{e.component("Badge",eh)}},Df=e=>/^(http?:|https?:|mailto:|tel:)/.test(e),Yc=e=>{try{return new URL(e),!0}catch{return!1}},Bo=(e,t)=>Object.prototype.toString.call(e)===`[object ${t}]`,ht=e=>Bo(e,"Function")||M7(e),ti=e=>e!==null&&Bo(e,"Object"),Gc=e=>Bo(e,"Number")&&!Number.isNaN(e),P7=e=>Je(e)?!Number.isNaN(Number(e)):!1,M7=e=>Bo(e,"AsyncFunction"),Je=e=>Bo(e,"String"),es=e=>Bo(e,"Boolean"),F7=e=>typeof Array.isArray>"u"?Object.prototype.toString.call(e)==="[object Array]":Array.isArray(e),Il=e=>typeof Element>"u"?!1:e instanceof Element,B7=()=>me&&window?.navigator?.userAgent&&(/iP(?:ad|hone|od)/.test(window.navigator.userAgent)||window?.navigator?.maxTouchPoints>2&&/iPad|Macintosh/.test(window?.navigator.userAgent)),N7=e=>{if(e.tabIndex>0||e.tabIndex===0&&e.getAttribute("tabIndex")!==null)return!0;if(e.tabIndex<0||e.hasAttribute("disabled")||e.getAttribute("aria-disabled")==="true")return!1;switch(e.nodeName){case"A":return!!e.href&&e.rel!=="ignore";case"INPUT":return!(e.type==="hidden"||e.type==="file");case"BUTTON":case"SELECT":case"TEXTAREA":return!0;default:return!1}},me=typeof window<"u"&&typeof document<"u",Rf=(e="yyyy-MM-dd hh:mm:ss",t=!0)=>pi(new Date,e,t),pi=(e,t="yyyy-MM-dd hh:mm:ss",n=!0)=>{if(!e)return"";const s=new Date(e),o=n?s.getUTCFullYear():s.getFullYear(),i=String((n?s.getUTCMonth():s.getMonth())+1).padStart(2,"0"),r=String(n?s.getUTCDate():s.getDate()).padStart(2,"0"),a=String(n?s.getUTCHours():s.getHours()).padStart(2,"0"),c=String(n?s.getUTCMinutes():s.getMinutes()).padStart(2,"0"),u=String(n?s.getUTCSeconds():s.getSeconds()).padStart(2,"0");return t.replace("yyyy",o.toString()).replace("MM",i).replace("dd",r).replace("hh",a).replace("mm",c).replace("ss",u)},V7=(e,t)=>{const n=+new Date(e),s=+new Date,o=Math.abs(s-n),i=1e3,r=i*60,a=r*60,c=a*24,u=c*7,f=c*30,d=f*12;return o<1?"刚刚":o{const n=+new Date(e),s=+new Date;return Math.floor(Math.abs(n-s)/(1e3*60*60*24))},Hf=e=>e.charAt(0).toUpperCase()+e.slice(1),sn=(e,t="px")=>e?Gc(e)||P7(e)?`${e}${t}`:Je(e)?e:"":"",D7=(e,t="px")=>{if(e){if(Gc(e))return e;if(Je(e))return Number(e.replace(t,""))}},R7=(e,t,n)=>{let s={...e};return t.includes(".")?(t.split(".").forEach(o=>s=s[o]??""),s||n):s[t]||n},Eh=e=>{let t="";if(!/^\#?[0-9A-Fa-f]{6}$/.test(e))return console.error("[Teek Error] 输入错误的 hex");e=e.replace("#",""),t=e.match(/../g);for(let s=0;s<3;s++)t[s]=parseInt(t[s],16);return t},xh=(e,t,n)=>{const s=/^\d{1,3}$/;if(!s.test(e)||!s.test(t)||!s.test(n))return console.error("[Teek Error] 输入错误的 rgb 颜色值");const o=[e.toString(16),t.toString(16),n.toString(16)];for(let i=0;i<3;i++)o[i].length===1&&(o[i]=`0${o[i]}`);return`#${o.join("")}`},Cn=(e,t)=>{if(!/^\#?[0-9A-Fa-f]{6}$/.test(e))return console.error("[Teek Error] 输入错误的 hex 颜色值");const s=Eh(e);for(let o=0;o<3;o++)s[o]=Math.round(20.5*t+s[o]*(1-t));return xh(s[0],s[1],s[2])},_n=(e,t)=>{if(!/^\#?[0-9A-Fa-f]{6}$/.test(e))return console.error("[Teek Error] 输入错误的 hex 颜色值");const s=Eh(e);for(let o=0;o<3;o++)s[o]=Math.round(255*t+s[o]*(1-t));return xh(s[0],s[1],s[2])},H7=e=>{if(!me)return;const{id:t,production:n=!0}=e||{};if(!t)return console.warn("[Teek Warning] Baidu analytics id is empty");if(!document.querySelector(`#baidu-analytics-${t}`)){window._hmt=window._hmt||[];const s=document.createElement("script");s.id=`baidu-analytics-${t}`,s.async=!0,s.src=`https://hm.baidu.com/hm.js?${t}`,document.querySelector("head")?.appendChild(s)}},z7=(e,t)=>{if(!me)return;const{id:n,production:s=!0}=e||{};if(n){if((!t||!Je(t))&&(t="/"),t.startsWith("http")){const o=t.split("/"),i=`${o[0]}//${o[2]}`;t=t.replace(i,"")}window._hmt&&(window._hmt.push(["_setAccount",n]),window._hmt.push(["_trackPageview",t]))}},j7=e=>{if(!me||window.dataLayer&&window.gtag)return;const{id:t,production:n=!0}=e||{};if(!t)return console.warn("[Teek Warning] Google analytics id is empty");if(!document.querySelector(`#google-analytics-${t}`)){const s=document.createElement("script");s.id=`google-analytics-${t}`,s.src=`https://www.googletagmanager.com/gtag/js?id=${t}`,s.async=!0,document.head.appendChild(s),window.dataLayer=window.dataLayer||[],window.gtag=function(){dataLayer.push(arguments)},gtag("js",new Date),gtag("config",t)}},U7=(e,t=!0)=>{if(!me)return;let n=[];if(Array.isArray(e)?n.push(...e):n.push(e),n=n.filter(s=>!!s.id),!!n.length)for(const s of n){const{id:o,src:i}=s;if(!document.querySelector(`#umami-analytics-${o}`)){const r=document.createElement("script");r.id=`umami-analytics-${o}`,r.async=!0,r.defer=!0,r.setAttribute("data-website-id",o),r.src=i,document.head.appendChild(r)}}};typeof window<"u"&&(window._iconfont_svg_string_4999519='',(e=>{var t=(n=(n=document.getElementsByTagName("script"))[n.length-1]).getAttribute("data-injectcss"),n=n.getAttribute("data-disable-injectsvg");if(!n){var s,o,i,r,a,c=function(d,h){h.parentNode.insertBefore(d,h)};if(t&&!e.__iconfont__svg__cssinject__){e.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(d){console&&console.log(d)}}s=function(){var d,h=document.createElement("div");h.innerHTML=e._iconfont_svg_string_4999519,(h=h.getElementsByTagName("svg")[0])&&(h.setAttribute("aria-hidden","true"),h.style.position="absolute",h.style.width=0,h.style.height=0,h.style.overflow="hidden",h=h,(d=document.body).firstChild?c(h,d.firstChild):d.appendChild(h))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(s,0):(o=function(){document.removeEventListener("DOMContentLoaded",o,!1),s()},document.addEventListener("DOMContentLoaded",o,!1)):document.attachEvent&&(i=s,r=e.document,a=!1,f(),r.onreadystatechange=function(){r.readyState=="complete"&&(r.onreadystatechange=null,u())})}function u(){a||(a=!0,i())}function f(){try{r.documentElement.doScroll("left")}catch{return void setTimeout(f,50)}u()}})(window));var Ah=` - - `,$h=` - - `,Gi=` - - - - `,Jc=` - - `,W7=` - - `,zf=` - - - - - - - - - - - - - - `,q7=` - - `,jf=` - - - - - `,K7=` - ICP备案号 - - - `,Y7=` - - `,G7=` - - `,Uf=` - - `,Ji=` - - - - - `,J7=` - 主题 - - `,Wf=` - - - - - - - - - - - - - - - - - - - `,Lh=` - - - `,X7=` - - - - `,Q7=` - - `,Z7=` - - `,Xc=` - - `,Qc=` - - `,e9=` - - `,qf=` - - - `,Ih=` - -`,t9=` - -`,n9=` - - `,s9=` - - `,Ph=` - - `,o9=` - - `,i9=` - - `,r9=` - - `,a9=` - - `,Mh=` - - `,Kf=``,Yf=``,l9=` - - `,c9=` - - `,u9=` - - `,Gf=` - - `,Fh=` - - `,f9=` - - `,Bh=` - - `,d9=` - - `,h9=` - - `,p9=` - - `,m9=` - - `,g9=` - - `,Nh=` - - `,Vh=` - - `,v9=` - - `,y9=` - - - `,b9=` - - - `,Or=` - - - - - - `,Oh=` - - - - - - `,k9=` - - `,w9=` - - `,C9=` - - - - - `,_9=` - - `,S9=` - - - - - - `,T9=` - - - - - `,Dh=` - - - - - `,E9=` - - `;const Un=e=>_i()?(uc(e),!0):!1,Ve=(e,t,n,s)=>{const o=[],i=()=>{o.forEach(f=>f()),o.length=0},r=(f,d,h,p)=>(f.addEventListener(d,h,p),()=>f.removeEventListener(d,h,p)),a=F(()=>{if(!me)return;const f=Se(e)||window;return f?.$el??f}),c=te(a,f=>{i(),f&&o.push(r(f,t,n,s))},{flush:"post",immediate:!0}),u=()=>{c(),i()};return Un(i),u};let Jf=!1;const x9=(e,t,n={})=>{const{ignore:s=[],capture:o=!0,detectIframe:i=!1,controls:r=!1}=n;if(!me)return r?{stop:()=>{},cancel:()=>{},trigger:()=>{}}:()=>{};if(B7()&&!Jf){Jf=!0;const v={passive:!0};Array.from(window.document.body.children).forEach(k=>Ve(k,"click",()=>{},v)),Ve(window.document.documentElement,"click",()=>{},v)}let a=!0;const c=v=>Se(s).some(k=>{if(typeof k=="string")return Array.from(window.document.querySelectorAll(k)).some(b=>b===v.target||v.composedPath().includes(b));{const b=Se(k);return b&&(v.target===b||v.composedPath().includes(b))}});function u(v){const k=Se(v);return k&&k.$.subTree.shapeFlag===16}function f(v,k){const b=Se(v),w=b.$.subTree&&b.$.subTree.children;return w==null||!Array.isArray(w)?!1:w.some(y=>y.el===k.target||k.composedPath().includes(y.el))}const d=v=>{const k=Se(e),b=k?.$el??k;if(v.target!=null&&!(!(b instanceof Element)&&u(e)&&f(e,v))&&!(!b||b===v.target||v.composedPath().includes(b))){if("detail"in v&&v.detail===0&&(a=!c(v)),!a){a=!0;return}t(v)}};let h=!1;const p=[Ve(window,"click",v=>{h||(h=!0,setTimeout(()=>{h=!1},0),d(v))},{passive:!0,capture:o}),Ve(window,"pointerdown",v=>{const k=Se(e),b=k?.$el??k;a=!c(v)&&!!(b&&!v.composedPath().includes(b))},{passive:!0}),i&&Ve(window,"blur",v=>{setTimeout(()=>{const k=Se(e),b=k?.$el??k;window.document.activeElement?.tagName==="IFRAME"&&!b?.contains(window.document.activeElement)&&t(v)},0)},{passive:!0})].filter(Boolean),g=()=>p.forEach(v=>v());return r?{stop:g,cancel:()=>{a=!1},trigger:v=>{a=!0,d(v),a=!1}}:g},No=(e,t={})=>{const{sync:n=!1,nexTick:s=!0}=t,o=ze(!1),i=dt();return i?be(()=>{o.value=!0,e?.()},i):n?e?.():s&&Oe(()=>e?.()),o},A9=()=>{const{theme:e}=Ae(),t=Dn({id:"",top:-1}),n=()=>{const o=document.querySelectorAll(".content-container .main :is(h1, h2, h3, h4, h5, h6)");for(let i=0;i{Ve(window,"scroll",n)}),{startWatch:()=>{e.value.anchorScroll!==!1&&te(()=>t.id,o=>{!me||!o||window.history.replaceState(history.state||null,"",`#${o}`)})}}},$9=9999,L9=9999,I9=9999,P9=9999,M9={site_pv:9999,site_uv:9999,page_pv:9999,page_uv:9999},F9={site_pv:9999,site_uv:9999,page_pv:9999,page_uv:9999},Rh=(e=!1,t={})=>{const{url:n,provider:s="busuanzi",tryRequest:o=!1,tryCount:i=5,tryIterationTime:r=2e3,requestFn:a}=t,c=j(0),u=j(0),f=j(0),d=j(0),h=j({site_pv:0,site_uv:0,page_pv:0,page_uv:0}),p=j({site_pv:0,site_uv:0,page_pv:0,page_uv:0}),g=j(!0),v=()=>{if(!me||g.value===!1)return;g.value=!1,(async b=>{if(a){const w=await a(b,Zc);return window.dispatchEvent(new CustomEvent("views",{detail:w})),Promise.resolve(w)}switch(s){case"busuanzi":return Xf(b);case"vercount":return B9(b);default:return Xf(b)}})(n||void 0).then(b=>{c.value=b.site_pv||$9,u.value=b.site_uv||L9,f.value=b.page_pv||I9,d.value=b.page_uv||P9,h.value=b.today||M9,p.value=b.yesterday||F9,g.value=!0,window.dispatchEvent(new CustomEvent("views",{detail:b}))})};if(e&&Oe(v),o){let k=0;const b=y=>{y&&(clearInterval(y),y=null)},w=setInterval(()=>{if(g.value)return b(w);v(),k+=r,k>r*i&&b(w)},r);Un(()=>b(w))}return{sitePv:It(c),siteUv:It(u),pagePv:It(f),pageUv:It(d),today:It(h),yesterday:It(p),isGet:It(g),request:v}},Zc=(e,t=!0)=>{const n=document.createElement("script");return n.type="text/javascript",n.defer=!0,n.src=e,t&&document.body.appendChild(n),n},Xf=(e="//busuanzi.ibruce.info/busuanzi?jsonpCallback=BusuanziCallback")=>{const t="BusuanziCallback_"+Math.floor(1099511627776*Math.random());e=e.replace("=BusuanziCallback","="+t);const n=Zc(e);n.referrerPolicy="no-referrer-when-downgrade";let s;return window[t]=o=>s=o,new Promise((o,i)=>{n.onload=()=>{o(s),setTimeout(()=>{document.body.removeChild(n)},10)},n.onerror=()=>i("Error Loading "+e)})},B9=async(e="//events.vercount.one/js",t=5e3)=>{localStorage.removeItem("visitorCountData");const n=Zc(e);return new Promise((s,o)=>{n.onload=()=>{let r=t/500;const a=setInterval(()=>{r--,r<=0&&(clearInterval(a),s({}));const c=localStorage.getItem("visitorCountData");c&&(clearInterval(a),s(JSON.parse(c)))},500);setTimeout(()=>{document.body.removeChild(n)},10)},n.onerror=()=>o("Error Loading "+e)})},Hh=(e=1500)=>{const t=j(!1),n=j(""),s=j(!1);me&&navigator.clipboard&&document.execCommand,s.value=!0;const o=async(r,a=-1)=>{if(!me)return;if(navigator.clipboard)return await navigator.clipboard.writeText(r).then(()=>{n.value=r,t.value=!0,i()});const c=document.createElement("input");c.setAttribute("readonly","readonly"),c.setAttribute("value",r),document.body.appendChild(c),c.select(),a>0&&c.setSelectionRange(0,a),document.execCommand("copy")&&(n.value=r,document.execCommand("copy"),t.value=!0,i()),document.body.removeChild(c)},i=()=>{setTimeout(()=>{t.value=!1},e)};return{copy:o,text:n,copied:t,isSupported:s}};var Ya={namespace:"tk"};const ie=(e="",t)=>{const n=Ya.namespace,s=b=>h(n,e,b),o=b=>h(n,e,"",b),i=b=>h(n,e,"","",b),r=(b,w)=>h(n,e,b,w),a=(b,w)=>h(n,e,b,"",w),c=(b,w)=>h(n,e,"",b,w),u=(b,w,y)=>h(n,e,b,w,y),f=(b,w=!0)=>w?`is-${b}`:"",d=(b,w=!0)=>w?`has-${b}`:"",h=(b,w,y,_,x)=>{let L=`${b}-${w}`;return y&&(L+=`-${y}`),_&&(L+=`__${_}`),x&&(L+=`--${x}`),L},p=b=>`${n}-${b}`,g=b=>`var(--${n}-${b})`,v=b=>`--${n}-${b}`,k=(...b)=>`${n}:${b.join(":")}`;return{namespaceModule:Ya,namespace:Ya.namespace,b:s,e:o,m:i,be:r,bm:a,em:c,bem:u,is:f,has:d,createBem:h,join:p,cssVar:g,cssVarName:v,storageKey:k}},ts=(e,t=0,n=!1)=>{let s;return(...o)=>{n&&!s&&e(...o);const r=()=>{s&&(clearTimeout(s),s=null)},a=()=>{r(),n||e(...o)};r(),s=setTimeout(a,t)}},Pl=(e,t={})=>{const{delayEnter:n=0,delayLeave:s=0}=t,o=ze(!1);let i;const r=a=>{const c=a?n:s;i&&(clearTimeout(i),i=null),c?i=setTimeout(()=>o.value=a,c):o.value=a};return me&&(Ve(e,"mouseenter",()=>r(!0),{passive:!0}),Ve(e,"mouseleave",()=>r(!1),{passive:!0})),o};var N9={lang:"zh-CN",tk:{archives:{label:"归档页",title:"归档",totalCount:"总共 {count} 篇文章",year:"年",month:"月",count:"篇",notFound:"未指定"},articleAnalyze:{label:"文章分析",wordCount:"文章字数",readingTime:"预计阅读时长",pageView:"浏览量"},articleAppreciation:{label:"文章赞赏",contentLabel:"赞赏方式"},articleBreadcrumb:{label:"文章面包屑",home:"首页"},breadcrumb:{label:"面包屑"},articleInfo:{label:"文章信息",author:"作者",createTime:"创建时间",updateTime:"更新时间",category:"分类",tag:"标签"},articleOverview:{label:"文章清单",overview:" 清单",category:" 目录",name:"文章目录",title:"文章标题",date:"发布时间",wordCount:"文章字数",readingTime:"预阅读时长"},articleShare:{label:"文章分享",text:"分享此页面",copiedText:"链接已复制"},articleTitle:{label:"文章标题"},articleUpdate:{label:"最近更新"},catalogue:{label:"目录页",title:"目录"},demoCode:{playground:"在 Playground 中编辑",github:"在 Github 中编辑",copy:"复制代码",collapseSource:"查看源代码",expandSource:"隐藏源代码",notSupport:"浏览器不支持复制",copySuccess:"复制成功",copyFail:"复制失败"},footerInfo:{label:"页脚信息",socialLabel:"社交媒体",infoLabel:"页脚内容"},home:{label:"首页",postLabel:"文章列表",cardLabel:"侧边卡片栏"},homeBanner:{label:"首页横幅",wavesLabel:"首页横幅波浪",bgImgLabel:"首页横幅背景图",maskLabel:"首页横幅遮罩层",bgPureLabel:"首页横幅背景色",contentLabel:"首页横幅内容",titleLabel:"首页横幅标题",descLabel:"首页横幅描述",descSwitchLabel:"描述动态切换",descTypedLabel:"描述打字机效果",featureLabel:"首页横幅功能特性"},homePost:{label:"文章列表",emptyLabel:"暂无文章",pageLabel:"分页导航",moreLabel:"阅读全文 >",pin:"置顶:{sticky}",pinLabel:"置顶标志",excerptLabel:"文章摘要",infoLabel:"文章信息",coverImgLabel:"文章封面图"},pageCard:{label:"首页卡片",prev:"上一页",next:"下一页"},categoryCard:{pageTitle:"{icon}全部分类",homeTitle:"{icon}文章分类",label:"首页分类卡片",emptyLabel:"暂无文章分类",listLabel:"分类列表",moreLabel:"更多 ..."},docAnalysisCard:{title:"{icon}站点信息",totalPosts:"文章数目",weekAddNum:"近一周新增",monthAddNum:"近一月新增",runtime:"已运行时间",totalWordCount:"本站总字数",lastActiveTime:"最后活动时间",viewCount:"本站被访问了",visitCount:"本站曾来访过",fileUnit:"篇",runtimeLess:"不到一天",runtimeUnit:"天",wordCountUnit:"字",viewCountUnit:"次",visitCountUnit:"人",label:"首页站点分析卡片"},friendLinkCard:{title:"{icon}友情链接",emptyLabel:"暂无友情链接",label:"首页友情链接卡片",listLabel:"友情链接列表"},myCard:{label:"我的信息卡片",avatarAlt:"博主头像",avatarTitle:"我好看吗",socialLabel:"社交链接",bloggerLabel:"博主信息"},tagCard:{pageTitle:"{icon}全部标签",homeTitle:"{icon}热门标签",label:"首页标签卡片",emptyLabel:"暂无标签",listLabel:"标签列表",moreLabel:"更多 ..."},topArticleCard:{title:"{icon}精选文章",label:"首页精选文章卡片",emptyLabel:"暂无精选文章",listLabel:"精选文章列表"},image:{error:"加载失败"},notice:{label:"公告栏",title:"公告",openLabel:"打开公告弹窗",closeLabel:"关闭公告弹窗",headLabel:"公告头部区域",contentLabel:"公告内容"},pagination:{goto:"前往",pagesize:"条/页",total:"共 {total} 条",pageClassifier:"页",page:"页",prev:"上一页",next:"下一页",currentPage:"第 {pager} 页",prevPages:"向前 {pager} 页",nextPages:"向后 {pager} 页"},rightBottomButton:{backTopTitle:"返回顶部",themeSizeTitle:"主题尺寸切换",themeStyleTitle:"主题风格切换",toComment:"前往评论"},themeEnhance:{title:"布局增强",layoutSwitch:{title:"布局切换",helpDesc:"调整 VitePress 的布局样式,以适配不同的阅读习惯和屏幕环境。",fullWidthTipTitle:"全部展开",fullWidthHelpTipContent:"使侧边栏和内容区域占据整个屏幕的全部宽度。",sidebarWidthAdjustableOnlyTipTitle:"全部展开,但侧边栏宽度可调",sidebarWidthAdjustableOnlyHelpTipContent:"侧边栏宽度可调,但内容区域宽度不变,调整后的侧边栏将可以占据整个屏幕的最大宽度。",bothWidthAdjustableTipTitle:"全部展开,且侧边栏和内容区域宽度均可调",bothWidthAdjustableHelpTipContent:"侧边栏和内容区域宽度均可调,调整后的侧边栏和内容区域将可以占据整个屏幕的最大宽度。",originalWidthTipTitle:"原始宽度",originalWidthHelpTipContent:"原始的 VitePress 默认布局宽度"},docLayoutMaxWidth:{title:"文档内容最大宽度",helpDesc:"调整 VitePress 布局中文档内容区域的宽度,以适配不同的阅读习惯和屏幕环境。",helpTipTitle:"调整文档内容最大宽度",helpTipContent:"一个可调整的滑块,用于选择和自定义文档内容最大宽度。"},pageLayoutMaxWidth:{title:"页面最大宽度",helpDesc:"调整 VitePress 布局中页面的宽度,以适配不同的阅读习惯和屏幕环境。",helpTipTitle:"调整页面最大宽度",helpTipContent:"一个可调整的滑块,用于选择和自定义页面最大宽度。"},themeColor:{title:"主题色",speedLabel:"扩散",vpLabel:"VitePress 主题",epLabel:"ElementPlus 主题",vpTip:"VitePress 主题",epTip:"ElementPlus 主题",defaultLabel:"预设",blueLabel:"蓝色",greenLabel:"绿色",yellowLabel:"黄色",redLabel:"红色",helpDesc:"提供 VitePress 的基础色板和 ElementPlus 的基础色板进行选择,通过扩散开关可以将主题色扩散至其他元素,如侧边栏背景色、字体色等",vpHelpTipTitle:"VitePress 基础色板",vpHelpTipContent:"提供蓝(预设)、绿、黄、红 4 种 VitePress 基础色板",epHelpTipTitle:"ElementPlus 基础色板",epHelpTipContent:"提供蓝、绿、黄、红 4 种 ElementPlus 基础色板"},spotlight:{title:"聚光灯",helpDesc:"支持在正文中高亮当前鼠标悬停的行和元素,以优化阅读和专注困难的用户的阅读体验。",onTipTitle:"开启",onHelpTipContent:"开启聚光灯。",offTipTitle:"关闭",offHelpTipContent:"关闭聚光灯。"},spotlightStyles:{title:"聚光灯样式",helpDesc:"调整聚光灯的样式。",asideTipTitle:"置于侧边",asideHelpTipContent:"在当前鼠标悬停的元素旁边添加一条固定的纯色线以突出显示当前鼠标悬停的位置。",underTipTitle:"置于底部",underHelpTipContent:"在当前鼠标悬停的元素下方添加一个纯色背景以突出显示当前鼠标悬停的位置。"}},login:{label:"登录页",reset:"重置",login:"登录",loginSuccess:"登录成功!",loginError:"用户名或者密码错误!",loginInfoNonNull:"请输入用户名和密码!",usernamePlaceholder:"请输入用户名",passwordPlaceholder:"请输入密码",verifyCodePlaceholder:"请输入验证码",verifyCodeNonNull:"请输入验证码",verifyCodeError:"请输入正确的验证码"},riskLink:{label:"风险链接提示页",title:"即将离开 {name},请注意财产安全",linkIllegal:"链接安全性校验中,请稍后 ...",confirmButtonText:"继续访问"},sidebarTrigger:{label:"侧边栏展开/折叠"}}};const zh=Symbol("localeContextKey"),ge=e=>{const t=qe(zh,j()),n=F(()=>t?.value||N9),s=F(()=>n.value.lang),o=Ye(n)?n:j(n),i=(r,a,c)=>R7(c,r,r).replace(/\{(\w+)\}/g,(u,f)=>`${a?.[f]??`{${f}}`}`);return{lang:s,locale:o,t:(r,a)=>i(r,a,n.value),translate:i}},Xt=(e,t=!0)=>{const n=ze(!1);No(()=>{n.value=window&&"matchMedia"in window&&typeof window.matchMedia=="function"});const s=ze(),o=ze(!1),i=r=>{o.value=r.matches};return zn(()=>{n.value&&(s.value=window.matchMedia(Se(e)),o.value=s.value.matches)}),Ve(s,"change",i,{passive:!0}),F(()=>t?o.value:!o.value)},eu=(e,t={})=>{const{initialWidth:n=Number.POSITIVE_INFINITY,initialHeight:s=Number.POSITIVE_INFINITY,includeScrollbar:o=!0,type:i="inner"}=t,r=ze(n),a=ze(s);let c=()=>{};const u=ts(()=>{if(me){if(i==="outer")r.value=window.outerWidth,a.value=window.outerHeight;else if(i==="visual"&&window.visualViewport){const{width:f,height:d,scale:h}=window.visualViewport;r.value=Math.round(f*h),a.value=Math.round(d*h)}else o?(r.value=window.innerWidth,a.value=window.innerHeight):(r.value=window.document.documentElement.clientWidth,a.value=window.document.documentElement.clientHeight);e?.(r.value,a.value)}},100);return u(),No(u),c=Ve(()=>window,"resize",u,{passive:!0}),me&&i==="visual"&&window.visualViewport&&(c=Ve(window.visualViewport,"resize",u,{passive:!0})),{width:r,height:a,update:u,stop:c}},V9=()=>{const e=j(0),t=j(0);let n=null;const s=()=>n||(document.querySelector("#measure-element")?.remove(),n=document.createElement("div"),n.id="measure-element",n.style.cssText=` - position: fixed; - top: -9999px; - left: 0; - width: 100px; - height: 100px; - overflow: scroll; - visibility: hidden; - `,document.body.appendChild(n),n),o=()=>{n&&document.body.contains(n)&&(document.body.removeChild(n),n=null)},i=()=>{if(!me)return;const a=document.documentElement,c=document.compatMode==="BackCompat",u=c?document.body.scrollHeight>document.body.clientHeight:a.scrollHeight>a.clientHeight,f=c?document.body.scrollWidth>document.body.clientWidth:a.scrollWidth>a.clientWidth;if(!u&&!f){e.value=0,t.value=0;return}const d=s();e.value=u?d.offsetWidth-d.clientWidth:0,t.value=f?d.offsetHeight-d.clientHeight:0},r=()=>{i()};return Ve(()=>window,"resize",r),No(()=>{s(),i()}),i(),Un(o),{width:e,height:t,update:r}},xt="auto",ds=10,O9=(e,t,n={})=>{const{placement:s="bottom",offset:o=0,xOffset:i=0,yOffset:r=0}=n,a=j(xt),c=j(xt),u=j(xt),f=j(xt),{width:d,height:h}=eu(),{width:p,height:g}=V9(),v=F(()=>{const y=Se(e);return y?.$el??y}),k=F(()=>{const y=Se(t);return y?.$el??y}),b=async()=>{if(!me||!v.value||!k.value)return;await Oe();const{top:y,right:_,bottom:x,left:L,width:V,height:E}=v.value.getBoundingClientRect(),I=d.value-_,P=h.value-x,N=k.value.offsetWidth,$=k.value.offsetHeight,U=window.scrollX+(o||i),q=window.scrollY+(o||r);let J=xt,G=xt,ae=xt,ne=xt;const he=["top","bottom"].some(gt=>s.startsWith(gt)),st=["left","right"].some(gt=>s.startsWith(gt)),je=()=>y+E+q,yt=()=>I+V-U-p.value,Wn=()=>P+E-q-g.value,us=()=>L+V+U;he?s.endsWith("start")?ne=us()-V:s.endsWith("end")?G=yt()-V:ne=L+V/2-N/2+U:st&&(s.endsWith("start")?J=je()-E:s.endsWith("end")?ae=Wn()-E:J=y+E/2-$/2+q),s.startsWith("top")?ae=Wn()+ds:s.startsWith("right")?ne=us()+ds:s.startsWith("bottom")?J=je()+ds:s.startsWith("left")&&(G=yt()+ds);const Zs=()=>!Je(ae)&&ae+$>h.value-q,we=()=>!Je(ne)&&ne+N>d.value+U,Ne=()=>!Je(J)&&J+$>h.value+q,Ke=()=>!Je(G)&&G+N>d.value-U;Zs()&&(J=(st?je()-E:je())+ds,Ne()?J=xt:ae=xt),Ne()&&(ae=(st?Wn()-E:Wn())+ds,Zs()?ae=xt:J=xt),we()&&(G=(he?yt()-V:yt())+ds,Ke()?G=xt:ne=xt),Ke()&&(ne=(he?us()-V:us())+ds,we()?ne=xt:G=xt),a.value=J,c.value=G,u.value=ae,f.value=ne};b();const w=()=>{b()};return Ve(()=>window,"scroll",w),Ve(()=>window,"resize",w),{top:a,right:c,bottom:u,left:f,update:w}},D9=(e,t,n={})=>{const{intervalTime:s=3e3,reloadWhenDataChanged:o=!1}=n,i=F(()=>Se(e)||[]),r=j(i.value.slice(0,t));let a=t,c=null;const u=()=>{const p=(a+1)%i.value.length;r.value.push(i.value[p]),r.value.shift(),a=p},f=()=>{u(),c=setInterval(()=>{u()},s)},d=(p=!1)=>{c&&(clearInterval(c),c=null),p&&(r.value=i.value.slice(0,t),a=t)},h=()=>{d(!0),f()};return o&&te(i,()=>h()),Un(d),{data:r,start:f,stop:d,restart:h}},R9={boolean:{read:e=>e==="true",write:e=>String(e)},object:{read:e=>JSON.parse(e),write:e=>JSON.stringify(e)},number:{read:e=>Number.parseFloat(e),write:e=>String(e)},any:{read:e=>e,write:e=>String(e)},string:{read:e=>e,write:e=>String(e)},map:{read:e=>new Map(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e.entries()))},set:{read:e=>new Set(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e))},date:{read:e=>new Date(e),write:e=>e.toISOString()}},H9=e=>e==null?"any":e instanceof Set?"set":e instanceof Map?"map":e instanceof Date?"date":typeof e=="boolean"?"boolean":typeof e=="string"?"string":typeof e=="number"?"number":typeof e=="object"?"object":"any",bn=(e,t,n="localStorage",s={})=>{const{flush:o="pre",deep:i=!0,writeDefaults:r=!0,mergeDefaults:a=!1,initOnMounted:c}=s,u=Se(t),f=j(u);if(!me)return f;const d=H9(u),h=R9[d],p=F(()=>Se(e)),g=n==="localStorage"?localStorage:sessionStorage;te(p,()=>w(),{flush:o}),te(f,()=>k(f.value),{flush:o,deep:i}),No(()=>{c&&w()});const v=(y,_)=>{if(window){const x={key:p.value,oldValue:y,newValue:_,storageArea:g};window.dispatchEvent(new StorageEvent("storage",x))}},k=y=>{const _=g.getItem(p.value);if(y==null)v(_,null),g.removeItem(p.value);else{const x=h.write(y);_!==x&&(g.setItem(p.value,x),v(_,x))}},b=y=>{const _=y?y.newValue:g.getItem(p.value);if(_==null)return r&&u!=null&&g.setItem(p.value,h.write(u)),u;if(!y&&a){const x=h.read(_);return typeof a=="function"?a(x,u):d==="object"&&!Array.isArray(x)?{...u,...x}:x}return typeof _!="string"?_:h.read(_)},w=y=>{if(!(y&&y.storageArea!==g)){if(y&&y.key==null){f.value=u;return}y&&y.key!==p.value||y?.newValue!==h.write(f.value)&&(f.value=b(y))}};return c||w(),Ve(()=>window,"storage",w,{passive:!0}),f},tu=(e,t={})=>{const{timeout:n=4e3,shuffle:s=!1,reloadWhenDataChanged:o=!1,onBeforeUpdate:i,onUpdate:r,onAfterUpdate:a}=t,c=F(()=>Se(e)||[]),u=j(-1);let f;const d=y=>{let _;do _=Math.floor(Math.random()*y.length);while(_===u.value);return u.value=_,y[_]},h=j(s?d(c.value):c.value[0]),p=y=>(u.value=(u.value+1)%y.length,y[u.value]),g=()=>{f&&(clearTimeout(f),f=null)},v=()=>{g(),n>0&&(f=setTimeout(k,n))},k=()=>{const y=c.value;if(y.length<1)return;if(y.length===1){h.value=y[0];return}v();let _;if(s?_=d(y):_=p(y),_!==h.value){if(i?.(_),r)return r(h,_);h.value=_,a?.(_)}},b=(y=!1)=>{g(),y&&(u.value=-1)},w=()=>{b(!0),k()};return o&&te(c,()=>w()),Un(b),{data:h,index:u,start:k,stop:b,restart:w}},z9=(e,t={})=>{const{inputTime:n=200,outputTime:s=100,nextTime:o=800,shuffle:i=!1,reloadWhenDataChanged:r=!1}=t,a=F(()=>Se(e)||[]),c=j(""),u=j(!1);let f="",d,h,p=0,g=0;const v=()=>{d&&(clearInterval(d),d=null)},k=()=>{h&&(clearInterval(h),h=null)},b=()=>{if(u.value=!1,f=a.value[g],!f)return _();c.value=f.substring(0,p++),p>f.length&&(v(),u.value=!0,setTimeout(()=>{h=setInterval(()=>{w()},s)},o))},w=()=>{p>=0?(u.value=!1,c.value=f.substring(0,p--)):(k(),u.value=!0,setTimeout(()=>{if(i){let L;do L=Math.floor(Math.random()*a.value.length);while(L===g);g=L}else g=(g+1)%a.value.length;d=setInterval(()=>{b()},n)},o))},y=()=>{u.value=!1,d=setInterval(()=>{b()},n)},_=(L=!1)=>{v(),k(),u.value=!1,L&&(c.value="",f="",p=0,g=0)},x=()=>{_(!0),y()};return r&&te(a,()=>x()),Un(_),{text:c,isFinished:u,start:y,stop:_,restart:x}},Ml="--vp-c-brand-1",Fl="--vp-c-brand-2",Bl="--vp-c-brand-3",Nl="--vp-c-brand-soft",Vl="--vp-c-bg",Ol="--vp-c-bg-alt",Dl="--vp-c-bg-soft",Rl="--vp-c-bg-elv",Hl="--vp-c-text-1",jh="--vp-c-text-2",Uh="--vp-c-text-3",zl="--tk-bg-color-elm",jl="--tk-bg-color-mute",on={vpBrand1:Ml,vpBrand2:Fl,vpBrand3:Bl,vpBrandSoft:Nl,vpBg:Vl,vpBgAlt:Ol,vpBgSoft:Dl,vpBgElv:Rl,vpText1:Hl,vpText2:jh,vpText3:Uh,tkBgColorElm:zl,tkBgColorMute:jl},Wh=(e,t)=>{const n=j(!1),{isDark:s}=Ae(),o=(v,k)=>{me&&document.documentElement.style.setProperty(v,k)},i=v=>{me&&document.documentElement.style.removeProperty(v)},r=F(()=>Se(e)),a=()=>{Object.values(on).forEach(v=>{i(v)})},c=()=>{if(!me)return;const v=r.value;if(!v)return;const k={[Ml]:v,[Fl]:_n(v,.1),[Bl]:_n(v,.2),[Nl]:_n(v,.85)},b={[Vl]:_n(v,.96),[Ol]:_n(v,.93),[Rl]:_n(v,.945),[Dl]:_n(v,.93),[Hl]:Cn(v,.6),[jh]:Cn(v,.7),[Uh]:_n(v,.6),[zl]:_n(v,.945),[jl]:_n(v,.91)},w=ht(t)?t():t||[];Object.keys(k).forEach(y=>{w?.includes(y)||o(y,k[y])}),n.value&&Object.keys(b).forEach(y=>{w?.includes(y)||o(y,b[y])})},u=()=>{if(!me)return;const v=r.value;if(!v)return;const k={[Ml]:v,[Fl]:Cn(v,.1),[Bl]:Cn(v,.2),[Nl]:Cn(v,.85)},b={[Vl]:Cn(v,.92),[Ol]:Cn(v,.94),[Rl]:Cn(v,.92),[Dl]:Cn(v,.94),[Hl]:_n(v,.9),[zl]:Cn(v,.92),[jl]:Cn(v,.91)},w=ht(t)?t():t||[];Object.keys(k).forEach(y=>{w?.includes(y)||o(y,k[y])}),n.value&&Object.keys(b).forEach(y=>{w?.includes(y)||o(y,b[y])})},f=ze(!1);let d=null;const h=()=>{!f.value||d||(f.value=!1,p(),d=te(s,p,{flush:"post"}))},p=()=>{f.value||(a(),s.value?u():c())},g=()=>{d?.(),d=null,f.value=!0,a()};return h(),te(r,p),te(n,()=>{g(),h()}),{isSpread:It(n),start:h,stop:g,update:p,clear:a,updateSpread:v=>n.value=v}},j9=e=>{if(!me)return;const{enabled:t=!0,mode:n="out-in",duration:s=e.mode==="out-in"?300:600,easing:o="ease-in"}=e;if(!t)return;const i=n==="out-in",{isDark:r}=Ae();document.documentElement.setAttribute("view-transition",n);const a=()=>"startViewTransition"in document&&window.matchMedia("(prefers-reduced-motion: no-preference)").matches;In("toggle-appearance",async({clientX:c,clientY:u})=>{if(!a()){r.value=!r.value;return}const f=[`circle(0px at ${c}px ${u}px)`,`circle(${Math.hypot(Math.max(c,innerWidth-c),Math.max(u,innerHeight-u))}px at ${c}px ${u}px)`];await document.startViewTransition(async()=>{r.value=!r.value,await Oe()}).ready;const d=i?r.value:!1;document.documentElement.animate({clipPath:d?f.reverse():f},{duration:s,easing:o,fill:"forwards",pseudoElement:`::view-transition-${d?"old":"new"}(root)`})})},Is=()=>{const e=jn(),t=(r,a,c="after")=>{const{state:u={},onBeforeRouteChange:f}=e;if(u[r])return;const d=c==="before"?a:f,h=c==="after"?a:f;e.onBeforeRouteChange=async p=>await d?.(p)===!1?!1:await h?.(p),e.state={...u,[r]:!0}},n=(r,a,c="after")=>{const{state:u={},onBeforePageLoad:f}=e;if(u[r])return;const d=c==="before"?a:f,h=c==="after"?a:f;e.onBeforePageLoad=async p=>await d?.(p)===!1?!1:await h?.(p),e.state={...u,[r]:!0}},s=(r,a,c="after")=>{const{state:u={},onAfterPageLoad:f}=e;if(u[r])return;const d=c==="before"?a:f,h=c==="after"?a:f;e.onAfterPageLoad=async p=>{await d?.(p),await h?.(p)},e.state={...u,[r]:!0}},o=(r,a,c="after")=>{const{state:u={},onAfterRouteChange:f}=e;if(u[r])return;const d=c==="before"?a:f,h=c==="after"?a:f;e.onAfterRouteChange=async p=>{await d?.(p),await h?.(p)},e.state={...u,[r]:!0}},i=(r,a)=>{const{state:c={}}=e;c[r]||(a(e),e.state={...c,[r]:!0})};return{router:e,route:e.route,bindBeforeRouteChange:t,bindBeforePageLoad:n,bindAfterPageLoad:s,bindAfterRouteChange:o,bindRouterFn:i}},Ca=(e,t=!0)=>{let n=!1;const s=[],o=()=>{const c=l(e);c&&(F7(c)?c.forEach(u=>i(u)):i(c))},i=c=>{c.classList.add("scroll__animate");const{create:u,clean:f}=U9(c,d=>{d.forEach(h=>{h.isIntersecting&&requestAnimationFrame(()=>{try{c.classList.add("visible"),f()}catch(p){console.error("初始化动画失败:",p)}})})},.1);u(),s.push(f)},r=()=>{s.forEach(c=>c())},a=()=>{r(),o()};return te(()=>l(e),()=>{!n&&a()},{deep:!0}),No(async()=>{n=!0,t&&a(),await Oe(),n=!1}),Un(r),{start:o,stop:r,restart:a}},U9=(e,t,n)=>{let s=null;const o=()=>{const r=l(e);s||!r||(s=new IntersectionObserver(t,{threshold:n}),s.observe(r))},i=()=>{s&&(s.disconnect(),s=null)};return Un(i),{create:o,clean:i}},Qf={current:0},Zf=j(0),W9=2e3,ed=Symbol("tkZIndexContextKey"),q9=Symbol("zIndexContextKey"),nu=e=>{const t=dt()?qe(ed,Qf):Qf,n=dt()?qe(q9,void 0):void 0,s=F(()=>{const r=n?.value;return Gc(r)?r:W9}),o=F(()=>s.value+Zf.value),i=()=>(t.current++,Zf.value=t.current,o.value);return qe(ed,void 0)&&console.warn("ZIndexInjection",`Looks like you are using server rendering, you must provide a z-index provider to ensure the hydration process to be succeed -usage: app.provide(ZINDEX_INJECTION_KEY, { current: 0 })`),{initialZIndex:s,currentZIndex:o,nextZIndex:i}};function qh(e){return typeof e>"u"||e===null}function K9(e){return typeof e=="object"&&e!==null}function Y9(e){return Array.isArray(e)?e:qh(e)?[]:[e]}function G9(e,t){var n,s,o,i;if(t)for(i=Object.keys(t),n=0,s=i.length;n=0?"0b"+e.toString(2):"-0b"+e.toString(2).slice(1)},octal:function(e){return e>=0?"0o"+e.toString(8):"-0o"+e.toString(8).slice(1)},decimal:function(e){return e.toString(10)},hexadecimal:function(e){return e>=0?"0x"+e.toString(16).toUpperCase():"-0x"+e.toString(16).toUpperCase().slice(1)}},defaultStyle:"decimal",styleAliases:{binary:[2,"bin"],octal:[8,"oct"],decimal:[10,"dec"],hexadecimal:[16,"hex"]}}),$y=new RegExp("^(?:[-+]?(?:[0-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?|\\.[0-9_]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$");function Ly(e){return!(e===null||!$y.test(e)||e[e.length-1]==="_")}function Iy(e){var t,n;return t=e.replace(/_/g,"").toLowerCase(),n=t[0]==="-"?-1:1,"+-".indexOf(t[0])>=0&&(t=t.slice(1)),t===".inf"?n===1?Number.POSITIVE_INFINITY:Number.NEGATIVE_INFINITY:t===".nan"?NaN:n*parseFloat(t,10)}var Py=/^[-+]?[0-9]+e/;function My(e,t){var n;if(isNaN(e))switch(t){case"lowercase":return".nan";case"uppercase":return".NAN";case"camelcase":return".NaN"}else if(Number.POSITIVE_INFINITY===e)switch(t){case"lowercase":return".inf";case"uppercase":return".INF";case"camelcase":return".Inf"}else if(Number.NEGATIVE_INFINITY===e)switch(t){case"lowercase":return"-.inf";case"uppercase":return"-.INF";case"camelcase":return"-.Inf"}else if(su.isNegativeZero(e))return"-0.0";return n=e.toString(10),Py.test(n)?n.replace("e",".e"):n}function Fy(e){return Object.prototype.toString.call(e)==="[object Number]"&&(e%1!==0||su.isNegativeZero(e))}var By=new Ft("tag:yaml.org,2002:float",{kind:"scalar",resolve:Ly,construct:Iy,predicate:Fy,represent:My,defaultStyle:"lowercase"}),Ny=hy.extend({implicit:[vy,wy,Ay,By]}),Vy=Ny,Yh=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"),Gh=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$");function Oy(e){return e===null?!1:Yh.exec(e)!==null||Gh.exec(e)!==null}function Dy(e){var t,n,s,o,i,r,a,c=0,u=null,f,d,h;if(t=Yh.exec(e),t===null&&(t=Gh.exec(e)),t===null)throw new Error("Date resolve error");if(n=+t[1],s=+t[2]-1,o=+t[3],!t[4])return new Date(Date.UTC(n,s,o));if(i=+t[4],r=+t[5],a=+t[6],t[7]){for(c=t[7].slice(0,3);c.length<3;)c+="0";c=+c}return t[9]&&(f=+t[10],d=+(t[11]||0),u=(f*60+d)*6e4,t[9]==="-"&&(u=-u)),h=new Date(Date.UTC(n,s,o,i,r,a,c)),u&&h.setTime(h.getTime()-u),h}function Ry(e){return e.toISOString()}var Hy=new Ft("tag:yaml.org,2002:timestamp",{kind:"scalar",resolve:Oy,construct:Dy,instanceOf:Date,represent:Ry});function zy(e){return e==="<<"||e===null}var jy=new Ft("tag:yaml.org,2002:merge",{kind:"scalar",resolve:zy}),ou=`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/= -\r`;function Uy(e){if(e===null)return!1;var t,n,s=0,o=e.length,i=ou;for(n=0;n64)){if(t<0)return!1;s+=6}return s%8===0}function Wy(e){var t,n,s=e.replace(/[\r\n=]/g,""),o=s.length,i=ou,r=0,a=[];for(t=0;t>16&255),a.push(r>>8&255),a.push(r&255)),r=r<<6|i.indexOf(s.charAt(t));return n=o%4*6,n===0?(a.push(r>>16&255),a.push(r>>8&255),a.push(r&255)):n===18?(a.push(r>>10&255),a.push(r>>2&255)):n===12&&a.push(r>>4&255),new Uint8Array(a)}function qy(e){var t="",n=0,s,o,i=e.length,r=ou;for(s=0;s>18&63],t+=r[n>>12&63],t+=r[n>>6&63],t+=r[n&63]),n=(n<<8)+e[s];return o=i%3,o===0?(t+=r[n>>18&63],t+=r[n>>12&63],t+=r[n>>6&63],t+=r[n&63]):o===2?(t+=r[n>>10&63],t+=r[n>>4&63],t+=r[n<<2&63],t+=r[64]):o===1&&(t+=r[n>>2&63],t+=r[n<<4&63],t+=r[64],t+=r[64]),t}function Ky(e){return Object.prototype.toString.call(e)==="[object Uint8Array]"}var Yy=new Ft("tag:yaml.org,2002:binary",{kind:"scalar",resolve:Uy,construct:Wy,predicate:Ky,represent:qy}),Gy=Object.prototype.hasOwnProperty,Jy=Object.prototype.toString;function Xy(e){if(e===null)return!0;var t=[],n,s,o,i,r,a=e;for(n=0,s=a.length;nz({name:"TeekConfigProvider",setup(t,{slots:n}){In(fb,Jh()),A9().startWatch();const{getTeekConfig:s}=fe(),o=s("viewTransition",{enabled:!0,mode:"out-in",easing:"ease-in"});return o.enabled&&j9(o),()=>nn(e,null,n)}}),fe=()=>{const{theme:e,frontmatter:t}=Ae(),n=qe(db,{}),s=(i,r)=>{let a=r;if(ht(r)&&(a=r()),!i)return{...a,...e.value,...t.value,...t.value.tk,...l(n)};const c=e.value[i],u=t.value.tk?.[i]??t.value[i],f=l(n)?.[i];return ti(c)||ti(u)||ti(f)?{...a,...c,...u,...f}:f??u??c??a};return{getTeekConfig:s,getTeekConfigRef:(i,r)=>F(()=>s(i,r))}},iu=()=>{const{frontmatter:e}=Ae(),t=F(()=>!n.value&&!s.value&&e.value.layout==="home"),n=F(()=>!!e.value.categoriesPage),s=F(()=>!!e.value.tagsPage),o=F(()=>!!e.value.archivesPage),i=F(()=>!!e.value.catalogue),r=F(()=>!!e.value.articleOverviewPage),a=F(()=>!!e.value.loginPage),c=F(()=>!!e.value.riskLinkPage);return{isHomePage:t,isCategoriesPage:n,isTagsPage:s,isArchivesPage:o,isCataloguePage:i,isArticleOverviewPage:r,isLoginUrl:a,isRiskLinkPage:c}},Li=()=>{const{getTeekConfigRef:e}=fe(),{localeIndex:t,site:n}=Ae(),s=Pn(),o=e("category",{path:"/categories"}),i=e("tag",{path:"/tags"}),r=F(()=>{const u=t.value;return`${u!=="root"?`/${u}`:""}${o.value.path}${n.value.cleanUrls?"":".html"}`}),a=F(()=>{const u=t.value;return`${u!=="root"?`/${u}`:""}${i.value.path}${n.value.cleanUrls?"":".html"}`}),c=F(()=>{let u="",f="",d="",h="";return s.value.allPosts.forEach(p=>{const{frontmatter:{layout:g,archivesPage:v,articleOverviewPage:k,loginPage:b,riskLinkPage:w},url:y}=p,_=g==="page";(g==="TkCataloguePage"||_&&v===!0)&&(u=y),(g==="TkArticleOverviewPage"||_&&k===!0)&&(f=y),g===!1&&b===!0&&(d=y),g===!1&&w===!0&&(h=y)}),{archivesUrl:u,articleOverviewUrl:f,loginUrl:d,riskLinkUrl:h}});return{categoryPath:r,tagPath:a,archivesPath:F(()=>c.value.archivesUrl),articleOverviewPath:F(()=>c.value.articleOverviewUrl),loginPath:F(()=>c.value.loginUrl),riskLinkPath:F(()=>c.value.riskLinkUrl)}},Jh=()=>{const{theme:e}=Ae();return e.value.posts||ub},Pn=()=>{const{localeIndex:e}=Ae(),t=Jh();return F(()=>t.locales?.[e.value]||t)},Xh=()=>{const{getTeekConfigRef:e}=fe();return e("tagColor",[{border:"#bfdbfe",bg:"#eff6ff",text:"#2563eb"},{border:"#e9d5ff",bg:"#faf5ff",text:"#9333ea"},{border:"#fbcfe8",bg:"#fdf2f8",text:"#db2777"},{border:"#a7f3d0",bg:"#ecfdf5",text:"#059669"},{border:"#fde68a",bg:"#fffbeb",text:"#d97706"},{border:"#a5f3fc",bg:"#ecfeff",text:"#0891b2"},{border:"#c7d2fe",bg:"#eef2ff",text:"#4f46e5"}])},_a=e=>{const{getTeekConfigRef:t}=fe(),n=t("windowTransition",!0);return F(()=>{const s=n.value;return s===void 0?!0:ti(s)?e?.(s)??!0:s!==!1})},Qh=()=>({isMobile:Xt("(max-width: 768px)")}),Zh=()=>{const e=j(!0),t=kn();return te(()=>t.path,async()=>{if(!me)return;await Oe(),document.querySelector(".VPSidebar")?e.value=!0:e.value=!1},{immediate:!0,flush:"post"}),{hasSidebar:e}},pb=/\b(?:VPBadge|header-anchor|footnote-ref|ignore-header)\b/,Wl=[];function mb(e){return typeof e.outline=="object"&&!Array.isArray(e.outline)&&e.outline.label||"On this page"}function sd(e){const t=ie(),n=[...document.querySelectorAll(`.${t.join("article-page")} :where(h1,h2,h3,h4,h5,h6)`)].filter(s=>s.id&&s.hasChildNodes()).map(s=>{const o=Number(s.tagName[1]);return{element:s,title:gb(s),link:"#"+s.id,level:o}});return vb(n,e)}function gb(e){let t="";for(const n of e.childNodes)if(n.nodeType===1){if(pb.test(n.className))continue;t+=n.textContent}else n.nodeType===3&&(t+=n.textContent);return t.trim()}function vb(e,t){if(t===!1)return[];const n=(typeof t=="object"&&!Array.isArray(t)?t.level:t)||2,[s,o]=typeof n=="number"?[n,n]:n==="deep"?[2,6]:n;return kb(e,s,o)}const yb=(e,t)=>{const n=Xt("(min-width: 1280px)"),s=ts(i,100);let o=null;be(()=>{requestAnimationFrame(i),window.addEventListener("scroll",s)}),Fo(()=>{r(location.hash)}),cn(()=>{window.removeEventListener("scroll",s)});function i(){if(!n.value)return;const a=window.scrollY,c=window.innerHeight,u=document.body.offsetHeight,f=Math.abs(a+c-u)<1,d=Wl.map(({element:p,link:g})=>({link:g,top:bb(p)})).filter(({top:p})=>!Number.isNaN(p)).sort((p,g)=>p.top-g.top);if(!d.length){r(null);return}if(a<1){r(null);return}if(f){r(d[d.length-1].link);return}let h=null;for(const{link:p,top:g}of d){if(g>a+Hc()+4)break;h=p}r(h)}function r(a){o&&o.classList.remove("active"),a==null?o=null:o=e.value.querySelector(`a[href="${decodeURIComponent(a)}"]`);const c=o;c?(c.classList.add("active"),t.value.style.top=c.offsetTop+39+"px",t.value.style.opacity="1"):(t.value.style.top="33px",t.value.style.opacity="0")}};function bb(e){let t=0;for(;e!==document.body;){if(e===null)return NaN;t+=e.offsetTop,e=e.offsetParent}return t}function kb(e,t,n){Wl.length=0;const s=[],o=[];return e.forEach(i=>{const r={...i,children:[]};let a=o[o.length-1];for(;a&&a.level>=r.level;)o.pop(),a=o[o.length-1];if(r.element.classList.contains("ignore-header")||a&&"shouldIgnore"in a){o.push({level:r.level,shouldIgnore:!0});return}r.level>n||r.level{const i=un("DocAsideOutlineItem",!0);return m(),C("ul",{class:T([l(t).b(),e.root?l(t).is("root"):l(t).is("nested")])},[(m(!0),C(Y,null,le(e.headers,({children:r,link:a,title:c})=>(m(),C("li",{key:a},[S("a",{class:T(l(t).m("link")),href:a,onClick:n,title:c},W(c),11,wb),r?.length?(m(),D(i,{key:0,headers:r},null,8,["headers"])):A("v-if",!0)]))),128))],2)}}}),_b=z({name:"DocAsideOutline",__name:"DocAsideOutline",setup(e){const t=ie("aside-outline"),{frontmatter:n,theme:s}=Ae(),o=ze([]);Ai(()=>{o.value=sd(n.value.outline??s.value.outline)}),be(()=>{o.value?.length||(o.value=sd(n.value.outline??s.value.outline))});const i=j(),r=j();return yb(i,r),(a,c)=>(m(),C("nav",{"aria-labelledby":"doc-outline-aria-label",class:T([l(t).b(),{"has-outline":o.value.length>0}]),ref_key:"container",ref:i},[S("div",{class:T(l(t).e("content"))},[S("div",{class:T(l(t).m("marker")),ref_key:"marker",ref:r},null,2),S("div",{id:"doc-outline-aria-label","aria-level":"2",class:T(l(t).m("title")),role:"heading"},W(l(mb)(l(s))),3),H(Cb,{headers:o.value,root:!0},null,8,["headers"])],2)],2))}}),ru=z({name:"ArticlePage",__name:"index",props:{doc:{type:Boolean},aside:{type:Boolean}},setup(e){const t=ie("article-page");return(n,s)=>(m(),C("div",{class:T([l(t).b(),l(t).is("aside",e.aside)])},[e.aside?(m(),C("div",{key:0,class:T(l(t).e("aside"))},[S("div",{class:T(l(t).e("aside__container"))},[H(_b)],2)],2)):A("v-if",!0),S("div",{class:T([l(t).join("doc"),{"vp-doc":e.doc}])},[S("div",null,[M(n.$slots,"default")])],2)],2))}}),Dr=z({name:"TitleTag",__name:"index",props:{text:{},type:{},position:{},size:{}},setup(e){const t=ie("title-tag");return(n,s)=>e.text||n.$slots.default?(m(),C("span",{key:0,class:T([l(t).b(),e.type&&l(t).m(e.type),e.position&&l(t).m(e.position),e.size&&l(t).m(e.size)])},[M(n.$slots,"default",{},()=>[rt(W(e.text),1)])],2)):A("v-if",!0)}});const Sb=["href","aria-label"],Tb=["innerHTML"],Eb=["id","aria-labelledby"],xb=["href","aria-label"],Ab=["id"],$b=["aria-label"];var Lb=z({name:"CatalogueItem",__name:"CatalogueItem",props:{item:{},index:{}},setup(e){const t=ie("sub-catalogue"),n=ie("catalogue-item");return(s,o)=>{const i=un("CatalogueItem",!0);return m(),C("li",{class:T(e.item.children?l(t).b():l(n).b())},[e.item.children?e.item.children.length?(m(),C(Y,{key:1},[S("div",{id:e.item.title,class:T(l(t).e("title")),role:"group","aria-labelledby":`${e.item.title}-label`},[S("a",{href:`#${e.item.title}`,class:"anchor","aria-label":e.item.title},"#",8,xb),S("span",{id:`${e.item.title}-label`},W(`${e.index}. ${e.item.title}`),9,Ab)],10,Eb),e.item.children?(m(),C("ul",{key:0,class:T(`${l(t).e("inline")} flx-wrap-between`),"aria-label":e.item.title},[A(" 递归自己 "),(m(!0),C(Y,null,le(e.item.children,(r,a)=>(m(),D(i,{key:a,item:r,index:`${e.index}-${a+1}`},null,8,["item","index"]))),128))],10,$b)):A("v-if",!0)],64)):A("v-if",!0):(m(),C("a",{key:0,href:e.item.url&&l(Ee)(e.item.url),"aria-label":`${e.index}. ${e.item.title}`},[rt(W(e.index)+". ",1),S("span",{innerHTML:e.item.title},null,8,Tb),e.item.frontmatter?.titleTag?(m(),D(l(Dr),{key:0,text:e.item.frontmatter?.titleTag,position:"right",size:"small","aria-label":e.item.frontmatter?.titleTag},null,8,["text","aria-label"])):A("v-if",!0)],8,Sb))],2)}}});const Ib={id:"catalogue-header-title"},Pb={class:"description"},Mb={id:"catalogue-list-title",class:"title"},Fb={class:"flx-wrap-between"},Bb={class:"vp-doc"};var ep=z({name:"CataloguePage",__name:"index",setup(e){const t=ie("catalogue"),{t:n}=ge(),{theme:s,frontmatter:o}=Ae(),i=F(()=>s.value.catalogues?.inv[o.value.path]?.catalogues);return(r,a)=>{const c=un("Content");return m(),D(l(ru),{class:T(l(t).b()),"aria-label":l(n)("tk.catalogue.label")},{default:O(()=>[M(r.$slots,"teek-catalogue-top-before"),S("div",{class:T(l(t).e("header")),role:"group","aria-labelledby":"catalogue-header-title"},[S("h2",Ib,W(l(o).title),1),S("div",Pb,W(l(o).desc||l(o).description),1)],2),M(r.$slots,"teek-catalogue-top-after"),S("div",{class:T(l(t).e("wrapper")),"aria-labelledby":"catalogue-list-title"},[S("div",Mb,W(l(o).pageTitle||l(n)("tk.catalogue.title")),1),S("ul",Fb,[(m(!0),C(Y,null,le(i.value,(u,f)=>(m(),D(Lb,{key:f,item:u,index:f+1},null,8,["item","index"]))),128))])],2),S("div",Bb,[H(c)])]),_:3},8,["class","aria-label"])}}});const gi=Symbol(""),ni=Symbol(""),au=Symbol(""),Rr=Symbol(""),tp=Symbol(""),Ks=Symbol(""),np=Symbol(""),sp=Symbol(""),lu=Symbol(""),cu=Symbol(""),Ii=Symbol(""),uu=Symbol(""),op=Symbol(""),fu=Symbol(""),du=Symbol(""),hu=Symbol(""),pu=Symbol(""),mu=Symbol(""),gu=Symbol(""),ip=Symbol(""),rp=Symbol(""),Sa=Symbol(""),Hr=Symbol(""),vu=Symbol(""),yu=Symbol(""),vi=Symbol(""),Pi=Symbol(""),bu=Symbol(""),ql=Symbol(""),Nb=Symbol(""),Kl=Symbol(""),zr=Symbol(""),Vb=Symbol(""),Ob=Symbol(""),ku=Symbol(""),Db=Symbol(""),Rb=Symbol(""),wu=Symbol(""),ap=Symbol(""),Eo={[gi]:"Fragment",[ni]:"Teleport",[au]:"Suspense",[Rr]:"KeepAlive",[tp]:"BaseTransition",[Ks]:"openBlock",[np]:"createBlock",[sp]:"createElementBlock",[lu]:"createVNode",[cu]:"createElementVNode",[Ii]:"createCommentVNode",[uu]:"createTextVNode",[op]:"createStaticVNode",[fu]:"resolveComponent",[du]:"resolveDynamicComponent",[hu]:"resolveDirective",[pu]:"resolveFilter",[mu]:"withDirectives",[gu]:"renderList",[ip]:"renderSlot",[rp]:"createSlots",[Sa]:"toDisplayString",[Hr]:"mergeProps",[vu]:"normalizeClass",[yu]:"normalizeStyle",[vi]:"normalizeProps",[Pi]:"guardReactiveProps",[bu]:"toHandlers",[ql]:"camelize",[Nb]:"capitalize",[Kl]:"toHandlerKey",[zr]:"setBlockTracking",[Vb]:"pushScopeId",[Ob]:"popScopeId",[ku]:"withCtx",[Db]:"unref",[Rb]:"isRef",[wu]:"withMemo",[ap]:"isMemoSame"};function Hb(e){Object.getOwnPropertySymbols(e).forEach(t=>{Eo[t]=e[t]})}const fn={start:{line:1,column:1,offset:0},end:{line:1,column:1,offset:0},source:""};function zb(e,t=""){return{type:0,source:t,children:e,helpers:new Set,components:[],directives:[],hoists:[],imports:[],cached:[],temps:0,codegenNode:void 0,loc:fn}}function yi(e,t,n,s,o,i,r,a=!1,c=!1,u=!1,f=fn){return e&&(a?(e.helper(Ks),e.helper($o(e.inSSR,u))):e.helper(Ao(e.inSSR,u)),r&&e.helper(mu)),{type:13,tag:t,props:n,children:s,patchFlag:o,dynamicProps:i,directives:r,isBlock:a,disableTracking:c,isComponent:u,loc:f}}function Hs(e,t=fn){return{type:17,loc:t,elements:e}}function mn(e,t=fn){return{type:15,loc:t,properties:e}}function ft(e,t){return{type:16,loc:fn,key:_e(e)?Te(e,!0):e,value:t}}function Te(e,t=!1,n=fn,s=0){return{type:4,loc:n,content:e,isStatic:t,constType:t?3:s}}function An(e,t=fn){return{type:8,loc:t,children:e}}function mt(e,t=[],n=fn){return{type:14,loc:n,callee:e,arguments:t}}function xo(e,t=void 0,n=!1,s=!1,o=fn){return{type:18,params:e,returns:t,newline:n,isSlot:s,loc:o}}function Yl(e,t,n,s=!0){return{type:19,test:e,consequent:t,alternate:n,newline:s,loc:fn}}function jb(e,t,n=!1,s=!1){return{type:20,index:e,value:t,needPauseTracking:n,inVOnce:s,needArraySpread:!1,loc:fn}}function Ub(e){return{type:21,body:e,loc:fn}}function Ao(e,t){return e||t?lu:cu}function $o(e,t){return e||t?np:sp}function Cu(e,{helper:t,removeHelper:n,inSSR:s}){e.isBlock||(e.isBlock=!0,n(Ao(s,e.isComponent)),t(Ks),t($o(s,e.isComponent)))}const od=new Uint8Array([123,123]),id=new Uint8Array([125,125]);function rd(e){return e>=97&&e<=122||e>=65&&e<=90}function tn(e){return e===32||e===10||e===9||e===12||e===13}function hs(e){return e===47||e===62||tn(e)}function jr(e){const t=new Uint8Array(e.length);for(let n=0;n=0;o--){const i=this.newlines[o];if(t>i){n=o+2,s=t-i;break}}return{column:s,line:n,offset:t}}peek(){return this.buffer.charCodeAt(this.index+1)}stateText(t){t===60?(this.index>this.sectionStart&&this.cbs.ontext(this.sectionStart,this.index),this.state=5,this.sectionStart=this.index):!this.inVPre&&t===this.delimiterOpen[0]&&(this.state=2,this.delimiterIndex=0,this.stateInterpolationOpen(t))}stateInterpolationOpen(t){if(t===this.delimiterOpen[this.delimiterIndex])if(this.delimiterIndex===this.delimiterOpen.length-1){const n=this.index+1-this.delimiterOpen.length;n>this.sectionStart&&this.cbs.ontext(this.sectionStart,n),this.state=3,this.sectionStart=n}else this.delimiterIndex++;else this.inRCDATA?(this.state=32,this.stateInRCDATA(t)):(this.state=1,this.stateText(t))}stateInterpolation(t){t===this.delimiterClose[0]&&(this.state=4,this.delimiterIndex=0,this.stateInterpolationClose(t))}stateInterpolationClose(t){t===this.delimiterClose[this.delimiterIndex]?this.delimiterIndex===this.delimiterClose.length-1?(this.cbs.oninterpolation(this.sectionStart,this.index+1),this.inRCDATA?this.state=32:this.state=1,this.sectionStart=this.index+1):this.delimiterIndex++:(this.state=3,this.stateInterpolation(t))}stateSpecialStartSequence(t){const n=this.sequenceIndex===this.currentSequence.length;if(!(n?hs(t):(t|32)===this.currentSequence[this.sequenceIndex]))this.inRCDATA=!1;else if(!n){this.sequenceIndex++;return}this.sequenceIndex=0,this.state=6,this.stateInTagName(t)}stateInRCDATA(t){if(this.sequenceIndex===this.currentSequence.length){if(t===62||tn(t)){const n=this.index-this.currentSequence.length;if(this.sectionStart=t||(this.state===28?this.currentSequence===At.CdataEnd?this.cbs.oncdata(this.sectionStart,t):this.cbs.oncomment(this.sectionStart,t):this.state===6||this.state===11||this.state===18||this.state===17||this.state===12||this.state===13||this.state===14||this.state===15||this.state===16||this.state===20||this.state===19||this.state===21||this.state===9||this.cbs.ontext(this.sectionStart,t))}emitCodePoint(t,n){}}function ad(e,{compatConfig:t}){const n=t&&t[e];return e==="MODE"?n||3:n}function zs(e,t){const n=ad("MODE",t),s=ad(e,t);return n===3?s===!0:s!==!1}function bi(e,t,n,...s){return zs(e,t)}function _u(e){throw e}function lp(e){}function it(e,t,n,s){const o=`https://vuejs.org/error-reference/#compiler-${e}`,i=new SyntaxError(String(o));return i.code=e,i.loc=t,i}const Yt=e=>e.type===4&&e.isStatic;function cp(e){switch(e){case"Teleport":case"teleport":return ni;case"Suspense":case"suspense":return au;case"KeepAlive":case"keep-alive":return Rr;case"BaseTransition":case"base-transition":return tp}}const qb=/^$|^\d|[^\$\w\xA0-\uFFFF]/,Su=e=>!qb.test(e),up=/[A-Za-z_$\xA0-\uFFFF]/,Kb=/[\.\?\w$\xA0-\uFFFF]/,Yb=/\s+[.[]\s*|\s*[.[]\s+/g,fp=e=>e.type===4?e.content:e.loc.source,Gb=e=>{const t=fp(e).trim().replace(Yb,a=>a.trim());let n=0,s=[],o=0,i=0,r=null;for(let a=0;a|^\s*(?:async\s+)?function(?:\s+[\w$]+)?\s*\(/,Xb=e=>Jb.test(fp(e)),Qb=Xb;function pn(e,t,n=!1){for(let s=0;st.type===7&&t.name==="bind"&&(!t.arg||t.arg.type!==4||!t.arg.isStatic))}function Ga(e){return e.type===5||e.type===2}function ld(e){return e.type===7&&e.name==="pre"}function ek(e){return e.type===7&&e.name==="slot"}function Ur(e){return e.type===1&&e.tagType===3}function Wr(e){return e.type===1&&e.tagType===2}const tk=new Set([vi,Pi]);function hp(e,t=[]){if(e&&!_e(e)&&e.type===14){const n=e.callee;if(!_e(n)&&tk.has(n))return hp(e.arguments[0],t.concat(e))}return[e,t]}function qr(e,t,n){let s,o=e.type===13?e.props:e.arguments[2],i=[],r;if(o&&!_e(o)&&o.type===14){const a=hp(o);o=a[0],i=a[1],r=i[i.length-1]}if(o==null||_e(o))s=mn([t]);else if(o.type===14){const a=o.arguments[0];!_e(a)&&a.type===15?cd(t,a)||a.properties.unshift(t):o.callee===bu?s=mt(n.helper(Hr),[mn([t]),o]):o.arguments.unshift(mn([t])),!s&&(s=o)}else o.type===15?(cd(t,o)||o.properties.unshift(t),s=o):(s=mt(n.helper(Hr),[mn([t]),o]),r&&r.callee===Pi&&(r=i[i.length-2]));e.type===13?r?r.arguments[0]=s:e.props=s:r?r.arguments[0]=s:e.arguments[2]=s}function cd(e,t){let n=!1;if(e.key.type===4){const s=e.key.content;n=t.properties.some(o=>o.key.type===4&&o.key.content===s)}return n}function ki(e,t){return`_${t}_${e.replace(/[^\w]/g,(n,s)=>n==="-"?"_":e.charCodeAt(s).toString())}`}function nk(e){return e.type===14&&e.callee===wu?e.arguments[1].returns:e}const sk=/([\s\S]*?)\s+(?:in|of)\s+(\S[\s\S]*)/,pp={parseMode:"base",ns:0,delimiters:["{{","}}"],getNamespace:()=>0,isVoidTag:ao,isPreTag:ao,isIgnoreNewlineTag:ao,isCustomElement:ao,onError:_u,onWarn:lp,comments:!1,prefixIdentifiers:!1};let Re=pp,wi=null,ns="",Lt=null,$e=null,jt="",Yn=-1,Fs=-1,Tu=0,bs=!1,Gl=null;const ot=[],lt=new Wb(ot,{onerr:Kn,ontext(e,t){Xi(kt(e,t),e,t)},ontextentity(e,t,n){Xi(e,t,n)},oninterpolation(e,t){if(bs)return Xi(kt(e,t),e,t);let n=e+lt.delimiterOpen.length,s=t-lt.delimiterClose.length;for(;tn(ns.charCodeAt(n));)n++;for(;tn(ns.charCodeAt(s-1));)s--;let o=kt(n,s);o.includes("&")&&(o=Re.decodeEntities(o,!1)),Jl({type:5,content:pr(o,!1,ct(n,s)),loc:ct(e,t)})},onopentagname(e,t){const n=kt(e,t);Lt={type:1,tag:n,ns:Re.getNamespace(n,ot[0],Re.ns),tagType:0,props:[],children:[],loc:ct(e-1,t),codegenNode:void 0}},onopentagend(e){fd(e)},onclosetag(e,t){const n=kt(e,t);if(!Re.isVoidTag(n)){let s=!1;for(let o=0;o0&&Kn(24,ot[0].loc.start.offset);for(let r=0;r<=o;r++){const a=ot.shift();hr(a,t,r(s.type===7?s.rawName:s.name)===n)&&Kn(2,t)},onattribend(e,t){if(Lt&&$e){if(Vs($e.loc,t),e!==0)if(jt.includes("&")&&(jt=Re.decodeEntities(jt,!0)),$e.type===6)$e.name==="class"&&(jt=vp(jt).trim()),e===1&&!jt&&Kn(13,t),$e.value={type:2,content:jt,loc:e===1?ct(Yn,Fs):ct(Yn-1,Fs+1)},lt.inSFCRoot&&Lt.tag==="template"&&$e.name==="lang"&&jt&&jt!=="html"&<.enterRCDATA(jr("o.content==="sync"))>-1&&bi("COMPILER_V_BIND_SYNC",Re,$e.loc,$e.arg.loc.source)&&($e.name="model",$e.modifiers.splice(s,1))}($e.type!==7||$e.name!=="pre")&&Lt.props.push($e)}jt="",Yn=Fs=-1},oncomment(e,t){Re.comments&&Jl({type:3,content:kt(e,t),loc:ct(e-4,t+3)})},onend(){const e=ns.length;for(let t=0;t{const g=t.start.offset+h,v=g+d.length;return pr(d,!1,ct(g,v),0,p?1:0)},a={source:r(i.trim(),n.indexOf(i,o.length)),value:void 0,key:void 0,index:void 0,finalized:!1};let c=o.trim().replace(ok,"").trim();const u=o.indexOf(c),f=c.match(ud);if(f){c=c.replace(ud,"").trim();const d=f[1].trim();let h;if(d&&(h=n.indexOf(d,u+c.length),a.key=r(d,h,!0)),f[2]){const p=f[2].trim();p&&(a.index=r(p,n.indexOf(p,a.key?h+d.length:u+c.length),!0))}}return c&&(a.value=r(c,u,!0)),a}function kt(e,t){return ns.slice(e,t)}function fd(e){lt.inSFCRoot&&(Lt.innerLoc=ct(e+1,e+1)),Jl(Lt);const{tag:t,ns:n}=Lt;n===0&&Re.isPreTag(t)&&Tu++,Re.isVoidTag(t)?hr(Lt,e):(ot.unshift(Lt),(n===1||n===2)&&(lt.inXML=!0)),Lt=null}function Xi(e,t,n){{const i=ot[0]&&ot[0].tag;i!=="script"&&i!=="style"&&e.includes("&")&&(e=Re.decodeEntities(e,!1))}const s=ot[0]||wi,o=s.children[s.children.length-1];o&&o.type===2?(o.content+=e,Vs(o.loc,n)):s.children.push({type:2,content:e,loc:ct(t,n)})}function hr(e,t,n=!1){n?Vs(e.loc,mp(t,60)):Vs(e.loc,rk(t,62)+1),lt.inSFCRoot&&(e.children.length?e.innerLoc.end=Ie({},e.children[e.children.length-1].loc.end):e.innerLoc.end=Ie({},e.innerLoc.start),e.innerLoc.source=kt(e.innerLoc.start.offset,e.innerLoc.end.offset));const{tag:s,ns:o,children:i}=e;if(bs||(s==="slot"?e.tagType=2:dd(e)?e.tagType=3:lk(e)&&(e.tagType=1)),lt.inRCDATA||(e.children=gp(i)),o===0&&Re.isIgnoreNewlineTag(s)){const r=i[0];r&&r.type===2&&(r.content=r.content.replace(/^\r?\n/,""))}o===0&&Re.isPreTag(s)&&Tu--,Gl===e&&(bs=lt.inVPre=!1,Gl=null),lt.inXML&&(ot[0]?ot[0].ns:Re.ns)===0&&(lt.inXML=!1);{const r=e.props;if(!lt.inSFCRoot&&zs("COMPILER_NATIVE_TEMPLATE",Re)&&e.tag==="template"&&!dd(e)){const c=ot[0]||wi,u=c.children.indexOf(e);c.children.splice(u,1,...e.children)}const a=r.find(c=>c.type===6&&c.name==="inline-template");a&&bi("COMPILER_INLINE_TEMPLATE",Re,a.loc)&&e.children.length&&(a.value={type:2,content:kt(e.children[0].loc.start.offset,e.children[e.children.length-1].loc.end.offset),loc:a.loc})}}function rk(e,t){let n=e;for(;ns.charCodeAt(n)!==t&&n=0;)n--;return n}const ak=new Set(["if","else","else-if","for","slot"]);function dd({tag:e,props:t}){if(e==="template"){for(let n=0;n64&&e<91}const uk=/\r\n/g;function gp(e){const t=Re.whitespace!=="preserve";let n=!1;for(let s=0;sn.type!==3);return t.length===1&&t[0].type===1&&!Wr(t[0])?t[0]:null}function mr(e,t,n,s=!1,o=!1){const{children:i}=e,r=[];for(let f=0;f0){if(h>=2){d.codegenNode.patchFlag=-1,r.push(d);continue}}else{const p=d.codegenNode;if(p.type===13){const g=p.patchFlag;if((g===void 0||g===512||g===1)&&kp(d,n)>=2){const v=wp(d);v&&(p.props=n.hoist(v))}p.dynamicProps&&(p.dynamicProps=n.hoist(p.dynamicProps))}}}else if(d.type===12&&(s?0:rn(d,n))>=2){d.codegenNode.type===14&&d.codegenNode.arguments.length>0&&d.codegenNode.arguments.push("-1"),r.push(d);continue}if(d.type===1){const h=d.tagType===1;h&&n.scopes.vSlot++,mr(d,e,n,!1,o),h&&n.scopes.vSlot--}else if(d.type===11)mr(d,e,n,d.children.length===1,!0);else if(d.type===9)for(let h=0;hp.key===d||p.key.content===d);return h&&h.value}}r.length&&n.transformHoist&&n.transformHoist(i,n,e)}function rn(e,t){const{constantCache:n}=t;switch(e.type){case 1:if(e.tagType!==0)return 0;const s=n.get(e);if(s!==void 0)return s;const o=e.codegenNode;if(o.type!==13||o.isBlock&&e.tag!=="svg"&&e.tag!=="foreignObject"&&e.tag!=="math")return 0;if(o.patchFlag===void 0){let r=3;const a=kp(e,t);if(a===0)return n.set(e,0),0;a1)for(let c=0;cN&&(E.childIndex--,E.onNodeRemoved()),E.parent.children.splice(N,1)},onNodeRemoved:Ht,addIdentifiers(I){},removeIdentifiers(I){},hoist(I){_e(I)&&(I=Te(I)),E.hoists.push(I);const P=Te(`_hoisted_${E.hoists.length}`,!1,I.loc,2);return P.hoisted=I,P},cache(I,P=!1,N=!1){const $=jb(E.cached.length,I,P,N);return E.cached.push($),$}};return E.filters=new Set,E}function kk(e,t){const n=bk(e,t);Ea(e,n),t.hoistStatic&&vk(e,n),t.ssr||wk(e,n),e.helpers=new Set([...n.helpers.keys()]),e.components=[...n.components],e.directives=[...n.directives],e.imports=n.imports,e.hoists=n.hoists,e.temps=n.temps,e.cached=n.cached,e.transformed=!0,e.filters=[...n.filters]}function wk(e,t){const{helper:n}=t,{children:s}=e;if(s.length===1){const o=yp(e);if(o&&o.codegenNode){const i=o.codegenNode;i.type===13&&Cu(i,t),e.codegenNode=i}else e.codegenNode=s[0]}else if(s.length>1){let o=64;e.codegenNode=yi(t,n(gi),void 0,e.children,o,void 0,void 0,!0,void 0,!1)}}function Ck(e,t){let n=0;const s=()=>{n--};for(;ns===e:s=>e.test(s);return(s,o)=>{if(s.type===1){const{props:i}=s;if(s.tagType===3&&i.some(ek))return;const r=[];for(let a=0;a`${Eo[e]}: _${Eo[e]}`;function _k(e,{mode:t="function",prefixIdentifiers:n=t==="module",sourceMap:s=!1,filename:o="template.vue.html",scopeId:i=null,optimizeImports:r=!1,runtimeGlobalName:a="Vue",runtimeModuleName:c="vue",ssrRuntimeModuleName:u="vue/server-renderer",ssr:f=!1,isTS:d=!1,inSSR:h=!1}){const p={mode:t,prefixIdentifiers:n,sourceMap:s,filename:o,scopeId:i,optimizeImports:r,runtimeGlobalName:a,runtimeModuleName:c,ssrRuntimeModuleName:u,ssr:f,isTS:d,inSSR:h,source:e.source,code:"",column:1,line:1,offset:0,indentLevel:0,pure:!1,map:void 0,helper(v){return`_${Eo[v]}`},push(v,k=-2,b){p.code+=v},indent(){g(++p.indentLevel)},deindent(v=!1){v?--p.indentLevel:g(--p.indentLevel)},newline(){g(p.indentLevel)}};function g(v){p.push(` -`+" ".repeat(v),0)}return p}function Sk(e,t={}){const n=_k(e,t);t.onContextCreated&&t.onContextCreated(n);const{mode:s,push:o,prefixIdentifiers:i,indent:r,deindent:a,newline:c,scopeId:u,ssr:f}=n,d=Array.from(e.helpers),h=d.length>0,p=!i&&s!=="module";Tk(e,n);const v=f?"ssrRender":"render",b=(f?["_ctx","_push","_parent","_attrs"]:["_ctx","_cache"]).join(", ");if(o(`function ${v}(${b}) {`),r(),p&&(o("with (_ctx) {"),r(),h&&(o(`const { ${d.map(_p).join(", ")} } = _Vue -`,-1),c())),e.components.length&&(Ja(e.components,"component",n),(e.directives.length||e.temps>0)&&c()),e.directives.length&&(Ja(e.directives,"directive",n),e.temps>0&&c()),e.filters&&e.filters.length&&(c(),Ja(e.filters,"filter",n),c()),e.temps>0){o("let ");for(let w=0;w0?", ":""}_temp${w}`)}return(e.components.length||e.directives.length||e.temps)&&(o(` -`,0),c()),f||o("return "),e.codegenNode?Bt(e.codegenNode,n):o("null"),p&&(a(),o("}")),a(),o("}"),{ast:e,code:n.code,preamble:"",map:n.map?n.map.toJSON():void 0}}function Tk(e,t){const{ssr:n,prefixIdentifiers:s,push:o,newline:i,runtimeModuleName:r,runtimeGlobalName:a,ssrRuntimeModuleName:c}=t,u=a,f=Array.from(e.helpers);if(f.length>0&&(o(`const _Vue = ${u} -`,-1),e.hoists.length)){const d=[lu,cu,Ii,uu,op].filter(h=>f.includes(h)).map(_p).join(", ");o(`const { ${d} } = _Vue -`,-1)}Ek(e.hoists,t),i(),o("return ")}function Ja(e,t,{helper:n,push:s,newline:o,isTS:i}){const r=n(t==="filter"?pu:t==="component"?fu:hu);for(let a=0;a3||!1;t.push("["),n&&t.indent(),Mi(e,t,n),n&&t.deindent(),t.push("]")}function Mi(e,t,n=!1,s=!0){const{push:o,newline:i}=t;for(let r=0;rn||"null")}function Mk(e,t){const{push:n,helper:s,pure:o}=t,i=_e(e.callee)?e.callee:s(e.callee);o&&n(xa),n(i+"(",-2,e),Mi(e.arguments,t),n(")")}function Fk(e,t){const{push:n,indent:s,deindent:o,newline:i}=t,{properties:r}=e;if(!r.length){n("{}",-2,e);return}const a=r.length>1||!1;n(a?"{":"{ "),a&&s();for(let c=0;c "),(c||a)&&(n("{"),s()),r?(c&&n("return "),ce(r)?Eu(r,t):Bt(r,t)):a&&Bt(a,t),(c||a)&&(o(),n("}")),u&&(e.isNonScopedSlot&&n(", undefined, true"),n(")"))}function Vk(e,t){const{test:n,consequent:s,alternate:o,newline:i}=e,{push:r,indent:a,deindent:c,newline:u}=t;if(n.type===4){const d=!Su(n.content);d&&r("("),Sp(n,t),d&&r(")")}else r("("),Bt(n,t),r(")");i&&a(),t.indentLevel++,i||r(" "),r("? "),Bt(s,t),t.indentLevel--,i&&u(),i||r(" "),r(": ");const f=o.type===19;f||t.indentLevel++,Bt(o,t),f||t.indentLevel--,i&&c(!0)}function Ok(e,t){const{push:n,helper:s,indent:o,deindent:i,newline:r}=t,{needPauseTracking:a,needArraySpread:c}=e;c&&n("[...("),n(`_cache[${e.index}] || (`),a&&(o(),n(`${s(zr)}(-1`),e.inVOnce&&n(", true"),n("),"),r(),n("(")),n(`_cache[${e.index}] = `),Bt(e.value,t),a&&(n(`).cacheIndex = ${e.index},`),r(),n(`${s(zr)}(1),`),r(),n(`_cache[${e.index}]`),i()),n(")"),c&&n(")]")}new RegExp("\\b"+"arguments,await,break,case,catch,class,const,continue,debugger,default,delete,do,else,export,extends,finally,for,function,if,import,let,new,return,super,switch,throw,try,var,void,while,with,yield".split(",").join("\\b|\\b")+"\\b");const Dk=Cp(/^(?:if|else|else-if)$/,(e,t,n)=>Rk(e,t,n,(s,o,i)=>{const r=n.parent.children;let a=r.indexOf(s),c=0;for(;a-->=0;){const u=r[a];u&&u.type===9&&(c+=u.branches.length)}return()=>{if(i)s.codegenNode=pd(o,c,n);else{const u=Hk(s.codegenNode);u.alternate=pd(o,c+s.branches.length-1,n)}}}));function Rk(e,t,n,s){if(t.name!=="else"&&(!t.exp||!t.exp.content.trim())){const o=t.exp?t.exp.loc:e.loc;n.onError(it(28,t.loc)),t.exp=Te("true",!1,o)}if(t.name==="if"){const o=hd(e,t),i={type:9,loc:hk(e.loc),branches:[o]};if(n.replaceNode(i),s)return s(i,o,!0)}else{const o=n.parent.children;let i=o.indexOf(e);for(;i-->=-1;){const r=o[i];if(r&&r.type===3){n.removeNode(r);continue}if(r&&r.type===2&&!r.content.trim().length){n.removeNode(r);continue}if(r&&r.type===9){(t.name==="else-if"||t.name==="else")&&r.branches[r.branches.length-1].condition===void 0&&n.onError(it(30,e.loc)),n.removeNode();const a=hd(e,t);r.branches.push(a);const c=s&&s(r,a,!1);Ea(a,n),c&&c(),n.currentNode=null}else n.onError(it(30,e.loc));break}}}function hd(e,t){const n=e.tagType===3;return{type:10,loc:e.loc,condition:t.name==="else"?void 0:t.exp,children:n&&!pn(e,"for")?e.children:[e],userKey:Ta(e,"key"),isTemplateIf:n}}function pd(e,t,n){return e.condition?Yl(e.condition,md(e,t,n),mt(n.helper(Ii),['""',"true"])):md(e,t,n)}function md(e,t,n){const{helper:s}=n,o=ft("key",Te(`${t}`,!1,fn,2)),{children:i}=e,r=i[0];if(i.length!==1||r.type!==1)if(i.length===1&&r.type===11){const c=r.codegenNode;return qr(c,o,n),c}else return yi(n,s(gi),mn([o]),i,64,void 0,void 0,!0,!1,!1,e.loc);else{const c=r.codegenNode,u=nk(c);return u.type===13&&Cu(u,n),qr(u,o,n),c}}function Hk(e){for(;;)if(e.type===19)if(e.alternate.type===19)e=e.alternate;else return e;else e.type===20&&(e=e.value)}const zk=Cp("for",(e,t,n)=>{const{helper:s,removeHelper:o}=n;return jk(e,t,n,i=>{const r=mt(s(gu),[i.source]),a=Ur(e),c=pn(e,"memo"),u=Ta(e,"key",!1,!0);u&&u.type;let f=u&&(u.type===6?u.value?Te(u.value.content,!0):void 0:u.exp);const d=u&&f?ft("key",f):null,h=i.source.type===4&&i.source.constType>0,p=h?64:u?128:256;return i.codegenNode=yi(n,s(gi),void 0,r,p,void 0,void 0,!0,!h,!1,e.loc),()=>{let g;const{children:v}=i,k=v.length!==1||v[0].type!==1,b=Wr(e)?e:a&&e.children.length===1&&Wr(e.children[0])?e.children[0]:null;if(b?(g=b.codegenNode,a&&d&&qr(g,d,n)):k?g=yi(n,s(gi),d?mn([d]):void 0,e.children,64,void 0,void 0,!0,void 0,!1):(g=v[0].codegenNode,a&&d&&qr(g,d,n),g.isBlock!==!h&&(g.isBlock?(o(Ks),o($o(n.inSSR,g.isComponent))):o(Ao(n.inSSR,g.isComponent))),g.isBlock=!h,g.isBlock?(s(Ks),s($o(n.inSSR,g.isComponent))):s(Ao(n.inSSR,g.isComponent))),c){const w=xo(Xl(i.parseResult,[Te("_cached")]));w.body=Ub([An(["const _memo = (",c.exp,")"]),An(["if (_cached",...f?[" && _cached.key === ",f]:[],` && ${n.helperString(ap)}(_cached, _memo)) return _cached`]),An(["const _item = ",g]),Te("_item.memo = _memo"),Te("return _item")]),r.arguments.push(w,Te("_cache"),Te(String(n.cached.length))),n.cached.push(null)}else r.arguments.push(xo(Xl(i.parseResult),g,!0))}})});function jk(e,t,n,s){if(!t.exp){n.onError(it(31,t.loc));return}const o=t.forParseResult;if(!o){n.onError(it(32,t.loc));return}Ep(o);const{addIdentifiers:i,removeIdentifiers:r,scopes:a}=n,{source:c,value:u,key:f,index:d}=o,h={type:11,loc:t.loc,source:c,valueAlias:u,keyAlias:f,objectIndexAlias:d,parseResult:o,children:Ur(e)?e.children:[e]};n.replaceNode(h),a.vFor++;const p=s&&s(h);return()=>{a.vFor--,p&&p()}}function Ep(e,t){e.finalized||(e.finalized=!0)}function Xl({value:e,key:t,index:n},s=[]){return Uk([e,t,n,...s])}function Uk(e){let t=e.length;for(;t--&&!e[t];);return e.slice(0,t+1).map((n,s)=>n||Te("_".repeat(s+1),!1))}const gd=Te("undefined",!1),Wk=(e,t)=>{if(e.type===1&&(e.tagType===1||e.tagType===3)){const n=pn(e,"slot");if(n)return n.exp,t.scopes.vSlot++,()=>{t.scopes.vSlot--}}},qk=(e,t,n,s)=>xo(e,n,!1,!0,n.length?n[0].loc:s);function Kk(e,t,n=qk){t.helper(ku);const{children:s,loc:o}=e,i=[],r=[];let a=t.scopes.vSlot>0||t.scopes.vFor>0;const c=pn(e,"slot",!0);if(c){const{arg:k,exp:b}=c;k&&!Yt(k)&&(a=!0),i.push(ft(k||Te("default",!0),n(b,void 0,s,o)))}let u=!1,f=!1;const d=[],h=new Set;let p=0;for(let k=0;k{const y=n(b,void 0,w,o);return t.compatConfig&&(y.isNonScopedSlot=!0),ft("default",y)};u?d.length&&d.some(b=>Ql(b))&&(f?t.onError(it(39,d[0].loc)):i.push(k(void 0,d))):i.push(k(void 0,s))}const g=a?2:gr(e.children)?3:1;let v=mn(i.concat(ft("_",Te(g+"",!1))),o);return r.length&&(v=mt(t.helper(rp),[v,Hs(r)])),{slots:v,hasDynamicSlots:a}}function Qi(e,t,n){const s=[ft("name",e),ft("fn",t)];return n!=null&&s.push(ft("key",Te(String(n),!0))),mn(s)}function gr(e){for(let t=0;tfunction(){if(e=t.currentNode,!(e.type===1&&(e.tagType===0||e.tagType===1)))return;const{tag:s,props:o}=e,i=e.tagType===1;let r=i?Gk(e,t):`"${s}"`;const a=Ue(r)&&r.callee===du;let c,u,f=0,d,h,p,g=a||r===ni||r===au||!i&&(s==="svg"||s==="foreignObject"||s==="math");if(o.length>0){const v=Ap(e,t,void 0,i,a);c=v.props,f=v.patchFlag,h=v.dynamicPropNames;const k=v.directives;p=k&&k.length?Hs(k.map(b=>Xk(b,t))):void 0,v.shouldUseBlock&&(g=!0)}if(e.children.length>0)if(r===Rr&&(g=!0,f|=1024),i&&r!==ni&&r!==Rr){const{slots:k,hasDynamicSlots:b}=Kk(e,t);u=k,b&&(f|=1024)}else if(e.children.length===1&&r!==ni){const k=e.children[0],b=k.type,w=b===5||b===8;w&&rn(k,t)===0&&(f|=1),w||b===2?u=k:u=e.children}else u=e.children;h&&h.length&&(d=Qk(h)),e.codegenNode=yi(t,r,c,u,f===0?void 0:f,d,p,!!g,!1,i,e.loc)};function Gk(e,t,n=!1){let{tag:s}=e;const o=Zl(s),i=Ta(e,"is",!1,!0);if(i)if(o||zs("COMPILER_IS_ON_ELEMENT",t)){let a;if(i.type===6?a=i.value&&Te(i.value.content,!0):(a=i.exp,a||(a=Te("is",!1,i.arg.loc))),a)return mt(t.helper(du),[a])}else i.type===6&&i.value.content.startsWith("vue:")&&(s=i.value.content.slice(4));const r=cp(s)||t.isBuiltInComponent(s);return r?(n||t.helper(r),r):(t.helper(fu),t.components.add(s),ki(s,"component"))}function Ap(e,t,n=e.props,s,o,i=!1){const{tag:r,loc:a,children:c}=e;let u=[];const f=[],d=[],h=c.length>0;let p=!1,g=0,v=!1,k=!1,b=!1,w=!1,y=!1,_=!1;const x=[],L=P=>{u.length&&(f.push(mn(vd(u),a)),u=[]),P&&f.push(P)},V=()=>{t.scopes.vFor>0&&u.push(ft(Te("ref_for",!0),Te("true")))},E=({key:P,value:N})=>{if(Yt(P)){const $=P.content,U=Ys($);if(U&&(!s||o)&&$.toLowerCase()!=="onclick"&&$!=="onUpdate:modelValue"&&!Cs($)&&(w=!0),U&&Cs($)&&(_=!0),U&&N.type===14&&(N=N.arguments[0]),N.type===20||(N.type===4||N.type===8)&&rn(N,t)>0)return;$==="ref"?v=!0:$==="class"?k=!0:$==="style"?b=!0:$!=="key"&&!x.includes($)&&x.push($),s&&($==="class"||$==="style")&&!x.includes($)&&x.push($)}else y=!0};for(let P=0;Pst.content==="prop")&&(g|=32);const he=t.directiveTransforms[$];if(he){const{props:st,needRuntime:je}=he(N,e,t);!i&&st.forEach(E),ne&&U&&!Yt(U)?L(mn(st,a)):u.push(...st),je&&(d.push(N),Gt(je)&&xp.set(N,je))}else I2($)||(d.push(N),h&&(p=!0))}}let I;if(f.length?(L(),f.length>1?I=mt(t.helper(Hr),f,a):I=f[0]):u.length&&(I=mn(vd(u),a)),y?g|=16:(k&&!s&&(g|=2),b&&!s&&(g|=4),x.length&&(g|=8),w&&(g|=32)),!p&&(g===0||g===32)&&(v||_||d.length>0)&&(g|=512),!t.inSSR&&I)switch(I.type){case 15:let P=-1,N=-1,$=!1;for(let J=0;Jft(r,i)),o))}return Hs(n,e.loc)}function Qk(e){let t="[";for(let n=0,s=e.length;n{if(Wr(e)){const{children:n,loc:s}=e,{slotName:o,slotProps:i}=ew(e,t),r=[t.prefixIdentifiers?"_ctx.$slots":"$slots",o,"{}","undefined","true"];let a=2;i&&(r[2]=i,a=3),n.length&&(r[3]=xo([],n,!1,!1,s),a=4),t.scopeId&&!t.slotted&&(a=5),r.splice(a),e.codegenNode=mt(t.helper(ip),r,s)}};function ew(e,t){let n='"default"',s;const o=[];for(let i=0;i0){const{props:i,directives:r}=Ap(e,t,o,!1,!1);s=i,r.length&&t.onError(it(36,r[0].loc))}return{slotName:n,slotProps:s}}const $p=(e,t,n,s)=>{const{loc:o,modifiers:i,arg:r}=e;!e.exp&&!i.length&&n.onError(it(35,o));let a;if(r.type===4)if(r.isStatic){let d=r.content;d.startsWith("vue:")&&(d=`vnode-${d.slice(4)}`);const h=t.tagType!==0||d.startsWith("vnode")||!/[A-Z]/.test(d)?po(tt(d)):`on:${d}`;a=Te(h,!0,r.loc)}else a=An([`${n.helperString(Kl)}(`,r,")"]);else a=r,a.children.unshift(`${n.helperString(Kl)}(`),a.children.push(")");let c=e.exp;c&&!c.content.trim()&&(c=void 0);let u=n.cacheHandlers&&!c&&!n.inVOnce;if(c){const d=dp(c),h=!(d||Qb(c)),p=c.content.includes(";");(h||u&&d)&&(c=An([`${h?"$event":"(...args)"} => ${p?"{":"("}`,c,p?"}":")"]))}let f={props:[ft(a,c||Te("() => {}",!1,o))]};return s&&(f=s(f)),u&&(f.props[0].value=n.cache(f.props[0].value)),f.props.forEach(d=>d.key.isHandlerKey=!0),f},tw=(e,t,n)=>{const{modifiers:s,loc:o}=e,i=e.arg;let{exp:r}=e;return r&&r.type===4&&!r.content.trim()&&(r=void 0),i.type!==4?(i.children.unshift("("),i.children.push(') || ""')):i.isStatic||(i.content=i.content?`${i.content} || ""`:'""'),s.some(a=>a.content==="camel")&&(i.type===4?i.isStatic?i.content=tt(i.content):i.content=`${n.helperString(ql)}(${i.content})`:(i.children.unshift(`${n.helperString(ql)}(`),i.children.push(")"))),n.inSSR||(s.some(a=>a.content==="prop")&&yd(i,"."),s.some(a=>a.content==="attr")&&yd(i,"^")),{props:[ft(i,r)]}},yd=(e,t)=>{e.type===4?e.isStatic?e.content=t+e.content:e.content=`\`${t}\${${e.content}}\``:(e.children.unshift(`'${t}' + (`),e.children.push(")"))},nw=(e,t)=>{if(e.type===0||e.type===1||e.type===11||e.type===10)return()=>{const n=e.children;let s,o=!1;for(let i=0;ii.type===7&&!t.directiveTransforms[i.name])&&e.tag!=="template")))for(let i=0;i{if(e.type===1&&pn(e,"once",!0))return bd.has(e)||t.inVOnce||t.inSSR?void 0:(bd.add(e),t.inVOnce=!0,t.helper(zr),()=>{t.inVOnce=!1;const n=t.currentNode;n.codegenNode&&(n.codegenNode=t.cache(n.codegenNode,!0,!0))})},Lp=(e,t,n)=>{const{exp:s,arg:o}=e;if(!s)return n.onError(it(41,e.loc)),Zi();const i=s.loc.source.trim(),r=s.type===4?s.content:i,a=n.bindingMetadata[i];if(a==="props"||a==="props-aliased")return n.onError(it(44,s.loc)),Zi();if(!r.trim()||!dp(s))return n.onError(it(42,s.loc)),Zi();const c=o||Te("modelValue",!0),u=o?Yt(o)?`onUpdate:${tt(o.content)}`:An(['"onUpdate:" + ',o]):"onUpdate:modelValue";let f;const d=n.isTS?"($event: any)":"$event";f=An([`${d} => ((`,s,") = $event)"]);const h=[ft(c,e.exp),ft(u,f)];if(e.modifiers.length&&t.tagType===1){const p=e.modifiers.map(v=>v.content).map(v=>(Su(v)?v:JSON.stringify(v))+": true").join(", "),g=o?Yt(o)?`${o.content}Modifiers`:An([o,' + "Modifiers"']):"modelModifiers";h.push(ft(g,Te(`{ ${p} }`,!1,e.loc,2)))}return Zi(h)};function Zi(e=[]){return{props:e}}const ow=/[\w).+\-_$\]]/,iw=(e,t)=>{zs("COMPILER_FILTERS",t)&&(e.type===5?Kr(e.content,t):e.type===1&&e.props.forEach(n=>{n.type===7&&n.name!=="for"&&n.exp&&Kr(n.exp,t)}))};function Kr(e,t){if(e.type===4)kd(e,t);else for(let n=0;n=0&&(w=n.charAt(b),w===" ");b--);(!w||!ow.test(w))&&(r=!0)}}g===void 0?g=n.slice(0,p).trim():f!==0&&k();function k(){v.push(n.slice(f,p).trim()),f=p+1}if(v.length){for(p=0;p{if(e.type===1){const n=pn(e,"memo");return!n||wd.has(e)||t.inSSR?void 0:(wd.add(e),()=>{const s=e.codegenNode||t.currentNode.codegenNode;s&&s.type===13&&(e.tagType!==1&&Cu(s,t),e.codegenNode=mt(t.helper(wu),[n.exp,xo(void 0,s),"_cache",String(t.cached.length)]),t.cached.push(null))})}},lw=(e,t)=>{if(e.type===1){for(const n of e.props)if(n.type===7&&n.name==="bind"&&(!n.exp||n.exp.type===4&&!n.exp.content.trim())&&n.arg){const s=n.arg;if(s.type!==4||!s.isStatic)t.onError(it(52,s.loc)),n.exp=Te("",!0,s.loc);else{const o=tt(s.content);(up.test(o[0])||o[0]==="-")&&(n.exp=Te(o,!1,s.loc))}}}};function cw(e){return[[lw,sw,Dk,aw,zk,iw,Zk,Yk,Wk,nw],{on:$p,bind:tw,model:Lp}]}function uw(e,t={}){const n=t.onError||_u,s=t.mode==="module";t.prefixIdentifiers===!0?n(it(47)):s&&n(it(48));const o=!1;t.cacheHandlers&&n(it(49)),t.scopeId&&!s&&n(it(50));const i=Ie({},t,{prefixIdentifiers:o}),r=_e(e)?gk(e,i):e,[a,c]=cw();return kk(r,Ie({},i,{nodeTransforms:[...a,...t.nodeTransforms||[]],directiveTransforms:Ie({},c,t.directiveTransforms||{})})),Sk(r,i)}const fw=()=>({props:[]});const Ip=Symbol(""),Pp=Symbol(""),Mp=Symbol(""),Fp=Symbol(""),ec=Symbol(""),Bp=Symbol(""),Np=Symbol(""),Vp=Symbol(""),Op=Symbol(""),Dp=Symbol("");Hb({[Ip]:"vModelRadio",[Pp]:"vModelCheckbox",[Mp]:"vModelText",[Fp]:"vModelSelect",[ec]:"vModelDynamic",[Bp]:"withModifiers",[Np]:"withKeys",[Vp]:"vShow",[Op]:"Transition",[Dp]:"TransitionGroup"});let so;function dw(e,t=!1){return so||(so=document.createElement("div")),t?(so.innerHTML=`
`,so.children[0].getAttribute("foo")):(so.innerHTML=e,so.textContent)}const hw={parseMode:"html",isVoidTag:q2,isNativeTag:e=>j2(e)||U2(e)||W2(e),isPreTag:e=>e==="pre",isIgnoreNewlineTag:e=>e==="pre"||e==="textarea",decodeEntities:dw,isBuiltInComponent:e=>{if(e==="Transition"||e==="transition")return Op;if(e==="TransitionGroup"||e==="transition-group")return Dp},getNamespace(e,t,n){let s=t?t.ns:n;if(t&&s===2)if(t.tag==="annotation-xml"){if(e==="svg")return 1;t.props.some(o=>o.type===6&&o.name==="encoding"&&o.value!=null&&(o.value.content==="text/html"||o.value.content==="application/xhtml+xml"))&&(s=0)}else/^m(?:[ions]|text)$/.test(t.tag)&&e!=="mglyph"&&e!=="malignmark"&&(s=0);else t&&s===1&&(t.tag==="foreignObject"||t.tag==="desc"||t.tag==="title")&&(s=0);if(s===0){if(e==="svg")return 1;if(e==="math")return 2}return s}},pw=e=>{e.type===1&&e.props.forEach((t,n)=>{t.type===6&&t.name==="style"&&t.value&&(e.props[n]={type:7,name:"bind",arg:Te("style",!0,t.loc),exp:mw(t.value.content,t.loc),modifiers:[],loc:t.loc})})},mw=(e,t)=>{const n=o1(e);return Te(JSON.stringify(n),!1,t,3)};function Es(e,t){return it(e,t)}const gw=(e,t,n)=>{const{exp:s,loc:o}=e;return s||n.onError(Es(53,o)),t.children.length&&(n.onError(Es(54,o)),t.children.length=0),{props:[ft(Te("innerHTML",!0,o),s||Te("",!0))]}},vw=(e,t,n)=>{const{exp:s,loc:o}=e;return s||n.onError(Es(55,o)),t.children.length&&(n.onError(Es(56,o)),t.children.length=0),{props:[ft(Te("textContent",!0),s?rn(s,n)>0?s:mt(n.helperString(Sa),[s],o):Te("",!0))]}},yw=(e,t,n)=>{const s=Lp(e,t,n);if(!s.props.length||t.tagType===1)return s;e.arg&&n.onError(Es(58,e.arg.loc));const{tag:o}=t,i=n.isCustomElement(o);if(o==="input"||o==="textarea"||o==="select"||i){let r=Mp,a=!1;if(o==="input"||i){const c=Ta(t,"type");if(c){if(c.type===7)r=ec;else if(c.value)switch(c.value.content){case"radio":r=Ip;break;case"checkbox":r=Pp;break;case"file":a=!0,n.onError(Es(59,e.loc));break}}else Zb(t)&&(r=ec)}else o==="select"&&(r=Fp);a||(s.needRuntime=n.helper(r))}else n.onError(Es(57,e.loc));return s.props=s.props.filter(r=>!(r.key.type===4&&r.key.content==="modelValue")),s},bw=ln("passive,once,capture"),kw=ln("stop,prevent,self,ctrl,shift,alt,meta,exact,middle"),ww=ln("left,right"),Rp=ln("onkeyup,onkeydown,onkeypress"),Cw=(e,t,n,s)=>{const o=[],i=[],r=[];for(let a=0;aYt(e)&&e.content.toLowerCase()==="onclick"?Te(t,!0):e.type!==4?An(["(",e,`) === "onClick" ? "${t}" : (`,e,")"]):e,_w=(e,t,n)=>$p(e,t,n,s=>{const{modifiers:o}=e;if(!o.length)return s;let{key:i,value:r}=s.props[0];const{keyModifiers:a,nonKeyModifiers:c,eventOptionModifiers:u}=Cw(i,o,n,e.loc);if(c.includes("right")&&(i=Cd(i,"onContextmenu")),c.includes("middle")&&(i=Cd(i,"onMouseup")),c.length&&(r=mt(n.helper(Bp),[r,JSON.stringify(c)])),a.length&&(!Yt(i)||Rp(i.content.toLowerCase()))&&(r=mt(n.helper(Np),[r,JSON.stringify(a)])),u.length){const f=u.map(Js).join("");i=Yt(i)?Te(`${i.content}${f}`,!0):An(["(",i,`) + "${f}"`])}return{props:[ft(i,r)]}}),Sw=(e,t,n)=>{const{exp:s,loc:o}=e;return s||n.onError(Es(61,o)),{props:[],needRuntime:n.helper(Vp)}},Tw=(e,t)=>{e.type===1&&e.tagType===0&&(e.tag==="script"||e.tag==="style")&&t.removeNode()},Ew=[pw],xw={cloak:fw,html:gw,text:vw,model:yw,on:_w,show:Sw};function Aw(e,t={}){return uw(e,Ie({},hw,t,{nodeTransforms:[Tw,...Ew,...t.nodeTransforms||[]],directiveTransforms:Ie({},xw,t.directiveTransforms||{}),transformHoist:null}))}const Hp=e=>{const{code:t}=Aw(e),n=new Function("Vue",t)(Gv);return z({render:n})},$w=["aria-label"],Lw={key:1};var Fi=z({name:"ArticleTitle",__name:"index",props:{post:{},titleTagProps:{}},setup(e){const t=ie("article-title"),{t:n}=ge();return(s,o)=>(m(),C("span",{class:T(l(t).b()),"aria-label":l(n)("tk.articleTitle.label")},[e.post.frontmatter.titleTag&&e.titleTagProps?.position==="left"?(m(),D(l(Dr),nt({key:0,text:e.post.frontmatter.titleTag},e.titleTagProps,{"aria-label":e.post.frontmatter.titleTag}),null,16,["text","aria-label"])):A("v-if",!0),M(s.$slots,"default",{},()=>[e.post.title?(m(),C(Y,{key:0},[!e.post.title.includes("`<")&&!e.post.title.includes(">`")?(m(),D(Be(l(Hp)(e.post.title)),{key:0})):(m(),C("span",Lw,W(e.post.title),1))],64)):A("v-if",!0)]),e.post.frontmatter.titleTag&&e.titleTagProps?.position==="right"?(m(),D(l(Dr),nt({key:1,text:e.post.frontmatter.titleTag},e.titleTagProps,{"aria-label":e.post.frontmatter.titleTag}),null,16,["text","aria-label"])):A("v-if",!0)],10,$w))}});const Iw={class:"count"},Pw={class:"vp-doc"},Mw={class:"year"},Fw={class:"count"},Bw={class:"month"},Nw={class:"count"},Vw=["href","aria-label"],Ow={class:"date"};var zp=z({name:"ArchivesPage",__name:"index",setup(e){const t=ie("archives"),{t:n}=ge(),{frontmatter:s}=Ae(),o=Pn(),i=F(()=>{const u=s.value;return{title:u.title??n("tk.archives.title"),totalCount:u.totalCount??n("tk.archives.totalCount"),year:u.year??n("tk.archives.year"),month:u.month??n("tk.archives.month"),count:u.count??n("tk.archives.count"),notFound:u.notFound??n("tk.archives.notFound")}}),r=_a(u=>u.archives),a=j(null),{start:c}=Ca(a,!1);return be(()=>{r.value&&c()}),(u,f)=>{const d=un("Content");return m(),D(l(ru),{class:T(l(t).b()),"aria-label":l(n)("tk.archives.label")},{default:O(()=>[M(u.$slots,"teek-archives-top-before"),S("div",{class:T(`${l(t).e("header")} flx-justify-between`)},[S("h1",null,W(i.value.title),1),S("div",Iw,W(i.value.totalCount.replace("{count}",l(o).sortPostsByDate.length)),1)],2),M(u.$slots,"teek-archives-top-after"),S("div",Pw,[H(d)]),S("div",{class:T(l(t).e("timeline"))},[(m(!0),C(Y,null,le(l(o).groupPostsByYearMonth,(h,p)=>(m(),C(Y,{key:p},[S("div",{class:T(`${l(t).em("timeline","year")} flx-justify-between`)},[S("div",Mw,W(String(p).trim()==="NaN"?i.value.notFound:String(p).trim()+i.value.year),1),S("div",Fw,W(l(o).groupPostsByYear[p].length+i.value.count),1)],2),S("div",{class:T(l(t).e("timeline__m"))},[(m(!0),C(Y,null,le(h,(g,v)=>(m(),C(Y,{key:v},[S("div",{class:T(`${l(t).em("timeline__m","month")} flx-justify-between`)},[S("div",Bw,W(String(v)==="NaN"?i.value.notFound:v+i.value.month),1),S("div",Nw,W(g.length+i.value.count),1)],2),S("ul",null,[(m(!0),C(Y,null,le(g,k=>(m(),C("li",{ref_for:!0,ref_key:"timelineItemListInstance",ref:a,key:k.url},[S("a",{href:k.url&&l(Ee)(k.url),"aria-label":`${k.title}`},[S("span",Ow,W(k.date?.slice(5,10)),1),H(l(Fi),{post:k,"title-tag-props":{position:"right",size:"small"}},null,8,["post"])],8,Vw)]))),128))])],64))),128))],2)],64))),128))],2)]),_:3},8,["class","aria-label"])}}});const Dw={key:0},Rw=["href","aria-label"],Hw=["id"],zw=["href","aria-label"],jw=["href"],Uw={"aria-describedby":"overview-title"},Ww=["href","aria-label"];var jp=z({name:"ArticleOverviewPage",__name:"index",setup(e){const t=ie("article-overview"),{t:n}=ge(),s=Pn(),{localeIndex:o,site:i,theme:r,frontmatter:a}=Ae(),{getTeekConfigRef:c}=fe(),u=c("category",{path:"/categories"}),f=F(()=>s.value.groupPosts.categories),d=F(()=>r.value.docAnalysisInfo?.eachFileWords||[]),h=F(()=>{const k=o.value;return`${k!=="root"?`/${k}`:""}${u.value.path}${i.value.cleanUrls?"":".html"}`}),p=k=>d.value.filter(b=>{const w="/"+b.fileInfo.relativePath.replace(".md","");return[w,`${w}.html`].includes(k)})[0],g=F(()=>Object.entries(f.value).map(([k,b])=>({name:k,data:b.map(w=>{const y=p(w.url);return{...w,wordCount:y?.wordCount||"-",readingTime:y?.readingTime||"-"}})||[]})).sort((k,b)=>new Date(b.data[b.data.length-1].date).getTime()-new Date(k.data[k.data.length-1].date).getTime())),v=k=>{const b=a.value.publishDateFormat;return b?pi(k||new Date,b):k};return(k,b)=>{const w=un("Content");return m(),D(l(ru),{doc:"",aside:"",class:T(l(t).b())},{default:O(()=>[l(a).title?(m(),C("h1",Dw,[rt(W(l(a).title)+" ",1),S("a",{class:"header-anchor",href:`#${l(a).title}`,"aria-label":`Permalink to '${l(a).title}'`},null,8,Rw)])):A("v-if",!0),H(w),(m(!0),C(Y,null,le(g.value,y=>(m(),C(Y,{key:y.name},[S("h2",{id:`${y.name}-${l(n)("tk.articleOverview.overview")}`},[rt(W(y.name)+" "+W(l(n)("tk.articleOverview.overview"))+" ",1),S("a",{class:"header-anchor",href:`#${y.name}-${l(n)("tk.articleOverview.overview")}`,"aria-label":`Permalink to '${y.name}-${l(n)("tk.articleOverview.overview")}'`},null,8,zw)],8,Hw),S("a",{href:`${h.value}?category=${y.name}`,"aria-describedby":"overview-title"},W(y.name)+" "+W(l(n)("tk.articleOverview.category")),9,jw),S("table",Uw,[S("thead",null,[S("tr",null,[S("th",null,W(l(n)("tk.articleOverview.name")),1),S("th",null,W(l(n)("tk.articleOverview.title")),1),S("th",null,W(l(n)("tk.articleOverview.date")),1),S("th",null,W(l(n)("tk.articleOverview.wordCount")),1),S("th",null,W(l(n)("tk.articleOverview.readingTime")),1)])]),S("tbody",null,[(m(!0),C(Y,null,le(y.data,_=>(m(),C("tr",{key:_.url},[S("td",null,W(y.name),1),S("td",null,[S("a",{href:_.url&&l(Ee)(_.url),"aria-label":_.title},[_.title?(m(),D(Be(l(Hp)(_.title)),{key:0})):A("v-if",!0)],8,Ww)]),S("td",null,W(v(_.date)),1),S("td",null,W(_.wordCount),1),S("td",null,W(_.readingTime),1)]))),128))])])],64))),128))]),_:1},8,["class"])}}});const qw=["innerHTML"];var Kw=z({name:"SvgIcon",__name:"SvgIcon",props:{icon:{}},setup(e){return(t,n)=>(m(),C("i",{innerHTML:e.icon},null,8,qw))}});const Yw={key:0,class:"iconfont"},Gw={key:2,class:"icon-svg","aria-hidden":"true"},Jw=["xlink:href"];var Xw=z({name:"FontIcon",__name:"FontIcon",props:{icon:{},iconType:{}},setup(e){return(t,n)=>e.iconType==="unicode"?(m(),C("i",Yw,W(e.icon),1)):e.iconType==="iconfont"?(m(),C("i",{key:1,class:T(`iconfont ${e.icon}`)},null,2)):e.iconType==="symbol"?(m(),C("svg",Gw,[S("use",{"xlink:href":`#${e.icon}`},null,8,Jw)])):A("v-if",!0)}});const Up=/^[a-z0-9]+(-[a-z0-9]+)*$/,Aa=(e,t,n,s="")=>{const o=e.split(":");if(e.slice(0,1)==="@"){if(o.length<2||o.length>3)return null;s=o.shift().slice(1)}if(o.length>3||!o.length)return null;if(o.length>1){const a=o.pop(),c=o.pop(),u={provider:o.length>0?o[0]:s,prefix:c,name:a};return t&&!vr(u)?null:u}const i=o[0],r=i.split("-");if(r.length>1){const a={provider:s,prefix:r.shift(),name:r.join("-")};return t&&!vr(a)?null:a}if(n&&s===""){const a={provider:s,prefix:"",name:i};return t&&!vr(a,n)?null:a}return null},vr=(e,t)=>e?!!((t&&e.prefix===""||e.prefix)&&e.name):!1,Wp=Object.freeze({left:0,top:0,width:16,height:16}),Yr=Object.freeze({rotate:0,vFlip:!1,hFlip:!1}),$a=Object.freeze({...Wp,...Yr}),tc=Object.freeze({...$a,body:"",hidden:!1});function Qw(e,t){const n={};!e.hFlip!=!t.hFlip&&(n.hFlip=!0),!e.vFlip!=!t.vFlip&&(n.vFlip=!0);const s=((e.rotate||0)+(t.rotate||0))%4;return s&&(n.rotate=s),n}function _d(e,t){const n=Qw(e,t);for(const s in tc)s in Yr?s in e&&!(s in n)&&(n[s]=Yr[s]):s in t?n[s]=t[s]:s in e&&(n[s]=e[s]);return n}function Zw(e,t){const n=e.icons,s=e.aliases||Object.create(null),o=Object.create(null);function i(r){if(n[r])return o[r]=[];if(!(r in o)){o[r]=null;const a=s[r]&&s[r].parent,c=a&&i(a);c&&(o[r]=[a].concat(c))}return o[r]}return Object.keys(n).concat(Object.keys(s)).forEach(i),o}function eC(e,t,n){const s=e.icons,o=e.aliases||Object.create(null);let i={};function r(a){i=_d(s[a]||o[a],i)}return r(t),n.forEach(r),_d(e,i)}function qp(e,t){const n=[];if(typeof e!="object"||typeof e.icons!="object")return n;e.not_found instanceof Array&&e.not_found.forEach(o=>{t(o,null),n.push(o)});const s=Zw(e);for(const o in s){const i=s[o];i&&(t(o,eC(e,o,i)),n.push(o))}return n}const tC={provider:"",aliases:{},not_found:{},...Wp};function Xa(e,t){for(const n in t)if(n in e&&typeof e[n]!=typeof t[n])return!1;return!0}function Kp(e){if(typeof e!="object"||e===null)return null;const t=e;if(typeof t.prefix!="string"||!e.icons||typeof e.icons!="object"||!Xa(e,tC))return null;const n=t.icons;for(const o in n){const i=n[o];if(!o||typeof i.body!="string"||!Xa(i,tc))return null}const s=t.aliases||Object.create(null);for(const o in s){const i=s[o],r=i.parent;if(!o||typeof r!="string"||!n[r]&&!s[r]||!Xa(i,tc))return null}return t}const Sd=Object.create(null);function nC(e,t){return{provider:e,prefix:t,icons:Object.create(null),missing:new Set}}function Lo(e,t){const n=Sd[e]||(Sd[e]=Object.create(null));return n[t]||(n[t]=nC(e,t))}function Yp(e,t){return Kp(t)?qp(t,(n,s)=>{s?e.icons[n]=s:e.missing.add(n)}):[]}function sC(e,t,n){try{if(typeof n.body=="string")return e.icons[t]={...n},!0}catch{}return!1}let Ci=!1;function Gp(e){return typeof e=="boolean"&&(Ci=e),Ci}function oC(e){const t=typeof e=="string"?Aa(e,!0,Ci):e;if(t){const n=Lo(t.provider,t.prefix),s=t.name;return n.icons[s]||(n.missing.has(s)?null:void 0)}}function Jp(e,t){const n=Aa(e,!0,Ci);if(!n)return!1;const s=Lo(n.provider,n.prefix);return t?sC(s,n.name,t):(s.missing.add(n.name),!0)}function iC(e,t){if(typeof e!="object")return!1;if(typeof t!="string"&&(t=e.provider||""),Ci&&!t&&!e.prefix){let o=!1;return Kp(e)&&(e.prefix="",qp(e,(i,r)=>{Jp(i,r)&&(o=!0)})),o}const n=e.prefix;if(!vr({prefix:n,name:"a"}))return!1;const s=Lo(t,n);return!!Yp(s,e)}const Xp=Object.freeze({width:null,height:null}),Qp=Object.freeze({...Xp,...Yr}),rC=/(-?[0-9.]*[0-9]+[0-9.]*)/g,aC=/^-?[0-9.]*[0-9]+[0-9.]*$/g;function Td(e,t,n){if(t===1)return e;if(n=n||100,typeof e=="number")return Math.ceil(e*t*n)/n;if(typeof e!="string")return e;const s=e.split(rC);if(s===null||!s.length)return e;const o=[];let i=s.shift(),r=aC.test(i);for(;;){if(r){const a=parseFloat(i);isNaN(a)?o.push(i):o.push(Math.ceil(a*t*n)/n)}else o.push(i);if(i=s.shift(),i===void 0)return o.join("");r=!r}}function lC(e,t="defs"){let n="";const s=e.indexOf("<"+t);for(;s>=0;){const o=e.indexOf(">",s),i=e.indexOf("",i);if(r===-1)break;n+=e.slice(o+1,i).trim(),e=e.slice(0,s).trim()+e.slice(r+1)}return{defs:n,content:e}}function cC(e,t){return e?""+e+""+t:t}function uC(e,t,n){const s=lC(e);return cC(s.defs,t+s.content+n)}const fC=e=>e==="unset"||e==="undefined"||e==="none";function dC(e,t){const n={...$a,...e},s={...Qp,...t},o={left:n.left,top:n.top,width:n.width,height:n.height};let i=n.body;[n,s].forEach(v=>{const k=[],b=v.hFlip,w=v.vFlip;let y=v.rotate;b?w?y+=2:(k.push("translate("+(o.width+o.left).toString()+" "+(0-o.top).toString()+")"),k.push("scale(-1 1)"),o.top=o.left=0):w&&(k.push("translate("+(0-o.left).toString()+" "+(o.height+o.top).toString()+")"),k.push("scale(1 -1)"),o.top=o.left=0);let _;switch(y<0&&(y-=Math.floor(y/4)*4),y=y%4,y){case 1:_=o.height/2+o.top,k.unshift("rotate(90 "+_.toString()+" "+_.toString()+")");break;case 2:k.unshift("rotate(180 "+(o.width/2+o.left).toString()+" "+(o.height/2+o.top).toString()+")");break;case 3:_=o.width/2+o.left,k.unshift("rotate(-90 "+_.toString()+" "+_.toString()+")");break}y%2===1&&(o.left!==o.top&&(_=o.left,o.left=o.top,o.top=_),o.width!==o.height&&(_=o.width,o.width=o.height,o.height=_)),k.length&&(i=uC(i,'',""))});const r=s.width,a=s.height,c=o.width,u=o.height;let f,d;r===null?(d=a===null?"1em":a==="auto"?u:a,f=Td(d,c/u)):(f=r==="auto"?c:r,d=a===null?Td(f,u/c):a==="auto"?u:a);const h={},p=(v,k)=>{fC(k)||(h[v]=k.toString())};p("width",f),p("height",d);const g=[o.left,o.top,c,u];return h.viewBox=g.join(" "),{attributes:h,viewBox:g,body:i}}const hC=/\sid="(\S+)"/g,pC="IconifyId"+Date.now().toString(16)+(Math.random()*16777216|0).toString(16);let mC=0;function gC(e,t=pC){const n=[];let s;for(;s=hC.exec(e);)n.push(s[1]);if(!n.length)return e;const o="suffix"+(Math.random()*16777216|Date.now()).toString(16);return n.forEach(i=>{const r=typeof t=="function"?t(i):t+(mC++).toString(),a=i.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");e=e.replace(new RegExp('([#;"])('+a+')([")]|\\.[a-z])',"g"),"$1"+r+o+"$3")}),e=e.replace(new RegExp(o,"g"),""),e}const nc=Object.create(null);function vC(e,t){nc[e]=t}function sc(e){return nc[e]||nc[""]}function xu(e){let t;if(typeof e.resources=="string")t=[e.resources];else if(t=e.resources,!(t instanceof Array)||!t.length)return null;return{resources:t,path:e.path||"/",maxURL:e.maxURL||500,rotate:e.rotate||750,timeout:e.timeout||5e3,random:e.random===!0,index:e.index||0,dataAfterTimeout:e.dataAfterTimeout!==!1}}const Au=Object.create(null),Uo=["https://api.simplesvg.com","https://api.unisvg.com"],yr=[];for(;Uo.length>0;)Uo.length===1||Math.random()>.5?yr.push(Uo.shift()):yr.push(Uo.pop());Au[""]=xu({resources:["https://api.iconify.design"].concat(yr)});function yC(e,t){const n=xu(t);return n===null?!1:(Au[e]=n,!0)}function $u(e){return Au[e]}const bC=()=>{let e;try{if(e=fetch,typeof e=="function")return e}catch{}};let Ed=bC();function kC(e,t){const n=$u(e);if(!n)return 0;let s;if(!n.maxURL)s=0;else{let o=0;n.resources.forEach(r=>{o=Math.max(o,r.length)});const i=t+".json?icons=";s=n.maxURL-o-n.path.length-i.length}return s}function wC(e){return e===404}const CC=(e,t,n)=>{const s=[],o=kC(e,t),i="icons";let r={type:i,provider:e,prefix:t,icons:[]},a=0;return n.forEach((c,u)=>{a+=c.length+1,a>=o&&u>0&&(s.push(r),r={type:i,provider:e,prefix:t,icons:[]},a=c.length),r.icons.push(c)}),s.push(r),s};function _C(e){if(typeof e=="string"){const t=$u(e);if(t)return t.path}return"/"}const SC=(e,t,n)=>{if(!Ed){n("abort",424);return}let s=_C(t.provider);switch(t.type){case"icons":{const i=t.prefix,a=t.icons.join(","),c=new URLSearchParams({icons:a});s+=i+".json?"+c.toString();break}case"custom":{const i=t.uri;s+=i.slice(0,1)==="/"?i.slice(1):i;break}default:n("abort",400);return}let o=503;Ed(e+s).then(i=>{const r=i.status;if(r!==200){setTimeout(()=>{n(wC(r)?"abort":"next",r)});return}return o=501,i.json()}).then(i=>{if(typeof i!="object"||i===null){setTimeout(()=>{i===404?n("abort",i):n("next",o)});return}setTimeout(()=>{n("success",i)})}).catch(()=>{n("next",o)})},TC={prepare:CC,send:SC};function EC(e){const t={loaded:[],missing:[],pending:[]},n=Object.create(null);e.sort((o,i)=>o.provider!==i.provider?o.provider.localeCompare(i.provider):o.prefix!==i.prefix?o.prefix.localeCompare(i.prefix):o.name.localeCompare(i.name));let s={provider:"",prefix:"",name:""};return e.forEach(o=>{if(s.name===o.name&&s.prefix===o.prefix&&s.provider===o.provider)return;s=o;const i=o.provider,r=o.prefix,a=o.name,c=n[i]||(n[i]=Object.create(null)),u=c[r]||(c[r]=Lo(i,r));let f;a in u.icons?f=t.loaded:r===""||u.missing.has(a)?f=t.missing:f=t.pending;const d={provider:i,prefix:r,name:a};f.push(d)}),t}function Zp(e,t){e.forEach(n=>{const s=n.loaderCallbacks;s&&(n.loaderCallbacks=s.filter(o=>o.id!==t))})}function xC(e){e.pendingCallbacksFlag||(e.pendingCallbacksFlag=!0,setTimeout(()=>{e.pendingCallbacksFlag=!1;const t=e.loaderCallbacks?e.loaderCallbacks.slice(0):[];if(!t.length)return;let n=!1;const s=e.provider,o=e.prefix;t.forEach(i=>{const r=i.icons,a=r.pending.length;r.pending=r.pending.filter(c=>{if(c.prefix!==o)return!0;const u=c.name;if(e.icons[u])r.loaded.push({provider:s,prefix:o,name:u});else if(e.missing.has(u))r.missing.push({provider:s,prefix:o,name:u});else return n=!0,!0;return!1}),r.pending.length!==a&&(n||Zp([e],i.id),i.callback(r.loaded.slice(0),r.missing.slice(0),r.pending.slice(0),i.abort))})}))}let AC=0;function $C(e,t,n){const s=AC++,o=Zp.bind(null,n,s);if(!t.pending.length)return o;const i={id:s,icons:t,callback:e,abort:o};return n.forEach(r=>{(r.loaderCallbacks||(r.loaderCallbacks=[])).push(i)}),o}function LC(e,t=!0,n=!1){const s=[];return e.forEach(o=>{const i=typeof o=="string"?Aa(o,t,n):o;i&&s.push(i)}),s}var IC={resources:[],index:0,timeout:2e3,rotate:750,random:!1,dataAfterTimeout:!1};function PC(e,t,n,s){const o=e.resources.length,i=e.random?Math.floor(Math.random()*o):e.index;let r;if(e.random){let L=e.resources.slice(0);for(r=[];L.length>1;){const V=Math.floor(Math.random()*L.length);r.push(L[V]),L=L.slice(0,V).concat(L.slice(V+1))}r=r.concat(L)}else r=e.resources.slice(i).concat(e.resources.slice(0,i));const a=Date.now();let c="pending",u=0,f,d=null,h=[],p=[];typeof s=="function"&&p.push(s);function g(){d&&(clearTimeout(d),d=null)}function v(){c==="pending"&&(c="aborted"),g(),h.forEach(L=>{L.status==="pending"&&(L.status="aborted")}),h=[]}function k(L,V){V&&(p=[]),typeof L=="function"&&p.push(L)}function b(){return{startTime:a,payload:t,status:c,queriesSent:u,queriesPending:h.length,subscribe:k,abort:v}}function w(){c="failed",p.forEach(L=>{L(void 0,f)})}function y(){h.forEach(L=>{L.status==="pending"&&(L.status="aborted")}),h=[]}function _(L,V,E){const I=V!=="success";switch(h=h.filter(P=>P!==L),c){case"pending":break;case"failed":if(I||!e.dataAfterTimeout)return;break;default:return}if(V==="abort"){f=E,w();return}if(I){f=E,h.length||(r.length?x():w());return}if(g(),y(),!e.random){const P=e.resources.indexOf(L.resource);P!==-1&&P!==e.index&&(e.index=P)}c="completed",p.forEach(P=>{P(E)})}function x(){if(c!=="pending")return;g();const L=r.shift();if(L===void 0){if(h.length){d=setTimeout(()=>{g(),c==="pending"&&(y(),w())},e.timeout);return}w();return}const V={status:"pending",resource:L,callback:(E,I)=>{_(V,E,I)}};h.push(V),u++,d=setTimeout(x,e.rotate),n(L,t,V.callback)}return setTimeout(x),b}function e2(e){const t={...IC,...e};let n=[];function s(){n=n.filter(a=>a().status==="pending")}function o(a,c,u){const f=PC(t,a,c,(d,h)=>{s(),u&&u(d,h)});return n.push(f),f}function i(a){return n.find(c=>a(c))||null}return{query:o,find:i,setIndex:a=>{t.index=a},getIndex:()=>t.index,cleanup:s}}function xd(){}const Qa=Object.create(null);function MC(e){if(!Qa[e]){const t=$u(e);if(!t)return;const n=e2(t),s={config:t,redundancy:n};Qa[e]=s}return Qa[e]}function FC(e,t,n){let s,o;if(typeof e=="string"){const i=sc(e);if(!i)return n(void 0,424),xd;o=i.send;const r=MC(e);r&&(s=r.redundancy)}else{const i=xu(e);if(i){s=e2(i);const r=e.resources?e.resources[0]:"",a=sc(r);a&&(o=a.send)}}return!s||!o?(n(void 0,424),xd):s.query(t,o,n)().abort}function Ad(){}function BC(e){e.iconsLoaderFlag||(e.iconsLoaderFlag=!0,setTimeout(()=>{e.iconsLoaderFlag=!1,xC(e)}))}function NC(e){const t=[],n=[];return e.forEach(s=>{(s.match(Up)?t:n).push(s)}),{valid:t,invalid:n}}function Wo(e,t,n){function s(){const o=e.pendingIcons;t.forEach(i=>{o&&o.delete(i),e.icons[i]||e.missing.add(i)})}if(n&&typeof n=="object")try{if(!Yp(e,n).length){s();return}}catch(o){console.error(o)}s(),BC(e)}function $d(e,t){e instanceof Promise?e.then(n=>{t(n)}).catch(()=>{t(null)}):t(e)}function VC(e,t){e.iconsToLoad?e.iconsToLoad=e.iconsToLoad.concat(t).sort():e.iconsToLoad=t,e.iconsQueueFlag||(e.iconsQueueFlag=!0,setTimeout(()=>{e.iconsQueueFlag=!1;const{provider:n,prefix:s}=e,o=e.iconsToLoad;if(delete e.iconsToLoad,!o||!o.length)return;const i=e.loadIcon;if(e.loadIcons&&(o.length>1||!i)){$d(e.loadIcons(o,s,n),f=>{Wo(e,o,f)});return}if(i){o.forEach(f=>{const d=i(f,s,n);$d(d,h=>{const p=h?{prefix:s,icons:{[f]:h}}:null;Wo(e,[f],p)})});return}const{valid:r,invalid:a}=NC(o);if(a.length&&Wo(e,a,null),!r.length)return;const c=s.match(Up)?sc(n):null;if(!c){Wo(e,r,null);return}c.prepare(n,s,r).forEach(f=>{FC(n,f,d=>{Wo(e,f.icons,d)})})}))}const OC=(e,t)=>{const n=LC(e,!0,Gp()),s=EC(n);if(!s.pending.length){let c=!0;return t&&setTimeout(()=>{c&&t(s.loaded,s.missing,s.pending,Ad)}),()=>{c=!1}}const o=Object.create(null),i=[];let r,a;return s.pending.forEach(c=>{const{provider:u,prefix:f}=c;if(f===a&&u===r)return;r=u,a=f,i.push(Lo(u,f));const d=o[u]||(o[u]=Object.create(null));d[f]||(d[f]=[])}),s.pending.forEach(c=>{const{provider:u,prefix:f,name:d}=c,h=Lo(u,f),p=h.pendingIcons||(h.pendingIcons=new Set);p.has(d)||(p.add(d),o[u][f].push(d))}),i.forEach(c=>{const u=o[c.provider][c.prefix];u.length&&VC(c,u)}),t?$C(t,s,i):Ad};function DC(e,t){const n={...e};for(const s in t){const o=t[s],i=typeof o;s in Xp?(o===null||o&&(i==="string"||i==="number"))&&(n[s]=o):i===typeof n[s]&&(n[s]=s==="rotate"?o%4:o)}return n}const RC=/[\s,]+/;function HC(e,t){t.split(RC).forEach(n=>{switch(n.trim()){case"horizontal":e.hFlip=!0;break;case"vertical":e.vFlip=!0;break}})}function zC(e,t=0){const n=e.replace(/^-?[0-9.]*/,"");function s(o){for(;o<0;)o+=4;return o%4}if(n===""){const o=parseInt(e);return isNaN(o)?0:s(o)}else if(n!==e){let o=0;switch(n){case"%":o=25;break;case"deg":o=90}if(o){let i=parseFloat(e.slice(0,e.length-n.length));return isNaN(i)?0:(i=i/o,i%1===0?s(i):0)}}return t}function jC(e,t){let n=e.indexOf("xlink:")===-1?"":' xmlns:xlink="http://www.w3.org/1999/xlink"';for(const s in t)n+=" "+s+'="'+t[s]+'"';return'"+e+""}function UC(e){return e.replace(/"/g,"'").replace(/%/g,"%25").replace(/#/g,"%23").replace(//g,"%3E").replace(/\s+/g," ")}function WC(e){return"data:image/svg+xml,"+UC(e)}function qC(e){return'url("'+WC(e)+'")'}const Ld={...Qp,inline:!1},KC={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink","aria-hidden":!0,role:"img"},YC={display:"inline-block"},oc={backgroundColor:"currentColor"},t2={backgroundColor:"transparent"},Id={Image:"var(--svg)",Repeat:"no-repeat",Size:"100% 100%"},Pd={webkitMask:oc,mask:oc,background:t2};for(const e in Pd){const t=Pd[e];for(const n in Id)t[e+n]=Id[n]}const br={};["horizontal","vertical"].forEach(e=>{const t=e.slice(0,1)+"Flip";br[e+"-flip"]=t,br[e.slice(0,1)+"-flip"]=t,br[e+"Flip"]=t});function Md(e){return e+(e.match(/^[-0-9.]+$/)?"px":"")}const Fd=(e,t)=>{const n=DC(Ld,t),s={...KC},o=t.mode||"svg",i={},r=t.style,a=typeof r=="object"&&!(r instanceof Array)?r:{};for(let v in t){const k=t[v];if(k!==void 0)switch(v){case"icon":case"style":case"onLoad":case"mode":case"ssr":break;case"inline":case"hFlip":case"vFlip":n[v]=k===!0||k==="true"||k===1;break;case"flip":typeof k=="string"&&HC(n,k);break;case"color":i.color=k;break;case"rotate":typeof k=="string"?n[v]=zC(k):typeof k=="number"&&(n[v]=k);break;case"ariaHidden":case"aria-hidden":k!==!0&&k!=="true"&&delete s["aria-hidden"];break;default:{const b=br[v];b?(k===!0||k==="true"||k===1)&&(n[b]=!0):Ld[v]===void 0&&(s[v]=k)}}}const c=dC(e,n),u=c.attributes;if(n.inline&&(i.verticalAlign="-0.125em"),o==="svg"){s.style={...i,...a},Object.assign(s,u);let v=0,k=t.id;return typeof k=="string"&&(k=k.replace(/-/g,"_")),s.innerHTML=gC(c.body,k?()=>k+"ID"+v++:"iconifyVue"),nn("svg",s)}const{body:f,width:d,height:h}=e,p=o==="mask"||(o==="bg"?!1:f.indexOf("currentColor")!==-1),g=jC(f,{...u,width:d+"",height:h+""});return s.style={...i,"--svg":qC(g),width:Md(u.width),height:Md(u.height),...YC,...p?oc:t2,...a},nn("span",s)};Gp(!0);vC("",TC);if(typeof document<"u"&&typeof window<"u"){const e=window;if(e.IconifyPreload!==void 0){const t=e.IconifyPreload,n="Invalid IconifyPreload syntax.";typeof t=="object"&&t!==null&&(t instanceof Array?t:[t]).forEach(s=>{try{(typeof s!="object"||s===null||s instanceof Array||typeof s.icons!="object"||typeof s.prefix!="string"||!iC(s))&&console.error(n)}catch{console.error(n)}})}if(e.IconifyProviders!==void 0){const t=e.IconifyProviders;if(typeof t=="object"&&t!==null)for(let n in t){const s="IconifyProviders["+n+"] is invalid.";try{const o=t[n];if(typeof o!="object"||!o||o.resources===void 0)continue;yC(n,o)||console.error(s)}catch{console.error(s)}}}}const GC={...$a,body:""},n2=z({inheritAttrs:!1,data(){return{_name:"",_loadingIcon:null,iconMounted:!1,counter:0}},mounted(){this.iconMounted=!0},unmounted(){this.abortLoading()},methods:{abortLoading(){this._loadingIcon&&(this._loadingIcon.abort(),this._loadingIcon=null)},getIcon(e,t,n){if(typeof e=="object"&&e!==null&&typeof e.body=="string")return this._name="",this.abortLoading(),{data:e};let s;if(typeof e!="string"||(s=Aa(e,!1,!0))===null)return this.abortLoading(),null;let o=oC(s);if(!o)return(!this._loadingIcon||this._loadingIcon.name!==e)&&(this.abortLoading(),this._name="",o!==null&&(this._loadingIcon={name:e,abort:OC([s],()=>{this.counter++})})),null;if(this.abortLoading(),this._name!==e&&(this._name=e,t&&t(e)),n){o=Object.assign({},o);const r=n(o.body,s.name,s.prefix,s.provider);typeof r=="string"&&(o.body=r)}const i=["iconify"];return s.prefix!==""&&i.push("iconify--"+s.prefix),s.provider!==""&&i.push("iconify--"+s.provider),{data:o,classes:i}}},render(){this.counter;const e=this.$attrs,t=this.iconMounted||e.ssr?this.getIcon(e.icon,e.onLoad,e.customise):null;if(!t)return Fd(GC,e);let n=e;return t.classes&&(n={...e,class:(typeof e.class=="string"?e.class+" ":"")+t.classes.join(" ")}),Fd({...$a,...t.data},n)}});var JC=z({name:"IconifyOffline",__name:"IconifyOffline",props:{icon:{}},setup(e){const t=e;return be(()=>{const n=H1();Jp(`iconify-${n}`,t.icon)}),(n,s)=>(m(),D(l(n2),{icon:e.icon,style:{outline:"none"}},null,8,["icon"]))}}),XC=z({name:"IconifyOnline",__name:"IconifyOnline",props:{icon:{}},setup(e){return(t,n)=>(m(),D(l(n2),{icon:e.icon,style:{outline:"none"}},null,8,["icon"]))}});const QC=["innerHTML"],ZC=["src","alt"];var de=z({name:"Icon",__name:"index",props:{icon:{default:""},iconType:{},size:{},color:{},hover:{type:Boolean,default:!1},hoverColor:{},imgAlt:{},pointer:{type:Boolean,default:!1},style:{}},setup(e){const t=ie("icon"),n=Z1(e,["icon","iconType","color","hover","hoverColor","pointer"]),s=Ti(),o=()=>({...n.style,...e.pointer?{cursor:"pointer"}:void 0,"--icon-color":e.color,"--icon-size":n.size&&sn(n.size),"--icon-color-hover":e.hoverColor||t.cssVar("theme-color")}),i=F(()=>Je(e.icon)?e.icon.replace(/^(svg-|if-|uni-|sym-|img-)/i,""):Pe(e.icon)),r=F(()=>{if(e.iconType&&["unicode","iconfont","symbol"].includes(e.iconType))return e.iconType;if(!Je(e.icon))return"";const g=e.icon.toLowerCase();return g.startsWith("if-")||g.startsWith("iconfont")||i.value.startsWith("icon-")?"iconfont":g.startsWith("uni-")||/^&#x[\da-f]+/i.test(e.icon)||e.icon.length===1&&e.icon.charCodeAt(0)>=57344&&e.icon.charCodeAt(0)<=63743?"unicode":g.startsWith("sym-")?"symbol":""}),a=F(()=>Je(e.icon)&&(e.iconType==="svg"||e.icon.startsWith("svg-")||Je(e.icon))),c=F(()=>Je(e.icon)&&e.icon?.includes("Je(e.icon)&&r.value),f=F(()=>!Je(e.icon)&&(e.iconType==="component"||ti(e.icon)&&("setup"in e.icon||"render"in e.icon)||typeof e.icon=="function")),d=F(()=>!Je(e.icon)&&(e.iconType==="iconifyOffline"||"body"in e.icon)),h=F(()=>Je(e.icon)&&(e.iconType==="iconifyOnline"||e.icon.includes(":"))),p=F(()=>Je(e.icon)&&(e.iconType==="img"||e.icon.toLowerCase().startsWith("img-")||[".png",".jpg",".jpeg",".gif",".bmp",".webp",".svg"].some(g=>e.icon.endsWith(g))));return(g,v)=>!u.value&&!p.value&&!c.value?(m(),C("i",{key:0,class:T([l(t).b(),l(t).is("hover",e.hover)]),style:Fe(o())},[l(s).default?M(g.$slots,"default",{key:0}):f.value?(m(),D(Be(i.value),{key:1,size:e.size},null,8,["size"])):d.value?(m(),D(JC,{key:2,icon:i.value},null,8,["icon"])):h.value?(m(),D(XC,{key:3,icon:i.value},null,8,["icon"])):a.value?(m(),D(Kw,{key:4,icon:i.value},null,8,["icon"])):A("v-if",!0)],6)):c.value?(m(),C("i",{key:1,innerHTML:e.icon,class:T([l(t).b(),l(t).is("hover",e.hover)]),style:Fe(o())},null,14,QC)):u.value&&r.value?(m(),D(Xw,{key:2,icon:i.value,iconType:r.value,class:T([l(t).b(),l(t).is("hover",e.hover)]),style:Fe(o())},null,8,["icon","iconType","class","style"])):p.value?(m(),C("img",{key:3,src:i.value,alt:e.imgAlt,class:T([l(t).b(),l(t).is("hover",e.hover)]),style:Fe(o())},null,14,ZC)):A("v-if",!0)}});const e_=["primary","success","info","warning","error"],s2={customClass:"",center:!1,dangerouslyUseHTMLString:!1,duration:3e3,icon:void 0,id:"",message:"",onClose:void 0,showClose:!1,type:"info",plain:!1,offset:16,zIndex:0,grouping:!1,repeatNum:1},t_={...s2,appendTo:me?document.body:void 0},On=pc([]),n_=e=>{const t=On.findIndex(o=>o.id===e),n=On[t];let s;return t>0&&(s=On[t-1]),{current:n,prev:s}},s_=e=>{const{prev:t}=n_(e);return t?t.vm.exposed.bottom.value:0},o_=(e,t)=>On.findIndex(s=>s.id===e)>0?16:t,i_=["id"],r_=["innerHTML"];var a_=z({name:"Message",__name:"index",props:Q1({customClass:{},center:{type:Boolean},dangerouslyUseHTMLString:{type:Boolean},duration:{},icon:{},id:{},message:{type:[String,Object,Function]},onClose:{type:Function},showClose:{type:Boolean},type:{},plain:{type:Boolean},offset:{},zIndex:{},grouping:{type:Boolean},repeatNum:{}},s2),emits:["destroy"],setup(e,{expose:t,emit:n}){const s=e,o=n,i={success:Nh,warning:Vh,error:m9,info:g9},r=j(!1),a=ie("message"),{currentZIndex:c,nextZIndex:u}=nu(),f=j(),d=j(!1),h=j(0),p={info:"info",primary:"primary",success:"success",warning:"warning",error:"danger"},g=F(()=>s.type?p[s.type]:"info"),v=F(()=>{const N=s.type;return{[a.bm("icon",N)]:N&&i[N]}}),k=F(()=>s.icon||i[s.type]||""),b=F(()=>s_(s.id)),w=F(()=>o_(s.id,s.offset)+b.value),y=F(()=>h.value+w.value),_=F(()=>({top:`${w.value}px`,zIndex:c.value}));let x;const L=()=>{x&&(clearTimeout(x),x=null)},V=()=>{s.duration!==0&&(L(),x=setTimeout(()=>{E()},s.duration))},E=()=>{d.value=!1,Oe(()=>{r.value||(s.onClose?.(),o("destroy"))})},I=({code:N})=>{N==="Space"&&E()};let P;return be(()=>{V(),u(),d.value=!0,P=new ResizeObserver(()=>{f.value&&(h.value=f.value.getBoundingClientRect().height)}),f.value&&P.observe(f.value)}),cn(()=>{P&&f.value&&P.unobserve(f.value)}),te(()=>s.repeatNum,()=>{L(),V()}),Ve(document,"keydown",I),t({visible:d,bottom:y,close:E}),(N,$)=>(m(),D(vt,{name:l(a).b("fade"),onBeforeEnter:$[0]||($[0]=U=>r.value=!0),onBeforeLeave:e.onClose,onAfterLeave:$[1]||($[1]=U=>N.$emit("destroy")),persisted:""},{default:O(()=>[et(S("div",{id:e.id,ref_key:"messageRef",ref:f,class:T([l(a).b(),{[l(a).m(e.type)]:e.type},l(a).is("center",e.center),l(a).is("closable",e.showClose),l(a).is("plain",e.plain),e.customClass]),style:Fe(_.value),role:"alert",onMouseenter:L,onMouseleave:V},[e.repeatNum>1?(m(),D(l(eh),{key:0,text:e.repeatNum,type:g.value,class:T(l(a).e("badge"))},null,8,["text","type","class"])):A("v-if",!0),k.value?(m(),D(l(de),{key:1,icon:k.value,class:T([l(a).e("icon"),v.value])},null,8,["icon","class"])):A("v-if",!0),M(N.$slots,"default",{},()=>[e.dangerouslyUseHTMLString?(m(),C("p",{key:1,class:T(l(a).e("content")),innerHTML:e.message},null,10,r_)):(m(),C("p",{key:0,class:T(l(a).e("content"))},W(e.message),3))]),e.showClose?(m(),D(l(de),{key:2,icon:l(Jc),class:T(l(a).e("closeBtn")),onClick:To(E,["stop"])},null,8,["icon","class"])):A("v-if",!0)],46,i_),[[at,d.value]])]),_:3},8,["name","onBeforeLeave"]))}});let l_=1;const o2=e=>{const t=!e||Je(e)||Ln(e)||ht(e)?{message:e}:e,n={...t_,...t};if(!n.appendTo)n.appendTo=document.body;else if(Je(n.appendTo)){let s=document.querySelector(n.appendTo);Il(s)||(console.warn("Message","the appendTo option is not an HTMLElement. Falling back to document.body."),s=document.body),n.appendTo=s}return n},c_=e=>{const t=On.indexOf(e);if(t===-1)return;On.splice(t,1);const{handler:n}=e;n.close()},u_=({appendTo:e,...t},n)=>{const s=`message_${l_++}`,o=t.onClose,i=document.createElement("div"),r={...t,id:s,onClose:()=>{o?.(),c_(f)},onDestroy:()=>{hi(null,i)}},a=H(a_,r,ht(r.message)||Ln(r.message)?{default:ht(r.message)?r.message:()=>r.message}:null);a.appContext=n||Ct._context,hi(a,i),e.appendChild(i.firstElementChild);const c=a.component,f={id:s,vnode:a,vm:c,handler:{close:()=>{c.exposed.close()}},props:a.component.props};return f},Ct=(e={},t)=>{if(!me)return{close:()=>{}};const n=o2(e);if(n.grouping&&On.length){const o=On.find(({vnode:i})=>i.props?.message===n.message);if(o)return o.props.repeatNum+=1,o.props.type=n.type,o.handler}const s=u_(n,t);return On.push(s),s.handler};e_.forEach(e=>{Ct[e]=(t={},n)=>{const s=o2(t);return Ct({...s,type:e},n)}});function f_(e){const t=[...On];for(const n of t)(!e||e===n.props.type)&&n.handler.close()}Ct.closeAll=f_;Ct._context=null;const d_=(e=120,t=40)=>{const n=j(),s=j("");function o(r){s.value=r}function i(){n.value&&(s.value=h_(n.value,e,t))}return be(()=>{i()}),{domRef:n,imgCode:s,setImgCode:o,getImgCode:i}};function hn(e,t){return Math.floor(Math.random()*(t-e)+e)}function er(e,t){const n=hn(e,t),s=hn(e,t),o=hn(e,t);return`rgb(${n},${s},${o})`}function h_(e,t,n){let s="";const o="0123456789",i=e.getContext("2d");if(!i)return s;i.fillStyle=er(180,230),i.fillRect(0,0,t,n);for(let r=0;r<4;r+=1){const a=o[hn(0,o.length)];s+=a;const c=hn(18,41),u=hn(-30,30);i.font=`${c}px Simhei`,i.textBaseline="top",i.fillStyle=er(80,150),i.save(),i.translate(30*r+15,15),i.rotate(u*Math.PI/180),i.fillText(a,-10,-15),i.restore()}for(let r=0;r<5;r+=1)i.beginPath(),i.moveTo(hn(0,t),hn(0,n)),i.lineTo(hn(0,t),hn(0,n)),i.strokeStyle=er(180,230),i.closePath(),i.stroke();for(let r=0;r<41;r+=1)i.beginPath(),i.arc(hn(0,t),hn(0,n),1,0,2*Math.PI),i.closePath(),i.fillStyle=er(150,200),i.fill();return s}var p_=z({name:"ImageVerifyCode",__name:"index",props:{modelValue:{required:!0},modelModifiers:{}},emits:["update:modelValue"],setup(e,{expose:t}){const{domRef:n,imgCode:s,setImgCode:o,getImgCode:i}=d_(),r=Jt(e,"modelValue");return te(r,a=>{o(a)}),te(s,a=>{r.value=a}),t({getImgCode:i}),(a,c)=>(m(),C("canvas",{ref_key:"domRef",ref:n,width:"120",height:"40",class:"cursor-pointer",onClick:c[0]||(c[0]=(...u)=>l(i)&&l(i)(...u))},null,512))}});const i2=()=>{if(!me)return{siteLoginKey:"",pagesLoginKey:"",pageLoginKey:"",realmLoginKey:""};const e=ie(),t=e.storageKey("private","site",window.location.hostname),n=e.storageKey("private","pages",window.location.hostname),s=e.storageKey("private","page",window.location.hostname),o=e.storageKey("private","realm",window.location.hostname);return{siteLoginKey:t,pagesLoginKey:n,pageLoginKey:s,realmLoginKey:o}},uo={realm:"realm",toPath:"toPath",verifyMode:"verifyMode"},ws={site:"site",pages:"pages",page:"page",realm:"realm"},r2={enabled:!1,expire:"1d",session:!1,siteLogin:!1,site:[],pages:[],realm:{}},m_=["aria-label"],g_=["src"],v_=["src"],y_={class:"title"},b_={class:"flx-space-y-20 login-form"},k_=["for"],w_=["onUpdate:modelValue","type","placeholder","onFocus","onBlur"],C_=["aria-label"],__=["aria-label"];var a2=z({name:"LoginPage",__name:"index",setup(e){const t=ie("login"),n=jn(),{frontmatter:s}=Ae(),o=Pn(),{t:i}=ge(),{getTeekConfigRef:r}=fe(),a=r("private",r2),{siteLoginKey:c,pagesLoginKey:u,pageLoginKey:f,realmLoginKey:d}=i2(),h=j(""),p=Dn({username:{model:"",focusModel:!1,errorModel:!1,icon:Ih,placeholder:i("tk.login.usernamePlaceholder"),type:"text"},password:{model:"",focusModel:!1,errorModel:!1,icon:b9,placeholder:i("tk.login.passwordPlaceholder"),type:"password"},verifyCode:{model:"",focusModel:!1,errorModel:!1,icon:Vh,placeholder:i("tk.login.verifyCodePlaceholder"),type:"text",append:go(p_),appendModel:h}}),g=()=>p.verifyCode.model===""?(p.verifyCode.errorModel=!0,Ct.warning({message:i("tk.login.verifyCodeNonNull"),plain:!0}),!1):p.verifyCode.model!==h.value?(p.verifyCode.errorModel=!0,Ct.error({message:i("tk.login.verifyCodeError"),plain:!0}),!1):p.username.model===""||p.password.model===""?(p.username.errorModel=!0,Ct.warning({message:i("tk.login.loginInfoNonNull"),plain:!0}),!1):p.password.model===""?(p.password.errorModel=!0,Ct.warning({message:i("tk.login.loginInfoNonNull"),plain:!0}),!1):!0,v=E=>E?E.indexOf("d")!==-1?parseInt(E.replace("d",""))*24*60*60*1e3:E.indexOf("h")!==-1?parseInt(E.replace("h",""))*60*60*1e3:parseInt(E)*1e3:864e5,k=()=>{Object.values(p).forEach(E=>{E.model="",E.focusModel=!1})},b=()=>{const{searchParams:E}=new URL(window.location.href),I=E.get(uo.verifyMode),P=E.get(uo.toPath),N=E.get(uo.realm),{site:$=[],pages:U=[],realm:q={}}=a.value;return[{condition:()=>I===ws.page&&P,handle:()=>y([],f,{toPath:P})},{condition:()=>I===ws.realm&&N,handle:()=>y(q[N]||[],d,{isRealm:!0,realm:N})},{condition:()=>I===ws.pages,handle:()=>y(U,u)},{condition:()=>I===ws.site,handle:()=>y($,c,{isSite:!0})}].find(J=>J.condition())},w=()=>{if(!me)return;const{enabled:E=!1}=a.value;if(!E)return Ct.success({message:i("tk.login.loginSuccess"),plain:!0}),n.go("/");if(!g())return;const{searchParams:I}=new URL(window.location.href),P=I.get(uo.toPath);let N=!1;const $=b();if($){const{doLogin:U}=a.value,q={username:p.username.model,password:p.password.model},J=$.handle;N=U?U(q,"page",J):J()}N!==void 0&&(N?(Ct.success({message:i("tk.login.loginSuccess"),plain:!0}),P&&n.go(P)):Ct.error({message:i("tk.login.loginError"),plain:!0}))},y=(E,I,P={})=>{const{toPath:N}=P;if(N)return _(N,I);const $=E.find(U=>U.username===p.username.model&&U.password===p.password.model);return $?x($,I,P):!1},_=(E,I)=>{const P=o.value.originPosts.find(he=>[he.frontmatter.permalink,he.url].includes(E));if(!P)return!1;const{username:N,password:$,session:U,expire:q,strategy:J,realm:G}=P.frontmatter||{},ne=[...P.frontmatter.loginInfo||[],{username:N,password:$,session:U,expire:q,strategy:J,realm:G}].filter(he=>![void 0,""].includes(he.username)&&![void 0,""].includes(he.password)).find(he=>he.username===p.username.model&&he.password===p.password.model);if(ne)return x({...ne},I+P.url);if(G&&a.value.realm){const he=()=>y(a.value.realm[G],d,{isRealm:!0,realm:G});return a.value.doLogin?a.value.doLogin({username:N,password:$},"realm",he):he()}return!1},x=(E,I,P={})=>{const{session:N,expire:$,strategy:U="once",role:q="common"}=E,{isSite:J=!1,isRealm:G=!1,realm:ae}=P,ne=N||a.value.session?sessionStorage:localStorage,he=G?`${I}${ae}`:I,st=a.value.encrypt;try{return ne.setItem(he,JSON.stringify({username:p.username.model,password:st?st(p.password.model,s):p.password.model,loginTime:new Date().getTime(),expire:U==="always"?new Date().getTime()+30*1e3:v($||a.value.expire),strategy:U||"once",...J&&{role:q}})),!0}catch(je){return console.error("[Teek Error] Failed to store credentials:",je),!1}},L=(E,I)=>{E.focusModel=!0,E.errorModel=!1,a.value.onFocus?.(E.model,I)},V=(E,I)=>{E.focusModel=!1,E.model===""&&(E.errorModel=!0),a.value.onBlur?.(E.model,I)};return(E,I)=>(m(),C("div",{class:T(l(t).b()),"aria-label":l(i)("tk.login.label")},[S("div",{class:T(l(t).e("wrapper"))},[l(s).leftImg?(m(),C("div",{key:0,class:T(l(t).e("left"))},[S("img",{src:l(Ee)(l(s).leftImg),alt:"login"},null,8,g_)],2)):A("v-if",!0),S("div",{class:T(l(t).e("right"))},[S("div",{class:T([l(t).e("right__header"),"flx-center"])},[l(s).logo?(m(),C("img",{key:0,src:l(s).logo,alt:"logo"},null,8,v_)):A("v-if",!0),S("span",y_,W(l(s).name??"VitePress Theme Teek"),1)],2),S("form",b_,[(m(!0),C(Y,null,le(p,(P,N)=>(m(),C("div",{key:N,class:"flx login-form-item"},[S("div",{class:T([l(t).e("right__form"),l(t).is("focus",P.focusModel),l(t).is("error",P.errorModel)])},[H(l(de),{icon:P.icon},null,8,["icon"]),S("label",{for:"input-"+N,class:"sr-only"},W(P.placeholder),9,k_),et(S("input",{"onUpdate:modelValue":$=>P.model=$,type:P.type,class:T(l(t).em("right__form","control")),placeholder:P.placeholder,onFocus:$=>L(P,N),onBlur:$=>V(P,N),onKeydown:va(w,["enter"])},null,42,w_),[[Fc,P.model]])],2),P.append?(m(),D(Be(P.append),{key:0,modelValue:P.appendModel,"onUpdate:modelValue":$=>P.appendModel=$},null,8,["modelValue","onUpdate:modelValue"])):A("v-if",!0)]))),128)),S("div",{class:T(l(t).e("right__form__btn"))},[S("button",{type:"button",onClick:I[0]||(I[0]=P=>k()),class:"flx-center","aria-label":l(i)("tk.login.reset")},[H(l(de),{icon:l(Bh)},null,8,["icon"]),S("span",null,W(l(i)("tk.login.reset")),1)],8,C_),S("button",{type:"button",onClick:I[1]||(I[1]=P=>w()),class:"flx-center primary","aria-label":l(i)("tk.login.login")},[H(l(de),{icon:l(Nh)},null,8,["icon"]),S("span",null,W(l(i)("tk.login.login")),1)],8,__)],2)])],2)],2)],10,m_))}});const S_=()=>{const e=jn(),{frontmatter:t}=Ae(),{loginPath:n}=Li(),{siteLoginKey:s,pagesLoginKey:o,pageLoginKey:i,realmLoginKey:r}=i2(),{getTeekConfigRef:a}=fe(),c=a("private",r2),u=v=>{const k=localStorage.getItem(v)||sessionStorage.getItem(v);return k?JSON.parse(k):null},f=(v,k)=>{const b=c.value.decrypt;return v.some(w=>w.username===k.username&&w.password===(b?b(k.password,t):k.password))},d=(v,k)=>{const{expire:b,loginTime:w,strategy:y}=v;return y==="always"&&(sessionStorage.removeItem(k),localStorage.removeItem(k)),b&&w&&new Date().getTime()-w>b},h=(v,k,b)=>{const w=()=>{const y=u(v);return!!(y&&f(k,y)&&!d(y,v))};return c.value.doValidate?c.value.doValidate(b,t.value,w):w()};return{watchSite:()=>{if(!me||!c.value.enabled||!c.value.siteLogin||!n.value||e.route.data.frontmatter.loginPage)return;const{verifyMode:v,toPath:k}=uo,b=`${n.value}?${v}=${ws.site}&${k}=${window.location.href}`;h(s,c.value.site||[],"site")||e.go(b)},watchPages:()=>{me&&c.value.enabled&&te(e.route,v=>{if(!c.value.enabled||!t.value.private||!n.value||v.data.frontmatter.loginPage||h(s,c.value.site||[],"site")&&u(s).role==="admin")return;const{verifyMode:k,toPath:b,realm:w}=uo,y=`${n.value}?${k}={verifyMode}&${b}=${v.path}`,_=t.value.privateRealm,x=[...t.value.loginInfo||[],{username:t.value.username,password:t.value.password}].filter(E=>![void 0,""].includes(E.username)&&![void 0,""].includes(E.password));if(x.length){const E="/"+v.data.filePath.replace(".md",""),I=i+E;if(h(I,x,"page")||h(`${I}.html`,x,"page"))return}if(_){const E=y.replace("{verifyMode}",ws.realm)+`&${w}=${_}`;h(r+_,c.value.realm[_]||[],"realm")||e.go(E);return}if(x.length){const E=y.replace("{verifyMode}",ws.page);return e.go(E)}const L=y.replace("{verifyMode}",ws.pages),V=c.value.pages||[];h(o,V,"pages")||h(`${o}.html`,V,"pages")||e.go(L)},{immediate:!0})}}},T_=["src"],E_={key:1};var l2=z({name:"RiskLinkPage",__name:"index",setup(e){const t=ie("risk-link"),{t:n}=ge(),{frontmatter:s}=Ae(),o=j("");be(()=>{const{searchParams:r}=new URL(window.location.href),a=r.get("target");a&&Yc(a)&&(o.value=a)});const i=()=>{window.location.href=o.value};return(r,a)=>(m(),C("div",{class:T([l(t).b(),l(t).join("center"),"flx-space-y-20"])},[S("div",{class:T([l(t).e("header"),"flx-align-center"])},[l(s).logo?(m(),C("img",{key:0,src:l(s).logo,alt:"logo"},null,8,T_)):A("v-if",!0),o.value?(m(),C("p",{key:1,class:T(l(t).e("title"))},W(l(s).desc?l(s).desc:l(n)("tk.riskLink.title",{name:l(s).name||"VitePress Theme Teek"})),3)):(m(),C("p",{key:2,class:T(l(t).e("title"))},W(l(s).linkIllegal?l(s).linkIllegal:l(n)("tk.riskLink.linkIllegal")),3))],2),o.value?(m(),C("p",{key:0,class:T([l(t).e("link"),"sle"])},W(o.value),3)):A("v-if",!0),o.value?(m(),C("div",E_,[S("button",{class:"btn",onClick:i},W(l(n)("tk.riskLink.confirmButtonText")),1)])):A("v-if",!0)],2))}});const x_=(e={})=>{const t=new Set,n=[],{riskLinkPath:s}=Li(),{whitelist:o=[],blacklist:i=[]}=e,r=(d,h)=>d.some(p=>p===h||Je(p)&&h.startsWith(p)||p instanceof RegExp&&p.test(h)),a=(d,h)=>new URL(d,window.location.origin).hostname!==h&&!r(o,d),c=async()=>{await Oe(),me&&document.querySelectorAll("a").forEach(d=>{const h=d.getAttribute("href"),p=window.location.hostname;if(!h||t.has(d)||i.length&&!r(i,h)||!a(h,p))return;t.add(d);const g=Ve(d,"click",v=>{v.preventDefault();const k=encodeURIComponent(h);window.open(`${s.value}?target=${k}`)});n.push(g)})},u=()=>{n.forEach(d=>d()),n.length=0,t.clear()},f=()=>{u(),c()};return Un(u),{start:c,stop:u,restart:f}};var A_=z({name:"TransitionCollapse",__name:"index",setup(e){const t=ie("collapse-transition"),n=o=>{o.style.maxHeight="",o.style.overflow=o.dataset.oldOverflow,o.style.paddingTop=o.dataset.oldPaddingTop,o.style.paddingBottom=o.dataset.oldPaddingBottom},s={beforeEnter(o){o.dataset||(o.dataset={}),o.dataset.oldPaddingTop=o.style.paddingTop,o.dataset.oldPaddingBottom=o.style.paddingBottom,o.style.height&&(o.dataset.elExistsHeight=o.style.height),o.style.maxHeight=0,o.style.paddingTop=0,o.style.paddingBottom=0},enter(o){requestAnimationFrame(()=>{o.dataset.oldOverflow=o.style.overflow,o.dataset.elExistsHeight?o.style.maxHeight=o.dataset.elExistsHeight:o.scrollHeight!==0?o.style.maxHeight=`${o.scrollHeight}px`:o.style.maxHeight=0,o.style.paddingTop=o.dataset.oldPaddingTop,o.style.paddingBottom=o.dataset.oldPaddingBottom,o.style.overflow="hidden"})},afterEnter(o){o.style.maxHeight="",o.style.overflow=o.dataset.oldOverflow},enterCancelled(o){n(o)},beforeLeave(o){o.dataset||(o.dataset={}),o.dataset.oldPaddingTop=o.style.paddingTop,o.dataset.oldPaddingBottom=o.style.paddingBottom,o.dataset.oldOverflow=o.style.overflow,o.style.maxHeight=`${o.scrollHeight}px`,o.style.overflow="hidden"},leave(o){o.scrollHeight!==0&&(o.style.maxHeight=0,o.style.paddingTop=0,o.style.paddingBottom=0)},afterLeave(o){n(o)},leaveCancelled(o){n(o)}};return(o,i)=>(m(),D(vt,nt({name:l(t).b()},Ec(s)),{default:O(()=>[M(o.$slots,"default")]),_:3},16,["name"]))}});const $_=["innerHTML"],L_=["innerHTML"];var I_=z({name:"DemoCode",__name:"index",props:{source:{},rawSource:{},path:{},description:{},options:{},effect:{}},setup(e){const t=e,n=ie("demo-code"),{t:s}=ge(),{copy:o,copied:i,isSupported:r}=Hh(),{frontmatter:a,isDark:c}=Ae(),{playgroundUrl:u="",playgroundMainFileName:f="App.vue",githubUrl:d="",playgroundButtonTip:h=s("tk.demoCode.playground"),githubButtonTip:p=s("tk.demoCode.github"),copyButtonTip:g=s("tk.demoCode.copy"),collapseSourceButtonTip:v=s("tk.demoCode.collapseSource"),expandSourceButtonTip:k=s("tk.demoCode.expandSource")}={...JSON.parse(decodeURIComponent(t.options)),...a.value.demo},b=F(()=>decodeURIComponent(t.source)),w=F(()=>decodeURIComponent(t.rawSource)),y=F(()=>decodeURIComponent(t.description)),_=F(()=>t.effect==="true"),x=Object.assign({}),L=wc(async()=>{try{const U=Object.keys(x).find(q=>q.endsWith(`/${t.path}`));return x[U]}catch(U){console.error(`[Teek Error] Failed to load component: '/${t.path}'`,U)}}),V=j(!1),E=U=>{U!==void 0?V.value=U:V.value=!V.value},I=()=>{const U=P(t.source),q=c.value?"?theme=dark":"",G=`${(u.includes("?")?`${u}${q.replace("?","&")}`:`${u}${q}`).replace(/\/$/,"")}/#${U}`;window.open(G,"_blank")},P=U=>{const q=decodeURIComponent(U),J={[f]:q};return btoa(JSON.stringify(J))},N=()=>{const U=`${d}/${t.path}`;window.open(U,"_blank")},$=async()=>{r||console.error(s("tk.demoCode.notSupport")),await o(w.value),i.value?Ct.success({message:s("tk.demoCode.copySuccess"),plain:!0}):Ct.error({message:s("tk.demoCode.copyFail"),plain:!0})};return(U,q)=>(m(),C(Y,null,[y.value?(m(),C("div",{key:0,class:T(l(n).b("description")),innerHTML:y.value},null,10,$_)):A("v-if",!0),_.value?(m(),D(Be(l(L)),{key:1})):(m(),C("div",{key:2,class:T(l(n).b())},[S("div",{class:T(l(n).e("effect"))},[(m(),D(Be(l(L))))],2),S("div",{class:T(l(n).e("button-group"))},[M(U.$slots,"teek-demo-code-button-left"),l(u)?(m(),D(l(de),{key:0,title:l(h),onClick:I,icon:l(G7),role:"link","aria-label":l(h)},null,8,["title","icon","aria-label"])):A("v-if",!0),l(d)?(m(),D(l(de),{key:1,title:l(p),onClick:N,icon:l(o9),role:"link","aria-label":l(d)},null,8,["title","icon","aria-label"])):A("v-if",!0),H(l(de),{title:l(g),icon:l(i9),onClick:$,role:"button","aria-label":l(g)},null,8,["title","icon","aria-label"]),H(l(de),{title:V.value?l(k):l(v),onClick:q[0]||(q[0]=J=>E()),icon:l(r9),role:"button","aria-label":V.value?l(k):l(v)},null,8,["title","icon","aria-label"]),M(U.$slots,"teek-demo-code-button-right")],2),H(l(A_),null,{default:O(()=>[et(S("div",{class:T(l(n).join("vp-code")),innerHTML:b.value},null,10,L_),[[at,V.value]])]),_:1}),H(vt,{name:l(n).join("fade-linear"),persisted:""},{default:O(()=>[et(S("div",{class:T(l(n).e("float-control")),onClick:q[1]||(q[1]=J=>E(!1)),role:"button"},[H(l(de),{icon:l(a9)},null,8,["icon"]),S("span",null,W(l(k)),1)],2),[[at,V.value]])]),_:1},8,["name"])],2))],64))}}),P_=z({name:"HomeFullscreenWallpaper",__name:"index",setup(e){const t=ie("fullscreen-wallpaper"),{getTeekConfigRef:n}=fe(),s=j(!1),o=n("wallpaper",{hideBanner:!1,hideMask:!1}),i=f=>{if(f.key==="F12"&&s.value||f.key==="I"&&f.ctrlKey&&f.shiftKey&&s.value)return f.preventDefault();f.key==="F11"&&(f.preventDefault(),document.documentElement.requestFullscreen?document.documentElement.requestFullscreen():document.documentElement.mozRequestFullScreen?document.documentElement.mozRequestFullScreen():document.documentElement.webkitRequestFullscreen?document.documentElement.webkitRequestFullscreen():document.documentElement.msRequestFullscreen&&document.documentElement.msRequestFullscreen())},r=()=>{const f=document.documentElement;if(f.scrollTop!==0)return;const d=document.querySelector(".vp-doc"),h=document.querySelector(`.${t.join("banner__content")}`),p=document.querySelector(`.${t.join("banner-waves")}`),g=document.querySelector(`.${t.join("body-bg-image")} .mask`),v=document.querySelector(`.${t.join("banner-bg-image")} .mask`);s.value=!!document.fullscreenElement;const{hideBanner:k,hideMask:b}=o.value,w=[{el:f,executeClass:t.b()},{el:d,executeClass:"display-none"},{el:h,executeClass:"no-feature"},{el:h,executeClass:"display-none",execute:k},{el:p,executeClass:"display-none",execute:k},{el:g,executeClass:"display-none",execute:b},{el:v,executeClass:"display-none",execute:b}];a(!!document.fullscreenElement,w)},a=(f,d)=>{if(f){d.forEach(h=>{h.execute!==!1?h.executeClass&&h.el?.classList.add(h.executeClass):h.notExecuteClass&&h.el?.classList.add(h.notExecuteClass)});return}d.forEach(h=>{h.execute!==!1?h.executeClass&&h.el?.classList.remove(h.executeClass):h.notExecuteClass&&h.el?.classList.remove(h.notExecuteClass)})},c=f=>{s.value&&f.preventDefault()},u=()=>document;return Ve(u,"keydown",i),Ve(u,"fullscreenchange",r),Ve(u,"contextmenu",c),(f,d)=>(m(),C("div",{class:T(l(t).b())},null,2))}});const c2=Symbol("paginationKey"),M_=["disabled","aria-label","aria-disabled"],F_={key:0};var B_=z({name:"PaginationPrev",__name:"prev",props:{disabled:{type:Boolean},currentPage:{},prevText:{},prevIcon:{}},emits:["click"],setup(e){const t=e,{t:n}=ge(),s=F(()=>t.disabled||t.currentPage<=1);return(o,i)=>(m(),C("button",{type:"button",class:"btn-prev",disabled:s.value,"aria-label":e.prevText||l(n)("tk.pagination.prev"),"aria-disabled":s.value,onClick:i[0]||(i[0]=r=>o.$emit("click",r))},[e.prevText?(m(),C("span",F_,W(e.prevText),1)):e.prevIcon?(m(),D(l(de),{key:1,icon:e.prevIcon},null,8,["icon"])):A("v-if",!0)],8,M_))}});const N_=["disabled","aria-label","aria-disabled"],V_={key:0};var O_=z({name:"PaginationNext",__name:"next",props:{disabled:{type:Boolean},currentPage:{},pageCount:{},nextText:{},nextIcon:{}},emits:["click"],setup(e){const t=e,{t:n}=ge(),s=F(()=>t.disabled||t.currentPage===t.pageCount||t.pageCount===0);return(o,i)=>(m(),C("button",{type:"button",class:"btn-next",disabled:s.value,"aria-label":e.nextText||l(n)("tk.pagination.next"),"aria-disabled":s.value,onClick:i[0]||(i[0]=r=>o.$emit("click",r))},[e.nextText?(m(),C("span",V_,W(e.nextText),1)):e.nextIcon?(m(),D(l(de),{key:1,icon:e.nextIcon},null,8,["icon"])):A("v-if",!0)],8,N_))}});const u2=()=>qe(c2,{}),D_=["disabled"],R_=["disabled","aria-label"];var H_=z({name:"PaginationJumper",__name:"jumper",props:{size:{default:"default"}},setup(e){const t=ie("pagination"),{t:n}=ge(),{pageCount:s,disabled:o,currentPage:i,changeEvent:r}=u2(),a=j(i?.value||1),c=u=>{let f=u.target?.value||a.value;f<1&&(f=1),s?.value&&f>s.value&&(f=s.value);const d=Math.trunc(+f);r?.(d),a.value=d};return(u,f)=>(m(),C("span",{class:T(l(t).e("jump")),disabled:l(o)},[S("span",{class:T([l(t).e("goto")])},W(l(n)("tk.pagination.goto")),3),et(S("input",{type:"number","onUpdate:modelValue":f[0]||(f[0]=d=>a.value=d),disabled:l(o),onChange:c,"aria-label":l(n)("tk.pagination.page"),class:T([l(t).e("input"),l(t).em("input",e.size)])},null,42,R_),[[_o,a.value]]),S("span",{class:T([l(t).e("classifier")])},W(l(n)("tk.pagination.pageClassifier")),3)],10,D_))}});const z_=["disabled"];var j_=z({name:"PaginationTotal",__name:"total",props:{total:{}},setup(e){const t=ie("pagination"),{t:n}=ge(),{disabled:s}=u2();return(o,i)=>(m(),C("span",{class:T(l(t).e("total")),disabled:l(s)},W(l(n)("tk.pagination.total",{total:e.total})),11,z_))}});const U_=["aria-current","aria-label","tabindex"],W_=["tabindex","aria-label"],q_=["innerHTML"],K_=["innerHTML"],Y_=["aria-current","aria-label","tabindex"],G_=["tabindex","aria-label"],J_=["innerHTML"],X_=["innerHTML"],Q_=["aria-current","aria-label","tabindex"];var Z_=z({name:"PaginationPager",__name:"pager",props:{currentPage:{},pageCount:{},pagerCount:{},disabled:{type:Boolean}},emits:["change"],setup(e,{emit:t}){const n=e,s=t,o=ie("pager"),i=ie("icon"),{t:r}=ge(),a=j(!1),c=j(!1),u=j(!1),f=j(!1),d=j(!1),h=j(!1),p=F(()=>{const x=n.pagerCount||7,L=(x-1)/2,V=Number(n.currentPage),E=Number(n.pageCount);let I=!1,P=!1;E>x&&(V>x-L&&(I=!0),V["more","btn-quick-prev",i.b(),o.is("disabled",n.disabled)]),v=F(()=>["more","btn-quick-next",i.b(),o.is("disabled",n.disabled)]),k=F(()=>n.disabled?-1:0);zn(()=>{const x=(n.pagerCount-1)/2;a.value=!1,c.value=!1,n.pageCount>n.pagerCount&&(n.currentPage>n.pagerCount-x&&(a.value=!0),n.currentPage{n.disabled||(x?u.value=!0:f.value=!0)},w=(x=!1)=>{x?d.value=!0:h.value=!0},y=x=>{const L=x.target;if(L.tagName.toLowerCase()==="li"&&Array.from(L.classList).includes("number")){const V=Number(L.textContent);V!==n.currentPage&&s("change",V)}else L.tagName.toLowerCase()==="li"&&Array.from(L.classList).includes("more")&&_(x)},_=x=>{const L=x.target;if(L.tagName.toLowerCase()==="ul"||n.disabled)return;let V=Number(L.textContent);const E=n.pageCount,I=n.currentPage,P=n.pagerCount-2;L.className.includes("more")&&(L.className.includes("quick-prev")?V=I-P:L.className.includes("quick-next")&&(V=I+P)),Number.isNaN(+V)||(V<1&&(V=1),V>E&&(V=E)),V!==I&&s("change",V)};return(x,L)=>(m(),C("ul",{class:T(l(o).b()),onClick:_,onKeyup:va(y,["enter"])},[e.pageCount>0?(m(),C("li",{key:0,class:T([[l(o).is("active",e.currentPage===1),l(o).is("disabled",e.disabled)],"number"]),"aria-current":e.currentPage===1,"aria-label":l(r)("tk.pagination.currentPage",{pager:1}),tabindex:k.value}," 1 ",10,U_)):A("v-if",!0),a.value?(m(),C("li",{key:1,class:T(g.value),tabindex:k.value,"aria-label":l(r)("tk.pagination.prevPages",{pager:e.pagerCount-2}),onMouseenter:L[0]||(L[0]=V=>b(!0)),onMouseleave:L[1]||(L[1]=V=>u.value=!1),onFocus:L[2]||(L[2]=V=>w(!0)),onBlur:L[3]||(L[3]=V=>d.value=!1)},[(u.value||d.value)&&!e.disabled?(m(),C("span",{key:0,innerHTML:l(u9)},null,8,q_)):(m(),C("span",{key:1,innerHTML:l(Gf)},null,8,K_))],42,W_)):A("v-if",!0),(m(!0),C(Y,null,le(p.value,V=>(m(),C("li",{key:V,class:T([[l(o).is("active",e.currentPage===V),l(o).is("disabled",e.disabled)],"number"]),"aria-current":e.currentPage===V,"aria-label":l(r)("el.pagination.currentPage",{pager:V}),tabindex:k.value},W(V),11,Y_))),128)),c.value?(m(),C("li",{key:2,class:T(v.value),tabindex:k.value,"aria-label":l(r)("tk.pagination.nextPages",{pager:e.pagerCount-2}),onMouseenter:L[4]||(L[4]=V=>b()),onMouseleave:L[5]||(L[5]=V=>f.value=!1),onFocus:L[6]||(L[6]=V=>w()),onBlur:L[7]||(L[7]=V=>h.value=!1)},[(f.value||h.value)&&!e.disabled?(m(),C("span",{key:0,innerHTML:l(c9)},null,8,J_)):(m(),C("span",{key:1,innerHTML:l(Gf)},null,8,X_))],42,G_)):A("v-if",!0),e.pageCount>1?(m(),C("li",{key:3,class:T([[l(o).is("active",e.currentPage===e.pageCount),l(o).is("disabled",e.disabled)],"number"]),"aria-current":e.currentPage===e.pageCount,"aria-label":l(r)("tk.pagination.currentPage",{pager:e.pageCount}),tabindex:k.value},W(e.pageCount),11,Q_)):A("v-if",!0)],34))}}),eS=z({name:"Pagination",__name:"index",props:$n({total:{},pageCount:{},pagerCount:{default:7},layout:{default:["prev, pager, next, jumper, ->, total"].join(", ")},prevText:{},prevIcon:{default:()=>Xc},nextText:{},nextIcon:{default:()=>Qc},size:{default:"default"},background:{type:Boolean,default:!1},disabled:{type:Boolean,default:!1},hideOnSinglePage:{type:Boolean,default:!1}},{currentPage:{type:Number,default:1},currentPageModifiers:{},pageSize:{type:Number,default:10},pageSizeModifiers:{}}),emits:$n(["size-change","change","current-change","prev-click","next-click"],["update:currentPage","update:pageSize"]),setup(e,{emit:t}){const n=e,s=t,o=ie("pagination"),i=Ti(),r=Jt(e,"currentPage"),a=Jt(e,"pageSize"),c=b=>typeof b!="number",u=F(()=>{let b=0;return c(n.pageCount)?c(n.total)||(b=Math.max(1,Math.ceil(n.total/a.value))):b=n.pageCount,b});te(u,b=>{r.value>b&&(r.value=b)}),te([r,a],b=>{s("change",...b)},{flush:"post"});const f=b=>{a.value=b,s("size-change",a.value);const w=u.value;r.value>w&&(r.value=w)},d=()=>{n.disabled||(p(r.value-1),s("prev-click",r.value))},h=()=>{n.disabled||(p(r.value+1),s("next-click",r.value))},p=b=>{r.value=b;const w=u.value;r.value<1?r.value=1:r.value>w&&(r.value=w),s("current-change",r.value)},g=(b,w)=>{b&&(b.props||(b.props={}),b.props.class=[b.props.class,w].join(" "))};In(c2,{pageCount:u,disabled:F(()=>n.disabled),currentPage:r,changeEvent:p,handleSizeChange:f});const v=F(()=>{if(!n.layout)return[];if(n.hideOnSinglePage&&u.value<=1)return[];const b=n.layout.split(",").map(L=>L.trim()),w=[],y=[],_=nn("div",{class:o.e("right-wrapper")},y);let x=!1;return b.forEach(L=>{if(L==="->"){x=!0;return}x?y.push(k.value[L]):w.push(k.value[L])}),g(w[0],o.is("first")),g(w[w.length-1],o.is("last")),y.length>0&&(g(y[0],o.is("first")),g(y[y.length-1],o.is("last")),w.push(_)),w}),k=F(()=>({prev:nn(B_,{disabled:n.disabled,currentPage:r.value,prevText:n.prevText,prevIcon:n.prevIcon,onClick:d}),jumper:nn(H_,{size:n.size}),pager:nn(Z_,{currentPage:r.value,pageCount:u.value,pagerCount:n.pagerCount,onChange:p,disabled:n.disabled}),next:nn(O_,{disabled:n.disabled,currentPage:r.value,pageCount:u.value,nextText:n.nextText,nextIcon:n.nextIcon,onClick:h}),slot:i?.default?.()??null,total:nn(j_,{total:c(n.total)?0:n.total})}));return(b,w)=>(m(),C("div",{class:T([l(o).b(),l(o).is("background",e.background),l(o).m(e.size)])},[(m(!0),C(Y,null,le(v.value,y=>(m(),D(Be(y),{key:y}))),128))],2))}});const js="pageNum",tS=["aria-label"],nS=["aria-label"],sS=["title","href","target","aria-label"],oS=["title","href","aria-label"];var Lu=z({name:"ArticleInfo",__name:"index",props:{post:{},scope:{},split:{type:Boolean,default:!1}},setup(e){const t=ie("article-info"),{t:n}=ge(),{getTeekConfigRef:s}=fe(),{page:o}=Ae(),i=s("articleAnalyze",{showIcon:!0,dateFormat:"yyyy-MM-dd",showAuthor:!0,showCreateDate:!0,showUpdateDate:!1,showCategory:!1,showTag:!1}),r=Pn(),a=kn(),c=F(()=>{const h=r.value.originPosts,p=e.post.date||h.find(v=>[v.url,v.frontmatter.permalink].includes(a.path))?.date,g=i.value.dateFormat;return ht(g)?g(p||""):pi(p||new Date,g)}),u=F(()=>{const h=o.value.lastUpdated;if(!h)return"";const p=i.value.dateFormat;return ht(p)?p(h):pi(h,p)}),f=F(()=>{const{showAuthor:h,showCreateDate:p,showUpdateDate:g,showCategory:v,showTag:k}=i.value;return[{title:n("tk.articleInfo.author"),icon:Ih,data:e.post.author?.name,href:e.post.author?.link,target:e.post.author?.link?"_blank":"_self",show:d(h)},{title:n("tk.articleInfo.createTime"),icon:t9,data:c.value,show:d(p)},{title:n("tk.articleInfo.updateTime"),icon:Ph,data:u.value,show:u.value&&(e.scope==="article"&&g||e.scope==="article-banner")},{title:n("tk.articleInfo.category"),icon:n9,dataList:e.post.frontmatter?.categories||[],href:"/categories?category={data}",class:"or",show:e.scope!=="article-banner"&&(e.scope==="post"||d(v))},{title:n("tk.articleInfo.tag"),icon:s9,dataList:e.post.frontmatter?.tags||[],href:"/tags?tag={data}",class:"or",show:e.scope!=="article-banner"&&(e.scope==="post"||d(k))}]}),d=h=>{const p=[h||[]].flat();return p.includes(!0)||p.includes(e.scope)};return(h,p)=>(m(),C("div",{class:T([l(t).b(),e.scope]),role:"group","aria-label":l(n)("tk.articleInfo.label")},[(m(!0),C(Y,null,le(f.value,g=>(m(),C(Y,{key:g.title},[g.show&&(g.data||g.dataList?.length)?(m(),C("span",{key:0,class:T([l(t).e("item"),{split:e.split}]),role:"group","aria-label":g.title},[l(i).showIcon?(m(),D(l(de),{key:0,icon:g.icon,class:T(l(t).e("icon")),"aria-hidden":"true"},null,8,["icon","class"])):A("v-if",!0),g.data?(m(),C("a",{key:1,title:g.title,href:g.href&&l(Ee)(g.href),target:g.target,class:T([g.class,"hover-color"]),"aria-label":g.data},W(g.data),11,sS)):(m(!0),C(Y,{key:2},le(g.dataList,(v,k)=>(m(),C("a",{key:k,title:g.title,href:g.href&&l(Ee)(g.href.replace("{data}",encodeURIComponent(v))),class:T([g.class,"hover-color"]),"aria-label":v},W(v),11,oS))),128))],10,nS)):A("v-if",!0)],64))),128)),M(h.$slots,"default")],10,tS))}});const iS=["title","aria-label"],rS={class:"list flx"},aS=["href","aria-label"],lS=["aria-label"],cS=["innerHTML"],uS=["href","aria-label"],fS=["aria-label"],dS=["aria-label"],hS=["innerHTML"],pS=["href","aria-label"],mS=["href","aria-label"];var Bd=z({name:"HomePostItem",__name:"HomePostItem",props:{post:{},coverImgMode:{}},setup(e){const t=ie("post-item"),{t:n}=ge(),{getTeekConfigRef:s}=fe(),o=s("post",{excerptPosition:"bottom",showMore:!0,moreLabel:n("tk.homePost.moreLabel"),showCapture:!1,splitSeparator:!1,listStyleTitleTagPosition:"right",defaultCoverImg:[]}),i=s("articleAnalyze",{showInfo:!0}),r=e.post.url&&Ee(e.post.url),a=F(()=>e.post.frontmatter.description||e.post.excerpt||o.value.showCapture&&e.post.capture),c=F(()=>[e.post.frontmatter.coverImg||o.value.defaultCoverImg||[]].flat()),u=F(()=>{const d=c.value[Math.floor(Math.random()*c.value.length)];return{default:{is:"div",props:{style:`background-image: url(${Ee(d)});`}},full:{is:"img",props:{src:Ee(d)}}}}),f=F(()=>{const d=[i.value.showInfo].flat();return d.includes(!0)||d.includes("post")});return(d,h)=>(m(),C("div",{class:T(l(t).b())},[e.post.frontmatter.sticky?(m(),C("i",{key:0,class:"pin",title:l(n)("tk.homePost.pin",{sticky:e.post.frontmatter.sticky}),"aria-label":l(n)("tk.homePost.pinLabel")},null,8,iS)):A("v-if",!0),S("div",rS,[S("div",{class:T(l(t).e("left"))},[A(" 标题 "),S("a",{class:T([l(t).e("left__title"),"hover-color","sle"]),href:l(r),"aria-label":e.post.title},[H(l(Fi),{post:e.post,"title-tag-props":{position:l(o).listStyleTitleTagPosition}},null,8,["post","title-tag-props"])],10,aS),A(" 摘要 top "),a.value&&l(o).excerptPosition==="top"?(m(),C("div",{key:0,class:T(`${l(t).e("left__excerpt")} top`),"aria-label":l(n)("tk.homePost.excerptLabel")},[S("div",{class:"excerpt",innerHTML:a.value},null,8,cS),l(o).showMore?(m(),C("a",{key:0,class:"more",href:l(r),"aria-label":l(o).moreLabel},W(l(o).moreLabel),9,uS)):A("v-if",!0)],10,lS)):A("v-if",!0),A(" 文章信息 "),S("div",{class:T(l(t).e("left__footer")),"aria-label":l(n)("tk.homePost.infoLabel")},[f.value?(m(),D(l(Lu),{key:0,post:e.post,scope:"post",split:l(o).splitSeparator},null,8,["post","split"])):A("v-if",!0)],10,fS),A(" 摘要 bottom "),a.value&&l(o).excerptPosition==="bottom"?(m(),C("div",{key:1,class:T(`${l(t).e("left__excerpt")} bottom`),"aria-label":l(n)("tk.homePost.excerptLabel")},[S("div",{class:"excerpt",innerHTML:a.value},null,8,hS),l(o).showMore?(m(),C("a",{key:0,class:"more",href:l(r),"aria-label":l(o).moreLabel},W(l(o).moreLabel),9,pS)):A("v-if",!0)],10,dS)):A("v-if",!0)],2),A(" 右侧封面图 "),S("div",{class:T(`${l(t).e("right")} flx-align-center`)},[c.value.length?(m(),C("a",{key:0,href:l(r),class:T(`${e.coverImgMode} cover`),"aria-label":l(n)("tk.homePost.coverImgLabel")},[(m(),D(Be(u.value[e.coverImgMode].is),nt(u.value[e.coverImgMode].props,{"aria-hidden":"true",class:"cover-img"}),null,16))],10,mS)):A("v-if",!0)],2)])],2))}});const gS=["href","alt"],vS=["src"],yS=["href","aria-label"],bS=["innerHTML","aria-label"];var Nd=z({name:"HomePostItemCard",__name:"HomePostItemCard",props:{post:{}},setup(e){const t=ie("post-item-card"),{t:n}=ge(),{getTeekConfigRef:s}=fe(),o=s("post",{showCapture:!1,splitSeparator:!1,cardStyleTitleTagPosition:"left",defaultCoverImg:[]}),i=s("articleAnalyze",{showInfo:!0}),r=e.post.url&&Ee(e.post.url),a=F(()=>[e.post.frontmatter.coverImg||o.value.defaultCoverImg||[]].flat()),c=F(()=>e.post.frontmatter.description||e.post.excerpt||o.value.showCapture&&e.post.capture),u=F(()=>{const f=[i.value.showInfo].flat();return f.includes(!0)||f.includes("post")});return(f,d)=>(m(),C("div",{class:T(l(t).b())},[e.post.frontmatter.sticky?(m(),D(l(de),{key:0,icon:l(y9),class:"top",size:40,title:l(n)("tk.homePost.pin",{sticky:e.post.frontmatter.sticky}),"aria-label":l(n)("tk.homePost.pinLabel")},null,8,["icon","title","aria-label"])):A("v-if",!0),a.value.length?(m(),C("div",{key:1,class:T(l(t).e("cover-img"))},[S("a",{href:l(r),alt:e.post.title},[S("img",{src:l(Ee)(a.value[0]),class:"cover-img"},null,8,vS)],8,gS)],2)):A("v-if",!0),S("div",{class:T([l(t).e("info")])},[S("a",{class:"title hover-color, sle",href:l(r),"aria-label":e.post.title},[H(l(Fi),{post:e.post,"title-tag-props":{position:l(o).cardStyleTitleTagPosition}},null,8,["post","title-tag-props"])],8,yS),c.value?(m(),C("span",{key:0,class:"excerpt mle",innerHTML:c.value,"aria-label":l(n)("tk.homePost.excerptLabel")},null,8,bS)):A("v-if",!0),u.value?(m(),D(l(Lu),{key:1,post:e.post,scope:"post",split:l(o).splitSeparator,"aria-label":l(n)("tk.homePost.infoLabel")},null,8,["post","split","aria-label"])):A("v-if",!0)],2)],2))}});const kS=["aria-label"],wS=["aria-label"],Vd="small",Od="prev, pager, next";var CS=z({name:"HomePostList",__name:"index",props:{modelValue:{default:!1},modelModifiers:{}},emits:["update:modelValue"],setup(e,{expose:t}){const n=ie("post-list"),{t:s}=ge(),{getTeekConfigRef:o}=fe(),i=Pn(),{frontmatter:r}=Ae(),a=o("post",{postStyle:"list",coverImgMode:"default",emptyLabel:s("tk.homePost.emptyLabel"),transition:!0,transitionName:n.join("slide-fade")}),c=o("page",{}),u=j(1),f=j(0),d=j(a.value.coverImgMode),h=Jt(e,"modelValue"),p=F(()=>a.value.postStyle==="list"?10:15),g=F(()=>c.value.pageSize||p.value),v=kn(),k=j([]),b=j(0);zn(()=>{d.value=a.value.coverImgMode});const w=()=>{if(!me)return;const{searchParams:P}=new URL(window.location.href),N=Number(P.get(js))||1;N!==u.value&&(u.value=N),h.value=N>1;const $=i.value,U=r.value;let q=$.sortPostsByDateAndSticky;if(U.categoriesPage){const G=P.get("category");q=G?$.groupPosts.categories[G]:q.filter(ae=>ae.frontmatter.categories)}else if(U.tagsPage){const G=P.get("tag");q=G?$.groupPosts.tags[G]:q.filter(ae=>ae.frontmatter.tags)}f.value!==q?.length&&(f.value=q?.length||0);const J=q.filter(G=>G.frontmatter.inHomePost!==!1);b.value=J.length,k.value=J.slice((u.value-1)*g.value,u.value*g.value)};te(()=>v.path,w,{immediate:!0});const y=()=>{const{searchParams:P}=new URL(window.location.href);P.delete(js),P.append(js,String(u.value)),window.history.pushState({},"",`${window.location.pathname}?${P.toString()}`),w(),Oe(()=>{const N=getComputedStyle(document.documentElement),$=D7(N.getPropertyValue("--vp-c-text-1"));document.querySelector("html")?.scrollTo({top:window.innerHeight-$,behavior:"smooth"})})},_=Dn({...c.value}),{size:x="default",layout:L="prev, pager, next, jumper, ->, total"}=c.value;eu(P=>{P<=768?_.size!==Vd&&(_.size=Vd):_.size!==x&&(_.size=x),P<=960?_.layout!==Od&&(_.layout=Od):_.layout!==L&&(_.layout=L),P<=960?d.value!=="default"&&(d.value="default"):d.value!==a.value.coverImgMode&&(d.value=a.value.coverImgMode)});const V=_a(P=>P.post),E=j(null),{start:I}=Ca(E,!1);return be(()=>{V.value&&I()}),t({updateData:w}),(P,N)=>(m(),C("div",{class:T([l(n).b(),l(n).is("card",l(a).postStyle==="card")])},[k.value?(m(),C(Y,{key:0},[M(P.$slots,"teek-home-post-list",Ge(Ze({currentPosts:k.value,transitionName:l(a).transitionName})),()=>[H(Qs,{tag:"ul",name:l(a).transition?l(a).transitionName:"","aria-label":l(s)("tk.homePost.label")},{default:O(()=>[(m(!0),C(Y,null,le(k.value,$=>(m(),C("li",{key:$.url,class:T({"full-img":d.value==="full"})},[l(V)?(m(),C("div",{key:0,ref_for:!0,ref_key:"postItemListInstance",ref:E,style:{width:"100%",height:"100%"}},[l(a).postStyle==="card"?(m(),D(Nd,{key:0,post:$},null,8,["post"])):(m(),D(Bd,{key:1,post:$,coverImgMode:d.value},null,8,["post","coverImgMode"]))],512)):(m(),C(Y,{key:1},[l(a).postStyle==="card"?(m(),D(Nd,{key:0,post:$},null,8,["post"])):(m(),D(Bd,{key:1,post:$,coverImgMode:d.value},null,8,["post","coverImgMode"]))],64))],2))),128))]),_:1},8,["name","aria-label"])]),S("div",{class:T(`${l(n).e("pagination")} flx-justify-center`),"aria-label":l(s)("tk.homePost.pageLabel")},[b.value>=g.value?(m(),D(l(eS),nt({key:0,"page-size":g.value,"onUpdate:pageSize":N[0]||(N[0]=$=>g.value=$),"current-page":u.value,"onUpdate:currentPage":N[1]||(N[1]=$=>u.value=$),total:f.value,background:"",onCurrentChange:y},{..._}),null,16,["page-size","current-page","total"])):A("v-if",!0)],10,kS)],64)):(m(),C("div",{key:1,class:T([l(n).e("empty"),"flx-column-center"]),"aria-label":l(a).emptyLabel},[H(l(de),{icon:l(q7),size:160,color:"var(--vp-c-text-3)","aria-hidden":"true"},null,8,["icon"]),S("span",{class:T(l(n).e("empty__title"))},W(l(a).emptyLabel),3)],10,wS))],2))}});const _S=["aria-label"];var SS=z({name:"HomeBannerBgPure",__name:"HomeBannerBgPure",setup(e){const t=ie("banner-bg-pure"),{t:n}=ge(),{getTeekConfig:s}=fe(),o=()=>{const{pureBgColor:i="#28282d"}=s("banner",{});return{backgroundColor:i}};return(i,r)=>(m(),C("div",{class:T(l(t).b()),style:Fe(o()),"aria-label":l(n)("tk.homeBanner.bgPureLabel")},[M(i.$slots,"default")],14,_S))}});const TS=["aria-label"],ES=["aria-label"];var Dd=z({name:"HomeBannerBgImage",__name:"HomeBannerBgImage",setup(e){const t=ie("banner-bg-image"),{t:n}=ge(),{getTeekConfigRef:s}=fe(),o=s("banner",{bgStyle:void 0,imgSrc:void 0,imgInterval:15e3,imgShuffle:!1,mask:!0,maskBg:"rgba(0, 0, 0, 0.4)"}),i=F(()=>o.value.bgStyle==="partImg"),r=F(()=>o.value.bgStyle==="fullImg"),a=F(()=>{const h=o.value.imgSrc;return[ht(h)?h():h||[]].flat().map(p=>p&&Ee(p))}),{data:c,start:u,index:f}=tu(a,{timeout:o.value.imgInterval,shuffle:o.value.imgShuffle,onAfterUpdate:()=>{const h=(f.value+1)%a.value.length,p=a.value[h];if(p){const g=new Image;g.src=p}}});be(()=>{u()});const d=()=>{const{imgSrc:h,maskBg:p,imgInterval:g}=o.value,v=t.cssVarName("banner-img-bg"),k=t.cssVarName("banner-mask-bg-color"),b=t.cssVarName("banner-img-switch-interval-s");return h?.length?{[v]:`url(${c.value}) center center / cover no-repeat`,[k]:Je(p)?p:`rgba(0, 0, 0, ${p})`,[b]:g/1e3+"s"}:{[v]:t.cssVar("bg-img-default")}};return(h,p)=>(m(),C(Y,null,[S("div",{class:T([l(t).b(),{part:i.value,full:r.value}]),style:Fe(d()),"aria-label":l(n)("tk.homeBanner.bgImgLabel")},[l(o).mask&&l(o).imgSrc?(m(),C("div",{key:0,class:"mask","aria-label":l(n)("tk.homeBanner.maskLabel")},null,8,ES)):A("v-if",!0),i.value?M(h.$slots,"default",{key:1}):A("v-if",!0)],14,TS),r.value?M(h.$slots,"default",{key:0}):A("v-if",!0)],64))}});const xS=["aria-label"],AS=["aria-label"],$S=["aria-label"],LS={key:0},IS=["aria-label"],PS=["aria-label"];var MS=z({name:"HomeBannerContent",__name:"HomeBannerContent",setup(e){const t=ie("banner-content"),{t:n}=ge(),{getTeekConfigRef:s}=fe(),{site:o,frontmatter:i}=Ae(),r=s("banner",{name:i.value.tk?.name||o.value.title||"",descStyle:"default",description:[],switchTime:4e3,switchShuffle:!1,typesInTime:200,typesOutTime:100,typesNextTime:800,typesShuffle:!1}),a=F(()=>[...new Set([i.value.tk?.description||r.value.description||[]].flat()?.filter(k=>!!k))]),c=F(()=>r.value.descStyle==="default"),u=F(()=>r.value.descStyle==="types"),f=F(()=>r.value.descStyle==="switch"),{text:d,isFinished:h,start:p}=z9(a,{inputTime:r.value.typesInTime,outputTime:r.value.typesOutTime,nextTime:r.value.typesNextTime,shuffle:r.value.typesShuffle}),{data:g,start:v}=tu(a,{timeout:r.value.switchTime,shuffle:r.value.switchShuffle,onUpdate:(k,b)=>{k.value="",setTimeout(()=>{k.value=b},20)}});return be(()=>{u.value&&p(),f.value&&v()}),(k,b)=>(m(),C("div",{class:T(l(t).b()),"aria-label":l(n)("tk.homeBanner.contentLabel")},[A(" 首页 banner 图文字插槽 "),k.$slots["teek-home-banner-name"]?M(k.$slots,"teek-home-banner-name",Ge(nt({key:0},{name:l(r).name}))):(m(),C(Y,{key:1},[A(" 如果没有传入插槽,则渲染默认的 h1 标签及内容 "),S("h1",{class:T(l(t).e("title")),"aria-label":l(n)("tk.homeBanner.titleLabel")},W(l(r).name),11,AS)],2112)),S("p",{class:T(l(t).e("desc")),"aria-label":l(n)("tk.homeBanner.descLabel")},[c.value?(m(),C("span",LS,W(a.value[0]),1)):f.value?(m(),D(vt,{key:1,name:l(t).join("fade"),mode:"out-in"},{default:O(()=>[(m(),C("span",{key:l(g)||a.value[0],onClick:b[0]||(b[0]=(...w)=>l(v)&&l(v)(...w)),class:"switch","aria-label":l(n)("tk.homeBanner.descSwitchLabel")},W(l(g)||a.value[0]),9,IS))]),_:1},8,["name"])):u.value&&a.value.length?(m(),C(Y,{key:2},[S("span",{"aria-label":l(n)("tk.homeBanner.descTypedLabel")},W(l(d)),9,PS),S("span",{class:T(["typed",{"is-animation":l(h)}])},"|",2)],64)):A("v-if",!0)],10,$S)],10,xS))}});const FS=["aria-labelledby"],BS=["src","alt","aria-label"],NS=["id"],VS={class:"feature-details"};var OS=z({name:"HomeBannerFeature",__name:"HomeBannerFeature",setup(e){const t=ie("banner-feature"),{t:n}=ge(),{getTeekConfigRef:s}=fe(),{frontmatter:o}=Ae(),i=s("banner",{features:o.value.tk?.features||[],featureCarousel:4e3}),r=s("features",[]),a=j(0),c=j(!1);let u;const f=F(()=>i.value.features||r.value||[]),d=()=>{u&&(clearTimeout(u),u=null)};return eu(h=>{const{featureCarousel:p}=i.value;h<=719?(c.value=!0,d(),u=setInterval(()=>{a.value=(a.value+1)%f.value.length},p)):(c.value=!1,d())}),ls(()=>{d()}),(h,p)=>f.value.length?(m(),D(Qs,{key:0,name:l(t).join("slide-next"),tag:"div",class:T([l(t).b(),l(t).join("wallpaper-outside"),"flx-wrap-between"]),"aria-label":l(n)("tk.homeBanner.featureLabel")},{default:O(()=>[(m(!0),C(Y,null,le(l(i).features,(g,v)=>et((m(),C("div",{class:T(l(t).e("feature__item")),key:v,role:"group","aria-labelledby":`feature-title-${v}`},[(m(),D(Be(g.link?"a":"div"),{href:l(Ee)(g.link??""),class:"flx-column-center hover-color","aria-label":g.title},{default:O(()=>[g.image?(m(),C("img",{key:0,class:"feature-img",src:l(Ee)(g.image),alt:g.title,"aria-label":g.title},null,8,BS)):A("v-if",!0),S("p",{id:`feature-title-${v}`,class:"feature-title"},W(g.title),9,NS),S("p",VS,W(g.details),1)]),_:2},1032,["href","aria-label"]))],10,FS)),[[at,!c.value||a.value===v]])),128))]),_:1},8,["name","class","aria-label"])):A("v-if",!0)}}),f2=z({name:"HomeBannerWaves",__name:"HomeBannerWaves",setup(e){const t=ie("banner-waves");return(n,s)=>(m(),C("svg",{class:T(l(t).b()),xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 24 150 28",preserveAspectRatio:"none","shape-rendering":"auto"},[A("形状容器"),s[0]||(s[0]=S("defs",null,[S("path",{id:"gentle-wave",d:"M-160 44c30 0 58-18 88-18s 58 18 88 18 58-18 88-18 58 18 88 18 v44h-352z"})],-1)),A("组合波浪"),s[1]||(s[1]=E0('',1))],2))}});const DS=["aria-label"],Rd="full-img-nav-bar";var RS=z({name:"HomeBanner",__name:"index",props:{disabled:{type:Boolean,default:!1}},setup(e){const t=ie("banner"),{t:n}=ge(),{getTeekConfigRef:s}=fe(),{frontmatter:o}=Ae(),i=s("banner",{bgStyle:"pure",imgWaves:!0,textColor:"#ffffff",titleFontSize:"3.2rem",descFontSize:"1.4rem",features:o.value.tk?.features||[]}),r=s("bodyBgImg",{imgSrc:"",bannerStyle:"full"}),a=F(()=>{const{bgStyle:v}=i.value,{imgSrc:k,bannerStyle:b}=r.value,w=v==="pure",y=v==="partImg",_=v==="fullImg",x=!!k;return{isBannerPureBgStyle:w,isBannerPartImgBgStyle:y,isBannerFullImgBgStyle:_,isBodyImgBgStyle:x,isBodyPartImgBgStyle:x&&b==="part",isBodyFullImgBgStyle:x&&b==="full"}}),c=()=>{const v=t.cssVarName("banner-title-text"),k=t.cssVarName("banner-desc-text"),b=t.cssVarName("banner-text-color"),{titleFontSize:w,descFontSize:y,textColor:_}=i.value;return{[v]:w,[k]:y,[b]:_}},u=j(null),f=(v=!0)=>{const k=document.querySelector(".VPNavBar");v?k?.classList.add(Rd):k?.classList.remove(Rd)},d=async()=>{if(!u.value||e.disabled)return;const v=a.value;if(!v.isBannerFullImgBgStyle&&!v.isBodyFullImgBgStyle)return;await Oe();const k=v.isBodyImgBgStyle?0:100,b=document.documentElement.scrollTop+ke.disabled,()=>f(!e.disabled)),be(()=>{(!e.disabled&&a.value.isBannerFullImgBgStyle||a.value.isBodyFullImgBgStyle)&&(d(),Ve(window,"scroll",d))}),cn(()=>{f(!1)});const h=F(()=>{const{isBannerPureBgStyle:v,isBannerPartImgBgStyle:k,isBannerFullImgBgStyle:b,isBodyPartImgBgStyle:w,isBodyFullImgBgStyle:y}=a.value;return w?t.is("part-img"):y?t.is("full-img"):v?t.is("pure"):k?t.is("part-img"):b?t.is("full-img"):""}),p={bodyPart:{el:"div",props:{class:"body-pure"}},bodyFull:{el:"div",props:{class:"body-full"}},bannerPure:{el:SS},bannerPartImg:{el:Dd},bannerFullImg:{el:Dd}},g=F(()=>{const{isBodyImgBgStyle:v}=a.value,{bgStyle:k}=i.value,{bannerStyle:b}=r.value,w=v?`body${Hf(b)}`:`banner${Hf(k)}`;return p[w]});return(v,k)=>(m(),C(Y,null,[M(v.$slots,"teek-home-banner-before"),S("div",{ref_key:"bannerRef",ref:u,class:T([l(t).b(),h.value]),style:Fe(c()),"aria-label":l(n)("tk.homeBanner.label")},[(m(),D(Be(g.value.el),Ge(Ze(g.value.props)),{default:O(()=>[S("div",{class:T([l(t).e("content"),{"no-feature":!l(i).features.length}])},[M(v.$slots,"teek-home-banner-content-before"),H(MS,null,Wt({_:2},[le(v.$slots,(b,w)=>({name:w,fn:O(y=>[M(v.$slots,w,Ge(Ze(y)))])}))]),1024),M(v.$slots,"teek-home-banner-content-after"),M(v.$slots,"teek-home-banner-feature-before"),H(OS),M(v.$slots,"teek-home-banner-feature-after")],2)]),_:3},16)),l(i).imgWaves&&a.value.isBannerFullImgBgStyle&&!a.value.isBodyImgBgStyle?(m(),D(f2,{key:0,"aria-label":l(n)("tk.homeBanner.wavesLabel")},null,8,["aria-label"])):A("v-if",!0)],14,DS),M(v.$slots,"teek-home-banner-after")],64))}});const HS=["aria-label"],zS=["href","target","aria-label"],jS=["innerHTML"],US=["aria-label"],WS=["innerHTML"],qS=["innerHTML"],KS={key:0},YS=["aria-label","aria-disabled"],GS=["aria-label","aria-disabled"];var Vo=z({name:"PageCard",__name:"index",props:$n({title:{default:""},titleLink:{},titleClick:{type:Function},page:{type:Boolean,default:!1},pageSize:{default:4},total:{default:0},autoPage:{type:Boolean,default:!1},pageSpeed:{default:4e3}},{modelValue:{default:1},modelModifiers:{}}),emits:$n(["pagination"],["update:modelValue"]),setup(e,{emit:t}){const n=ie("page-card"),s=n.join("pointer"),{t:o}=ge(),i=t,r=Jt(e,"modelValue"),a=Math.ceil(e.total/e.pageSize),c=e.total!==0&&a!==1,u=j(n.join("scroll")),f=(v,k)=>{i("pagination",v,k),u.value=n.join(`slide-${k}`),e.page&&e.autoPage&&h();const w=(r.value%a+v)%a;w<1?r.value=a+w:w>a?r.value=1:r.value=w};let d;const h=()=>{p(),e.pageSpeed>0&&(d=setTimeout(()=>{f(1,"next")},e.pageSpeed))},p=()=>{d&&(clearTimeout(d),d=null)};be(()=>{e.page&&e.autoPage&&h()}),cn(()=>{e.page&&e.autoPage&&p()});const g=v=>v.replace(/<[^>]*>/g,"").trim();return(v,k)=>(m(),C("div",{class:T(`${l(n).b()} card`),"aria-label":l(o)("tk.pageCard.label")},[e.title?(m(),C("div",{key:0,class:T(`${l(n).e("header")} flx-justify-between`)},[M(v.$slots,"title",{},()=>[e.titleLink?(m(),C("a",{key:0,href:l(Ee)(e.titleLink),target:l(Yc)(e.titleLink)?"_blank":"_self","aria-label":g(e.title)},[S("span",{class:"title flx-align-center",innerHTML:e.title},null,8,jS)],8,zS)):e.titleClick?(m(),C("a",{key:1,onClick:k[0]||(k[0]=()=>e.titleClick()),class:T(l(s)),"aria-label":g(e.title)},[S("span",{class:"title flx-align-center",innerHTML:e.title},null,8,WS)],10,US)):(m(),C("span",{key:2,class:"title flx-align-center",innerHTML:e.title},null,8,qS))]),M(v.$slots,"page",Ge(Ze({pagination:f})),()=>[e.page?(m(),C("div",KS,[M(v.$slots,"page-left",Ge(Ze({pagination:f})),()=>[S("span",{class:T(["page-button",l(c)?l(s):"disabled"]),onClick:k[1]||(k[1]=b=>f(-1,"prev")),role:"button","aria-label":l(o)("tk.pageCard.prev"),"aria-disabled":!l(c)},[H(l(de),{icon:l(Xc),size:14,"aria-hidden":"true"},null,8,["icon"])],10,YS)]),M(v.$slots,"page-right",Ge(Ze({pagination:f})),()=>[S("span",{class:T(["page-button",l(c)?l(s):"disabled"]),onClick:k[2]||(k[2]=b=>f(1,"next")),role:"button","aria-label":l(o)("tk.pageCard.next"),"aria-disabled":!l(c)},[H(l(de),{icon:l(Qc),size:14,"aria-hidden":"true"},null,8,["icon"])],10,GS)])])):A("v-if",!0)])],2)):A("v-if",!0),M(v.$slots,"default",Ge(Ze({transitionName:u.value,startAutoPage:h,closeAutoPage:p})))],10,HS))}});const JS=["src","alt","srcSet"],XS={key:2};var Za=z({name:"Avatar",__name:"index",props:{size:{},shape:{default:"circle"},icon:{},iconSize:{},src:{},alt:{},srcSet:{},fit:{default:"cover"},bgColor:{},textColor:{},textSize:{},text:{}},emits:["error"],setup(e,{emit:t}){const n=t,s=ie("avatar"),o=j(!1),i=F(()=>{const f=[s.b()];return Je(e.size)&&f.push(s.m(e.size)),e.icon&&f.push(s.m("icon")),e.shape&&f.push(s.m(e.shape)),f}),r=F(()=>({[s.cssVarName("avatar-size")]:sn(e.size),[s.cssVarName("avatar-bg-color")]:e.bgColor,[s.cssVarName("avatar-text-color")]:e.textColor,[s.cssVarName("avatar-text-size")]:sn(e.textSize),[s.cssVarName("avatar-icon-size")]:sn(e.iconSize)})),a=F(()=>({objectFit:e.fit}));te(()=>e.src,()=>o.value=!1);const c=f=>{o.value=!0,n("error",f)},u=f=>{if(/^[\u4e00-\u9fa5]+$/.test(f))return f.charAt(0);const h=f.split(/\s+/).filter(p=>p.length>0);return h.length>=2?h.slice(0,2).map(p=>p.charAt(0).toUpperCase()).join(""):h.length===1?f.slice(0,2).toUpperCase():""};return(f,d)=>(m(),C("span",{class:T(i.value),style:Fe(r.value)},[(e.src||e.srcSet)&&!o.value?(m(),C("img",{key:0,src:e.src,alt:e.alt,srcSet:e.srcSet,style:Fe(a.value),onError:c},null,44,JS)):e.icon?(m(),D(l(de),{key:1,icon:e.icon},null,8,["icon"])):e.text?(m(),C("span",XS,W(u(e.text)),1)):M(f.$slots,"default",{key:3})],6))}});const QS=["aria-label"],ZS=["href","title","aria-label"],eT=["aria-label"],tT={class:"name"},nT={class:"slogan"};var sT=z({name:"HomeMyCard",__name:"index",setup(e){const t=ie("my"),{t:n}=ge(),{getTeekConfigRef:s}=fe(),o=s("blogger",{shape:"square",circleBgMask:!0}),i=s("social",[]),r=F(()=>o.value.shape.replace(/-.*$/,"")),a=F(()=>r.value==="circle"&&!!o.value.circleBgImg),c=F(()=>({backgroundImage:`url(${Ee(o.value.circleBgImg)})`})),u=F(()=>({color:o.value.color})),f=F(()=>{const d=o.value.status?.icon;return d?Yc(d)||d.startsWith("/"):!1});return(d,h)=>l(o).name?(m(),D(l(Vo),{key:0,class:T([l(t).b(),l(t).is("circle-bg",a.value)]),style:Fe(u.value),"aria-label":l(n)("tk.myCard.label")},{default:O(()=>[a.value?(m(),C("div",{key:0,class:T([l(t).em("avatar__circle","bg"),l(t).is("mask",l(o).circleBgMask)]),style:Fe(c.value)},null,6)):A("v-if",!0),S("div",{class:T(`${l(t).e("avatar")} ${l(o).shape} flx-center`)},[S("div",null,[l(o).avatar?(m(),D(l(Za),{key:0,src:l(Ee)(l(o).avatar),size:l(o).shape==="square"?"100%":l(o).circleSize??100,shape:r.value,"bg-color":"transparent",alt:l(n)("tk.myCard.avatarAlt"),title:l(n)("tk.myCard.avatarTitle"),"aria-hidden":"true"},null,8,["src","size","shape","alt","title"])):(m(),D(l(Za),{key:1,size:l(o).circleSize??100,shape:r.value,text:l(o).name,"text-size":50,"bg-color":l(t).cssVar("theme-color"),"aria-hidden":"true"},null,8,["size","shape","text","bg-color"])),l(o).status?.icon&&r.value?.startsWith("circle")?(m(),D(l(Za),{key:2,src:f.value?l(o).status.icon:"",text:l(o).status.icon,size:l(o).status.size??26,"icon-size":l(o).status.size??26,"text-size":l(o).status.size??26,title:l(o).status.title,circle:"","bg-color":"transparent",class:"avatar-sticker","aria-hidden":"true"},null,8,["src","text","size","icon-size","text-size","title"])):A("v-if",!0)])],2),l(i).length?(m(),C("div",{key:1,class:T(`${l(t).e("icons")} flx-justify-around`),"aria-label":l(n)("tk.myCard.socialLabel")},[(m(!0),C(Y,null,le(l(i),(p,g)=>(m(),C("a",{key:g,href:p.link&&l(Ee)(p.link),title:p.name,target:"_blank","aria-label":p.name},[p.icon?(m(),D(l(de),{key:0,iconType:p.iconType,icon:p.icon,size:"20px",hover:"",imgAlt:p.imgAlt,"aria-hidden":"true"},null,8,["iconType","icon","imgAlt"])):A("v-if",!0)],8,ZS))),128))],10,QS)):A("v-if",!0),S("div",{class:T(l(t).e("blogger")),"aria-label":l(n)("tk.myCard.bloggerLabel")},[S("h3",tT,W(l(o).name),1),S("span",nT,W(l(o).slogan),1)],10,eT)]),_:1},8,["class","style","aria-label"])):A("v-if",!0)}});const oT=["aria-label"],iT=["href"],rT={class:"date"},aT=["aria-label"];var lT=z({name:"HomeTopArticleCard",__name:"index",setup(e){const t=ie("top-article"),{t:n}=ge(),{getTeekConfigRef:s}=fe(),o=Pn(),i=s("topArticle",{limit:4,title:n("tk.topArticleCard.title",{icon:Wf}),emptyLabel:n("tk.topArticleCard.emptyLabel"),autoPage:!1,pageSpeed:4e3,dateFormat:"yyyy-MM-dd hh:mm:ss"}),r=F(()=>o.value.sortPostsByDateAndSticky.filter(b=>b.frontmatter.top)?.map((b,w)=>({...b,num:w+1}))),a=j(1),c=F(()=>{const{limit:k}=i.value,b=a.value;return r.value.slice((b-1)*k,b*k)}),u=k=>{const b=i.value.dateFormat;return ht(b)?b(k||""):pi(k||new Date,b)},f=F(()=>{const{title:k}=i.value;return ht(k)?k(Wf):k}),d=Xh(),h=j([]),p=(k,b)=>({[t.cssVarName("num-bg-color")]:d.value[k%d.value.length].text,top:`calc(${b} * (calc(${t.cssVar("home-top-article-gap")} + ${h.value?.[b]?.getBoundingClientRect().height||0}px)))`}),g=jn(),v=()=>{i.value.titleClick?.(g)};return(k,b)=>(m(),D(l(Vo),{page:"",modelValue:a.value,"onUpdate:modelValue":b[0]||(b[0]=w=>a.value=w),pageSize:l(i).limit,total:r.value.length,title:f.value,titleClick:l(i).titleClick?v:void 0,autoPage:l(i).autoPage,pageSpeed:l(i).pageSpeed,class:T(l(t).b()),"aria-label":l(n)("tk.topArticleCard.label")},{default:O(({transitionName:w})=>[r.value.length?(m(),D(Qs,{key:0,name:w,tag:"ul",mode:"out-in",class:T(`${l(t).e("list")} flx-column`),"aria-label":l(n)("tk.topArticleCard.listLabel")},{default:O(()=>[(m(!0),C(Y,null,le(c.value,(y,_)=>(m(),C("li",{ref_for:!0,ref_key:"itemRefs",ref:h,key:y.num,class:T(l(t).e("list__item")),style:Fe(p(y.num-1,_)),"aria-label":y.title},[S("span",{class:T(["num",{sticky:y.frontmatter.sticky}])},W(y.num),3),S("div",{class:T(l(t).e("list__item__info"))},[S("a",{href:y.url&&l(Ee)(y.url),class:"hover-color flx-align-center"},[H(l(Fi),{post:y,"title-tag-props":{position:"right",size:"mini"}},null,8,["post"])],8,iT),S("div",rT,W(u(y.date)),1)],2)],14,oT))),128))]),_:1},8,["name","class","aria-label"])):(m(),C("div",{key:1,class:T(l(t).m("empty")),"aria-label":l(i).emptyLabel},W(l(i).emptyLabel),11,aT))]),_:1},8,["modelValue","pageSize","total","title","titleClick","autoPage","pageSpeed","class","aria-label"]))}});const Iu=Symbol("postDataUpdate"),cT=["onClick","aria-label"],uT={class:"sle"},fT=["href","aria-label"],dT=["aria-label"],tr="category";var hT=z({name:"HomeCategoryCard",__name:"index",props:{categoriesPage:{type:Boolean,default:!1}},setup(e){const t=ie("category"),{t:n}=ge(),{getTeekConfigRef:s}=fe(),{categoryPath:o}=Li(),i=s("category",{path:"/categories",pageTitle:n("tk.categoryCard.pageTitle",{icon:Gi}),homeTitle:n("tk.categoryCard.homeTitle",{icon:Gi}),emptyLabel:n("tk.categoryCard.emptyLabel"),moreLabel:n("tk.categoryCard.moreLabel"),limit:5,autoPage:!1,pageSpeed:4e3}),r=Pn(),a=j(1),c=F(()=>r.value.groupCards.categories),u=F(()=>{const{limit:k}=i.value,b=c.value,w=a.value;return e.categoriesPage?b:b.slice((w-1)*k,w*k)}),f=F(()=>{const{pageTitle:k,homeTitle:b}=i.value,w=ht(k)?k(Gi):k,y=ht(b)?b(Gi):b;return{pt:w,ht:y}}),d=qe(Iu,()=>{}),h=jn(),p=j(""),g=(k="")=>{const{pathname:b,searchParams:w}=new URL(window.location.href),y=Ee(o.value),_=y===b;w.delete(js),w.append(js,"1"),w.delete(tr),k&&w.append(tr,k);const x=k?`?${w.toString()}`:"";if(!(_&&p.value===k)){if(p.value=k,!_)return h.go(y+x);window.history.pushState({},"",b+x),d()}};be(()=>{const{searchParams:k}=new URL(window.location.href),b=k.get(tr);b&&(p.value=b)}),te(()=>e.categoriesPage,()=>{if(!e.categoriesPage){p.value="";return}const{searchParams:k}=new URL(window.location.href),b=k.get(tr);b&&p.value!==b&&(p.value=b)});const v=j([]);return(k,b)=>(m(),D(l(Vo),{page:!e.categoriesPage,modelValue:a.value,"onUpdate:modelValue":b[0]||(b[0]=w=>a.value=w),pageSize:l(i).limit,total:c.value.length,title:f.value[e.categoriesPage?"pt":"ht"],titleClick:g,autoPage:l(i).autoPage,pageSpeed:l(i).pageSpeed,class:T([l(t).b(),l(t).is("page",e.categoriesPage)]),"aria-label":l(n)("tk.categoryCard.label")},{default:O(({transitionName:w})=>[c.value.length?(m(),D(Qs,{key:0,name:w,tag:"div",mode:"out-in",class:T(`${l(t).e("list")} flx-column`),"aria-label":l(n)("tk.categoryCard.listLabel")},{default:O(()=>[(m(!0),C(Y,null,le(u.value,(y,_)=>(m(),C("a",{ref_for:!0,ref_key:"itemRefs",ref:v,key:y.name,onClick:x=>g(y.name),class:T([{active:y.name===p.value},"hover-color"]),style:Fe(`top: ${_*v.value?.[_]?.getBoundingClientRect().height||0}px`),"aria-label":y.name},[S("span",uT,W(y.name),1),S("span",null,W(y.length),1)],14,cT))),128)),!e.categoriesPage&&l(i).limita.value.groupCards.tags),f=F(()=>{const{limit:b}=i.value,w=u.value,y=o.value;return e.tagsPage?w:w.slice((y-1)*b,y*b)}),d=F(()=>{const{pageTitle:b,homeTitle:w}=i.value,y=ht(b)?b(Ji):b,_=ht(w)?w(Ji):w;return{pt:y,ht:_}}),h=b=>{const w=c.value,y=w[b%w.length];return{[t.cssVarName("home-tag-bg-color")]:y.bg,backgroundColor:y.bg,color:y.text,borderColor:y.border}},p=qe(Iu,()=>{}),g=jn(),v=j(""),k=(b="")=>{const{pathname:w,searchParams:y}=new URL(window.location.href),_=Ee(r.value),x=_===w;y.delete(js),y.append(js,"1"),y.delete(nr),b&&y.append(nr,b);const L=b?`?${y.toString()}`:"";if(!(x&&v.value===b)){if(v.value=b,!x)return g.go(_+L);window.history.pushState({},"",w+L),p()}};return be(()=>{const{searchParams:b}=new URL(window.location.href),w=b.get(nr);w&&(v.value=w)}),te(()=>e.tagsPage,()=>{if(!e.tagsPage){v.value="";return}const{searchParams:b}=new URL(window.location.href),w=b.get(nr);w&&v.value!==w&&(v.value=w)}),(b,w)=>(m(),D(l(Vo),{page:!e.tagsPage,modelValue:o.value,"onUpdate:modelValue":w[0]||(w[0]=y=>o.value=y),pageSize:l(i).limit,total:u.value.length,title:d.value[e.tagsPage?"pt":"ht"],titleClick:k,autoPage:l(i).autoPage,pageSpeed:l(i).pageSpeed,class:T([l(t).b(),l(t).is("page",e.tagsPage)]),"aria-label":l(n)("tk.tagCard.label")},{default:O(({transitionName:y})=>[u.value.length?(m(),D(Qs,{key:0,name:y,tag:"div",mode:"out-in",class:T(l(t).e("list")),"aria-label":l(n)("tk.tagCard.listLabel")},{default:O(()=>[(m(!0),C(Y,null,le(f.value,(_,x)=>(m(),C("a",{key:_.name,style:Fe(h(x)),onClick:L=>k(_.name),class:T([{active:_.name===v.value},l(t).join("pointer")]),"aria-label":_.name},[S("span",null,W(_.name),1),S("span",mT,W(_.length),1)],14,pT))),128)),!e.tagsPage&&l(i).limit(m(),C("a",{href:e.item.link&&l(Ee)(e.item.link),target:"_blank",class:"hover-color flx-align-center","aria-label":e.item.name},[S("div",kT,[S("img",{src:e.item.avatar&&l(Ee)(e.item.avatar),class:"avatar",alt:e.item.alt||e.item.name,"aria-hidden":"true",onLoad:n[0]||(n[0]=s=>s.target?.classList.add("loaded")),onError:n[1]||(n[1]=s=>s.target?.classList.add("loaded"))},null,40,wT)]),S("div",{class:T(e.ns.e("list__item__info"))},[S("div",{class:"friend-name sle",title:e.item.name},W(e.item.name),9,CT),S("div",{class:"friend-desc sle",title:e.item.desc},W(e.item.desc),9,_T)],2)],8,bT))}});const ST=["aria-label"];var TT=z({name:"HomeFriendLinkCard",__name:"index",setup(e){const t=ie("friend-link"),{t:n}=ge(),{getTeekConfigRef:s}=fe(),o=s("friendLink",{list:[],limit:4,title:n("tk.friendLinkCard.title",{icon:jf}),emptyLabel:n("tk.friendLinkCard.emptyLabel"),autoScroll:!1,scrollSpeed:2500,autoPage:!1,pageSpeed:4e3,titleClick:void 0}),{data:i,start:r,stop:a}=D9(o.value.list,5,{intervalTime:o.value.scrollSpeed}),c=j(1),u=F(()=>{const{list:v,limit:k,autoScroll:b}=o.value;if(b)return i.value;const w=c.value;return v.slice((w-1)*k,w*k)}),f=F(()=>{const{title:v}=o.value;return ht(v)?v(jf):v});be(()=>{o.value.autoScroll&&r()});const d=j([]),h=v=>{if(o.value.autoScroll)return{};const k=d.value?.[v]?.getBoundingClientRect();return{top:`calc(${v} * (calc(${t.cssVar("home-friend-link-gap")} + ${k?.height||0}px)))`}},p=jn(),g=()=>{o.value.titleClick?.(p)};return(v,k)=>(m(),D(l(Vo),{page:!l(o).autoScroll,modelValue:c.value,"onUpdate:modelValue":k[0]||(k[0]=b=>c.value=b),pageSize:l(o).limit,total:l(o).list.length,title:f.value,titleClick:l(o).titleClick?g:void 0,autoPage:l(o).autoPage,pageSpeed:l(o).pageSpeed,class:T(l(t).b()),"aria-label":l(n)("tk.friendLinkCard.label")},{default:O(({transitionName:b,startAutoPage:w,closeAutoPage:y})=>[l(o).list.length?(m(),D(Qs,{key:0,name:b,tag:"ul",mode:"out-in",class:T(`${l(t).e("list")} flx-column`),onMouseenter:_=>l(o).autoScroll?l(a)():l(o).autoPage?y():()=>{},onMouseleave:_=>l(o).autoScroll?l(r)():l(o).autoPage?w():()=>{},"aria-label":l(n)("tk.friendLinkCard.listLabel")},{default:O(()=>[l(o).autoScroll?(m(!0),C(Y,{key:0},le(u.value,(_,x)=>(m(),C("li",{key:_.name,class:T(l(t).e("list__item")),style:Fe(h(x))},[H(Hd,{item:_,ns:l(t)},null,8,["item","ns"])],6))),128)):(m(!0),C(Y,{key:1},le(u.value,(_,x)=>(m(),C("li",{ref_for:!0,ref_key:"itemRefs",ref:d,key:_.name,class:T(l(t).e("list__item")),style:Fe(h(x))},[H(Hd,{item:_,ns:l(t)},null,8,["item","ns"])],6))),128))]),_:1},8,["name","class","onMouseenter","onMouseleave","aria-label"])):(m(),C("div",{key:1,class:T(l(t).m("empty")),"aria-label":l(o).emptyLabel},W(l(o).emptyLabel),11,ST))]),_:1},8,["page","modelValue","pageSize","total","title","titleClick","autoPage","pageSpeed","class","aria-label"]))}});const ET=["innerHTML"],xT=["innerHTML"];var AT=z({name:"HomeDocAnalysisCard",__name:"index",setup(e){const t=ie("doc-analysis"),{t:n}=ge(),{getTeekConfigRef:s}=fe(),{theme:o}=Ae(),i=Is(),r=s("docAnalysis",{createTime:void 0,title:n("tk.docAnalysisCard.title",{icon:zf}),statistics:{},overrideInfo:[],appendInfo:[]}),a=F(()=>o.value.docAnalysisInfo||{}),c=F(()=>{const{title:L}=r.value;return ht(L)?L(zf):L}),u=F(()=>O7(r.value.createTime||Rf())),f=Pn(),d=F(()=>{const L=f.value.sortPostsByDate;let V=0,E=0;const I=new Date(Rf());for(const P of L){if(!P.date)continue;const N=new Date(P.date);if(N.getTime()>I.getTime()-10080*60*1e3&&V++,N.getTime()>I.getTime()-720*60*60*1e3)E++;else return{weekAddNum:V,monthAddNum:E}}return{weekAddNum:V,monthAddNum:E}}),h=L=>L<1e3?L+"":L<1e6?Math.round(L/100)/10+"k":Math.round(L/1e4)/10+"w",p=F(()=>({url:"",provider:"",siteView:!0,iteration:!1,pageIteration:2e3,permalink:!0,...r.value.statistics})),g=F(()=>!!p.value.provider&&p.value.siteView),{router:v}=i,{sitePv:k,siteUv:b,isGet:w,request:y}=Rh(!1,p.value);te(g,L=>{L&&y()}),te(v.route,()=>{g.value&&(p.value.permalink&&v.state?.permalinkPlugin?Oe(y):y())},{immediate:!0});const _=F(()=>{const{appendInfo:L}=r.value;return ht(L)?L():L}),x=F(()=>{const{createTime:L,overrideInfo:V}=r.value,{fileList:E=[],totalFileWords:I,lastCommitTime:P}=a.value,N=[{key:"totalPosts",label:n("tk.docAnalysisCard.totalPosts"),originValue:E.length,value:`${E.length} ${n("tk.docAnalysisCard.fileUnit")}`},{key:"weekAddNum",label:n("tk.docAnalysisCard.weekAddNum"),originValue:d.value?.weekAddNum,value:`${d.value?.weekAddNum} ${n("tk.docAnalysisCard.fileUnit")}`},{key:"monthAddNum",label:n("tk.docAnalysisCard.monthAddNum"),originValue:d.value?.monthAddNum,value:`${d.value?.monthAddNum} ${n("tk.docAnalysisCard.fileUnit")}`},{key:"runtime",label:n("tk.docAnalysisCard.runtime"),originValue:L,value:`${u.value===0?n("tk.docAnalysisCard.runtimeLess"):`${u.value} ${n("tk.docAnalysisCard.runtimeUnit")}`}`},{key:"totalWordCount",label:n("tk.docAnalysisCard.totalWordCount"),originValue:I,value:`${h(I)} ${n("tk.docAnalysisCard.wordCountUnit")}`},{key:"lastActiveTime",label:n("tk.docAnalysisCard.lastActiveTime"),originValue:P,value:V7(P)},{key:"viewCount",label:n("tk.docAnalysisCard.viewCount"),originValue:k.value,value:w.value?`${k.value} ${n("tk.docAnalysisCard.viewCountUnit")}`:"Get...",show:g.value},{key:"visitCount",label:n("tk.docAnalysisCard.visitCount"),originValue:b.value,value:w.value?`${b.value} ${n("tk.docAnalysisCard.visitCountUnit")}`:"Get...",show:g.value},..._.value];return V.length&&N.forEach($=>{const U=V.find(q=>q.key===$.key);U&&($.label=U.label||$.label,$.value=U.value?U.value($.originValue||"",$.value):$.value,$.show=U.show!==!1)}),N});return(L,V)=>(m(),D(l(Vo),{title:c.value,class:T(l(t).b()),"aria-label":l(n)("tk.docAnalysisCard.label")},{default:O(()=>[(m(!0),C(Y,null,le(x.value,E=>(m(),C(Y,{key:E.key},[E.show!==!1?(m(),C("div",{key:0,class:T(l(t).e("item"))},[S("span",{innerHTML:E.label},null,8,ET),S("span",{innerHTML:E.value},null,8,xT)],2)):A("v-if",!0)],64))),128))]),_:1},8,["title","class","aria-label"]))}}),$T=z({name:"HomeCardList",__name:"index",setup(e){const t=ie("home-card-list"),{getTeekConfigRef:n}=fe(),s=n(null,{}),o=F(()=>{const h=s.value.homeCardSort||[];return["my",...new Set([...h,"topArticle","category","tag","friendLink","docAnalysis"])]}),{isHomePage:i,isCategoriesPage:r,isTagsPage:a}=iu(),c=F(()=>{const{topArticle:h,category:p,tag:g,docAnalysis:v,friendLink:k}=s.value,b=i.value,w=r.value,y=a.value;return{my:{el:sT,show:b,slot:"teek-home-card-my"},topArticle:{el:lT,show:b&&h?.enabled!==!1,slot:"teek-home-card-top-article"},category:{el:hT,props:{categoriesPage:w},show:(b||w)&&p?.enabled!==!1,slot:"teek-home-card-category"},tag:{el:yT,props:{tagsPage:y},show:(b||y)&&g?.enabled!==!1,slot:"teek-home-card-tag"},docAnalysis:{el:AT,show:b&&v?.enabled!==!1,slot:"teek-home-card-doc-analysis"},friendLink:{el:TT,show:b&&k?.enabled!==!1,slot:"teek-home-card-friend-link"}}}),u=_a(h=>h.card),f=j(null),{start:d}=Ca(f,!1);return be(()=>{u.value&&d()}),(h,p)=>(m(),C("div",{class:T([l(t).b(),"flx-column"])},[M(h.$slots,"teek-home-card-before"),M(h.$slots,"teek-home-card",{homeCard:o.value},()=>[(m(!0),C(Y,null,le(o.value,g=>(m(),C(Y,{key:g},[A(" 使用淡入动画 "),l(u)?(m(),C(Y,{key:0},[h.$slots[`${c.value[g]?.slot}-before`]?(m(),C("div",{key:0,ref_for:!0,ref_key:"cardListInstance",ref:f},[M(h.$slots,`${c.value[g]?.slot}-before`)],512)):A("v-if",!0),S("div",{ref_for:!0,ref_key:"cardListInstance",ref:f},[M(h.$slots,c.value[g]?.slot,{},()=>[c.value[g]?.show?(m(),D(Be(c.value[g]?.el),nt({key:0,ref_for:!0},c.value[g]?.props),null,16)):A("v-if",!0)])],512),h.$slots[`${c.value[g]?.slot}-after`]?(m(),C("div",{key:1,ref_for:!0,ref_key:"cardListInstance",ref:f},[M(h.$slots,`${c.value[g]?.slot}-after`)],512)):A("v-if",!0)],64)):(m(),C(Y,{key:1},[A(" 不使用淡入动画 "),c.value[g]?.slot?M(h.$slots,`${c.value[g]?.slot}-before`,{key:0}):A("v-if",!0),c.value[g]?.slot?M(h.$slots,c.value[g]?.slot,{key:1},()=>[c.value[g]?.show?(m(),D(Be(c.value[g]?.el),nt({key:0,ref_for:!0},c.value[g]?.props),null,16)):A("v-if",!0)]):A("v-if",!0),c.value[g]?.slot?M(h.$slots,`${c.value[g]?.slot}-after`,{key:2}):A("v-if",!0)],64))],64))),128))]),M(h.$slots,"teek-home-card-after")],2))}});const LT=["aria-label"],IT={key:0},PT=["aria-label"],MT=["aria-label"];var FT=z({name:"Home",__name:"index",setup(e){const t=ie("home"),{t:n}=ge(),{isHomePage:s}=iu(),{getTeekConfigRef:o}=fe(),i=o(null,{teekHome:!0,homeCardListPosition:"right",banner:{},wallpaper:{},bodyBgImg:{}}),r=j(null);In(Iu,()=>r.value?.updateData());const a=j(!1);return(c,u)=>(m(),C("div",{class:T(l(t).b()),role:"main","aria-label":l(n)("tk.home.label")},[l(s)&&(l(i).banner.enabled??!0)?et((m(),C("div",IT,[H(l(RS),{disabled:a.value},Wt({_:2},[le(c.$slots,(f,d)=>({name:d,fn:O(h=>[M(c.$slots,d,Ge(Ze(h)))])}))]),1032,["disabled"])],512)),[[at,!a.value]]):A("v-if",!0),S("div",{class:T([l(t).e("content"),l(t).join("wallpaper-outside"),"flx-start-justify-center"])},[S("div",{class:T(l(t).e("content__post")),"aria-label":l(n)("tk.home.postLabel")},[M(c.$slots,"teek-home-post-before"),H(l(CS),{modelValue:a.value,"onUpdate:modelValue":u[0]||(u[0]=f=>a.value=f),ref_key:"homePostListInstance",ref:r},Wt({_:2},[le(c.$slots,(f,d)=>({name:d,fn:O(h=>[M(c.$slots,d,Ge(Ze(h)))])}))]),1032,["modelValue"]),M(c.$slots,"teek-home-post-after")],10,PT),l(i).homeCardListPosition?(m(),C("div",{key:0,class:T([l(t).e("content__info"),l(i).homeCardListPosition==="left"?l(t).is("left"):l(t).is("right")]),"aria-label":l(n)("tk.home.cardLabel")},[H(l($T),null,Wt({_:2},[le(c.$slots,(f,d)=>({name:d,fn:O(h=>[M(c.$slots,d,Ge(Ze(h)))])}))]),1024)],10,MT)):A("v-if",!0)],2),l(i).wallpaper.enabled&&(l(i).banner.bgStyle==="fullImg"||l(i).bodyBgImg.imgSrc)?(m(),D(l(P_),{key:1})):A("v-if",!0)],10,LT))}});const BT=["src","alt"],NT=["aria-label"],VT={class:"name"},OT={class:"slogan"};var DT=z({name:"HomeMyCardScreen",__name:"HomeMyCardScreen",setup(e){const t=ie("my-screen"),{t:n}=ge(),{getTeekConfigRef:s}=fe(),o=s("blogger",{}),i=Xt("(max-width: 960px)");return(r,a)=>l(i)&&l(o).name&&l(o).avatar&&l(o).slogan?(m(),C(Y,{key:0},[M(r.$slots,"teek-home-card-my-screen-before"),M(r.$slots,"teek-home-card-my-screen",{},()=>[S("div",{class:T(l(t).b())},[S("div",{class:T(l(t).e("avatar"))},[l(o).avatar?(m(),C("img",{key:0,src:l(Ee)(l(o).avatar),alt:l(n)("tk.myCard.avatarAlt")},null,8,BT)):A("v-if",!0)],2),S("div",{class:T(l(t).e("blogger")),"aria-label":l(n)("tk.myCard.bloggerLabel")},[S("h3",VT,W(l(o).name),1),S("span",OT,W(l(o).slogan),1)],10,NT)],2)]),M(r.$slots,"teek-home-card-my-screen-after")],64)):A("v-if",!0)}});const RT={key:0,class:"mask"};var HT=z({name:"BodyBgImage",__name:"index",setup(e){const t=ie("body-bg-image"),{getTeekConfigRef:n}=fe(),s=n("bodyBgImg",{imgSrc:void 0,imgOpacity:1,imgInterval:15e3,imgShuffle:!1,mask:!1,maskBg:"rgba(0, 0, 0, 0.2)"}),o=F(()=>{const u=s.value.imgSrc;return[ht(u)?u():u||[]].flat().map(f=>f&&Ee(f))}),{data:i,start:r,index:a}=tu(o,{timeout:s.value.imgInterval,shuffle:s.value.imgShuffle,onAfterUpdate:()=>{const u=(a.value+1)%o.value.length,f=o.value[u];if(f){const d=new Image;d.src=f}}});be(()=>{r()});const c=()=>{const{imgSrc:u,imgOpacity:f,maskBg:d}=s.value,h=t.cssVarName("body-bg-img"),p=t.cssVarName("body-bg-img-opacity"),g=t.cssVarName("body-mask-bg-color");return u?.length?{[h]:`url(${i.value}) center center / cover no-repeat`,[p]:f,[g]:Je(d)?d:`rgba(0, 0, 0, ${d})`}:{[h]:t.cssVar("bg-img-default")}};return(u,f)=>(m(),C("div",{class:T(l(t).b()),style:Fe(c())},[l(s).mask?(m(),C("div",RT)):A("v-if",!0)],6))}});const zT=["name","href","title","target","aria-label","aria-describedby"],jT={class:"sle"};var UT=z({name:"FooterGroup",__name:"index",setup(e){const t=ie("footer-group"),{getTeekConfigRef:n}=fe(),s=n("footerGroup",[]);return(o,i)=>l(s).length?(m(),C("div",{key:0,class:T(l(t).b())},[(m(!0),C(Y,null,le(l(s),(r,a)=>(m(),C("div",{key:(r.title||"")+a},[S("div",{class:T([l(t).e("title"),"flx-center"])},[r.icon?(m(),D(l(de),{key:0,icon:r.icon,style:{"margin-right":"4px"},"aria-hidden":"true"},null,8,["icon"])):A("v-if",!0),rt(" "+W(r.title),1)],2),S("ul",null,[(m(!0),C(Y,null,le(r.links||[],(c,u)=>(m(),C("li",{key:(c.name||"")+u,class:T([l(t).e("link")])},[c.icon?(m(),D(l(de),{key:0,icon:c.icon,style:{"margin-right":"4px"},"aria-hidden":"true"},null,8,["icon"])):A("v-if",!0),S("a",{name:c.name,href:c.link,title:c.name,target:l(Df)(c.link||"")?"_blank":"_self",class:"hover-color","aria-label":c.name,rel:"noopener noreferrer","aria-describedby":c.name},[S("span",jT,W(c.name),1),l(Df)(c.link||"")?(m(),D(l(de),{key:0,icon:l(l9),class:T(l(t).e("link__external-icon")),"aria-hidden":"true"},null,8,["icon","class"])):A("v-if",!0)],8,zT)],2))),128))])]))),128))],2)):A("v-if",!0)}}),WT="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKTWlDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVN3WJP3Fj7f92UPVkLY8LGXbIEAIiOsCMgQWaIQkgBhhBASQMWFiApWFBURnEhVxILVCkidiOKgKLhnQYqIWotVXDjuH9yntX167+3t+9f7vOec5/zOec8PgBESJpHmomoAOVKFPDrYH49PSMTJvYACFUjgBCAQ5svCZwXFAADwA3l4fnSwP/wBr28AAgBw1S4kEsfh/4O6UCZXACCRAOAiEucLAZBSAMguVMgUAMgYALBTs2QKAJQAAGx5fEIiAKoNAOz0ST4FANipk9wXANiiHKkIAI0BAJkoRyQCQLsAYFWBUiwCwMIAoKxAIi4EwK4BgFm2MkcCgL0FAHaOWJAPQGAAgJlCLMwAIDgCAEMeE80DIEwDoDDSv+CpX3CFuEgBAMDLlc2XS9IzFLiV0Bp38vDg4iHiwmyxQmEXKRBmCeQinJebIxNI5wNMzgwAABr50cH+OD+Q5+bk4eZm52zv9MWi/mvwbyI+IfHf/ryMAgQAEE7P79pf5eXWA3DHAbB1v2upWwDaVgBo3/ldM9sJoFoK0Hr5i3k4/EAenqFQyDwdHAoLC+0lYqG9MOOLPv8z4W/gi372/EAe/tt68ABxmkCZrcCjg/1xYW52rlKO58sEQjFu9+cj/seFf/2OKdHiNLFcLBWK8ViJuFAiTcd5uVKRRCHJleIS6X8y8R+W/QmTdw0ArIZPwE62B7XLbMB+7gECiw5Y0nYAQH7zLYwaC5EAEGc0Mnn3AACTv/mPQCsBAM2XpOMAALzoGFyolBdMxggAAESggSqwQQcMwRSswA6cwR28wBcCYQZEQAwkwDwQQgbkgBwKoRiWQRlUwDrYBLWwAxqgEZrhELTBMTgN5+ASXIHrcBcGYBiewhi8hgkEQcgIE2EhOogRYo7YIs4IF5mOBCJhSDSSgKQg6YgUUSLFyHKkAqlCapFdSCPyLXIUOY1cQPqQ28ggMor8irxHMZSBslED1AJ1QLmoHxqKxqBz0XQ0D12AlqJr0Rq0Hj2AtqKn0UvodXQAfYqOY4DRMQ5mjNlhXIyHRWCJWBomxxZj5Vg1Vo81Yx1YN3YVG8CeYe8IJAKLgBPsCF6EEMJsgpCQR1hMWEOoJewjtBK6CFcJg4Qxwicik6hPtCV6EvnEeGI6sZBYRqwm7iEeIZ4lXicOE1+TSCQOyZLkTgohJZAySQtJa0jbSC2kU6Q+0hBpnEwm65Btyd7kCLKArCCXkbeQD5BPkvvJw+S3FDrFiOJMCaIkUqSUEko1ZT/lBKWfMkKZoKpRzame1AiqiDqfWkltoHZQL1OHqRM0dZolzZsWQ8ukLaPV0JppZ2n3aC/pdLoJ3YMeRZfQl9Jr6Afp5+mD9HcMDYYNg8dIYigZaxl7GacYtxkvmUymBdOXmchUMNcyG5lnmA+Yb1VYKvYqfBWRyhKVOpVWlX6V56pUVXNVP9V5qgtUq1UPq15WfaZGVbNQ46kJ1Bar1akdVbupNq7OUndSj1DPUV+jvl/9gvpjDbKGhUaghkijVGO3xhmNIRbGMmXxWELWclYD6yxrmE1iW7L57Ex2Bfsbdi97TFNDc6pmrGaRZp3mcc0BDsax4PA52ZxKziHODc57LQMtPy2x1mqtZq1+rTfaetq+2mLtcu0W7eva73VwnUCdLJ31Om0693UJuja6UbqFutt1z+o+02PreekJ9cr1Dund0Uf1bfSj9Rfq79bv0R83MDQINpAZbDE4Y/DMkGPoa5hpuNHwhOGoEctoupHEaKPRSaMnuCbuh2fjNXgXPmasbxxirDTeZdxrPGFiaTLbpMSkxeS+Kc2Ua5pmutG003TMzMgs3KzYrMnsjjnVnGueYb7ZvNv8jYWlRZzFSos2i8eW2pZ8ywWWTZb3rJhWPlZ5VvVW16xJ1lzrLOtt1ldsUBtXmwybOpvLtqitm63Edptt3xTiFI8p0in1U27aMez87ArsmuwG7Tn2YfYl9m32zx3MHBId1jt0O3xydHXMdmxwvOuk4TTDqcSpw+lXZxtnoXOd8zUXpkuQyxKXdpcXU22niqdun3rLleUa7rrStdP1o5u7m9yt2W3U3cw9xX2r+00umxvJXcM970H08PdY4nHM452nm6fC85DnL152Xlle+70eT7OcJp7WMG3I28Rb4L3Le2A6Pj1l+s7pAz7GPgKfep+Hvqa+It89viN+1n6Zfgf8nvs7+sv9j/i/4XnyFvFOBWABwQHlAb2BGoGzA2sDHwSZBKUHNQWNBbsGLww+FUIMCQ1ZH3KTb8AX8hv5YzPcZyya0RXKCJ0VWhv6MMwmTB7WEY6GzwjfEH5vpvlM6cy2CIjgR2yIuB9pGZkX+X0UKSoyqi7qUbRTdHF09yzWrORZ+2e9jvGPqYy5O9tqtnJ2Z6xqbFJsY+ybuIC4qriBeIf4RfGXEnQTJAntieTE2MQ9ieNzAudsmjOc5JpUlnRjruXcorkX5unOy553PFk1WZB8OIWYEpeyP+WDIEJQLxhP5aduTR0T8oSbhU9FvqKNolGxt7hKPJLmnVaV9jjdO31D+miGT0Z1xjMJT1IreZEZkrkj801WRNberM/ZcdktOZSclJyjUg1plrQr1zC3KLdPZisrkw3keeZtyhuTh8r35CP5c/PbFWyFTNGjtFKuUA4WTC+oK3hbGFt4uEi9SFrUM99m/ur5IwuCFny9kLBQuLCz2Lh4WfHgIr9FuxYji1MXdy4xXVK6ZHhp8NJ9y2jLspb9UOJYUlXyannc8o5Sg9KlpUMrglc0lamUycturvRauWMVYZVkVe9ql9VbVn8qF5VfrHCsqK74sEa45uJXTl/VfPV5bdra3kq3yu3rSOuk626s91m/r0q9akHV0IbwDa0b8Y3lG19tSt50oXpq9Y7NtM3KzQM1YTXtW8y2rNvyoTaj9nqdf13LVv2tq7e+2Sba1r/dd3vzDoMdFTve75TsvLUreFdrvUV99W7S7oLdjxpiG7q/5n7duEd3T8Wej3ulewf2Re/ranRvbNyvv7+yCW1SNo0eSDpw5ZuAb9qb7Zp3tXBaKg7CQeXBJ9+mfHvjUOihzsPcw83fmX+39QjrSHkr0jq/dawto22gPaG97+iMo50dXh1Hvrf/fu8x42N1xzWPV56gnSg98fnkgpPjp2Snnp1OPz3Umdx590z8mWtdUV29Z0PPnj8XdO5Mt1/3yfPe549d8Lxw9CL3Ytslt0utPa49R35w/eFIr1tv62X3y+1XPK509E3rO9Hv03/6asDVc9f41y5dn3m978bsG7duJt0cuCW69fh29u0XdwruTNxdeo94r/y+2v3qB/oP6n+0/rFlwG3g+GDAYM/DWQ/vDgmHnv6U/9OH4dJHzEfVI0YjjY+dHx8bDRq98mTOk+GnsqcTz8p+Vv9563Or59/94vtLz1j82PAL+YvPv655qfNy76uprzrHI8cfvM55PfGm/K3O233vuO+638e9H5ko/ED+UPPR+mPHp9BP9z7nfP78L/eE8/sl0p8zAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAAQjSURBVHjaVNNZbFRlGIDh95w525zpdGa6TVtbykBbyiICxQY0AhYTJUCiiYqGqEEiJhKQmBg0ESPeeCGRENEYb4jhBr0gNQrRlCBiSgyLaSlSaKEs3Wemy+xnzuqFYdD/6rt6ku/N9wue55EcPwWArCgIgkx5ZRuYVxsnJ801Z05f3jY1MRnb/HxHV+uSph9RKq4mhkdwbZVgdQ2SHkPTwgj/h1QUWWi8/tfg/hM/XN/Y2zfaZnkSnuRDtLMsXhBOvrJtya/LlrcdMs1Qb1lVRQmSAEDAsU1kxpgamXp3y+azu1esreK9dyRqs9PIjkW6OsLx7lTV1ld/237s8HRV57MbnvO8CA+e9GCQFTk6Mza+4/0P+t9a9VSEI3uyTH/eR27aB2Ed31Q/Hx1sI6BHOPT13c5Frd0HW9p3HPUQEwAigJW9RDp+bstrOy981nVGLN/7RpHUV70YfXnEAtjxFPasxPDBQXatjzNTdOQXtg983H/51AFFy1KCIg2bNIdC+8270NwmUmelsXqSqHkDK5PDl8iCW0QcnEW+lqCjvcjQuMZ4YnQRTkotQUZu4GkjcfZNv19G011kXw4vayNYNvqCCvSVTciOgABgeuhBGwhgz5zbkI2ff7HUqJiNR2QktbbSYnBYYqbMT/ilKI4SIbT/GcRylbnvLmJ2X8N7tJ7rR8OE/BbliqEYea81WIotmOs02WFpc55Lf0f5/mSI3dsamOgxSX7ZjaALuBmB6M6FnB+S+POCwmOLk1QFFAqZyQWl1YrpiRZJLvDkygyC5NJ1XCax7xYNiTQVEYVIuUulayIcGeLkpw6WK7GuPY/fb2CkhleXIFFe8XPGaKBj9QxLW1Ik0bg8EuT2zRCJYZvZIYepe0EGbvi4bQUJVZhs2phADFYj+df0lBqJUnaekS4SUHXe3jrOnoE2PhSewHfRpfZGgcryIvfHdQruQlLo7Ns6QizqkJ31CIUlqwQJXuWUpDXj6qOsW32HT3YNImll9FwJsb4jyaLmWQ4fa6a+2sQw0ry8YZSiHcPxxXBtMfCv4XkUCrfliWs/fTE31rtTVfv9vsIorvQIniMhqXM4popVcJFVMHMpfMEaLPdxR1Tnna1b1vl6tGntpAjgCTNWONZyIFBR8Ydtr6EgrCI3VySfzZPLBDHyIq5gkpmzcOUmTGMF+bh7M9LYulfWzMmHBzk7Fpq9deWEYxjrtaCMXjWfstp6BCGNXZzBdYqYhogWqkMum4+oBVD0YnP63u/fFqbv1D+M7VSlBbmmK5uYaLYLYwslfwFVAyXQiOfcx3XyyGIM8DDn0lgWyGokHogu/0UJxpL/+f2e569s/CZQZ53OpzJr0+NXludUfb5jVdf7VUGXJUPIZast1S9PeII6jFDT5xMjFwO1S4c8zwTgnwEAxufYSzA67PMAAAAASUVORK5CYII=";const qT=["aria-label"],KT=["aria-label"],YT=["href","title","aria-label"],GT={key:1},JT=["innerHTML"],XT=["aria-label"],QT=["href","aria-label"],ZT={key:2},eE=["innerHTML"],tE=["innerHTML"];var nE=z({name:"FooterInfo",__name:"index",setup(e){const t=ie("footer-info"),{t:n}=ge(),{getTeekConfigRef:s}=fe(),o=s("footerInfo",{}),i=s("social",[]),r=F(()=>{const{theme:a={},copyright:c={},icpRecord:u,securityRecord:f}=o.value||{},d=[];a.show!==!1&&d.push({name:"Theme By Teek",icon:J7,link:"https://github.com/Kele-Bingtang/vitepress-theme-teek",...a});const{show:h=!0,createYear:p="",suffix:g=""}=c;return h&&d.push({name:`Copyright ${p?`${p}-`:""}${new Date().getFullYear()} ${g}`,icon:W7,...c}),u&&d.push({icon:K7,...u}),f&&d.push({icon:WT,iconType:"img",imgAlt:"Security Record",...f}),d});return(a,c)=>l(o)||l(i).length?(m(),C("div",{key:0,class:T([l(t).b(),l(t).join("wallpaper-outside")]),role:"contentinfo","aria-label":l(n)("tk.footerInfo.label")},[l(i).length?(m(),C("div",{key:0,class:T(`${l(t).e("icons")} flx-center`),role:"group","aria-label":l(n)("tk.footerInfo.socialLabel")},[(m(!0),C(Y,null,le(l(i),(u,f)=>(m(),C("a",{key:f,href:u.link&&l(Ee)(u.link),title:u.name,target:"_blank","aria-label":u.name},[u.icon?(m(),D(l(de),{key:0,iconType:u.iconType,icon:u.icon,size:"20px",color:"var(--vp-c-text-2)",hover:"",imgAlt:u.imgAlt,"aria-hidden":"true"},null,8,["iconType","icon","imgAlt"])):u.name?(m(),C("span",GT,W(u.name),1)):A("v-if",!0)],8,YT))),128))],10,KT)):A("v-if",!0),l(o)?(m(),C(Y,{key:1},[(m(!0),C(Y,null,le([l(o).topMessage||[]].flat(),(u,f)=>(m(),C("p",{key:f,innerHTML:u,class:"flx-wrap-justify-center"},null,8,JT))),128)),S("div",{class:T(`${l(t).e("list")} flx-wrap-justify-center`),role:"list","aria-label":l(n)("tk.footerInfo.infoLabel")},[(m(!0),C(Y,null,le(r.value,u=>(m(),C("div",{key:u.name,class:T(`${l(t).e("list__item")} flx-align-center`),role:"listitem"},[u.icon?(m(),D(l(de),{key:0,iconType:u.iconType,icon:u.icon,size:"16px",color:"var(--vp-c-text-2)",imgAlt:u.imgAlt,"aria-hidden":"true"},null,8,["iconType","icon","imgAlt"])):A("v-if",!0),u.link?(m(),C("a",{key:1,href:l(Ee)(u.link),target:"_blank","aria-label":u.name},W(u.name),9,QT)):(m(),C("span",ZT,W(u.name),1))],2))),128)),l(o).customHtml?(m(),C("span",{key:0,innerHTML:l(o).customHtml},null,8,eE)):A("v-if",!0)],10,XT),(m(!0),C(Y,null,le([l(o).bottomMessage||[]].flat(),(u,f)=>(m(),C("p",{key:f,innerHTML:u,class:"flx-wrap-justify-center"},null,8,tE))),128))],64)):A("v-if",!0)],10,qT)):A("v-if",!0)}});let ro=[];const zd=e=>{e.code==="Escape"&&ro.forEach(t=>t(e))},sE=e=>{be(()=>{ro.length===0&&document.addEventListener("keydown",zd),me&&ro.push(e)}),ls(()=>{ro=ro.filter(t=>t!==e),ro.length===0&&me&&document.removeEventListener("keydown",zd)})},el="focus-trap.focus-after-trapped",tl="focus-trap.focus-after-released",oE="focus-trap.focusout-prevented",jd={cancelable:!0,bubbles:!1},iE={cancelable:!0,bubbles:!1},Ud="focusAfterTrapped",Wd="focusAfterReleased",rE=Symbol("focusTrap"),Pu=j(),La=j(0),Mu=j(0);let sr=0;const d2=e=>{const t=[],n=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT,{acceptNode:s=>{const o=s.tagName==="INPUT"&&s.type==="hidden";return s.disabled||s.hidden||o?NodeFilter.FILTER_SKIP:s.tabIndex>=0||s===document.activeElement?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP}});for(;n.nextNode();)t.push(n.currentNode);return t},qd=(e,t)=>{for(const n of e)if(!aE(n,t))return n},aE=(e,t)=>{if(getComputedStyle(e).visibility==="hidden")return!0;for(;e;){if(t&&e===t)return!1;if(getComputedStyle(e).display==="none")return!0;e=e.parentElement}return!1},lE=e=>{const t=d2(e),n=qd(t,e),s=qd(t.reverse(),e);return[n,s]},cE=e=>e instanceof HTMLInputElement&&"select"in e,ms=(e,t)=>{if(e&&e.focus){const n=document.activeElement;let s=!1;Il(e)&&!N7(e)&&!e.getAttribute("tabindex")&&(e.setAttribute("tabindex","-1"),s=!0),e.focus({preventScroll:!0}),Mu.value=window.performance.now(),e!==n&&cE(e)&&t&&e.select(),Il(e)&&s&&e.removeAttribute("tabindex")}};function Kd(e,t){const n=[...e],s=e.indexOf(t);return s!==-1&&n.splice(s,1),n}const uE=()=>{let e=[];return{push:s=>{const o=e[0];o&&s!==o&&o.pause(),e=Kd(e,s),e.unshift(s)},remove:s=>{e=Kd(e,s),e[0]?.resume?.()}}},fE=(e,t=!1)=>{const n=document.activeElement;for(const s of e)if(ms(s,t),document.activeElement!==n)return},Yd=uE(),dE=()=>La.value>Mu.value,or=()=>{Pu.value="pointer",La.value=window.performance.now()},Gd=()=>{Pu.value="keyboard",La.value=window.performance.now()},hE=()=>(be(()=>{sr===0&&(document.addEventListener("mousedown",or),document.addEventListener("touchstart",or),document.addEventListener("keydown",Gd)),sr++}),ls(()=>{sr--,sr<=0&&(document.removeEventListener("mousedown",or),document.removeEventListener("touchstart",or),document.removeEventListener("keydown",Gd))}),{focusReason:Pu,lastUserFocusTimestamp:La,lastAutomatedFocusTimestamp:Mu}),ir=e=>new CustomEvent(oE,{...iE,detail:e});var pE=z({name:"FocusTrap",inheritAttrs:!1,props:{loop:Boolean,trapped:Boolean,focusTrapEl:Object,focusStartEl:{type:[Object,String],default:"first"}},emits:[Ud,Wd,"focusin","focusout","focusout-prevented","release-requested"],setup(e,{emit:t}){const n=j();let s,o;const{focusReason:i}=hE();sE(g=>{e.trapped&&!r.paused&&t("release-requested",g)});const r={paused:!1,pause(){this.paused=!0},resume(){this.paused=!1}},a=g=>{if(!e.loop&&!e.trapped||r.paused)return;const{code:v,altKey:k,ctrlKey:b,metaKey:w,currentTarget:y,shiftKey:_}=g,{loop:x}=e,L=v==="Tab"&&!k&&!b&&!w,V=document.activeElement;if(L&&V){const E=y,[I,P]=lE(E);if(I&&P){if(!_&&V===P){const $=ir({focusReason:i.value});t("focusout-prevented",$),$.defaultPrevented||(g.preventDefault(),x&&ms(I,!0))}else if(_&&[I,E].includes(V)){const $=ir({focusReason:i.value});t("focusout-prevented",$),$.defaultPrevented||(g.preventDefault(),x&&ms(P,!0))}}else if(V===E){const $=ir({focusReason:i.value});t("focusout-prevented",$),$.defaultPrevented||g.preventDefault()}}};In(rE,{focusTrapRef:n,onKeydown:a}),te(()=>e.focusTrapEl,g=>{g&&(n.value=g)},{immediate:!0}),te([n],([g],[v])=>{g&&(g.addEventListener("keydown",a),g.addEventListener("focusin",f),g.addEventListener("focusout",d)),v&&(v.removeEventListener("keydown",a),v.removeEventListener("focusin",f),v.removeEventListener("focusout",d))});const c=g=>{t(Ud,g)},u=g=>t(Wd,g),f=g=>{const v=n.value;if(!v)return;const k=g.target,b=g.relatedTarget,w=k&&v.contains(k);e.trapped||b&&v.contains(b)||(s=b),w&&t("focusin",g),!r.paused&&e.trapped&&(w?o=k:ms(o,!0))},d=g=>{const v=n.value;if(!(r.paused||!v))if(e.trapped){const k=g.relatedTarget;!k&&!v.contains(k)&&setTimeout(()=>{if(!r.paused&&e.trapped){const b=ir({focusReason:i.value});t("focusout-prevented",b),b.defaultPrevented||ms(o,!0)}},0)}else{const k=g.target;k&&v.contains(k)||t("focusout",g)}};async function h(){await Oe();const g=n.value;if(g){Yd.push(r);const v=g.contains(document.activeElement)?s:document.activeElement;if(s=v,!g.contains(v)){const b=new Event(el,jd);g.addEventListener(el,c),g.dispatchEvent(b),b.defaultPrevented||Oe(()=>{let w=e.focusStartEl;Je(w)||(ms(w),document.activeElement!==w&&(w="first")),w==="first"&&fE(d2(g),!0),(document.activeElement===v||w==="container")&&ms(g)})}}}function p(){const g=n.value;if(g){g.removeEventListener(el,c);const v=new CustomEvent(tl,{...jd,detail:{focusReason:i.value}});g.addEventListener(tl,u),g.dispatchEvent(v),!v.defaultPrevented&&(i.value==="keyboard"||!dE()||g.contains(document.activeElement))&&ms(s??document.body),g.removeEventListener(tl,u),Yd.remove(r)}}return be(()=>{e.trapped&&h(),te(()=>e.trapped,g=>{g?h():p()})}),ls(()=>{e.trapped&&p(),n.value&&(n.value.removeEventListener("keydown",a),n.value.removeEventListener("focusin",f),n.value.removeEventListener("focusout",d),n.value=void 0)}),{onKeydown:a}}}),mE=(e,t)=>{const n=e.__vccOpts||e;for(const[s,o]of t)n[s]=o;return n};function gE(e,t,n,s,o,i){return M(e.$slots,"default",{handleKeydown:e.onKeydown})}var h2=mE(pE,[["render",gE]]);const vE=["src","crossorigin"];var yE=z({name:"ImageViewer",__name:"ImageViewer",props:{urlList:{default:()=>[]},zIndex:{},initialIndex:{default:0},infinite:{type:Boolean,default:!0},hideOnClickModal:{type:Boolean,default:!1},teleported:{type:Boolean},closeOnPressEscape:{type:Boolean,default:!0},zoomRate:{default:1.2},minScale:{default:.2},maxScale:{default:7},showProgress:{type:Boolean,default:!1},crossorigin:{}},emits:["close","switch","rotate"],setup(e,{expose:t,emit:n}){const s={CONTAIN:{name:"contain",icon:Fh},ORIGINAL:{name:"original",icon:d9}},o=e,i=n;let r="";const a=ie("image-viewer"),{t:c}=ge(),{nextZIndex:u}=nu(),f=j(),d=j([]),h=l1(),p=j(!0),g=j(o.initialIndex),v=ze(s.CONTAIN),k=j({scale:1,deg:0,offsetX:0,offsetY:0,enableTransition:!1}),b=j(o.zIndex??u()),w=F(()=>{const{urlList:we}=o;return we.length<=1}),y=F(()=>g.value===0),_=F(()=>g.value===o.urlList.length-1),x=F(()=>o.urlList[g.value]),L=F(()=>[a.e("btn"),a.e("prev"),a.is("disabled",!o.infinite&&y.value)]),V=F(()=>[a.e("btn"),a.e("next"),a.is("disabled",!o.infinite&&_.value)]),E=F(()=>{const{scale:we,deg:Ne,offsetX:Ke,offsetY:gt,enableTransition:bt}=k.value;let Nt=Ke/we,Qt=gt/we;const B=Ne*Math.PI/180,R=Math.cos(B),K=Math.sin(B);Nt=Nt*R+Qt*K,Qt=Qt*R-Ke/we*K;const ee={transform:`scale(${we}) rotate(${Ne}deg) translate(${Nt}px, ${Qt}px)`,transition:bt?"transform .3s":""};return v.value.name===s.CONTAIN.name&&(ee.maxWidth=ee.maxHeight="100%"),ee}),I=F(()=>`${g.value+1} / ${o.urlList.length}`),P=()=>{$(),Zs?.(),document.body.style.overflow=r,i("close")},N=()=>{const we=ts(Ke=>{switch(Ke.code){case"Escape":o.closeOnPressEscape&&P();break;case"Space":ae();break;case"ArrowLeft":he();break;case"ArrowUp":je("zoomIn");break;case"ArrowRight":st();break;case"ArrowDown":je("zoomOut");break}}),Ne=ts(Ke=>{const gt=Ke.deltaY||Ke.deltaX;je(gt<0?"zoomIn":"zoomOut",{zoomRate:o.zoomRate,enableTransition:!1})});h.run(()=>{Ve(document,"keydown",we),Ve(document,"wheel",Ne)})},$=()=>{h.stop()},U=()=>{p.value=!1},q=we=>{p.value=!1,we.target.alt=c("tk.image.error")},J=we=>{if(p.value||we.button!==0||!f.value)return;k.value.enableTransition=!1;const{offsetX:Ne,offsetY:Ke}=k.value,gt=we.pageX,bt=we.pageY,Nt=ts(B=>{k.value={...k.value,offsetX:Ne+B.pageX-gt,offsetY:Ke+B.pageY-bt}}),Qt=()=>{document.removeEventListener("mousemove",Nt),document.removeEventListener("mouseup",Qt)};document.addEventListener("mousemove",Nt),document.addEventListener("mouseup",Qt),we.preventDefault()},G=()=>{k.value={scale:1,deg:0,offsetX:0,offsetY:0,enableTransition:!1}},ae=()=>{if(p.value)return;const we=Object.keys(s),Ne=Object.values(s),Ke=v.value.name,bt=(Ne.findIndex(Nt=>Nt.name===Ke)+1)%we.length;v.value=s[we[bt]],G()},ne=we=>{const Ne=o.urlList.length;g.value=(we+Ne)%Ne},he=()=>{y.value&&!o.infinite||ne(g.value-1)},st=()=>{_.value&&!o.infinite||ne(g.value+1)},je=(we,Ne={})=>{if(p.value)return;const{minScale:Ke,maxScale:gt}=o,{zoomRate:bt,rotateDeg:Nt,enableTransition:Qt}={zoomRate:o.zoomRate,rotateDeg:90,enableTransition:!0,...Ne};switch(we){case"zoomOut":k.value.scale>Ke&&(k.value.scale=Number.parseFloat((k.value.scale/bt).toFixed(3)));break;case"zoomIn":k.value.scale{we.detail?.focusReason==="pointer"&&we.preventDefault()},Wn=()=>{o.closeOnPressEscape&&P()},us=we=>{if(we.ctrlKey){if(we.deltaY<0)return we.preventDefault(),!1;if(we.deltaY>0)return we.preventDefault(),!1}};te(x,()=>{Oe(()=>{d.value[0]?.complete||(p.value=!0)})}),te(g,we=>{G(),i("switch",we)}),N();const Zs=Ve(document,"wheel",us,{passive:!1});return be(()=>{r=document.body.style.overflow,document.body.style.overflow="hidden"}),t({setActiveItem:ne}),(we,Ne)=>(m(),D(ca,{disabled:!e.teleported,to:"body"},[H(vt,{name:"viewer-fade",appear:""},{default:O(()=>[S("div",{ref_key:"wrapper",ref:f,tabindex:-1,class:T(l(a).e("wrapper")),style:Fe({zIndex:b.value})},[H(l(h2),{loop:"",trapped:"","focus-trap-el":f.value,"focus-start-el":"container",onFocusoutPrevented:yt,onReleaseRequested:Wn},{default:O(()=>[S("div",{class:T(l(a).e("mask")),onClick:Ne[0]||(Ne[0]=To(Ke=>e.hideOnClickModal&&P(),["self"]))},null,2),A(" CLOSE "),S("span",{class:T([l(a).e("btn"),l(a).e("close")]),onClick:P},[H(l(de),{icon:l(Jc)},null,8,["icon"])],2),A(" ARROW "),w.value?A("v-if",!0):(m(),C(Y,{key:0},[S("span",{class:T(L.value),onClick:he},[H(l(de),{icon:l(Xc)},null,8,["icon"])],2),S("span",{class:T(V.value),onClick:st},[H(l(de),{icon:l(Qc)},null,8,["icon"])],2)],64)),we.$slots.progress||e.showProgress?(m(),C("div",{key:1,class:T([l(a).e("btn"),l(a).e("progress")])},[M(we.$slots,"progress",{activeIndex:g.value,total:e.urlList.length},()=>[rt(W(I.value),1)])],2)):A("v-if",!0),A(" ACTIONS "),S("div",{class:T([l(a).e("btn"),l(a).e("actions")])},[S("div",{class:T(l(a).e("actions__inner"))},[M(we.$slots,"toolbar",{actions:je,prev:he,next:st,reset:ae,activeIndex:g.value,setActiveItem:ne},()=>[H(l(de),{icon:l(p9),onClick:Ne[1]||(Ne[1]=Ke=>je("zoomOut"))},null,8,["icon"]),H(l(de),{icon:l(h9),onClick:Ne[2]||(Ne[2]=Ke=>je("zoomIn"))},null,8,["icon"]),S("i",{class:T(l(a).e("actions__divider"))},null,2),H(l(de),{icon:v.value.icon,onClick:ae},null,8,["icon"]),S("i",{class:T(l(a).e("actions__divider"))},null,2),H(l(de),{icon:l(f9),onClick:Ne[3]||(Ne[3]=Ke=>je("anticlockwise"))},null,8,["icon"]),H(l(de),{icon:l(Bh),onClick:Ne[4]||(Ne[4]=Ke=>je("clockwise"))},null,8,["icon"])])],2)],2),A(" CANVAS "),S("div",{class:T(l(a).e("canvas"))},[(m(!0),C(Y,null,le(e.urlList,(Ke,gt)=>et((m(),C("img",{ref_for:!0,ref:bt=>d.value[gt]=bt,key:Ke,src:Ke,style:Fe(E.value),class:T([l(a).e("img"),"image-viewer__img"]),crossorigin:e.crossorigin,onLoad:U,onError:q,onMousedown:J},null,46,vE)),[[at,gt===g.value]])),128))],2),M(we.$slots,"default")]),_:3},8,["focus-trap-el"])],6)]),_:3})],8,["disabled"]))}}),bE=z({name:"ImageViewerControl",__name:"index",props:{modelValue:{default:!1},modelModifiers:{}},emits:["update:modelValue"],setup(e){const t=Jt(e,"modelValue"),n=()=>{document.body.style.overflow="",t.value=!1};return(s,o)=>t.value?(m(),D(yE,nt({key:0},s.$attrs,{onClose:n}),null,16)):A("v-if",!0)}});let Jd=null;const kE=e=>{if(typeof window>"u")return;const{modelValue:t=!0}=e;e.modelValue=t,document.body.style.overflow="hidden";const n=document.createElement("div");document.body.appendChild(n),Jd=H(bE,e),hi(Jd,n)};var wE=z({__name:"index",setup(e){const{getTeekConfig:t}=fe(),n=F(()=>{const{imageViewer:o={}}=t("articleAnalyze",{});return o});return Ve(()=>document.querySelector("#VPContent"),"click",o=>{const i=o.target;if(i.tagName.toLowerCase()==="img"&&!i.className.includes("image-viewer__img")&&!i.className.includes("no-preview")){const r=i.querySelectorAll(".content-container .main img"),a=Array.from(r),c=a.map(d=>d.src);let u=a.findIndex(d=>d===i);const f=i.getAttribute("src");u===-1&&f&&(c.push(f),u=c.length-1),kE({infinite:!1,...n.value,urlList:c,initialIndex:u})}}),(o,i)=>null}});const p2=Symbol("breadcrumbKey"),si=ie("breadcrumb"),CE=["aria-label"];var _E=z({name:"Breadcrumb",__name:"Breadcrumb",props:{separator:{default:"/"}},setup(e){const{t}=ge(),n=j();return In(p2,{separator:e.separator}),be(()=>{const s=n.value?.querySelectorAll(`.${si.e("item")}`);s?.length&&s[s.length-1].setAttribute("aria-current","page")}),(s,o)=>(m(),C("div",{ref_key:"breadcrumb",ref:n,class:T(l(si).b()),role:"navigation","aria-label":l(t)("tk.breadcrumb.label")},[M(s.$slots,"default")],10,CE))}}),Xd=z({name:"BreadcrumbItem",__name:"BreadcrumbItem",setup(e){const t=qe(p2,void 0);return(n,s)=>(m(),C("span",{class:T(l(si).e("item"))},[S("span",{ref:"link",class:T(l(si).e("inner")),role:"link"},[M(n.$slots,"default")],2),S("span",{class:T(l(si).e("separator")),role:"presentation"},W(l(t)?.separator),3)],2))}});const SE=["aria-label"],TE=["href","title","aria-label"];var m2=z({name:"ArticleBreadcrumb",__name:"index",setup(e){const t=ie("article-breadcrumb"),{t:n}=ge(),{getTeekConfigRef:s}=fe(),{localeIndex:o,theme:i,page:r}=Ae(),a=s("breadcrumb",{enabled:!0,showCurrentName:!1,separator:"/",homeLabel:n("tk.articleBreadcrumb.home")}),c=F(()=>r.value.filePath.split("/")||[]),u=F(()=>{const f=[],d=c.value;return d.forEach((h,p)=>{const g=h.replace(/^\d+\./,"").split(".")?.[0]||"";(p!==d.length-1||a.value.showCurrentName)&&g!==o.value&&f.push({fileName:g,url:i.value.catalogues?.inv[h]?.url||""})}),f});return(f,d)=>l(a)?.enabled?(m(),C("div",{key:0,class:T(l(t).b()),role:"navigation","aria-label":l(n)("tk.articleBreadcrumb.label")},[H(l(_E),{separator:l(a).separator},{default:O(()=>[H(l(Xd),null,{default:O(()=>[S("a",{href:l(Ee)("/"),title:l(a).homeLabel,class:"home hover-color","aria-label":l(a).homeLabel},[H(l(de),{icon:l(Z7),"aria-hidden":"true"},null,8,["icon"])],8,TE)]),_:1}),(m(!0),C(Y,null,le(u.value,(h,p)=>(m(),D(l(Xd),{key:p},{default:O(()=>[(m(),D(Be(h.url?"a":"span"),{href:h.url&&l(Ee)(`${h.url}`),title:h.fileName,class:T([h.url?"hover-color":""]),"aria-label":h.fileName},{default:O(()=>[rt(W(h.fileName),1)]),_:2},1032,["href","title","class","aria-label"]))]),_:2},1024))),128))]),_:1},8,["separator"])],10,SE)):A("v-if",!0)}});const EE=["aria-label"],xE={key:0,class:"flx-center"},AE=["title","aria-label"],$E={key:1,class:"flx-center"},LE=["title","aria-label"],IE={key:2,class:"flx-center"},PE=["title","aria-label"];var g2=z({name:"ArticleAnalyze",__name:"index",props:{breadcrumb:{type:Boolean,default:!0},scope:{default:"article"}},setup(e){const t=ie("article-analyze"),{t:n}=ge(),{getTeekConfig:s,getTeekConfigRef:o}=fe(),{theme:i,frontmatter:r}=Ae(),a=Is(),{router:c}=a,u=F(()=>({author:s("author",{}),date:r.value.date,frontmatter:r.value,url:"",relativePath:""})),f=F(()=>i.value.docAnalysisInfo||{}),d=F(()=>{let L={};return f.value.eachFileWords?.forEach(V=>{V.fileInfo.relativePath===c.route.data.filePath&&(L=V)}),L}),h=o("articleAnalyze",{showInfo:!0,showIcon:!0,teleport:{}}),p=F(()=>{const L=[h.value.showInfo].flat();return!!(L.includes(!0)||L.includes("article"))}),g=j(),v=()=>{const{selector:L,position:V="after",className:E="teleport"}=h.value.teleport||{},I=g.value;if(!L||!I)return;const N=document.querySelector("#VPContent")?.querySelector(L);N?.parentElement?.querySelectorAll(`.${t.e("wrapper")}`).forEach($=>$.remove()),I.classList.add(E),N?.[V]?.(I)};te(c.route,()=>Oe(v),{immediate:!0,flush:"post"});const k=o("docAnalysis",{wordCount:!0,readingTime:!0,statistics:{}}),b=F(()=>({url:"",provider:"",pageView:!0,tryRequest:!1,tryCount:5,tryIterationTime:2e3,permalink:!0,...k.value.statistics})),w=F(()=>!!b.value.provider&&b.value.pageView),{pagePv:y,isGet:_,request:x}=Rh(!1,b.value);return te(w,L=>{L&&x()}),te(c.route,()=>{w.value&&(b.value.permalink&&c.state?.permalinkPlugin?Oe(x):x())},{immediate:!0}),(L,V)=>(m(),C("div",{class:T(`${l(t).b()} flx-justify-between`),"aria-label":l(n)("tk.articleAnalyze.label")},[e.breadcrumb?(m(),D(l(m2),{key:0})):A("v-if",!0),p.value?(m(),C("div",{key:1,ref_key:"baseInfoRef",ref:g,class:T(`${l(t).e("wrapper")} flx-align-center`)},[H(l(Lu),{post:u.value,scope:e.scope},null,8,["post","scope"]),l(k).wordCount&&d.value.wordCount?(m(),C("div",xE,[l(h).showIcon?(m(),D(l(de),{key:0,icon:l(Lh),"aria-hidden":"true"},null,8,["icon"])):A("v-if",!0),S("a",{title:l(n)("tk.articleAnalyze.wordCount"),class:"hover-color","aria-label":l(n)("tk.articleAnalyze.wordCount")},W(d.value.wordCount),9,AE)])):A("v-if",!0),l(k).readingTime&&d.value.readingTime?(m(),C("div",$E,[l(h).showIcon?(m(),D(l(de),{key:0,icon:l(X7)},null,8,["icon"])):A("v-if",!0),S("a",{title:l(n)("tk.articleAnalyze.readingTime"),class:"hover-color","aria-label":l(n)("tk.articleAnalyze.readingTime")},W(d.value.readingTime),9,LE)])):A("v-if",!0),w.value?(m(),C("div",IE,[l(h).showIcon?(m(),D(l(de),{key:0,icon:l(Q7)},null,8,["icon"])):A("v-if",!0),S("a",{title:l(n)("tk.articleAnalyze.pageView"),class:"hover-color","aria-label":l(n)("tk.articleAnalyze.pageView")},W(l(_)?l(y):"Get..."),9,PE)])):A("v-if",!0)],2)):A("v-if",!0)],10,EE))}});const ME=["aria-label"],FE={key:0,class:"flx-center"},BE={key:1,class:"flx-center"};var NE=z({name:"ArticleShare",__name:"index",setup(e){const t=ie("article-share"),{t:n}=ge(),{getTeekConfigRef:s}=fe(),o=s("articleShare",{icon:Kf,text:n("tk.articleShare.text"),copiedIcon:Yf,copiedText:n("tk.articleShare.copiedText"),query:!1,hash:!1}),i=F(()=>{const{hash:c,query:u}=o.value,{origin:f,pathname:d,search:h}=location;return`${f}${d}${u?h:""}${c?location.hash:""}`}),{copy:r,copied:a}=Hh(2e3);return(c,u)=>(m(),C("div",{class:T(l(t).b())},[S("button",{class:T([l(t).e("button"),{copied:l(a)},"flx-center"]),"aria-label":l(a)?l(o).copiedText:l(o).text,"aria-live":"polite",onClick:u[0]||(u[0]=f=>l(r)(i.value))},[l(a)?(m(),C("div",BE,[H(l(de),{icon:l(Yf),style:{"margin-right":"4px"}},null,8,["icon"]),rt(" "+W(l(o).copiedText),1)])):(m(),C("div",FE,[H(l(de),{icon:l(Kf),style:{"margin-right":"4px"}},null,8,["icon"]),rt(" "+W(l(o).text),1)]))],10,ME)],2))}});const VE=["href","aria-label"],OE={key:1},DE=["href","aria-label"];var RE=z({name:"ArticleUpdate",__name:"index",setup(e){const t=ie("article-update"),{t:n}=ge(),s=Pn(),o=kn(),{frontmatter:i}=Ae(),{getTeekConfigRef:r}=fe(),{archivesPath:a}=Li(),c=r("articleUpdate",{limit:3}),u=F(()=>{const f="/"+o.data.filePath.replace(".md","");return[...s.value.sortPostsByDate.filter(d=>![o.path,f,`${f}.html`].includes(d.url)).slice(0,c.value.limit),{title:"更多文章 >",url:a.value,frontmatter:{},date:""}]});return(f,d)=>et((m(),C("div",{class:T(l(t).b())},[S("div",{class:T([l(t).e("title"),"flx-align-center"])},[H(l(de),{icon:l(Ph),class:"edit-icon","aria-hidden":"true"},null,8,["icon"]),l(a)?(m(),C("a",{key:0,href:l(Ee)(l(a)),class:"hover-color","aria-label":l(n)("tk.articleUpdate.label")},W(l(n)("tk.articleUpdate.label")),9,VE)):(m(),C("span",OE,W(l(n)("tk.articleUpdate.label")),1))],2),S("ul",null,[(m(!0),C(Y,null,le(u.value,(h,p)=>(m(),C("li",{key:h.url,class:"flx-center"},[S("span",{class:T(l(t).m("num")),"aria-hidden":"true"},W(p!==u.value.length-1?(p+1).toString().padStart(2,"0"):""),3),S("div",{class:T(l(t).e("content"))},[h.url?(m(),C("a",{key:0,href:l(Ee)(h.url),class:"flx-1 hover-color sle","aria-label":h.title},[H(l(Fi),{post:h,"title-tag-props":{position:"right",size:"small"}},null,8,["post"])],8,DE)):A("v-if",!0),h.date?(m(),C("span",{key:1,class:T(l(t).em("content","date"))},W(h.date),3)):A("v-if",!0)],2)]))),128))])],2)),[[at,l(i).article!==!1]])}}),HE=z({__name:"index",setup(e){const t=ie("article-heading-highlight"),n=()=>{if(!me||!window.location.hash)return;const o=decodeURIComponent(window.location.hash);if(!o)return;let i;try{i=document.querySelector(o)}catch(r){return console.error(r)}i&&(i.classList.contains(t.b())||i.classList.add(t.b()),i.classList.remove(t.b()),setTimeout(()=>{i&&i.classList.add(t.b())},10))},s=kn();return te(s,async()=>{await Oe(),n()}),Ve(()=>window,"hashchange",n),(o,i)=>null}}),zE=z({__name:"index",setup(e){const t=ie(),{getTeekConfigRef:n}=fe(),s=n(null,{vpHome:!0,pageStyle:"default"}),o=async()=>{if(!me)return;await Oe();const i=document.querySelector(`.${t.join("layout")}`);["default","card","card-nav","segment","segment-nav"].forEach(r=>i?.classList.remove(t.join(r))),i?.classList.add(t.join(s.value.pageStyle))};return te(()=>s.value.pageStyle,o,{immediate:!0}),te(()=>s.value.vpHome,o),(i,r)=>null}});const jE=["aria-label"],UE=["innerHTML"],WE=["innerHTML"];var qE=z({name:"AsideBottomAppreciation",__name:"AsideBottomAppreciation",setup(e){const t=ie("article-appreciation"),{t:n}=ge(),{getTeekConfigRef:s}=fe(),o=s("appreciation",{position:""}),i=F(()=>o.value.options||{});return(r,a)=>(m(),C("div",{class:T([l(t).b(),l(t).m("aside-bottom")]),"aria-label":l(n)("tk.articleAppreciation.label")},[S("span",{innerHTML:i.value.title},null,8,UE),S("div",{class:T(l(t).e("content")),innerHTML:i.value.content},null,10,WE)],10,jE))}});const KE=["aria-label"],YE=["innerHTML","aria-expanded","aria-controls"],GE=["aria-expanded","aria-controls"],JE=["innerHTML"],XE=["innerHTML"],QE=["aria-label"],ZE=["innerHTML"];var ex=z({name:"DocAfterAppreciation",__name:"DocAfterAppreciation",setup(e){const t=ie("article-appreciation"),{t:n}=ge(),{getTeekConfigRef:s}=fe(),o=s("appreciation",{position:""}),i=F(()=>o.value.options||{expand:!1}),r=j(i.value.expand),a=F(()=>{const{icon:u}=i.value;return u==="aliPay"?Ah:u==="weChatPay"?Mh:u}),c=()=>{r.value=!r.value};return te(()=>i.value.expand,u=>{r.value=u}),(u,f)=>(m(),C("div",{class:T([l(t).b(),l(t).m("doc-after")]),"aria-label":l(n)("tk.articleAppreciation.label")},[i.value.buttonHtml?(m(),C("div",{key:0,innerHTML:i.value.buttonHtml,role:"button","aria-expanded":r.value,"aria-controls":`${l(t).e("content")}`},null,8,YE)):i.value.expandTitle||i.value.collapseTitle?(m(),C("button",{key:1,class:T(l(t).e("button")),onClick:c,"aria-expanded":r.value,"aria-controls":`${l(t).e("content")}`,"aria-live":"polite"},[a.value?(m(),D(l(de),{key:0,class:T(l(t).e("button__icon")),icon:a.value,size:16,"aria-hidden":"true"},null,8,["class","icon"])):A("v-if",!0),r.value?(m(),C("span",{key:1,innerHTML:i.value.collapseTitle},null,8,JE)):(m(),C("span",{key:2,innerHTML:i.value.expandTitle},null,8,XE))],10,GE)):A("v-if",!0),H(vt,{name:l(t).join("fade")},{default:O(()=>[r.value?(m(),C("div",{key:0,class:T(l(t).e("content")),"aria-label":l(n)("tk.articleAppreciation.contentLabel")},[S("div",{class:T(l(t).e("content")),innerHTML:i.value.content},null,10,ZE)],10,QE)):A("v-if",!0)]),_:1},8,["name"])],10,KE))}});const tx=(e,t)=>{const n=j();return{focusStartRef:n,onFocusAfterTrapped:()=>{t("focus")},onFocusAfterReleased:c=>{c.detail?.focusReason!=="pointer"&&(n.value="first",t("blur"))},onFocusInTrap:c=>{e.value&&c.target&&(n.value=c.target)},onFocusoutPrevented:c=>{c.detail.focusReason==="pointer"&&c.preventDefault()},onReleaseRequested:()=>{t("close")}}};var Ia=z({name:"Popover",__name:"index",props:$n({trigger:{default:"hover"},placement:{default:"bottom"},content:{default:""},width:{},height:{},offset:{default:0},xOffset:{default:0},yOffset:{default:0},disabled:{type:Boolean,default:!1},transition:{type:Boolean,default:!0},transitionName:{},triggerEl:{},zIndex:{},popperClass:{},popperStyle:{},beforePopup:{type:Function}},{modelValue:{default:!1},modelModifiers:{}}),emits:$n(["focus","blur","close"],["update:modelValue"]),setup(e,{emit:t}){const n=ie("popover"),{nextZIndex:s}=nu(),o=j(e.zIndex??s()),i=Jt(e,"modelValue"),r=j(),a=j(),c=Pl(r),u=Pl(a),f=F(()=>e.triggerEl||r.value),{top:d,right:h,left:p,bottom:g,update:v}=O9(f,a,{placement:e.placement,offset:e.offset,xOffset:e.xOffset,yOffset:e.yOffset}),k=F(()=>({zIndex:o.value,top:sn(d.value),right:sn(h.value),bottom:sn(g.value),left:sn(p.value),width:sn(e.width),height:sn(e.height),...e.popperStyle})),b=()=>{if(!r.value||!a.value){i.value=!1;return}v();const N=e.beforePopup?.({top:d.value,right:h.value,bottom:p.value,left:g.value,triggerElement:e.triggerEl||r.value,popoverElement:a.value})??{};N.top&&(d.value=N.top),N.right&&(h.value=N.right),N.bottom&&(g.value=N.bottom),N.left&&(p.value=N.left)};e.trigger==="hover"&&te(c,N=>{e.trigger==="hover"&&(i.value=N)});const w=N=>{N===e.trigger&&(i.value=!i.value)};te(i,N=>{N&&b()}),te(u,N=>{e.trigger==="hover"&&(i.value=N)}),x9(a,N=>{N.composedPath().includes(r.value)||e.trigger!=="hover"&&i.value!==!1&&(i.value=!1)});const y=n.join("popover-container");Mo(()=>{if(!document.querySelector(`#${y}`)){const $=document.createElement("div");$.id=y,document.body.appendChild($)}});const _=t,{focusStartRef:x,onFocusAfterTrapped:L,onFocusAfterReleased:V,onFocusInTrap:E,onFocusoutPrevented:I,onReleaseRequested:P}=tx(i,_);return(N,$)=>(m(),C(Y,null,[S("div",nt({ref_key:"triggerRef",ref:r,onClick:$[0]||($[0]=U=>w("click")),onContextmenu:$[1]||($[1]=U=>w("contextmenu")),onFocus:$[2]||($[2]=U=>w("focus")),onTouchstart:$[3]||($[3]=U=>i.value=!i.value)},N.$attrs),[M(N.$slots,"reference")],16),(m(),D(ca,{to:`#${l(y)}`},[H(vt,{name:e.transition?e.transitionName||l(n).join("fade-linear"):""},{default:O(()=>[e.disabled?A("v-if",!0):et((m(),C("div",{key:0,ref_key:"popoverRef",ref:a,style:Fe(k.value),class:T([l(n).b(),e.popperClass]),onClick:$[4]||($[4]=To(()=>{},["stop"])),onTouchstart:$[5]||($[5]=To(()=>{},["stop"]))},[H(l(h2),{loop:"",trapped:i.value,"focus-trap-el":a.value,"focus-start-el":l(x),onFocusAfterTrapped:l(L),onFocusAfterReleased:l(V),onFocusin:l(E),onFocusoutPrevented:l(I),onReleaseRequested:l(P)},{default:O(()=>[M(N.$slots,"default",{},()=>[rt(W(e.content),1)])]),_:3},8,["trapped","focus-trap-el","focus-start-el","onFocusAfterTrapped","onFocusAfterReleased","onFocusin","onFocusoutPrevented","onReleaseRequested"])],38)),[[at,i.value]])]),_:3},8,["name"])],8,["to"]))],64))}});const nx=["aria-label"],sx=["innerHTML","aria-expanded","aria-controls"],ox=["aria-expanded","aria-controls"],ix=["innerHTML"],rx=["aria-label"],ax=["innerHTML"];var lx=z({name:"DocAfterAppreciationPopper",__name:"DocAfterAppreciationPopper",setup(e){const t=ie("article-appreciation"),{t:n}=ge(),{getTeekConfigRef:s}=fe(),o=s("appreciation",{position:""}),i=j(!1),r=F(()=>({trigger:"click",...o.value.options})),a=F(()=>{const{icon:c}=r.value;return c==="aliPay"?Ah:c==="weChatPay"?Mh:c});return(c,u)=>(m(),C("div",{class:T(l(t).b()),"aria-label":l(n)("tk.articleAppreciation.label")},[H(l(Ia),{modelValue:i.value,"onUpdate:modelValue":u[0]||(u[0]=f=>i.value=f),trigger:r.value.trigger},{reference:O(()=>[r.value.buttonHtml?(m(),C("div",{key:0,innerHTML:r.value.buttonHtml,role:"button","aria-expanded":i.value,"aria-controls":`${l(t).e("content")}`},null,8,sx)):r.value.title?(m(),C("button",{key:1,class:T(l(t).e("button")),"aria-expanded":i.value,"aria-controls":`${l(t).e("content")}`,"aria-live":"polite"},[a.value?(m(),D(l(de),{key:0,class:T(l(t).e("button__icon")),icon:a.value,size:16,"aria-hidden":"true"},null,8,["class","icon"])):A("v-if",!0),r.value.title?(m(),C("span",{key:1,innerHTML:r.value.title},null,8,ix)):A("v-if",!0)],10,ox)):A("v-if",!0)]),default:O(()=>[S("div",{class:T([l(t).e("content"),l(t).m("doc-after-popper")]),"aria-label":l(n)("tk.articleAppreciation.contentLabel")},[S("div",{class:T(l(t).e("content")),innerHTML:r.value.content},null,10,ax)],10,rx)]),_:1},8,["modelValue","trigger"])],10,nx))}});const v2=Symbol("twikoo"),cx=["href","integrity"];var ux=z({name:"CommentTwikoo",__name:"index",setup(e){const t=ie(),n=Is(),{getTeekConfig:s}=fe(),o=s("comment",{}).options,{envId:i,jsLink:r="https://cdn.jsdelivr.net/npm/twikoo@{version}/dist/twikoo.nocss.js",jsIntegrity:a,cssLink:c="https://cdn.jsdelivr.net/npm/twikoo@{version}/dist/twikoo.css",version:u="1.6.44",katex:f,timeout:d=700,...h}=o,p=()=>{if(!me)return console.error("[Teek Error] Not in a client");if(!i)return console.error("[Teek Error] Twikoo initialization failed. Please configure the 'envId'");const w=qe(v2,()=>null),y={...h,envId:i};w?w("#twikoo",y):window.twikoo&&window.twikoo.init({...y,el:"#twikoo"})},g=j(null),v=()=>{const w=g.value;w&&(w.onload=p)},k=w=>{w&&setTimeout(p,d)},b=()=>{fetch(c.replace("{version}",u)).then(w=>{if(!w.ok)throw new Error("[Teek Error] Twikoo Css Link Network response was not ok");return w.text()}).then(w=>{if(document.getElementById("twikoo-css"))return;const y=document.createElement("style");y.type="text/css",y.id="twikoo-css",y.textContent=`.${t.b("twikoo")} {${w}}`,document.head.appendChild(y)})};return be(()=>{v(),b(),g.value&&n.bindAfterRouteChange(t.join("twikoo"),w=>k(w))}),(w,y)=>(m(),C("div",{class:T(l(t).b("twikoo"))},[A(" KaTeX "),l(f)?(m(),C(Y,{key:0},[S("link",{rel:"stylesheet",href:l(f).cssLink,integrity:l(f).cssIntegrity,crossorigin:"anonymous"},null,8,cx),(m(),D(Be("script"),{defer:"",src:l(f).coreJsLink,integrity:l(f).coreJsIntegrity,crossorigin:"anonymous"},null,8,["src","integrity"])),(m(),D(Be("script"),{defer:"",src:l(f).renderJsLink,integrity:l(f).renderJsIntegrity,crossorigin:"anonymous"},null,8,["src","integrity"]))],64)):A("v-if",!0),y[0]||(y[0]=S("div",{id:"twikoo"},null,-1)),(m(),D(Be("script"),{src:l(r).replace("{version}",l(u)),integrity:l(a),crossorigin:"anonymous",ref_key:"twikooJs",ref:g},null,8,["src","integrity"]))],2))}});const y2=Symbol("artalk"),fx=["href"],nl="artalk";var dx=z({name:"CommentArtalk",__name:"index",setup(e){const t=ie(),n=Is(),{getTeekConfig:s}=fe(),{isDark:o,page:i}=Ae(),r=s("comment",{}).options,{server:a,site:c,...u}=r,f=j(null),d=j(null),h=j(),p=()=>{const w=qe(y2,()=>null),y=f.value||`#${nl}`,_=w?.(y,r);return _?(h.value=_,b(),!0):!1},g=()=>{if(!me)return console.error("[Teek Error] Not in a client");const w=window.Artalk,y=f.value||`#${nl}`;if(!w||!f.value)return console.error("[Teek Error] Artalk initialization failed. Unable to load online js file from "+a);h.value=w.init({darkMode:o.value,...u,el:y,pageKey:n.route.path,pageTitle:i.value.title,server:a,site:c}),b()},v=()=>{const w=d.value;w&&(w.onload=g)},k=()=>{const w=h.value;w?.update({pageKey:n.route.path,pageTitle:i.value.title}),w?.reload()};be(()=>{if(!p()&&a)return v(),h.value&&n.bindAfterRouteChange(t.join("artalk"),()=>k());console.error("[Teek Error] Artalk initialization failed. Please configure the 'server' and 'site' or provide the artalk instance")}),cn(()=>{const w=h.value;w&&w.destroy()});const b=()=>{setTimeout(()=>{const w=h.value;w&&w.setDarkMode(o.value)},100)};return te(o,()=>b()),(w,y)=>(m(),C("div",{class:T(l(t).b("artalk"))},[l(a)?(m(),C("link",{key:0,rel:"stylesheet",href:`${l(a)}/dist/Artalk.css`,crossorigin:"anonymous"},null,8,fx)):A("v-if",!0),S("div",{id:nl,ref_key:"artalkRef",ref:f},null,512),l(a)?(m(),D(Be("script"),{key:1,src:`${l(a)}/dist/Artalk.js`,crossorigin:"anonymous",ref_key:"artalkJs",ref:d},null,8,["src"])):A("v-if",!0)],2))}});const b2=Symbol("giscus");var hx=z({name:"CommentGiscus",__name:"index",setup(e){const t=ie(),n=Is(),{getTeekConfig:s}=fe(),{isDark:o}=Ae(),i=s("comment",{}).options,{repo:r,repoId:a,category:c,categoryId:u,mapping:f="pathname",strict:d="0",reactionsEnabled:h="1",emitMetadata:p="0",inputPosition:g="top",lang:v="zh-CN",theme:k,loading:b="eager",useOnline:w=!0,link:y="https://giscus.app/client.js",integrity:_,...x}=i,L=F(()=>ht(k)?k(o.value):k||(o.value?"dark":"light")),E=qe(b2,()=>null)?.(i),I=j(!1),P=()=>{I.value=!1,Oe(()=>{I.value=!0})};return be(()=>{if(!w&&!E)return console.error("[Teek Error] Giscus initialization failed. Please configure the 'useOnline' to 'true' or provide the giscus component");P(),n.bindAfterRouteChange(t.join("giscus"),()=>{P()})}),(N,$)=>I.value?(m(),C("div",{key:0,class:T(l(t).b("giscus"))},[l(E)?(m(),D(Be(l(E)),nt({key:0,repo:l(r),"repo-id":l(a),category:l(c),"category-id":l(u),mapping:l(f),"reactions-enabled":l(h),"emit-metadata":l(p),"input-position":l(g),lang:l(v),theme:L.value,loading:l(b)},x),null,16,["repo","repo-id","category","category-id","mapping","reactions-enabled","emit-metadata","input-position","lang","theme","loading"])):l(w)?(m(),D(Be("script"),nt({key:1,defer:"",src:l(y),integrity:l(_),"data-repo":l(r),"data-repo-id":l(a),"data-category":l(c),"data-category-id":l(u),"data-mapping":l(f),"data-strict":l(d),"data-reactions-enabled":l(h),"data-emit-metadata":l(p),"data-input-position":l(g),"data-theme":L.value,"data-lang":l(v)},x,{crossorigin:"anonymous"}),null,16,["src","integrity","data-repo","data-repo-id","data-category","data-category-id","data-mapping","data-strict","data-reactions-enabled","data-emit-metadata","data-input-position","data-theme","data-lang"])):A("v-if",!0)],2)):A("v-if",!0)}});const k2=Symbol("waline"),px=["href","integrity"],sl="waline";var mx=z({name:"CommentWaline",__name:"index",setup(e){const t=ie(),n=Is(),{getTeekConfig:s}=fe(),o=s("comment",{}).options,{serverURL:i,jsLink:r,cssLink:a,dark:c="html[class='dark']",cssIntegrity:u,...f}=o;let d=null;const h=()=>{const v=qe(k2,()=>null);return v&&(d=v?.(`#${sl}`,o)),d},p=async()=>{if(!r)return;const{init:v}=await import(r);d=v({dark:c,...f,serverURL:i,el:`#${sl}`})},g=()=>{if(!me)return;const v=document.querySelector(".wl-login-nick");v&&v.removeAttribute("href")};return be(async()=>{if(!h()&&i&&r)return await p(),g(),n.bindAfterRouteChange(t.join("waline"),()=>d?.update());console.error("[Teek Error] Waline initialization failed. Please configure the 'jsLink' and 'serverURL' or provide the waline instance")}),(v,k)=>(m(),C("div",{class:T(l(t).b("waline"))},[l(a)?(m(),C("link",{key:0,rel:"stylesheet",href:l(a),integrity:l(u),crossorigin:"anonymous"},null,8,px)):A("v-if",!0),S("div",{id:sl})],2))}}),gx=z({__name:"Overlay",emits:["click"],setup(e,{emit:t}){const n=t,s=()=>n("click");return(o,i)=>(m(),C("div",{class:"code-block-overlay",onClick:s},[i[0]||(i[0]=S("span",null,"查看更多",-1)),H(l(de),{class:"overlay-icon",icon:l($h)},null,8,["icon"])]))}});const vx=e=>{const t=document.createDocumentFragment();return Br(gx,{onClick:e}).mount(t).$el},Qd="code-block",Zd="fold",e1="code-arrow";var yx=z({name:"CodeBlockToggle",__name:"index",setup(e){const t=ie(),{getTeekConfigRef:n}=fe(),s=n("codeBlock",{enabled:!0,collapseHeight:700,copiedDone:void 0,overlay:!1,overlayHeight:400,langTextTransform:""});te(s,a=>{if(!me)return;const{enabled:c=!0,langTextTransform:u}=a||{};if(!c)return document.documentElement.removeAttribute(Qd);document.documentElement.setAttribute(Qd,t.namespace),u&&document.documentElement.style.setProperty(t.cssVarName("code-block-lang-transform"),u),Oe(()=>o())},{immediate:!0});const o=()=>{const a=document.querySelectorAll(".vp-doc div[class*='language-']");Array.from(a).forEach(c=>{c.querySelector(".copy")?.addEventListener("click",()=>{s.value.copiedDone?.(Ct)});const f=c.parentElement?.className;if(f?.includes("details")||f?.includes(t.join("vp-code"))||c.querySelector(`.${e1}`))return;const h=document.createElement("div");if(h.setAttribute("aria-hidden","true"),h.classList.add(e1),h.innerHTML=$h,s.value.overlay){const p=vx(()=>h.click());c.appendChild(p)}i(h,c),c.append(h)})},i=(a,c)=>{const u=r(c);c.style.height=sn(u);const f=c.querySelector("pre"),d=c.querySelector(".line-numbers-wrapper"),h=c.querySelector(".code-block-overlay"),p={expand:{height:sn(u),display:"block",overlayDisplay:"none",speed:80},fold:{height:s.value.overlay?sn(s.value.overlayHeight)??"400px":t.cssVar("code-block-fold-height"),display:s.value.overlay?"block":"none",overlayDisplay:"flex",speed:400}};let g;const v=()=>{g&&(clearTimeout(g),g=null)},k=()=>{const w=a.classList.contains(Zd),y=p[w?"expand":"fold"];c.style.height=y.height,v(),(f||d)&&(g=setTimeout(()=>{f&&(f.style.display=y.display),d&&(d.style.display=y.display),h&&(h.style.display=y.overlayDisplay),v()},y.speed)),a.classList.toggle(Zd)};Ve(a,"click",k);const b=s.value.collapseHeight;es(b)?b?k():h&&(h.style.display="none"):b&&u>b?k():h&&(h.style.display="none")},r=a=>{const c=a.parentElement?.className||"";if(!c.includes("blocks")||c.includes("blocks")&&a.className.includes("active"))return a.offsetHeight;a.style.display="block";const u=a.offsetHeight;return a.style.display="",u};return(a,c)=>null}}),En=(e=>(e.FullWidth="fullWidth",e.SidebarWidthAdjustableOnly="sidebarWidthAdjustableOnly",e.BothWidthAdjustable="bothWidthAdjustable",e.Original="original",e))(En||{}),Us=(e=>(e.Under="under",e.Aside="aside",e))(Us||{}),Sn=(e=>(e.vpDefault="vp-default",e.vpGreen="vp-green",e.vpYellow="vp-yellow",e.vpRed="vp-red",e.epBlue="ep-blue",e.epGreen="ep-green",e.epYellow="ep-yellow",e.epRed="ep-red",e))(Sn||{});const Gr=["vp-default","vp-green","vp-yellow","vp-red","ep-blue","ep-green","ep-yellow","ep-red"],Oo="(max-width: 768px)",w2="(min-width: 1440px)",C2="(pointer: coarse)",Jr="layout-mode",Xr="theme-color",gn=ie("right-bottom-button"),bx=["title","aria-label","aria-valuenow"],kx={key:0,class:"content"};var wx=z({name:"BackTop",__name:"BackTop",setup(e){const{t}=ge(),{getTeekConfigRef:n}=fe(),s=n("backTop",{enabled:!0,content:"progress"}),o=j(0),i=F(()=>o.value>100),r=j(0),a=ts(()=>{me&&(document.querySelector("html")?.scrollIntoView({behavior:"smooth"}),setTimeout(()=>{s.value.done?.(Ct)},600))},500,!0),c=()=>{o.value=document.documentElement.scrollTop||document.body.scrollTop||0,u()},u=()=>{const f=window.scrollY/(document.documentElement.scrollHeight-window.innerHeight);r.value=Math.round(f*100)};return be(()=>{u()}),Ve(()=>window,"scroll",c),(f,d)=>(m(),D(vt,{name:l(gn).join("fade")},{default:O(()=>[M(f.$slots,"default",{show:i.value,progress:r.value,icon:l(Uf),scrollToTop:l(a)},()=>[et(S("div",{title:l(t)("tk.rightBottomButton.backTopTitle"),class:T([l(gn).e("button"),"back-top"]),onClick:d[0]||(d[0]=(...h)=>l(a)&&l(a)(...h)),style:Fe({[l(gn).cssVarName("progress")]:r.value}),role:"button","aria-label":l(t)("tk.rightBottomButton.backTopTitle"),"aria-valuenow":r.value,"aria-valuemin":"0","aria-valuemax":"100"},[l(s).content==="progress"?(m(),C("span",kx,W(r.value),1)):l(s).content==="icon"?(m(),D(l(de),{key:1,icon:l(Uf),"aria-hidden":"true"},null,8,["icon"])):A("v-if",!0)],14,bx),[[at,i.value]])])]),_:3},8,["name"]))}});const Cx=["title","aria-label"];var _x=z({name:"ToComment",__name:"ToComment",setup(e){const{t}=ge(),{getTeekConfigRef:n}=fe(),s=n("toComment",{}),o=j(0),i=F(()=>{if(!me)return!1;const c=document.querySelector(".content-container .main")?.getBoundingClientRect().height,u=document.querySelector(".VPDocFooter")?.getBoundingClientRect().height||200;let f=0;return c&&(f=c-u-window.innerHeight/2),o.value{me&&(document.querySelector(`#${gn.join("comment")}`)?.scrollIntoView({behavior:"smooth"}),setTimeout(()=>{s.value.done?.(Ct)},600))},500,!0);return Ve(()=>window,"scroll",()=>{o.value=document.documentElement.scrollTop||document.body.scrollTop||0}),(c,u)=>(m(),D(vt,{name:l(gn).join("fade")},{default:O(()=>[M(c.$slots,"default",{show:i.value,icon:l(qf),scrollToComment:l(r)},()=>[et(S("div",{title:l(t)("tk.rightBottomButton.toComment"),class:T(l(gn).e("button")),onClick:u[0]||(u[0]=(...f)=>l(r)&&l(r)(...f)),role:"button","aria-label":l(t)("tk.rightBottomButton.toComment")},[H(l(de),{icon:l(qf),"aria-hidden":"true"},null,8,["icon"])],10,Cx),[[at,i.value]])])]),_:3},8,["name"]))}});const He=ie("theme-enhance"),Fu=He.join("theme-enhance-slide"),Sx=He.cssVarName("page-max-width"),Tx=He.cssVarName("doc-max-width"),Bu=He.storageKey("layoutMode"),Ex=He.storageKey("pageMaxWidthSlide"),xx=He.storageKey("docMaxWidthSlide"),_2=He.storageKey("themeColor"),Ax=He.storageKey("themeBgColor"),S2=He.storageKey("spotlight"),T2=He.storageKey("spotlightStyle"),E2=()=>{if(!me)return;const{getTeekConfigRef:e}=fe(),t=e("themeEnhance",{}),{t:n}=ge();return F(()=>{const{customize:s=!1,append:o=[]}=t.value.themeColor||{},i=es(s)?s===!1:s?.vitepressTheme??!0,r=es(s)?s===!1:s?.elementPlusTheme??!0,a=i?[{label:n("tk.themeEnhance.themeColor.vpLabel"),tip:n("tk.themeEnhance.themeColor.vpTip"),options:[{value:Sn.vpDefault,label:n("tk.themeEnhance.themeColor.defaultLabel"),title:`VitePress ${n("tk.themeEnhance.themeColor.defaultLabel")}`,ariaLabel:`VitePress ${n("tk.themeEnhance.themeColor.defaultLabel")}`,color:getComputedStyle(document.documentElement).getPropertyValue("--vp-c-indigo-1")},{value:Sn.vpGreen,label:n("tk.themeEnhance.themeColor.greenLabel"),title:`VitePress ${n("tk.themeEnhance.themeColor.greenLabel")}`,ariaLabel:`VitePress ${n("tk.themeEnhance.themeColor.greenLabel")}`,color:getComputedStyle(document.documentElement).getPropertyValue("--vp-c-green-1")},{value:Sn.vpYellow,label:n("tk.themeEnhance.themeColor.yellowLabel"),title:`VitePress ${n("tk.themeEnhance.themeColor.yellowLabel")}`,ariaLabel:`VitePress ${n("tk.themeEnhance.themeColor.yellowLabel")}`,color:getComputedStyle(document.documentElement).getPropertyValue("--vp-c-yellow-1")},{value:Sn.vpRed,label:n("tk.themeEnhance.themeColor.redLabel"),title:`VitePress ${n("tk.themeEnhance.themeColor.redLabel")}`,ariaLabel:`VitePress ${n("tk.themeEnhance.themeColor.redLabel")}`,color:getComputedStyle(document.documentElement).getPropertyValue("--vp-c-red-1")}]}]:[],c=r?[{label:n("tk.themeEnhance.themeColor.epLabel"),tip:n("tk.themeEnhance.themeColor.epTip"),options:[{value:Sn.epBlue,label:`${n("tk.themeEnhance.themeColor.blueLabel")}`,title:`ElementPlus ${n("tk.themeEnhance.themeColor.blueLabel")}`,ariaLabel:`ElementPlus ${n("tk.themeEnhance.themeColor.blueLabel")}`,color:getComputedStyle(document.documentElement).getPropertyValue("--tk-el-color-primary")},{value:Sn.epGreen,label:`${n("tk.themeEnhance.themeColor.greenLabel")}`,title:`ElementPlus ${n("tk.themeEnhance.themeColor.greenLabel")}`,ariaLabel:`ElementPlus ${n("tk.themeEnhance.themeColor.greenLabel")}`,color:getComputedStyle(document.documentElement).getPropertyValue("--tk-el-color-success")},{value:Sn.epYellow,label:`${n("tk.themeEnhance.themeColor.yellowLabel")}`,title:`ElementPlus ${n("tk.themeEnhance.themeColor.yellowLabel")}`,ariaLabel:`ElementPlus ${n("tk.themeEnhance.themeColor.yellowLabel")}`,color:getComputedStyle(document.documentElement).getPropertyValue("--tk-el-color-warning")},{value:Sn.epRed,label:`${n("tk.themeEnhance.themeColor.redLabel")}`,title:`ElementPlus ${n("tk.themeEnhance.themeColor.redLabel")}`,ariaLabel:`ElementPlus ${n("tk.themeEnhance.themeColor.redLabel")}`,color:getComputedStyle(document.documentElement).getPropertyValue("--tk-el-color-danger")}]}]:[];return[...a,...c,...o]})},$x=["title","aria-label"],Lx=["onClick","title","aria-label"];var Ix=z({name:"ThemeColor",__name:"ThemeColor",setup(e){const{t}=ge(),{frontmatter:n}=Ae(),{getTeekConfigRef:s}=fe(),o=s("themeEnhance",{}),i=bn(_2,o.value.themeColor?.defaultColorName||Sn.vpDefault),r=j(i.value),a=j(""),{clear:c}=Wh(a,()=>{if(Gr.includes(i.value))return[on.vpBrand1,on.vpBrand2,on.vpBrand3,on.vpBrandSoft]}),u=E2(),f=h=>{if(!me)return;const p=document.documentElement;if(i.value=h,p.getAttribute(Xr)!==h){if(p.setAttribute(Xr,h),Gr.includes(h))c(),a.value=getComputedStyle(p).getPropertyValue(on.vpBrand1);else{const k=(o.value.themeColor?.append||[]).map(b=>b.options).flat().filter(b=>b.value===h)[0]?.color;!k&&c(),a.value=k||getComputedStyle(p).getPropertyValue(on.vpBrand1)}o.value.themeColor?.switchColorDone?.(h)}};te(i,f,{immediate:!0}),te(()=>n.value.themeColorName,h=>{h?(r.value=i.value,i.value=h):i.value=r.value},{immediate:!0}),be(()=>{n.value.themeColor?f(n.value.themeColor):f(i.value)});const d=h=>{i.value=h.value};return(h,p)=>(m(),D(l(Ia),{class:T(l(gn).e("button")),"popper-class":l(gn).e("dropdown"),placement:"left-start",width:120,"x-offset":15,"transition-name":l(gn).join("fade-scale"),title:l(t)("tk.themeEnhance.themeColor.title"),role:"button","aria-label":l(t)("tk.themeEnhance.themeColor.title")},{reference:O(()=>[H(l(de),{icon:l(e9),"aria-hidden":"true"},null,8,["icon"])]),default:O(()=>[(m(!0),C(Y,null,le(l(u),g=>(m(),C("ul",{key:g.label},[S("li",{class:T(`${l(gn).e("dropdown__title")} sle`),title:g.tip,"aria-label":g.label},W(g.label),11,$x),S("li",null,[S("ul",null,[(m(!0),C(Y,null,le(g.options,v=>(m(),C("li",{key:g.label+v.value,class:T(["dropdown-item","sle",{active:v.value===l(i)}]),onClick:k=>d(v),role:"button",title:v.title,"aria-label":v.ariaLabel??v.title??v.label},W(v.label),11,Lx))),128))])])]))),128))]),_:1},8,["class","popper-class","transition-name","title","aria-label"]))}}),Px=z({name:"RightBottomButton",__name:"index",setup(e){const{getTeekConfigRef:t}=fe(),n=t("backTop",{enabled:!0}),s=t("toComment",{enabled:!0}),o=t("themeEnhance",{enabled:!0}),i=t(null,{comment:{provider:""}}),{frontmatter:r}=Ae(),a=F(()=>{const f=r.value.comment??i.value.comment;if(es(f))return{enabled:f};const d=qe(y2,null),h=qe(b2,null),p=qe(v2,null),g=qe(k2,null);return d||h||p||g?{enabled:!0}:{enabled:!0,provider:f.provider}}),c=Xt(Oo),u=F(()=>{const{enabled:f=!0,themeColor:d={},position:h="top"}=o.value,p=d.disabled??d.disabledInMobile;return f?p!==void 0?p:!c.value&&h==="top":!0});return(f,d)=>(m(),C("div",{class:T([l(gn).b(),l(gn).join("wallpaper-outside"),"flx-column"])},[M(f.$slots,"teek-right-bottom-before"),l(n).enabled?(m(),D(wx,{key:0},{default:O(h=>[M(f.$slots,"teek-back-top",Ge(Ze(h)))]),_:3})):A("v-if",!0),l(s).enabled&&(a.value.enabled||a.value.provider)?(m(),D(_x,{key:1},{default:O(h=>[M(f.$slots,"teek-to-comment",Ge(Ze(h)))]),_:3})):A("v-if",!0),u.value?A("v-if",!0):(m(),D(Ix,{key:2})),M(f.$slots,"teek-right-bottom-after")],2))}});const Mx=["aria-label"],Fx=["aria-label"],Bx=["aria-label"],Nx={class:"flx-align-center"},Vx={id:"notice-title",class:"title sle"},Ox=["aria-label"];var Dx=z({name:"Notice",__name:"index",setup(e){const t=ie("notice"),{t:n}=ge(),{getTeekConfigRef:s}=fe(),o=Is(),{localeIndex:i}=Ae(),r=s("notice",{noticeStyle:void 0,iconStyle:{},popoverStyle:{},title:n("tk.notice.title"),initOpen:!0,duration:0,mobileMinify:!1,reopen:!0,useStorage:!0,twinkle:!1,position:"top",noticeIcon:Y7,closeIcon:Jc,onAfterRouteChange:void 0}),a=j(!1),c=F(()=>!u.value&&!a.value),u=j(r.value.initOpen);te(()=>r.value.initOpen,_=>u.value=_);const f=F(()=>{const{noticeStyle:_}=r.value;return _?_.trim().startsWith(`.${t.b()}`)?_:`.${t.b()} { ${_} }`:""}),d=F(()=>{const{title:_}=r.value;return Je(_)?_:_(i.value)}),{isMobile:h}=Qh();te(()=>r.value.mobileMinify,_=>{h.value&&(a.value=_)},{immediate:!0});let p;const g=()=>{const{duration:_}=r.value;u.value&&_>0&&(p&&(clearTimeout(p),p=null),p=setTimeout(w,_))};be(()=>{o.bindAfterRouteChange(t.join("notice"),()=>r.value.onAfterRouteChange?.(o.route,c.value,u.value)),g()});const v=_=>{if(!me||r.value.position!=="center")return;const x={open:"remove",disable:"add"};document.documentElement.classList[x[_]]("disable-scroll")},k=F(()=>t.storageKey("notice",i.value,me?window.location.hostname:""));r.value.useStorage&&te(i,()=>{if(!r.value.useStorage)return;const _=localStorage.getItem(k.value);if(_){const x=_==="true";u.value=x,x&&v("disable")}},{immediate:!0});const b=()=>{u.value=!0,y("true"),g(),v("disable")},w=()=>{u.value=!1,y("false"),r.value.reopen||(a.value=!0),p&&clearTimeout(p),v("open")},y=_=>{r.value.useStorage&&localStorage.setItem(k.value,_)};return(_,x)=>(m(),C("div",{class:T([l(t).b(),l(t).join("wallpaper-outside")]),"aria-label":l(n)("tk.notice.label")},[f.value?(m(),D(Be("style"),{key:0},{default:O(()=>[rt(W(f.value),1)]),_:1})):A("v-if",!0),A(" 公告图标 "),a.value?A("v-if",!0):et((m(),C("div",{key:1,class:T([l(t).e("icon"),{twinkle:l(r).twinkle},"flx"]),style:Fe(l(r).iconStyle),onClick:b,role:"button","aria-label":l(n)("tk.notice.openLabel")},[H(l(de),{icon:l(r).noticeIcon,color:"#ffffff",size:"14px","aria-hidden":"true"},null,8,["icon"])],14,Fx)),[[at,c.value]]),A(" 公告弹窗 "),et(S("div",{class:T([l(t).e("popover"),l(t).is(l(r).position)]),style:Fe(l(r).popoverStyle),role:"dialog","aria-modal":!0,"aria-labelledby":"notice-title"},[M(_.$slots,"header",{},()=>[S("div",{class:T([l(t).e("popover__header"),"flx-justify-between"]),"aria-label":l(n)("tk.notice.headLabel")},[S("div",Nx,[H(l(de),{icon:l(r).noticeIcon,color:"#ffffff",size:"20px","aria-hidden":"true"},null,8,["icon"]),S("span",Vx,W(d.value),1)]),H(l(de),{icon:l(r).closeIcon,color:"#ffffff",size:"20px",class:T(l(t).join("pointer")),onClick:w,role:"button","aria-label":l(n)("tk.notice.closeLabel")},null,8,["icon","class","aria-label"])],10,Bx)]),S("div",{class:T(l(t).e("popover__content")),"aria-label":l(n)("tk.notice.contentLabel")},[M(_.$slots,"teek-notice-content")],10,Ox)],6),[[at,u.value]]),A(" 遮罩层,与公告弹窗一起出现 "),et(S("div",{class:T(l(t).e("mask")),role:"presentation"},null,2),[[at,u.value&&l(r).position==="center"]])],10,Mx))}});const Rx=["title","disabled"],Hx=["value","name","disabled","checked","aria-checked"],zx={key:1};var jx=z({name:"SegmentedItem",__name:"SegmentedItem",props:$n({disabled:{type:Boolean},value:{type:[String,Number,Object,Boolean]},label:{},icon:{},title:{},name:{}},{modelValue:{type:[String,Number,Object,Boolean]},modelModifiers:{}}),emits:["update:modelValue"],setup(e){const t=ie("segmented-item"),n=Jt(e,"modelValue");return(s,o)=>(m(),C("label",{class:T([l(t).b(),l(t).is("active",n.value===e.value&&!e.disabled),l(t).is("disabled",e.disabled)]),title:e.title,disabled:e.disabled},[et(S("input",{"onUpdate:modelValue":o[0]||(o[0]=i=>n.value=i),type:"radio",value:e.value,name:e.name,disabled:e.disabled,checked:n.value===e.value,"aria-checked":n.value===e.value,role:"radio",style:{display:"none"}},null,8,Hx),[[ga,n.value]]),S("span",{class:T(l(t).e("content"))},[e.icon?(m(),D(l(de),{key:0,icon:e.icon,"aria-hidden":"true"},null,8,["icon"])):A("v-if",!0),e.label?(m(),C("span",zx,W(e.label),1)):A("v-if",!0)],2)],10,Rx))}}),Nu=z({name:"Segmented",__name:"Segmented",props:$n({options:{},disabled:{type:Boolean}},{modelValue:{type:[String,Number,Object,Boolean]},modelModifiers:{}}),emits:["update:modelValue"],setup(e){const t=ie("segmented"),n=Jt(e,"modelValue");return(s,o)=>(m(),C("fieldset",{class:T(l(t).b())},[(m(!0),C(Y,null,le(e.options,i=>(m(),D(jx,nt({key:i.name,modelValue:n.value,"onUpdate:modelValue":o[0]||(o[0]=r=>n.value=r)},{ref_for:!0},i,{disabled:e.disabled}),null,16,["modelValue","disabled"]))),128))],2))}});const Vu=(e=1e3,t=!1)=>{let n=null;const s=()=>{n&&(clearTimeout(n),n=null)},o=()=>{if(me){if(!t){t=!0;return}s(),document.documentElement.setAttribute(`${Jr}-animated`,"true"),n=setTimeout(()=>{document.documentElement.removeAttribute(`${Jr}-animated`)},Se(e))}};return Un(s),{start:o,stop:s}},Ux={key:0};var Wx=z({__name:"Title",props:{title:{},disabled:{type:Boolean},icon:{}},setup(e){return(t,n)=>(m(),C("div",{class:T([l(He).e("title"),l(He).is("disabled",!!e.disabled)])},[M(t.$slots,"icon",{},()=>[e.icon?(m(),D(l(de),{key:0,icon:e.icon,size:16},null,8,["icon"])):A("v-if",!0)]),M(t.$slots,"default",{},()=>[e.title?(m(),C("span",Ux,W(e.title),1)):A("v-if",!0)])],2))}}),qx=z({name:"Helper",__name:"Helper",props:$n({triggerEl:{}},{modelValue:{default:!1},modelModifiers:{}}),emits:["update:modelValue"],setup(e){const t=Jt(e,"modelValue"),n=j(t.value);return te(n,s=>{t.value=s}),(s,o)=>(m(),D(l(Ia),{class:T(l(He).e("helper")),modelValue:n.value,"onUpdate:modelValue":o[0]||(o[0]=i=>n.value=i),"trigger-el":e.triggerEl,placement:"left-start"},{reference:O(()=>[H(l(de),{icon:l(v9),size:16},null,8,["icon"])]),default:O(()=>[S("div",{class:T(l(He).e("helper__popup"))},[M(s.$slots,"default")],2)]),_:3},8,["class","modelValue","trigger-el"]))}}),Kx=z({name:"BorderHighlight",__name:"BorderHighlight",props:{active:{type:Boolean}},setup(e){const t=ie("border-highlight");return(n,s)=>(m(),C("div",{class:T([l(t).b(),l(t).is("active",!!e.active)])},[M(n.$slots,"default")],2))}});const Yx={class:"flx-align-center",style:{"margin-bottom":"6px"}},Gx={key:1,style:{"font-weight":"600"}},Jx={key:0},Xx={key:1,style:{"margin-top":"8px"}};var Do=z({name:"BaseTemplate",__name:"BaseTemplate",props:{title:{},helperDesc:{},icon:{},tips:{},disabled:{type:Boolean},helper:{type:Boolean},borderHighlight:{type:Boolean,default:!0}},setup(e){const t=j(!1),n=j();return(s,o)=>(m(),C("div",null,[S("div",{ref_key:"titleElementRef",ref:n,class:"flx-align-center"},[H(Wx,{title:e.title,icon:e.icon,disabled:e.disabled,"aria-label":e.title},{default:O(()=>[M(s.$slots,"title")]),_:3},8,["title","icon","disabled","aria-label"]),e.helper?(m(),D(qx,{key:0,modelValue:t.value,"onUpdate:modelValue":o[0]||(o[0]=i=>t.value=i),"trigger-el":n.value},{default:O(()=>[S("div",{class:T(l(He).e("helper__body"))},[S("h4",{class:T(l(He).em("helper","title"))},[M(s.$slots,"helper-title",{},()=>[rt(W(e.title),1)])],2),S("p",{class:T(l(He).em("helper","desc"))},[M(s.$slots,"helper-desc",{},()=>[rt(W(e.helperDesc),1)])],2),(m(!0),C(Y,null,le(e.tips,(i,r)=>(m(),C("div",{key:r,class:T(l(He).e("helper__body__tip"))},[S("div",Yx,[i.icon?(m(),D(l(de),{key:0,icon:i.icon,size:16,style:{"margin-right":"4px"}},null,8,["icon"])):A("v-if",!0),i.title?(m(),C("span",Gx,W(i.title),1)):A("v-if",!0)]),i.content?(m(),C("span",Jx,W(i.content),1)):A("v-if",!0)],2))),128))],2)]),_:3},8,["modelValue","trigger-el"])):A("v-if",!0)],512),e.borderHighlight?(m(),D(Kx,{key:0,active:t.value,style:{"margin-top":"8px"}},{default:O(()=>[M(s.$slots,"default")]),_:3},8,["active"])):(m(),C("div",Xx,[M(s.$slots,"default")]))]))}}),Qx=z({name:"LayoutSwitch",__name:"LayoutSwitch",setup(e){const{getTeekConfigRef:t}=fe(),n=t("themeEnhance",{}),{t:s}=ge(),{frontmatter:o}=Ae(),i=bn(Bu,n.value.layoutSwitch?.defaultMode||En.Original),r=Xt(Oo),a=j(i.value),{start:c}=Vu();te(i,p=>{if(!me)return;const{layoutSwitch:g}=n.value;g?.disableAnimation||c();const v=document.documentElement;v.getAttribute(Jr)!==p&&(v.setAttribute(Jr,p),n.value.layoutSwitch?.switchModeDone?.(p))},{immediate:!0}),te(()=>o.value.layoutMode,p=>{p?(a.value=i.value,i.value=p):i.value=a.value},{immediate:!0}),te(()=>n.value.layoutSwitch?.defaultMode,p=>{p&&(i.value=p)});const f=F(()=>[{value:En.FullWidth,title:s("tk.themeEnhance.layoutSwitch.fullWidthTipTitle"),tipContent:s("tk.themeEnhance.layoutSwitch.fullWidthHelpTipContent"),icon:k9},{value:En.SidebarWidthAdjustableOnly,title:s("tk.themeEnhance.layoutSwitch.sidebarWidthAdjustableOnlyTipTitle"),tipContent:s("tk.themeEnhance.layoutSwitch.sidebarWidthAdjustableOnlyHelpTipContent"),icon:w9},{value:En.BothWidthAdjustable,title:s("tk.themeEnhance.layoutSwitch.bothWidthAdjustableTipTitle"),tipContent:s("tk.themeEnhance.layoutSwitch.bothWidthAdjustableHelpTipContent"),icon:Fh},{value:En.Original,title:s("tk.themeEnhance.layoutSwitch.originalWidthTipTitle"),tipContent:s("tk.themeEnhance.layoutSwitch.originalWidthHelpTipContent"),icon:_9}]),d=F(()=>f.value.map(p=>({value:p.value,title:p.title,ariaLabel:p.title,icon:p.icon}))),h=F(()=>f.value.map(p=>({title:p.title,icon:p.icon,content:p.tipContent})));return(p,g)=>(m(),D(Do,{icon:l(C9),title:l(s)("tk.themeEnhance.layoutSwitch.title"),helper:!l(n).layoutSwitch?.disableHelp,"helper-desc":l(s)("tk.themeEnhance.layoutSwitch.helpDesc"),tips:h.value,disabled:l(r)},{default:O(()=>[H(l(Nu),{modelValue:l(i),"onUpdate:modelValue":g[0]||(g[0]=v=>Ye(i)?i.value=v:null),options:d.value,disabled:l(r)},null,8,["modelValue","options","disabled"])]),_:1},8,["icon","title","helper","helper-desc","tips","disabled"]))}});const Zx=["name","min","max","disabled","step"];var x2=z({name:"InputSlide",__name:"index",props:$n({name:{default:"Slider"},disabled:{type:Boolean},min:{default:0},max:{default:100},step:{default:1},format:{type:Function}},{modelValue:{default:0},modelModifiers:{}}),emits:["update:modelValue"],setup(e){const t=ie("input-slide"),n=Jt(e,"modelValue"),s=j(),o=j(),i=Pl(s),r=j(!1),a=t.cssVarName("slider-value"),c=t.cssVarName("slider-min"),u=t.cssVarName("slider-max");Ve(s,"input",()=>{s.value&&s.value.style.setProperty(a,s.value.value.toString())}),be(()=>{if(!s.value)return;const d=s.value.style;d.setProperty(a,n.value.toString()),d.setProperty(c,e.min?.toString()??"0"),d.setProperty(u,e.max?.toString()??"100")});const f=(d,h)=>{const p=e.max||100,g=e.min||0,v=(n.value-g)/(p-g),k=d.getBoundingClientRect(),w=(h.getBoundingClientRect().width-32)/2;h.style.setProperty("left",`${v*(k.width-32)-w}px`)};return te(i,()=>{r.value=!0,setTimeout(()=>{if(!i.value){r.value=!1;return}if(!s.value){r.value=!1;return}if(!o.value){r.value=!1;return}f(s.value,o.value),r.value=!1},50)}),te(n,d=>{de.max&&(d=e.max),!(!s.value||!o.value)&&f(s.value,o.value)}),te(()=>e.min,d=>{n.value>=d||(n.value=d)}),te(()=>e.max,d=>{n.value<=d||(n.value=d)}),(d,h)=>(m(),C("div",{class:T(l(t).b())},[S("label",{class:T(l(t).e("label"))},[et(S("input",{ref_key:"inputSliderRef",ref:s,"onUpdate:modelValue":h[0]||(h[0]=p=>n.value=p),type:"range",name:e.name,min:e.min,max:e.max,disabled:e.disabled,step:e.step,class:T([l(t).e("label__input"),l(t).e("label__input-progress"),l(t).is("disabled",e.disabled)])},null,10,Zx),[[_o,n.value,void 0,{number:!0}]]),H(vt,{name:"fade",persisted:""},{default:O(()=>[et(S("span",{ref_key:"inputSliderTooltipRef",ref:o,class:T([l(t).e("label__tooltip"),l(t).is("opacity-0",l(i)&&r.value)])},W(e.format?e.format(n.value):n.value),3),[[at,l(i)]])]),_:1})],2)],2))}}),eA=z({name:"LayoutPageWidthSlide",__name:"LayoutPageWidthSlide",setup(e){const{getTeekConfigRef:t}=fe(),n=t("themeEnhance",{}),{t:s}=ge(),o=F(()=>6e3),i=F(()=>1e4),r=bn(Ex,(n.value.layoutSwitch?.defaultPageMaxWidth||90)*100),a=bn(Bu,n.value.layoutSwitch?.defaultMode||En.Original),{start:c}=Vu(),u=v=>{me&&(n.value.layoutSwitch?.disableAnimation||c(),document.body.style.setProperty(Sx,`${Math.ceil(v/100)}%`))},f=Xt(Oo),d=Xt(w2);te(d,()=>{u(r.value)});const h=ts(u,1e3);te(r,h);const p=v=>`${Math.ceil(v/100)}%`,g=[{title:s("tk.themeEnhance.pageLayoutMaxWidth.helpTipTitle"),icon:Dh,content:s("tk.themeEnhance.pageLayoutMaxWidth.helpTipContent")}];return(v,k)=>(m(),D(vt,{name:l(Fu),persisted:""},{default:O(()=>[et(H(Do,{icon:l(Or),title:l(s)("tk.themeEnhance.pageLayoutMaxWidth.title"),helper:!l(n).layoutSwitch?.disablePageMaxWidthHelp,"helper-desc":l(s)("tk.themeEnhance.pageLayoutMaxWidth.helpDesc"),tips:g,disabled:l(f)},{default:O(()=>[H(l(x2),{modelValue:l(r),"onUpdate:modelValue":k[0]||(k[0]=b=>Ye(r)?r.value=b:null),disabled:l(f),min:o.value,max:i.value,format:p,class:T(l(He).e("slide")),"aria-label":l(s)("tk.themeEnhance.pageLayoutMaxWidth.helperTipTitle")},null,8,["modelValue","disabled","min","max","class","aria-label"])]),_:1},8,["icon","title","helper","helper-desc","disabled"]),[[at,l(a)===l(En).SidebarWidthAdjustableOnly||l(a)===l(En).BothWidthAdjustable]])]),_:1},8,["name"]))}}),tA=z({name:"LayoutDocWidthSlide",__name:"LayoutDocWidthSlide",setup(e){const{getTeekConfigRef:t}=fe(),n=t("themeEnhance",{}),{t:s}=ge(),o=F(()=>6e3),i=F(()=>1e4),r=bn(xx,(n.value.layoutSwitch?.defaultDocMaxWidth||95)*100),a=bn(Bu,n.value.layoutSwitch?.defaultMode||En.Original),{start:c}=Vu(),u=v=>{if(!me)return;n.value.layoutSwitch?.disableAnimation||c();const k=document.body.style;d.value||k.setProperty(He.join("page-max-width"),"100%"),k.setProperty(Tx,`${Math.ceil(v/100)}%`)},f=Xt(Oo),d=Xt(w2);te(d,()=>{u(r.value)});const h=ts(u,1e3);te(r,h);const p=v=>`${Math.ceil(v/100)}%`,g=[{title:s("tk.themeEnhance.docLayoutMaxWidth.helpTipTitle"),icon:Dh,content:s("tk.themeEnhance.docLayoutMaxWidth.helpTipContent")}];return(v,k)=>(m(),D(vt,{name:l(Fu),persisted:""},{default:O(()=>[et(H(Do,{icon:l(Or),title:l(s)("tk.themeEnhance.docLayoutMaxWidth.title"),helper:!l(n).layoutSwitch?.disableDocMaxWidthHelp,"helper-desc":l(s)("tk.themeEnhance.docLayoutMaxWidth.helpDesc"),tips:g,disabled:l(f)},{default:O(()=>[H(l(x2),{modelValue:l(r),"onUpdate:modelValue":k[0]||(k[0]=b=>Ye(r)?r.value=b:null),disabled:l(f),min:o.value,max:i.value,format:p,class:T(l(He).e("slide")),"aria-label":l(s)("tk.themeEnhance.docLayoutMaxWidth.helperTipTitle")},null,8,["modelValue","disabled","min","max","class","aria-label"])]),_:1},8,["icon","title","helper","helper-desc","disabled"]),[[at,l(a)===l(En).BothWidthAdjustable]])]),_:1},8,["name"]))}}),nA=z({__name:"Switch",props:{modelValue:{default:!1},modelModifiers:{}},emits:["update:modelValue"],setup(e){const t=Jt(e,"modelValue"),n=()=>{t.value=!t.value};return(s,o)=>(m(),C("span",{class:T([l(He).e("switch"),l(He).is("checked",t.value)]),onClick:n},[...o[0]||(o[0]=[S("div",{class:"action"},null,-1)])],2))}});const sA={class:"flx-justify-between flx-1"},oA={class:"flx-align-center"},iA={class:"label"},rA=["title","aria-label"],aA={class:"color-list flx-justify-between flx-wrap"},lA=["onClick","title","aria-label"];var cA=z({name:"ThemeColor",__name:"ThemeColor",setup(e){const{getTeekConfigRef:t}=fe(),n=t("themeEnhance",{}),{t:s}=ge(),{frontmatter:o}=Ae(),i=Xt(Oo),r=bn(_2,n.value.themeColor?.defaultColorName||Sn.vpDefault),a=bn(Ax,n.value.themeColor?.defaultSpread||!1),c=j(r.value),u=j(""),{clear:f,updateSpread:d}=Wh(u,()=>{if(Gr.includes(r.value))return[on.vpBrand1,on.vpBrand2,on.vpBrand3,on.vpBrandSoft]}),h=E2();te(r,b=>{if(!me)return;const w=document.documentElement;if(w.getAttribute(Xr)!==b){if(w.setAttribute(Xr,b),Gr.includes(b))f(),u.value=getComputedStyle(w).getPropertyValue(on.vpBrand1);else{const x=(n.value.themeColor?.append||[]).map(L=>L.options).flat().filter(L=>L.value===b)[0]?.color;!x&&f(),u.value=x||getComputedStyle(w).getPropertyValue(on.vpBrand1)}n.value.themeColor?.switchColorDone?.(b)}},{immediate:!0}),te(()=>o.value.themeColorName,b=>{b?(c.value=r.value,r.value=b):r.value=c.value},{immediate:!0}),te(a,d,{immediate:!0,flush:"post"});const g=[{title:s("tk.themeEnhance.themeColor.vpHelpTipTitle"),content:s("tk.themeEnhance.themeColor.vpHelpTipContent")},{title:s("tk.themeEnhance.themeColor.epHelpTipTitle"),content:s("tk.themeEnhance.themeColor.epHelpTipContent")}],v=b=>{r.value=b.value},k=b=>b?{backgroundColor:b}:{};return(b,w)=>(m(),D(Do,{class:T(l(He).e("theme-color")),icon:l(E9),title:l(s)("tk.themeEnhance.themeColor.title"),helper:!l(n).themeColor?.disableHelp,"helper-desc":l(s)("tk.themeEnhance.themeColor.helpDesc"),tips:g,disabled:l(i)},{title:O(()=>[S("div",sA,[rt(W(l(s)("tk.themeEnhance.themeColor.title"))+" ",1),S("div",oA,[S("span",iA,W(l(s)("tk.themeEnhance.themeColor.speedLabel")),1),H(nA,{modelValue:l(a),"onUpdate:modelValue":w[0]||(w[0]=y=>Ye(a)?a.value=y:null)},null,8,["modelValue"])])])]),default:O(()=>[(m(!0),C(Y,null,le(l(h),y=>(m(),C(Y,{key:y.label},[S("h3",{title:y.tip,"aria-label":y.label},W(y.label),9,rA),S("ul",aA,[(m(!0),C(Y,null,le(y.options,_=>(m(),C("li",{key:y.label+_.value,class:"flx-column-center",onClick:x=>v(_),title:_.title,"aria-label":_.ariaLabel??_.title??_.label},[S("div",{class:T(["color-wrapper flx-center",l(He).is("active",_.value===l(r))])},[S("div",{class:"color-bg",style:Fe(k(_.color))},null,4)],2),S("span",null,W(_.label),1)],8,lA))),128))])],64))),128))]),_:1},8,["class","icon","title","helper","helper-desc","disabled"]))}}),uA=z({name:"SpotlightHover",__name:"SpotlightHover",props:{enabled:{type:Boolean}},setup(e){const t=e,n=j(!1),s=j({display:"none"}),o=j(),i=j(),r=bn(T2,Us.Aside),a=j({x:0,y:0}),c=h=>({display:"block",width:`${h.width+8}px`,height:`${h.height+8}px`,left:`${h.left-4}px`,top:`${h.top-4}px`,transition:"all 0.2s ease",borderRadius:"8px"}),u=h=>h===null?null:h.parentElement===document.querySelector(".VPDoc main .vp-doc > div")?h:u(h.parentElement),f=()=>{if(!me)return;const h=document.elementFromPoint(a.value.x,a.value.y);if(!(h&&o.value?.contains(h)))return;const p=u(h);if(i.value=p||void 0,i.value&&i.value.tagName==="P"){const g=i.value,v=window.getComputedStyle(g),k=Number.parseFloat(v.lineHeight),b=Math.floor(g.offsetHeight/k),w=g.getBoundingClientRect(),y=a.value.y-w.top;for(let _=0;_=x&&ydocument,"mousemove",h=>{a.value={x:h.clientX,y:h.clientY}}),Ve(()=>document,"scroll",f,!0),be(()=>{o.value=document.querySelector(".VPDoc main .vp-doc")});const d=kn();return te(d,()=>{o.value=document.querySelector(".VPDoc main .vp-doc"),n.value=!0,s.value={display:"none"},f(),n.value=!1},{flush:"post"}),te([()=>a.value.x,()=>a.value.y],()=>{t.enabled&&f()}),te(()=>t.enabled,h=>{h||(s.value={display:"none"})}),(h,p)=>(m(),D(ca,{to:"body"},[t.enabled&&!n.value?(m(),C("div",{key:0,style:Fe(s.value),class:T([l(He).join("spotlight-hover"),l(r)===l(Us).Under?l(He).join("spotlight-hover__under"):"",l(r)===l(Us).Aside?l(He).join("spotlight-hover__aside"):""]),"aria-hidden":"true",focusable:"false"},null,6)):A("v-if",!0)]))}}),fA=z({name:"Spotlight",__name:"Spotlight",setup(e){const{getTeekConfigRef:t}=fe(),n=t("themeEnhance",{}),{t:s}=ge(),{frontmatter:o}=Ae(),i=Xt(C2),r=bn(S2,n.value.spotlight?.defaultValue??!0),a=j(r.value);te(()=>o.value.spotlight,f=>{f!==void 0?(a.value=r.value,r.value=f):r.value=a.value},{immediate:!0});const c=F(()=>[{value:!0,label:"ON",title:s("tk.themeEnhance.spotlight.onTipTitle"),ariaLabel:s("tk.themeEnhance.spotlight.onTipTitle")},{value:!1,label:"OFF",title:s("tk.themeEnhance.spotlight.offTipTitle"),ariaLabel:s("tk.themeEnhance.spotlight.offTipTitle")}]),u=[{title:`ON ${s("tk.themeEnhance.spotlight.onTipTitle")}`,content:s("tk.themeEnhance.spotlight.onHelpTipContent")},{title:`OFF ${s("tk.themeEnhance.spotlight.offTipTitle")}`,content:s("tk.themeEnhance.spotlight.offHelpTipContent")}];return(f,d)=>(m(),C(Y,null,[H(Do,{icon:l(Oh),title:l(s)("tk.themeEnhance.spotlight.title"),helper:!l(n).spotlight?.disableHelp,"helper-desc":l(s)("tk.themeEnhance.spotlight.helpDesc"),tips:u,disabled:l(i)},{default:O(()=>[H(l(Nu),{modelValue:l(r),"onUpdate:modelValue":d[0]||(d[0]=h=>Ye(r)?r.value=h:null),options:c.value,disabled:l(i)},null,8,["modelValue","options","disabled"])]),_:1},8,["icon","title","helper","helper-desc","disabled"]),l(r)&&!l(i)?(m(),D(uA,{key:0,enabled:l(r)&&!l(i)},null,8,["enabled"])):A("v-if",!0)],64))}}),dA=z({name:"SpotlightStyle",__name:"SpotlightStyle",setup(e){const{getTeekConfigRef:t}=fe(),n=t("themeEnhance",{}),{t:s}=ge(),o=bn(T2,n.value.spotlight?.defaultStyle||Us.Aside),i=bn(S2,n.value.spotlight?.defaultValue??!0),r=Xt(C2),a=F(()=>[{value:Us.Aside,title:s("tk.themeEnhance.spotlightStyles.asideTipTitle"),helpMessage:s("tk.themeEnhance.spotlightStyles.asideHelpTipContent"),ariaLabel:s("tk.themeEnhance.spotlightStyles.asideTipTitle"),icon:T9},{value:Us.Under,title:s("tk.themeEnhance.spotlightStyles.underTipTitle"),helpMessage:s("tk.themeEnhance.spotlightStyles.underHelpTipContent"),ariaLabel:s("tk.themeEnhance.spotlightStyles.underTipTitle"),icon:S9}]),c=F(()=>a.value.map(f=>({value:f.value,title:f.title,ariaLabel:f.ariaLabel,icon:f.icon}))),u=F(()=>a.value.map(f=>({title:f.title,icon:f.icon,content:f.helpMessage})));return(f,d)=>(m(),D(vt,{name:l(Fu)},{default:O(()=>[l(i)?(m(),D(Do,{key:0,icon:l(Oh),title:l(s)("tk.themeEnhance.spotlightStyles.title"),helper:!l(n).spotlight?.disableHelp,"helper-desc":l(s)("tk.themeEnhance.spotlightStyles.helpDesc"),tips:u.value,disabled:l(r)},{default:O(()=>[H(l(Nu),{modelValue:l(o),"onUpdate:modelValue":d[0]||(d[0]=h=>Ye(o)?o.value=h:null),options:c.value,disabled:l(r)},null,8,["modelValue","options","disabled"])]),_:1},8,["icon","title","helper","helper-desc","tips","disabled"])):A("v-if",!0)]),_:1},8,["name"]))}}),hA=z({name:"ThemeEnhance",__name:"index",setup(e){const{getTeekConfigRef:t}=fe(),n=t("themeEnhance",{position:"top"}),s=Xt(Oo),o=F(()=>({layoutSwitch:n.value.layoutSwitch?.disabled??!1,themeColor:n.value.themeColor?.disabled??!1,spotlight:n.value.spotlight?.disabled??!1}));return(i,r)=>!l(s)&&l(n).position==="top"?(m(),D(l(Ia),{key:0,class:T([l(He).b(),"flx-align-center"]),"popper-class":l(He).e("popover"),"y-offset":-15},{reference:O(()=>[H(l(de),{icon:l(Lh),size:20},null,8,["icon"])]),default:O(()=>[S("div",{class:T(l(He).e("content"))},[M(i.$slots,"teek-theme-enhance-top"),o.value.layoutSwitch?A("v-if",!0):(m(),C(Y,{key:0},[H(Qx),H(eA),H(tA)],64)),o.value.themeColor?A("v-if",!0):(m(),D(cA,{key:1})),o.value.spotlight?A("v-if",!0):(m(),C(Y,{key:2},[H(fA),H(dA)],64)),M(i.$slots,"teek-theme-enhance-bottom")],2)]),_:3},8,["class","popper-class"])):A("v-if",!0)}});const pA={key:0,class:"custom-block-title"},mA=["innerHTML"],gA={key:1},vA=["innerHTML"];var t1=z({name:"VpContainer",__name:"index",props:{type:{default:"tip"},title:{},text:{default:""}},setup(e){const t=ie("vp-container"),n=Ti(),s=F(()=>e.title||n.title),o=F(()=>e.text||n.default);return(i,r)=>s.value||o.value?(m(),C("div",{key:0,class:T([l(t).b(),"vp-doc"])},[S("div",{class:T([e.type,"custom-block",{"no-title":!e.title}])},[s.value?(m(),C("div",pA,[M(i.$slots,"title",{},()=>[S("span",{innerHTML:e.title},null,8,mA)])])):A("v-if",!0),o.value?(m(),C("p",gA,[M(i.$slots,"default",{},()=>[S("span",{innerHTML:e.text},null,8,vA)])])):A("v-if",!0)],2)],2)):A("v-if",!0)}});const yA=["title","aria-label"];var bA=z({__name:"index",setup(e){const t=ie("sidebar-trigger"),{t:n}=ge(),s=j(!1),o=Xt("(max-width: 960px)"),i=()=>{const r=document.querySelector(`.${t.join("layout")}`);r&&r.classList.toggle(t.is("sidebar-collapse")),s.value||(s.value=!0,setTimeout(()=>{s.value=!1},300))};return be(async()=>{await Oe(),document.querySelector(".VPContent.has-sidebar")?.classList.add("sidebar-trigger-transition")}),(r,a)=>l(o)?A("v-if",!0):M(r.$slots,"default",{key:0,active:s.value,icon:l(Or),toggleSideBar:i},()=>[S("div",{class:T([l(t).b(),l(t).is("active",s.value)]),onClick:i,title:l(n)("tk.sidebarTrigger.label"),role:"button","aria-label":l(n)("tk.sidebarTrigger.label")},[S("div",{class:T([l(t).join("right-bottom-button__button")])},[H(l(de),{icon:l(Or),"aria-hidden":"true"},null,8,["icon"])],2)],10,yA)])}});const kA=["src"],wA=["innerHTML"],CA=["innerHTML"],_A={key:0,class:"features"},SA=["innerHTML"],TA=["innerHTML"],EA=["src"],xA=["innerHTML"],AA=["innerHTML"],$A={key:0,class:"highlights"},LA=["innerHTML"],IA=["innerHTML"];var PA=z({__name:"index",setup(e){const t=ie("home-features"),{getTeekConfigRef:n}=fe(),s=n("features",[]),o=_a(a=>a.feature),i=j(null),{start:r}=Ca(i,!1);return be(()=>{o.value&&r()}),(a,c)=>l(s)?.length?(m(),C("div",{key:0,class:T([l(t).b(),"vp-doc"])},[(m(!0),C(Y,null,le(l(s),u=>(m(),C(Y,{key:u.title},[u.features?(m(),C("div",{key:0,class:T([l(t).e("feature-wrapper"),"features-wrapper"])},[S("div",{class:T(l(t).e("feature__content"))},[S("img",{src:u.image,class:"image"},null,8,kA),S("div",{class:T([l(t).e("feature__header"),"header"])},[S("h2",{ref_for:!0,ref_key:"textInstance",ref:i,innerHTML:u.title},null,8,wA),u.details?(m(),C("p",{key:0,ref_for:!0,ref_key:"textInstance",ref:i,innerHTML:u.details},null,8,CA)):A("v-if",!0)],2),u.features?.length?(m(),C("div",_A,[(m(!0),C(Y,null,le(u.features,f=>(m(),D(Be(f.link?"a":"div"),{key:f.title,href:l(Ee)(f.link??""),class:"features__item item"},{default:O(()=>[S("h3",{ref_for:!0,ref_key:"textInstance",ref:i,class:"flx-align-center"},[f.icon?(m(),D(l(de),{key:0,icon:f.icon,class:"feature-icon"},null,8,["icon"])):A("v-if",!0),S("span",{innerHTML:f.title},null,8,SA)],512),f.details?(m(),C("p",{key:0,ref_for:!0,ref_key:"textInstance",ref:i,innerHTML:f.details},null,8,TA)):A("v-if",!0)]),_:2},1032,["href"]))),128))])):A("v-if",!0)],2)],2)):u.highlights?(m(),C("div",{key:1,class:T([l(t).e("highlight-wrapper"),"features-wrapper"])},[S("div",{class:T(l(t).e("highlight"))},[S("img",{src:u.image,class:"image"},null,8,EA),S("div",{class:T(l(t).e("highlight__content"))},[S("div",{class:T([l(t).e("highlight__header"),"header"])},[S("h2",{ref_for:!0,ref_key:"textInstance",ref:i,innerHTML:u.title},null,8,xA),u.details?(m(),C("p",{key:0,ref_for:!0,ref_key:"textInstance",ref:i,innerHTML:u.details},null,8,AA)):A("v-if",!0)],2),u.highlights?.length?(m(),C("div",$A,[(m(!0),C(Y,null,le(u.highlights,f=>(m(),D(Be(f.link?"a":"div"),{key:f.title,href:l(Ee)(f.link??""),class:T([{"no-details":!f.details},"highlights__item item"])},{default:O(()=>[S("h3",{ref_for:!0,ref_key:"textInstance",ref:i},[f.icon?(m(),D(l(de),{key:0,icon:f.icon,class:"feature-icon"},null,8,["icon"])):A("v-if",!0),S("span",{innerHTML:f.title},null,8,LA)],512),f.details?(m(),C("p",{key:0,ref_for:!0,ref_key:"textInstance",ref:i,innerHTML:f.details},null,8,IA)):A("v-if",!0)]),_:2},1032,["href","class"]))),128))])):A("v-if",!0)],2)],2)],2)):A("v-if",!0)],64))),128))],2)):A("v-if",!0)}});const MA={__name:"index",props:{modelValue:{default:!0},modelModifiers:{}},emits:["update:modelValue"],setup(e){const t=Jt(e,"modelValue"),n=ie("route-loading"),s=Is(),{getTeekConfigRef:o}=fe(),i=o("loading",!1),r=()=>{t.value||(t.value=!0)},a=()=>{setTimeout(()=>{t.value&&(t.value=!1)},Math.floor(Math.random()*41)+460)};return s.bindBeforeRouteChange("routeLoadingBefore",()=>{r()},"before"),s.bindAfterRouteChange("routeLoadingAfter",()=>{a()},"before"),te(()=>s.route.path,()=>{r(),a()}),Mo(r),be(a),Ai(a),(c,u)=>M(c.$slots,"default",{loading:t.value},()=>[S("div",{class:T(l(n).b())},[H(vt,{name:l(n).join("fade"),mode:"out-in",persisted:""},{default:O(()=>[et(S("div",{class:T(l(n).e("mask"))},[S("div",{class:T(l(n).e("loader"))},[S("div",{class:T(l(n).e("spinner"))},null,2),S("p",null,W(l(Je)(l(i))?l(i):"Teek 拼命加载中 ..."),1)],2)],2),[[at,t.value]])]),_:1},8,["name"])],2)])}},FA=["src"],BA={key:0,class:"categories flx-center"},NA=["href","title"],VA={key:1,class:"tags flx-center"},OA=["href","title"];var DA=z({__name:"index",setup(e){const t=j(!1),n=ie("article-banner"),{frontmatter:s}=Ae(),o=kn(),{hasSidebar:i}=Zh(),{isMobile:r}=Qh(),{getTeekConfigRef:a}=fe(),c=a("articleBanner",{enabled:!1,showCategory:!0,showTag:!0,defaultCoverImg:"",defaultCoverBgColor:""}),u=a("post",{defaultCoverImg:[]}),f=F(()=>{const h=[s.value.coverImg||c.value.defaultCoverImg||u.value.defaultCoverImg||[]].flat();return h.length?h[Math.floor(Math.random()*h.length)]:""}),d=F(()=>({[n.cssVarName("article-banner-bg-color")]:s.value.coverBgColor||c.value.defaultCoverBgColor}));return te(()=>o.path,async()=>{await Oe(),t.value=!0,setTimeout(()=>t.value=!1,1)}),(h,p)=>!l(i)&&l(c).enabled?et((m(),C("div",{key:0,class:T(l(n).b()),style:Fe(d.value)},[S("div",{class:T([l(n).e("wrapper"),"flx-justify-center"])},[f.value?(m(),C("div",{key:0,class:T(l(n).e("cover"))},[S("img",{src:f.value,class:"no-preview",alt:"cover"},null,8,FA)],2)):A("v-if",!0),S("div",{class:T(l(n).e("info"))},[M(h.$slots,"teek-article-banner-info-top"),l(r)?A("v-if",!0):(m(),D(l(m2),{key:0})),S("div",{class:T([l(n).e("meta"),"flx-center flx-wrap"])},[l(s).categories&&l(c).showCategory?(m(),C("div",BA,[(m(!0),C(Y,null,le(l(s).categories,g=>(m(),C("a",{key:g,href:l(Ee)(`/categories?category=${g}`),class:"meta-info category",title:g},W(g),9,NA))),128))])):A("v-if",!0),l(s).tags&&l(c).showTag?(m(),C("div",VA,[(m(!0),C(Y,null,le(l(s).tags,g=>(m(),C("a",{key:g,href:l(Ee)(`/tags?tag=${g}`),class:"meta-info tag",title:g},[p[0]||(p[0]=S("span",null,"#",-1)),S("span",null,W(g),1)],8,OA))),128))])):A("v-if",!0)],2),S("h1",null,W(l(s).title),1),H(l(g2),{breadcrumb:!1,scope:"article-banner"}),M(h.$slots,"teek-article-banner-info-bottom")],2)],2),H(l(f2))],6)),[[at,!t.value]]):A("v-if",!0)}}),RA=z({name:"TeekLayout",__name:"index",props:{locale:{}},setup(e){const t=e;In(zh,F(()=>t.locale));const{Layout:n}=Th,s=ie("layout"),{getTeekConfigRef:o}=fe(),{isHomePage:i,isArchivesPage:r,isCataloguePage:a,isArticleOverviewPage:c}=iu(),{frontmatter:u,localeIndex:f,page:d}=Ae(),{hasSidebar:h}=Zh(),p=o(null,{teekTheme:!0,teekHome:!0,vpHome:!0,sidebarTrigger:!1,loading:!1,codeBlock:{enabled:!0},themeSize:"",bodyBgImg:{},notice:{},comment:{provider:""},articleUpdate:{enabled:!0},articleTopTip:void 0,articleBottomTip:void 0,articleShare:{},appreciation:{},riskLink:{enabled:!1},themeEnhance:{enabled:!0},articleBanner:{enabled:!1},pageStyle:"default"}),g=j(p.value.loading),v=F(()=>{const E=u.value.comment,I=p.value.comment;let P=E??I;if(es(E)){if(E===!1)return{enabled:!1};P=I}return{enabled:!0,components:{twikoo:ux,waline:mx,giscus:hx,artalk:dx},provider:P.provider,options:P.options}}),k=F(()=>es(p.value.articleTopTip)?p.value.articleTopTip:p.value.articleTopTip?.(u.value,f.value,d.value)),b=F(()=>es(p.value.articleBottomTip)?p.value.articleBottomTip:p.value.articleBottomTip?.(u.value,f.value,d.value)),w=F(()=>u.value.articleBanner!==!1&&p.value.articleBanner.enabled&&!h.value&&u.value.article!==!1&&(!u.value.layout||u.value.layout==="doc")&&p.value.pageStyle==="default"),y=s.join("theme-size");te(()=>p.value.themeSize,E=>{me&&(E?document.documentElement.setAttribute(y,E):document.documentElement.removeAttribute(y))},{immediate:!0,flush:"post"});const{watchSite:_,watchPages:x}=S_(),{restart:L}=x_({whitelist:p.value.riskLink.whitelist,blacklist:p.value.riskLink.blacklist});_(),x(),Ai(()=>{p.value.riskLink.enabled&&L()});const V=["home-hero-before","home-features-after","nav-bar-content-after","layout-top","layout-bottom","doc-footer-before","doc-before","doc-after","aside-bottom","page-top","aside-outline-before","sidebar-nav-before"];return(E,I)=>l(p).teekTheme?(m(),C(Y,{key:0},[l(p).loading??!1?(m(),D(l(MA),{key:0,modelValue:g.value,"onUpdate:modelValue":I[0]||(I[0]=P=>g.value=P)},{default:O(P=>[M(E.$slots,"teek-loading",Ge(Ze(P)))]),_:3},8,["modelValue"])):A("v-if",!0),l(u).loginPage===!0?M(E.$slots,"teek-login-page",{key:1},()=>[et(H(l(a2),null,null,512),[[at,!g.value]])]):A("v-if",!0),l(u).riskLinkPage===!0?M(E.$slots,"teek-risk-link-page",{key:2},()=>[et(H(l(l2),null,null,512),[[at,!g.value]])]):A("v-if",!0),l(u).layout!==!1?(m(),C(Y,{key:3},[l(p).bodyBgImg?.imgSrc?(m(),D(l(HT),{key:0})):A("v-if",!0),H(l(HE)),l(p).notice?.enabled?(m(),D(l(Dx),{key:1},Wt({_:2},[le(E.$slots,(P,N)=>({name:N,fn:O($=>[M(E.$slots,N,Ge(Ze($)))])}))]),1024)):A("v-if",!0),H(l(Px),null,Wt({_:2},[le(E.$slots,(P,N)=>({name:N,fn:O($=>[M(E.$slots,N,Ge(Ze($)))])}))]),1024)],64)):A("v-if",!0),et(H(l(n),{class:T([l(s).b(),{[l(s).m("hide-vp-home")]:!l(p).vpHome},l(s).has("sidebar-trigger",l(p).sidebarTrigger)])},Wt({"home-hero-before":O(()=>[M(E.$slots,"home-hero-before"),M(E.$slots,"teek-home-before"),A(" 自定义首页 "),l(p).teekHome?(m(),D(l(FT),{key:0},Wt({_:2},[le(E.$slots,(P,N)=>({name:N,fn:O($=>[M(E.$slots,N,Ge(Ze($)))])}))]),1024)):A("v-if",!0),M(E.$slots,"teek-home-after")]),"home-features-after":O(()=>[l(p).teekHome?A("v-if",!0):(m(),C(Y,{key:0},[M(E.$slots,"teek-home-features-before"),H(l(PA)),M(E.$slots,"teek-home-features-after")],64)),M(E.$slots,"home-features-after")]),"nav-bar-content-after":O(()=>[M(E.$slots,"nav-bar-content-after"),l(p).themeEnhance.enabled??!0?(m(),D(l(hA),{key:0},Wt({_:2},[le(E.$slots,(P,N)=>({name:N,fn:O($=>[M(E.$slots,N,Ge(Ze($)))])}))]),1024)):A("v-if",!0)]),"layout-top":O(()=>[M(E.$slots,"layout-top"),w.value?(m(),C(Y,{key:0},[M(E.$slots,"teek-article-banner-before"),H(l(DA),null,Wt({_:2},[le(E.$slots,(P,N)=>({name:N,fn:O($=>[M(E.$slots,N,Ge(Ze($)))])}))]),1024),M(E.$slots,"teek-article-banner-after")],64)):A("v-if",!0)]),"layout-bottom":O(()=>[l(i)?(m(),C(Y,{key:0},[M(E.$slots,"teek-footer-group-before"),H(l(UT)),M(E.$slots,"teek-footer-group-after"),M(E.$slots,"teek-footer-info-before"),M(E.$slots,"teek-footer-info",{},()=>[H(l(nE))]),M(E.$slots,"teek-footer-info-after")],64)):A("v-if",!0),M(E.$slots,"layout-bottom")]),"sidebar-nav-before":O(()=>[H(l(DT))]),"doc-before":O(()=>[M(E.$slots,"doc-before"),l(u).article!==!1&&!w.value?(m(),C(Y,{key:0},[M(E.$slots,"teek-article-analyze-before"),H(l(g2)),M(E.$slots,"teek-article-analyze-after")],64)):A("v-if",!0),H(l(wE)),H(l(zE)),l(p).codeBlock.enabled??!0?(m(),D(l(yx),{key:1})):A("v-if",!0),k.value?(m(),D(l(t1),Ge(nt({key:2},l(es)(k.value)?{}:k.value)),null,16)):A("v-if",!0),l(p).sidebarTrigger?(m(),D(l(bA),{key:3},{default:O(P=>[M(E.$slots,"teek-sidebar-trigger",Ge(Ze(P)))]),_:3})):A("v-if",!0)]),"doc-footer-before":O(()=>[M(E.$slots,"doc-footer-before"),b.value?(m(),C(Y,{key:0},[M(E.$slots,"teek-article-bottom-tip-before"),H(l(t1),Ge(Ze(l(es)(b.value)?{}:b.value)),null,16),M(E.$slots,"teek-article-bottom-tip-after")],64)):A("v-if",!0)]),"doc-after":O(()=>[M(E.$slots,"doc-after"),(l(p).articleUpdate.enabled??!0)&&l(u).articleUpdate!==!1?(m(),C(Y,{key:0},[M(E.$slots,"teek-doc-update-before"),H(l(RE)),M(E.$slots,"teek-doc-update-after")],64)):A("v-if",!0),["doc-after","doc-after-popper"].includes(l(p).appreciation.position)?(m(),C(Y,{key:1},[M(E.$slots,"teek-doc-after-appreciation-before"),l(p).appreciation.position==="doc-after"?(m(),D(l(ex),{key:0})):l(p).appreciation.position==="doc-after-popper"?(m(),D(l(lx),{key:1})):A("v-if",!0),M(E.$slots,"teek-doc-after-appreciation-after")],64)):A("v-if",!0),A(" 评论区 "),v.value.enabled&&v.value.provider?(m(),C(Y,{key:2},[M(E.$slots,"teek-comment-before"),v.value.provider==="render"?M(E.$slots,"teek-comment",{key:0}):(m(),D(Be(v.value.components?.[v.value.provider]),{key:1,id:`${l(s).namespace}-comment`,class:T(l(s).e("comment"))},null,8,["id","class"])),M(E.$slots,"teek-comment-after")],64)):A("v-if",!0)]),"aside-bottom":O(()=>[M(E.$slots,"aside-bottom"),l(p).appreciation.position==="aside-bottom"?(m(),C(Y,{key:0},[M(E.$slots,"teek-aside-bottom-appreciation-before"),H(l(qE)),M(E.$slots,"teek-aside-bottom-appreciation-after")],64)):A("v-if",!0)]),"page-top":O(()=>[M(E.$slots,"page-top"),l(r)||l(a)||l(c)?(m(),C(Y,{key:0},[M(E.$slots,"teek-page-top-before"),l(r)?(m(),D(l(zp),{key:0},Wt({_:2},[le(E.$slots,(P,N)=>({name:N,fn:O($=>[M(E.$slots,N,Ge(Ze($)))])}))]),1024)):l(a)?(m(),D(l(ep),{key:1},Wt({_:2},[le(E.$slots,(P,N)=>({name:N,fn:O($=>[M(E.$slots,N,Ge(Ze($)))])}))]),1024)):l(c)?(m(),D(l(jp),{key:2})):A("v-if",!0),M(E.$slots,"teek-page-top-after")],64)):A("v-if",!0)]),"aside-outline-before":O(()=>[l(p).articleShare.enabled?(m(),C(Y,{key:0},[M(E.$slots,"teek-article-share-before"),H(l(NE)),M(E.$slots,"teek-article-share-after")],64)):A("v-if",!0),M(E.$slots,"aside-outline-before")]),_:2},[le(Object.keys(E.$slots).filter(P=>!V.includes(P)),P=>({name:P,fn:O(N=>[M(E.$slots,P,Ge(Ze(N)))])}))]),1032,["class"]),[[at,!g.value]])],64)):(m(),D(l(n),{key:1},Wt({_:2},[le(E.$slots,(P,N)=>({name:N,fn:O($=>[M(E.$slots,N,Ge(Ze($)))])}))]),1024))}}),ZA={extends:Th,Layout:hb(RA),async enhanceApp({app:e,siteData:t,router:n}){if(e.component("TkCataloguePage",ep),e.component("TkArchivesPage",zp),e.component("TkArticleOverviewPage",jp),e.component("TkLoginPage",a2),e.component("TkRiskLinkPage",l2),e.component("TkDemoCode",I_),e.component("TkTitleTag",Dr),e.component("TkIcon",de),!me)return;const{themeConfig:s}=t.value;HA(s),s.permalinks&&await zA({siteData:t,router:n})}};const HA=e=>{const t=e.siteAnalytics||[],n={baidu:s=>{H7(s),me&&z7(s,window.location.href)},google:s=>j7(s),umami:s=>U7(s)};t.forEach(s=>{n[s.provider]?.(s.options)})},zA=async({siteData:e,router:t})=>{const{base:n,cleanUrls:s,themeConfig:o}=e.value;if(t.route.path===n&&t.route.data.isNotFound){const{pathname:i,search:r,hash:a}=new URL(location.href),c="/"+decodeURIComponent(i.slice(n.length)).replace(/\/$/,"").replace(/\.html/,""),u=s?c:c+".html",f=o.permalinks.inv[u];if(f){const d=n+f+r+a;await t.go(d)}}};export{ze as $,ZA as A,wt as B,YA as C,zn as D,B3 as E,Y as F,V3 as G,kn as H,cn as I,JA as J,GA as K,j3 as L,QA as M,ks as N,XA as O,X0 as P,nn as Q,W3 as R,rt as S,ca as T,E0 as U,M as V,Fe as W,Be as X,vt as Y,d5 as Z,ke as _,Pn as a,ur as a0,Se as a1,ba as a2,Qv as a3,Bc as a4,xe as a5,UA as a6,qA as a7,WA as a8,jA as a9,_l as aa,h5 as ab,Hn as ac,ch as ad,ls as ae,et as af,_o as ag,Ye as ah,go as ai,Br as aj,KA as ak,z1 as b,F as c,z as d,U9 as e,pi as f,C as g,m as h,S as i,jn as j,T as k,l,Ee as m,Oe as n,be as o,D as p,Vo as q,j as r,O as s,le as t,Ae as u,To as v,te as w,W as x,A as y,H as z}; diff --git a/assets/fullstack_ai-change-work-workflow.md.D9DK-zPn.js b/assets/fullstack_ai-change-work-workflow.md.D9DK-zPn.js new file mode 100644 index 00000000..37fc7f3e --- /dev/null +++ b/assets/fullstack_ai-change-work-workflow.md.D9DK-zPn.js @@ -0,0 +1 @@ +import{H as a}from"./chunks/HighLightText.BD5ARcjF.js";import{g as l,h as s,i as o,U as i,S as r,z as e,s as n}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const p={class:"tip custom-block"},q=JSON.parse('{"title":"读 Anthropic 研究报告,探寻 AI 时代的工程范式重塑","description":"软件工程正经历从“手写逻辑”向“意图调度”的范式迁徙。Anthropic 的研究揭示了 AI 并非简单的提效工具,而是通过释放 27% 曾经“不划算”的工程任务,重塑了软件质量的密度。在自然语言即编程语言的时代,我们需要通过规格驱动(SDD)与多智能体编排,破解“监督悖论”带来的技能平庸化危机,将 AI 的概率性生成驯化为确定性的工程交付。当编码成本趋于零,工程师的终极壁垒将是定义完美的品味,以及在 AI 迷雾中识破平庸的洞察力。","frontmatter":{"date":"2025-12-06T22:05:50.000Z","title":"读 Anthropic 研究报告,探寻 AI 时代的工程范式重塑","description":"软件工程正经历从“手写逻辑”向“意图调度”的范式迁徙。Anthropic 的研究揭示了 AI 并非简单的提效工具,而是通过释放 27% 曾经“不划算”的工程任务,重塑了软件质量的密度。在自然语言即编程语言的时代,我们需要通过规格驱动(SDD)与多智能体编排,破解“监督悖论”带来的技能平庸化危机,将 AI 的概率性生成驯化为确定性的工程交付。当编码成本趋于零,工程师的终极壁垒将是定义完美的品味,以及在 AI 迷雾中识破平庸的洞察力。","permalink":"/fullstack/ai-change-work-workflow/","top":true,"tags":["全栈","AI"],"categories":["全栈"]},"headers":[],"relativePath":"fullstack/ai-change-work-workflow.md","filePath":"01.全栈/01.AI Native 工程思维/10.读 Anthropic 研究报告,探寻 AI 时代的工程范式重塑.md"}'),u={name:"fullstack/ai-change-work-workflow.md"},I=Object.assign(u,{setup(A){return(d,t)=>(s(),l("div",null,[t[10]||(t[10]=o("h1",{id:"读-anthropic-研究报告-探寻-ai-时代的工程范式重塑",tabindex:"-1"},[r("读 Anthropic 研究报告,探寻 AI 时代的工程范式重塑 "),o("a",{class:"header-anchor",href:"#读-anthropic-研究报告-探寻-ai-时代的工程范式重塑","aria-label":"Permalink to “读 Anthropic 研究报告,探寻 AI 时代的工程范式重塑”"},"​")],-1)),t[11]||(t[11]=o("blockquote",null,[o("p",null,[o("strong",null,"摘要总结"),r(":软件工程正经历从“手写逻辑”向“意图调度”的范式迁徙。Anthropic 的研究揭示了 AI 并非简单的提效工具,而是通过释放 27% 曾经“不划算”的工程任务,重塑了软件质量的密度。在自然语言即编程语言的时代,我们需要通过规格驱动(SDD)与多智能体编排,破解“监督悖论”带来的技能平庸化危机,将 AI 的概率性生成驯化为确定性的工程交付。当编码成本趋于零,工程师的终极壁垒将是定义完美的品味,以及在 AI 迷雾中识破平庸的洞察力。")])],-1)),o("div",p,[t[3]||(t[3]=i('

博客原文

地址How AI is transforming work at Anthropic

核心标签AI辅助编程 工程 范式转移 工作转型 生产力提升 技能发展 人机协作

一句话介绍:Anthropic 不仅仅是 AI 工具的生产者,更是第一个进入“未来实验室”的深度观察者。他们通过内部数月的实验数据告诉我们:大模型对软件工程的改造,绝非简单的“提效”,而是一场关于工程范式与职业认同的重塑。

',4)),o("p",null,[t[1]||(t[1]=o("strong",null,"延伸思考",-1)),t[2]||(t[2]=r(":",-1)),e(a,{type:"note",bold:""},{default:n(()=>[...t[0]||(t[0]=[r("工程团队要用多少年,才会把现在的'人+AI 协作方式',沉淀为一个稳定的工程范式?",-1)])]),_:1})])]),t[12]||(t[12]=i('

1. 引言

软件工程的历史,本质上是一部不断通过“抽象”来对抗“复杂度”的进化史。从汇编语言到高级语言,从手动内存管理到垃圾回收,每一次抽象层的上移,都会让一部分曾经引以为傲的手艺淡出舞台,同时释放出更宏大的创造力。

2025 年底,Anthropic 发布了一份具有里程碑意义的研究报告:《AI 如何改变 Anthropic 的工作方式》。作为大模型的缔造者,Anthropic 将自己变成了一个“AI 时代工作范式的实验室”。他们不仅向外输出模型,更在内部深度观测:当工程师拥有了像 Claude 这样具备自主能力的“AI 同事”后,代码的生产流程、团队的协作边界、甚至是“工程师”这一职业的底层逻辑,究竟发生了怎样的质变?

这份报告揭示了一组迷人且令人警醒的数据:在 AI 辅助下,工程师们不仅在提速,更在处理那 27% 曾经“不划算”或“超出能力边界”的任务。然而,光鲜的数据背后,是“编程技能萎缩”的隐忧和“监督悖论”的挑战。

站在产品与应用工程师的角度看,我最关心的不仅是“AI 能写多快”,而是如何将这种碎片化的、依赖“灵感”的 AI 协作,沉淀为一套稳定的工程范式

本文将基于 Anthropic 的这份深度观测,结合我们在 AI Native 应用架构、以及“规格驱动开发(SDD)”中的一些实践,探讨三个核心命题:

  • 任务重构:当编码成本趋于零时,哪些被长期忽视的“工程债务”将变成核心资产?

  • 能力重塑:在“英语/中文即编程语言”的时代,如何保持技术尖锐度并构建新的“工程 Sense”?

  • 范式落地:我们该如何设计一套人机协作的链路,让 AI 的产出从“不确定的随机性”走向“可交付的工程化”?

2. 盯准任务构成,而非单一速度,重获“工程尊严”的 27%

一句话总结:

AI 对工程团队的真正馈赠,是让我们从繁琐的、“不得不做”的苦力活中抽身,去夺回对软件质量的掌控力。速度是副产品,质量的密度才是衡量 AI 协作水平的终极标准。

在讨论 AI 提效时,我们很容易掉入的陷阱就是 “速度幻觉”。如果单纯观察代码产出行数(LOC)或需求交付周期,我们可能会得出“工程师变快了”的浅层结论,但 Anthropic 的研究给出了一个更具洞察力的视角:AI 带来的最大变量,不是让既有任务变快了,而是改变了“任务的构成比例”

报告中提到的那个关键数字——27%,代表了那些如果没有 AI 辅助,工程师根本不会去碰的任务。这 27% 并非边缘工作,而是软件工程中长期被牺牲掉的“工程尊严”。

2.1 从"技术债务"到"系统韧性"

在传统开发模式下,那些遗留的烂代码、缺失的测试覆盖、疏于维护的内部工具——这些"技术债务"虽不至于让系统立刻崩溃,却如同慢性毒药,持续侵蚀团队的认知资源与开发效率。

Anthropic 的观察揭示了一个关键转折点:当 AI 介入后,清偿这些"技术债务"的成本首次降到了可接受的阈值之下。

  • 重构民主化:曾经需要资深工程师耗费数小时、如履薄冰的手动重构,如今在 AI 辅助下几分钟即可完成初稿并通过基础验证,重构从"高风险操作"变成了"日常习惯"。
  • 测试与文档的范式转移:最令人抵触的单元测试编写和技术文档维护,正逐渐演变为 AI 擅长的"结构化填空"——工程师定义意图与边界,AI 负责填充实现细节,人类则专注于验收与精炼。
  • 可视化与工具的自动化:随着 AI 能力的提升,可视化工具、内部工具等也开始被自动化,工程师可以更专注于业务逻辑的实现,而不是手动维护这些工具。

2.2 从"不划算"到"高价值":任务优先级的重新洗牌

作为产品工程师,我们每天都在做取舍:哪些任务值得投入时间,哪些只能往后放?过去,很多工程改进任务——比如增加可观测性的埋点、搭建内部性能看板——虽然对系统长期健康很重要,但因为做起来太费功夫,往往被无限期搁置。我们心里都明白这些任务有价值,但"性价比"太低,排不上优先级。

AI 的出现改变了这个算式。它像一根杠杆,把那些原本需要花费大量时间的繁琐工作,变成了可以快速完成的"轻量级任务"。过去可能要花一整天写的监控脚本,现在几分钟就能让 AI 生成初稿;以前需要专门排期的重构工作,现在可以随手完成。

这意味着什么?那些曾经因为"太麻烦"而被忽视的任务,现在突然变得"很划算"了。团队不再只是追求开发速度,而是有能力把系统打磨得更健壮、更可维护。我们不再只是跑得更快,而是能跑得更稳、更远。

2.3 跨领域能力的“无痛溢出”

研究还揭示了一个引人注目的现象:工程师的角色边界正在变得愈发模糊,"全栈化"趋势日益明显。

  • 后端工程师借助 AI 轻松涉足复杂的数据可视化前端开发。
  • 研究员也能独立搭建用于实验的内部管理后台。

这种能力的自然延伸并非意味着人人都成为通才,而是 AI 将跨领域协作的摩擦成本大幅降低。当技术壁垒被削平,原本需要数周协调的跨职能配合,如今可在数小时内完成闭环验证——反馈周期实现了量级压缩。

3. 对抗“平庸化” —— 在自然语言编程时代重塑工程 Sense

一句话总结:

抽象层的上移并不意味着底层知识的贬值,反而意味着识别平庸的能力变得空前昂贵。当每个人都有一个能写代码的 AI 同事时,你对“完美工程”的定义能力,决定了你在这个时代的价值上限。

当编程的门槛降低到“只要会说话就能写代码”时,软件工程正经历一场权力的交接:自然语言(英语/中文)正在成为最高级的编程语言。

这种转变带来了一种极其诱人的“Vibe Coding(凭感觉编程)”体验。然而,Anthropic 的研究揭示了一个冷酷的现实:AI 往往表现得像一个“极其聪明但缺乏责任感的初级工程师”。如果我们全盘接受这种便利,而不去有意识地重构自身的职业能力,我们可能会陷入一种“监督悖论(Supervision Paradox)”——即当你失去了手动解决问题的能力时,你也失去了监督 AI 的资格。

3.1 警惕“监督悖论”与能力的平庸化

Anthropic 的报告中提到,有效使用 AI 需要极强的“监督力”,而这种能力恰恰源于那些正在被 AI 取代的底层编码实践。这种转变催生了一个深刻的监督悖论:

  • 技能萎缩的风险:长期依赖 AI 生成代码,会导致开发者对内存管理、并发模型、边界条件等底层细节的敏感度下降。

(附带学习)的丧失: 过去我们在翻阅文档、调试 Bug 的痛苦过程中,会意外学到系统的运行机理。AI 直接给出答案,切断了这种深度学习的路径。

AI Free 的刻意练习:每周或每个迭代,挑选一个核心逻辑块,尝试在完全不求助 AI 的情况下,手写实现并进行性能调优。这就像飞行员必须定期进行手动起降练习一样,是保持底层“肌肉记忆”的唯一方式。

3.2 从 Vibe Coding 进化到规范驱动(SDD)

为了不让工程质量滑向“随机性”的深渊,我们需要将“凭感觉”转化为 “定规范”。在“英语即编程语言”的时代,工程师的独特价值不再是实现细节,而是对约束条件的定义。

  • 定义验收标准:我们需要比以前更清晰地告诉 AI,什么是“正确”。这就要求具备极强的系统架构思维和对业务逻辑的深度拆解能力。
  • 引入工程语义:模糊的指令只会带来模糊的结果。正如近期在实践中推崇的 Specification Driven Development (SDD),我们需要在自然语言与 AI 执行之间,建立一套严谨的语义层。这套语义标准如同工程契约,确保 AI 生成的代码不是随机"发散"的,而是始终锚定于可预期的工程范式之内。

3.3. 构建新型“工程 Sense”:从手艺人到导演

未来的高级工程师,其核心竞争力将体现在对品味与评判权的掌控上。

  • 批判性审美:AI 给出三个方案,你为什么选这一个?是因为它的扩展性更好,还是因为它在特定高并发场景下更稳健?这种基于经验的“选择权”就是新的工程 Sense。
  • 逆向工程能力:能够快速读懂 AI 生成的大体量代码,并在其中精准定位“聪明但危险”的逻辑缺陷。这要求我们必须保持对新技术的“深度阅读”习惯,而非仅仅停留在“调用”层面。

4. 范式落地——在随机性之上,构建确定性的工程基座

一句话总结:

范式的落地不是一蹴而就的规则设定,而是一场伴随模型能力进化的动态博弈。我们要构建的是一套 “宽容输入、严格输出” 的链路:给 AI 足够的空间去创造和提效,但在交付的最后一公里,用最传统的工程理性进行最严苛的审判。

如果说 AI 是一台拥有无限爆发力的引擎,那么软件工程范式就是承载它的底盘。当前最核心的矛盾在于:大模型本质上是概率性的,而工程交付要求的却是确定性的。

如何让"不确定的生成"进化为"可交付的代码"?这不只是技术层面的挑战,更是一个关于全链路治理的系统性命题。我们不能以静态的视角审视现有工具,而需要动态地观察 LLM 能力演进、Agent 架构革新与传统工程设施的深度融合与协同演化。

4.1 从“单点指令”转向“多智能体编排(Multi-Agent Orchestration)”

正如 Anthropic 内部使用 Claude Code 处理日益复杂的任务,未来的落地范式绝非"人与单一窗口的对话",而是一个闭环的多智能体协作流水线。

  • 角色专业化分工:将复杂任务拆解并委派给不同的"专家智能体"。一个 Agent 专注于需求理解与方案设计,另一个负责代码实现,第三个则扮演"红队审查者"的角色,进行自动化的对抗性测试与漏洞挖掘。

  • 迭代式错误收敛:工程确定性不源于单次生成的完美,而来自 "生成-验证-诊断-修复-再验证" 的自动化闭环。在代码合并入主分支之前,它应当已在隔离的沙盒环境中,历经多轮 Agent 驱动的自我修正与质量收敛。

4.2 构建"上下文护城河":从 Prompt 到知识图谱

AI 输出的质量,本质上取决于它对业务语境的理解深度。当前最大的工程化障碍,正是模型面对团队私有知识时的"冷启动"困境——它缺乏对特定代码规范、架构决策和历史演进的隐性认知。

  • 动态上下文注入: 超越传统的 RAG(检索增强生成),将代码库、架构文档乃至团队的代码评审偏好,实时编织为 AI 的"工作记忆"。这不再是简单的信息检索,而是让 AI 真正"融入"团队的工程文化。

  • 工程语义翻译层: 在人类的模糊意图与机器的结构化理解之间,我们需要一座桥梁。这座桥梁将自然语言需求转化为 AI 可精确解析的语义图谱——基于 Graph 的代码索引、依赖关系网络与领域知识建模,共同构成这一翻译层的核心骨架。

4.3 "可观测性":让 AI 的决策过程透明可见

传统 DevOps 关注的是服务器负载、响应时间等机器指标;而在 AI 工程时代,我们需要追踪的是 AI 的"思考过程"。

  • 记录 AI 的决策链路:当 AI 修改代码时,我们不仅要看到"改了什么",更要理解"为什么这么改"——完整还原它的推理链条,让每一次变更都可追溯、可解释。

  • 建立分级信任机制:不是所有任务都需要人工逐一审核。对于 AI 表现稳定的标准化工作(如调整样式、生成单元测试),可以自动放行;一旦发现 AI 在推理过程中反复纠结、多次修正或出现异常,立即触发人工深度审查,形成人机协同的质量把关。

4.4 拥抱"不确定性",但守住"质量底线"

我们需要认清一个现实:未来的软件开发将是人与 AI 协作的过渡态,不会是非黑即白的完全自动化。与其追求每一步都人工可控,不如确保最终结果可验证、可信赖

这意味着工程团队的核心能力要从"亲自写代码"转向 "搭建完善的评估体系"。只要你的测试、监控、回滚机制足够健壮,即使 AI 的输出带有一定随机性,也能被牢牢限制在安全的边界之内。

5. 结语

Anthropic 的这份报告,本质上是为我们展现了一个软件工程的“后工业时代”。在这个时代,AI 不是取代你的收割机,而是给了你“一百万匹马”的爆发力。

',56)),o("p",null,[t[5]||(t[5]=r("正如报告中所揭示的那样:我们不应再纠结于单应仰望更高应仰望更高维度的景观。",-1)),e(a,{bold:""},{default:n(()=>[...t[4]||(t[4]=[r("当写代码变得不再昂贵,对“什么是好代码”的定义权,以及对“系统为何而存在”的理解力,便成了这个行业最后的稀缺品",-1)])]),_:1}),t[6]||(t[6]=r("。",-1))]),t[13]||(t[13]=o("p",null,"未来,最优秀的工程师或许不再是那个能手写极致算法的人,而是那个能在随机生成的迷雾中,凭借深厚的底层功底,一眼识破平庸与风险,并为 AI 指明方向的人。",-1)),o("p",null,[t[8]||(t[8]=r("范式的沉淀或许仍需时间,请务必在享受 AI 提效的同时,刻意保持你的技术尖锐度。因为 ",-1)),e(a,{type:"warning",bold:""},{default:n(()=>[...t[7]||(t[7]=[r("在“机器执行”的洪流下,人类的品位与责任感,依然是软件工程中那道最坚固、也最温暖的防御线",-1)])]),_:1}),t[9]||(t[9]=r("。",-1))])]))}});export{q as __pageData,I as default}; diff --git a/assets/fullstack_ai-change-work-workflow.md.D9DK-zPn.lean.js b/assets/fullstack_ai-change-work-workflow.md.D9DK-zPn.lean.js new file mode 100644 index 00000000..f815ac76 --- /dev/null +++ b/assets/fullstack_ai-change-work-workflow.md.D9DK-zPn.lean.js @@ -0,0 +1 @@ +import{H as a}from"./chunks/HighLightText.BD5ARcjF.js";import{g as l,h as s,i as o,U as i,S as r,z as e,s as n}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const p={class:"tip custom-block"},q=JSON.parse('{"title":"读 Anthropic 研究报告,探寻 AI 时代的工程范式重塑","description":"软件工程正经历从“手写逻辑”向“意图调度”的范式迁徙。Anthropic 的研究揭示了 AI 并非简单的提效工具,而是通过释放 27% 曾经“不划算”的工程任务,重塑了软件质量的密度。在自然语言即编程语言的时代,我们需要通过规格驱动(SDD)与多智能体编排,破解“监督悖论”带来的技能平庸化危机,将 AI 的概率性生成驯化为确定性的工程交付。当编码成本趋于零,工程师的终极壁垒将是定义完美的品味,以及在 AI 迷雾中识破平庸的洞察力。","frontmatter":{"date":"2025-12-06T22:05:50.000Z","title":"读 Anthropic 研究报告,探寻 AI 时代的工程范式重塑","description":"软件工程正经历从“手写逻辑”向“意图调度”的范式迁徙。Anthropic 的研究揭示了 AI 并非简单的提效工具,而是通过释放 27% 曾经“不划算”的工程任务,重塑了软件质量的密度。在自然语言即编程语言的时代,我们需要通过规格驱动(SDD)与多智能体编排,破解“监督悖论”带来的技能平庸化危机,将 AI 的概率性生成驯化为确定性的工程交付。当编码成本趋于零,工程师的终极壁垒将是定义完美的品味,以及在 AI 迷雾中识破平庸的洞察力。","permalink":"/fullstack/ai-change-work-workflow/","top":true,"tags":["全栈","AI"],"categories":["全栈"]},"headers":[],"relativePath":"fullstack/ai-change-work-workflow.md","filePath":"01.全栈/01.AI Native 工程思维/10.读 Anthropic 研究报告,探寻 AI 时代的工程范式重塑.md"}'),u={name:"fullstack/ai-change-work-workflow.md"},I=Object.assign(u,{setup(A){return(d,t)=>(s(),l("div",null,[t[10]||(t[10]=o("h1",{id:"读-anthropic-研究报告-探寻-ai-时代的工程范式重塑",tabindex:"-1"},[r("读 Anthropic 研究报告,探寻 AI 时代的工程范式重塑 "),o("a",{class:"header-anchor",href:"#读-anthropic-研究报告-探寻-ai-时代的工程范式重塑","aria-label":"Permalink to “读 Anthropic 研究报告,探寻 AI 时代的工程范式重塑”"},"​")],-1)),t[11]||(t[11]=o("blockquote",null,[o("p",null,[o("strong",null,"摘要总结"),r(":软件工程正经历从“手写逻辑”向“意图调度”的范式迁徙。Anthropic 的研究揭示了 AI 并非简单的提效工具,而是通过释放 27% 曾经“不划算”的工程任务,重塑了软件质量的密度。在自然语言即编程语言的时代,我们需要通过规格驱动(SDD)与多智能体编排,破解“监督悖论”带来的技能平庸化危机,将 AI 的概率性生成驯化为确定性的工程交付。当编码成本趋于零,工程师的终极壁垒将是定义完美的品味,以及在 AI 迷雾中识破平庸的洞察力。")])],-1)),o("div",p,[t[3]||(t[3]=i("",4)),o("p",null,[t[1]||(t[1]=o("strong",null,"延伸思考",-1)),t[2]||(t[2]=r(":",-1)),e(a,{type:"note",bold:""},{default:n(()=>[...t[0]||(t[0]=[r("工程团队要用多少年,才会把现在的'人+AI 协作方式',沉淀为一个稳定的工程范式?",-1)])]),_:1})])]),t[12]||(t[12]=i("",56)),o("p",null,[t[5]||(t[5]=r("正如报告中所揭示的那样:我们不应再纠结于单应仰望更高应仰望更高维度的景观。",-1)),e(a,{bold:""},{default:n(()=>[...t[4]||(t[4]=[r("当写代码变得不再昂贵,对“什么是好代码”的定义权,以及对“系统为何而存在”的理解力,便成了这个行业最后的稀缺品",-1)])]),_:1}),t[6]||(t[6]=r("。",-1))]),t[13]||(t[13]=o("p",null,"未来,最优秀的工程师或许不再是那个能手写极致算法的人,而是那个能在随机生成的迷雾中,凭借深厚的底层功底,一眼识破平庸与风险,并为 AI 指明方向的人。",-1)),o("p",null,[t[8]||(t[8]=r("范式的沉淀或许仍需时间,请务必在享受 AI 提效的同时,刻意保持你的技术尖锐度。因为 ",-1)),e(a,{type:"warning",bold:""},{default:n(()=>[...t[7]||(t[7]=[r("在“机器执行”的洪流下,人类的品位与责任感,依然是软件工程中那道最坚固、也最温暖的防御线",-1)])]),_:1}),t[9]||(t[9]=r("。",-1))])]))}});export{q as __pageData,I as default}; diff --git a/assets/fullstack_ai-coding_resources.md.CCLNidMN.js b/assets/fullstack_ai-coding_resources.md.CCLNidMN.js new file mode 100644 index 00000000..e0bf1fe7 --- /dev/null +++ b/assets/fullstack_ai-coding_resources.md.CCLNidMN.js @@ -0,0 +1 @@ +import{_ as s,g as l,h as n,U as e,i as t}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const h=JSON.parse('{"title":"AI 编程工具与资源推荐","description":"摘要总结:本文深度解析了 AI 驱动编程的三大演进范式:Vibe Coding(自然语言零门槛构建)、AI IDE(编辑器深度辅助提效)及 Agentic Engineering(自主工程师执行任务)。通过横向对比 Bolt.new、Cursor、Claude Code 等前沿工具,文章勾勒出一条从“快速原型”到“高效协同”再到“自主交付”的进阶路径。核心旨在指导用户利用 AI 工具矩阵打破技术边界,实现从创意描述到工业级交付的生产力飞跃,重塑软件开发全生命周期。","frontmatter":{"date":"2025-11-25T00:52:28.000Z","title":"AI 编程工具与资源推荐","description":"摘要总结:本文深度解析了 AI 驱动编程的三大演进范式:Vibe Coding(自然语言零门槛构建)、AI IDE(编辑器深度辅助提效)及 Agentic Engineering(自主工程师执行任务)。通过横向对比 Bolt.new、Cursor、Claude Code 等前沿工具,文章勾勒出一条从“快速原型”到“高效协同”再到“自主交付”的进阶路径。核心旨在指导用户利用 AI 工具矩阵打破技术边界,实现从创意描述到工业级交付的生产力飞跃,重塑软件开发全生命周期。","permalink":"/fullstack/ai-coding/resources","coverImg":"https://insight-stack-1252300811.cos.ap-shanghai.myqcloud.com/img/cover/source_sites_bg.png","categories":["资源推荐"],"tags":["资源推荐","AI","AI Coding","Vibe Coding","Agentic Engineering"]},"headers":[],"relativePath":"fullstack/ai-coding/resources.md","filePath":"01.全栈/10.AI 编程实践指南/00.AI编程工具与资源.md"}'),d={name:"fullstack/ai-coding/resources.md"};function i(o,a,r,c,g,_){return n(),l("div",null,[...a[0]||(a[0]=[e('

AI 编程工具与资源推荐

摘要总结:本文深度解析了 AI 驱动编程的三大演进范式:Vibe Coding(自然语言零门槛构建)、AI IDE(编辑器深度辅助提效)及 Agentic Engineering(自主工程师执行任务)。通过横向对比 Bolt.new、Cursor、Claude Code 等前沿工具,文章勾勒出一条从“快速原型”到“高效协同”再到“自主交付”的进阶路径。核心旨在指导用户利用 AI 工具矩阵打破技术边界,实现从创意描述到工业级交付的生产力飞跃,重塑软件开发全生命周期。

1. 三种编程范式速览

范式一句话描述你的角色
Vibe Coding用自然语言描述需求,AI 直接生成可运行的完整项目描述需求,让 AI 写代码(新手友好)
AI IDE在编辑器里引入 AI 辅助,边写边补全、边问边改主导开发,让 AI 做副驾驶(更多控制)
Agentic EngineeringAI 作为"自主工程师",接收任务后自动规划并执行全套代码工作流提任务、审结果,让 AI 执行(极致提效)

新手路线建议:先用 Bolt.new 或 v0.dev 体验 Vibe Coding 零门槛出产品的感觉 → 再切换到 Cursor 做日常编码提效 → 最后尝试 Claude Code/opencode 体验 AI 自主完成工程任务,三步感受"AI 如何重塑编程工作流"。

注意:使用 Claude Code 等 CLI Agent 工具,需要订阅官方模型服务(Claude Pro / API)。若暂无订阅,可通过配置自定义模型服务,支持对接兼容 第三方服务(如 GLM、DeepSeek、通义千问),实现低成本上手。

2. Vibe Coding — 用自然语言"说"出一个应用

2.1 关键点说明

适合人群:产品经理、设计师、创业者,或想快速验证想法的非专业开发者。

核心价值:从一段文字描述到可运行的 Web 应用,无需搭建开发环境;天生适合 MVP 原型验证UI 快速迭代

如何上手:打开网站 → 在输入框描述你的应用(如"做一个番茄钟 App,有开始暂停按钮,完成后有提示音")→ AI 生成代码并实时预览 → 继续对话迭代功能。

',9),t("div",{class:"container nav-card-container"},[t("div",{class:"nav-card index-auto",style:{"--row-gap":"20px","--column-gap":"20px","--column-min-width":"calc(100% / 4 - 60px)"}},[t("a",{href:"https://bolt.new/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[t("div",{class:"nav-card__item__info"},[t("div",{class:"nav-card__item__img skeleton-image"},[t("img",{src:"https://bolt.new/static/favicon-192x192.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),t("span",{class:"name"},"Bolt.new")]),t("p",{class:"desc"},"StackBlitz 推出的全栈 AI 开发平台,在浏览器中直接生成并运行完整的 React 项目,支持多轮对话迭代,可一键部署到 Netlify / Vercel,零环境配置从描述到上线全链路打通。"),t("span",{class:"VPBadge tip badge"},"一键部署")]),t("a",{href:"https://v0.dev/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[t("div",{class:"nav-card__item__info"},[t("div",{class:"nav-card__item__img skeleton-image"},[t("img",{src:"https://v0.app/assets/icon-dark-32x32.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),t("span",{class:"name"},"v0 (Vercel)")]),t("p",{class:"desc"},"Vercel 推出的 UI 组件生成工具,专注前端界面:用自然语言描述界面,生成 React + Tailwind CSS + shadcn/ui 组件代码,可直接复制进项目,天生与 Next.js 生态无缝衔接,非常适合前端 UI 的快速原型。"),t("span",{class:"VPBadge tip badge"},"UI 生成")]),t("a",{href:"https://lovable.dev/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[t("div",{class:"nav-card__item__info"},[t("div",{class:"nav-card__item__img skeleton-image"},[t("img",{src:"https://lovable.dev/favicon.ico",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),t("span",{class:"name"},"Lovable")]),t("p",{class:"desc"},"面向非技术用户的 AI 全栈应用生成器,输入产品想法生成前后端完整应用,内置 Supabase 数据库集成与一键部署,支持实时预览和多轮对话修改,让没有编程基础的人也能独立做出可上线的 Web 产品。"),t("span",{class:"VPBadge tip badge"},"无代码全栈")]),t("a",{href:"https://replit.com/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[t("div",{class:"nav-card__item__info"},[t("div",{class:"nav-card__item__img skeleton-image"},[t("img",{src:"https://replit.com/public/icons/favicon-prompt-192.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),t("span",{class:"name"},"Replit Agent")]),t("p",{class:"desc"},"云端在线 IDE Replit 内置的 AI Agent,能从需求描述自动生成完整项目、安装依赖、运行调试,全程在浏览器内完成,内置托管与分享功能,零本地环境要求,适合快速原型和在线学习编程。"),t("span",{class:"VPBadge tip badge"},"云端全栈")]),t("a",{href:"https://same.dev/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[t("div",{class:"nav-card__item__info"},[t("div",{class:"nav-card__item__img skeleton-image"},[t("img",{src:"https://same.dev/favicon.ico",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),t("span",{class:"name"},"Same.dev")]),t("p",{class:"desc"},'专注"克隆任意网站 UI"的 AI 编码工具,输入目标网站 URL,AI 自动还原其界面并生成对应前端代码,适合学习参考优秀设计、快速复现竞品界面,以及建站初始模板快速搭建。'),t("span",{class:"VPBadge tip badge"},"UI 克隆")]),t("a",{href:"https://www.miaoda.cn/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[t("div",{class:"nav-card__item__info"},[t("div",{class:"nav-card__item__img skeleton-image"},[t("img",{src:"https://resource-static.cdn.bcebos.com/img/favicon.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),t("span",{class:"name"},"秒哒 Miaoda")]),t("p",{class:"desc"},'百度出品的无代码应用搭建平台,口号"一句话做应用"。在输入框用自然语言描述需求,即可一键生成可部署的 Web 应用或微信小程序;内置深度开发模式、插件市场与风格定制,帮助想法从描述直达成品。配套"应用广场"汇聚社区作品,可浏览、点赞并参考他人案例,适合产品原型快速验证、学习参考与演示展示。'),t("span",{class:"VPBadge tip badge"},"中文体验佳")])])],-1),e('

2.2 六款工具横向对比

💡 快速选择建议

  • 要做完整全栈 Web 并直接上线Bolt.new(成熟度最高)
  • 只需前端 UI 组件嵌入现有项目 → v0
  • 非技术背景想独立做出有数据库的产品 → Lovable
  • 在线学编程或使用 Python / Go 等非 React 语言 → Replit Agent
  • 手头有参考网站想直接还原其界面 → Same.dev
  • 中文用户或目标平台是微信小程序秒哒 Miaoda
工具核心定位输出形态技术栈最适场景上手门槛
Bolt.new应用生成完整 Web 应用React快速生成可部署全栈 Demo
v0UI 组件生成React 组件代码片段React + Tailwind + shadcn/ui前端界面快速出图,嵌入 Next.js 项目
Lovable零代码全栈建站含数据库的完整 Web 产品前端 + Supabase 后端非技术人员独立做出可上线产品
Replit Agent云端多语言全栈多语言完整项目Python / JS / Go 等多语言在线学编程、非 React 技术栈原型⭐⭐
Same.dev网站 UI 克隆前端页面还原代码前端(URL → 代码)参考竞品设计、快速获取建站初始模板
秒哒 Miaoda无代码应用搭建Web 应用 / 微信小程序Web + 小程序双端中文一句话出原型,尤其适合小程序

3. AI IDE — 与代码编辑器深度融合

3.1 关键点说明

适合人群:有一定编程基础、追求研发效率的开发者。

核心价值:上下文感知补全 + 自然语言对话改代码 + Agent 自主多文件重构,让"写代码"变成"描述 + 确认"。

如何上手:安装对应工具 → 打开项目 → 用快捷键呼出 AI 对话框(如 Cursor 的 Cmd+K)→ 用自然语言描述要改什么 → 确认差异后应用。

',6),t("div",{class:"container nav-card-container"},[t("div",{class:"nav-card index-auto",style:{"--row-gap":"20px","--column-gap":"20px","--column-min-width":"calc(100% / 4 - 60px)"}},[t("a",{href:"https://www.cursor.com/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[t("div",{class:"nav-card__item__info"},[t("div",{class:"nav-card__item__img skeleton-image"},[t("img",{src:"https://www.cursor.com/favicon.ico",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),t("span",{class:"name"},"Cursor")]),t("p",{class:"desc"},"基于 VS Code 深度改造的 AI 原生 IDE,三大核心能力:① Tab 智能补全(感知上下文多文件);② Cmd+K 行内生成与修改;③ Cursor Agent 可自主规划、读写多文件、运行终端完成复杂任务。是目前口碑最好的 AI 编程工具。"),t("span",{class:"VPBadge tip badge"},"强烈推荐")]),t("a",{href:"https://www.trae.cn/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[t("div",{class:"nav-card__item__info"},[t("div",{class:"nav-card__item__img skeleton-image"},[t("img",{src:"https://lf-cdn.trae.com.cn/obj/trae-com-cn/trae_website_prod_cn/favicon.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),t("span",{class:"name"},"Trae IDE")]),t("p",{class:"desc"},'国内出品的 AI 原生 IDE,"The Real AI Engineer(真正的 AI 工程师)",免费可用。三大核心能力:① 智能补全与对话式改代码;② 多文件 Agent 自主重构,全面对标 Cursor;③ **数据安全优先** — 坚持"本地优先、最小化数据收集"原则,内置隐私模式,代码默认存于本地。另提供 SOLO 在线轻量版供快速体验,适合关注数据主权的国内开发者与有合规要求的企业团队。'),t("span",{class:"VPBadge tip badge"},"国内自主支持")]),t("a",{href:"https://windsurf.com/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[t("div",{class:"nav-card__item__info"},[t("div",{class:"nav-card__item__img skeleton-image"},[t("img",{src:"https://codeium.com/favicon.ico",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),t("span",{class:"name"},"Windsurf")]),t("p",{class:"desc"},'Codeium 出品的 AI 原生 IDE,现已迁至独立域名 windsurf.com,口号"开发者做出最佳工作的地方"。两大核心能力:① **Cascade Agent** — 能前瞻 10 步以上,自动规划、编码、修复 Bug,深度理解整个代码库并串联多步骤任务;② **Windsurf Tab** — 一键补全代码、跳转光标、自动导入依赖,保持开发"心流"不中断。支持 GPT-4.5、Gemini 等主流模型,提供个人免费版与企业版。'),t("span",{class:"VPBadge tip badge"},"分析代码")])])],-1),e('

3.2 三款工具横向对比

💡 选择建议

  • 追求口碑最佳 + 生态最成熟的 AI IDE → Cursor(社区资源最丰富)
  • 数据安全 / 合规要求,或想要免费的国产方案 → Trae IDE
  • 喜欢 AI 自动串联多步任务,享受不中断的"心流"编程体验 → Windsurf
  • 三款均基于 VS Code 改造,现有 VS Code 插件和快捷键习惯均可无缝迁移
工具核心特色Agent 能力数据安全费用最适场景
Cursor多文件上下文感知补全 + Cmd+K 行内生成强 — 多文件规划 + 终端执行一般(代码发往云端)免费额度 + 订阅日常功能开发、多文件重构、代码 Review
Trae IDE国产免费 + 本地优先数据安全强 — 对标 Cursor,含在线 SOLO 版本地优先 + 隐私模式免费有合规需求的国内团队、个人日常开发
WindsurfCascade 前瞻规划 + Tab 一键心流强 — 前瞻 10 步、自动串联多步任务一般(代码发往云端)免费额度 + 订阅复杂多步任务自动执行、追求"心流"开发体验

4. Agentic Engineering — AI 自主完成工程任务

4.1 关键点说明

适合人群:希望将完整工程任务交给 AI 自主处理的资深开发者或团队。

核心价值:AI 不再只是"副驾驶",而是能自主读取代码库、运行测试、修复 Bug、甚至提交 PR 的"自主工程师",适合 Bug 修复、功能迭代、代码重构等完整工程周期。

如何上手(以 Claude Code 为例)npm install -g @anthropic-ai/claude-code → 在项目根目录执行 claude → 输入任务(如"帮我找出 #123 这个 Bug 的根因,写好测试后提交")→ Claude Code 自主读取代码库、执行命令并逐步反馈,审查后确认提交。

',6),t("div",{class:"container nav-card-container"},[t("div",{class:"nav-card index-auto",style:{"--row-gap":"20px","--column-gap":"20px","--column-min-width":"calc(100% / 4 - 60px)"}},[t("a",{href:"https://claude-update-code.squarespace.com/?gad_source=1&gad_campaignid=23635038607&gbraid=0AAAAADBLX79DSBI8Ftftv8_FSgjubKKve&gclid=CjwKCAiAtq_NBhA_EiwA78nNWBwq9FGhmQLtwZ0ImoSZ5098wJU2cJMAwk8pHy9DtfDpt6Zf_TzDNhoCptgQAvD_BwE",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[t("div",{class:"nav-card__item__info"},[t("div",{class:"nav-card__item__img skeleton-image"},[t("img",{src:"https://claude.ai/favicon.ico",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),t("span",{class:"name"},"Claude Code")]),t("p",{class:"desc"},'Anthropic 官方推出的命令行 AI 编程 Agent,在终端中直接与代码库深度对话,支持多文件读写、执行 Shell 命令、Git 操作,能够完成"读懂整个代码库→制定方案→逐步执行"的完整工程任务流,是最贴近真实工程流程的终端 Agent。'),t("span",{class:"VPBadge tip badge"},"CLI Agent")]),t("a",{href:"https://opencode.ai",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[t("div",{class:"nav-card__item__info"},[t("div",{class:"nav-card__item__img skeleton-image"},[t("img",{src:"https://opencode.ai/favicon.ico",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),t("span",{class:"name"},"opencode")]),t("p",{class:"desc"},"开源 AI 编程代理,Claude Code 的开源平替,内置免费模型,也可配置、连接任意提供商的任意模型,包括 Claude、GPT、Gemini,以及国内模型。"),t("span",{class:"VPBadge tip badge"},"开源 CLI Agent")]),t("a",{href:"https://devin.ai/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[t("div",{class:"nav-card__item__info"},[t("div",{class:"nav-card__item__img skeleton-image"},[t("img",{src:"https://devin.ai/favicon.ico",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),t("span",{class:"name"},"Devin")]),t("p",{class:"desc"},'全球首个商用"AI 软件工程师",能接收 GitHub Issue 或自然语言任务,自主浏览文档、搜索资料、编写代码、运行测试并提交 PR,具备完整工程任务自主执行闭环,是 Agentic Engineering 的行业标杆。'),t("span",{class:"VPBadge tip badge"},"自主 Agent 标杆")]),t("a",{href:"https://github.com/All-Hands-AI/OpenHands",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[t("div",{class:"nav-card__item__info"},[t("div",{class:"nav-card__item__img skeleton-image"},[t("img",{src:"https://github.githubassets.com/favicons/favicon.svg",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),t("span",{class:"name"},"OpenHands")]),t("p",{class:"desc"},"前 OpenDevin,完全开源的 AI 软件工程师平台,Devin 的开源可自托管替代方案,可本地 Docker 部署,支持接入多种 LLM(GPT / Claude / DeepSeek 等),自主执行代码库任务、运行 Shell 命令、浏览网页查阅文档。"),t("span",{class:"VPBadge tip badge"},"开源可自部署")]),t("a",{href:"https://www.augmentcode.com/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[t("div",{class:"nav-card__item__info"},[t("div",{class:"nav-card__item__img skeleton-image"},[t("img",{src:"https://www.augmentcode.com/favicon.ico",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),t("span",{class:"name"},"Augment Code")]),t("p",{class:"desc"},"专为大型代码库设计的 AI 编程 Agent 平台,能深度索引企业级代码库(百万行级别),提供精准的上下文感知补全和 Agent 任务执行,适合中大型团队在已有复杂代码库上进行 AI 辅助开发。"),t("span",{class:"VPBadge tip badge"},"企业级 Agent")])])],-1),e('

4.2 五款 Agentic 工具横向对比

选型建议

  • 个人 / 小项目:优先 Claude Code(体验最流畅),无订阅则用 opencode 接入低成本模型平替。
  • 团队 / 私有部署:用 OpenHands 自托管,统一管控模型与 API Key,保障数据不出域。
  • Issue 驱动的研发流:接入 Devin,让 AI 全程完成 Issue → 代码 → PR 闭环,人工只做 Review。
  • 大型存量代码库:优先 Augment Code,深度索引能力是 CLI Agent 难以替代的。
工具交互方式核心优势适场景典型任务示例费用
Claude Code终端 CLI与本地代码库深度结合,可执行 Shell / Git,多文件读写全自动个人或小团队的重构、批量 Bug 修复、自动提交等完整工程周期claude → "重构 auth 模块,保持接口不变,补齐单测后提交"Claude Pro / API 按量计费
opencode终端 CLI完全开源,内置免费模型,支持接入任意 LLM(含国内模型)无官方订阅、希望接入 DeepSeek / 通义等低成本模型的场景opencode → 配置自定义模型 → 同上工程任务取决于所接模型
DevinWeb 界面高度自主,可持续跟进 GitHub Issue,全链路无人值守有明确 Issue 驱动的团队研发流,AI 自动完成功能开发并提 PR粘贴 Issue URL → 指定验收标准 → 审查 PR付费(企业为主)
OpenHandsWeb / API开源自托管,支持多 LLM,可定制扩展 Agentic 流程企业私有化部署,团队共享 AI 工程师能力,保障数据安全Docker 启动 → 接入 DeepSeek → 批量分配修复任务开源免费,按模型计费
Augment CodeIDE 插件深度索引百万行级代码库,上下文感知精准大型企业存量代码库的日常开发、重构与工程管理圈选模块 → "梳理调用链并生成文档"免费额度 + 订阅
',3)])])}const m=s(d,[["render",i]]);export{h as __pageData,m as default}; diff --git a/assets/fullstack_ai-coding_resources.md.CCLNidMN.lean.js b/assets/fullstack_ai-coding_resources.md.CCLNidMN.lean.js new file mode 100644 index 00000000..532c1274 --- /dev/null +++ b/assets/fullstack_ai-coding_resources.md.CCLNidMN.lean.js @@ -0,0 +1 @@ +import{_ as s,g as l,h as n,U as e,i as t}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const h=JSON.parse('{"title":"AI 编程工具与资源推荐","description":"摘要总结:本文深度解析了 AI 驱动编程的三大演进范式:Vibe Coding(自然语言零门槛构建)、AI IDE(编辑器深度辅助提效)及 Agentic Engineering(自主工程师执行任务)。通过横向对比 Bolt.new、Cursor、Claude Code 等前沿工具,文章勾勒出一条从“快速原型”到“高效协同”再到“自主交付”的进阶路径。核心旨在指导用户利用 AI 工具矩阵打破技术边界,实现从创意描述到工业级交付的生产力飞跃,重塑软件开发全生命周期。","frontmatter":{"date":"2025-11-25T00:52:28.000Z","title":"AI 编程工具与资源推荐","description":"摘要总结:本文深度解析了 AI 驱动编程的三大演进范式:Vibe Coding(自然语言零门槛构建)、AI IDE(编辑器深度辅助提效)及 Agentic Engineering(自主工程师执行任务)。通过横向对比 Bolt.new、Cursor、Claude Code 等前沿工具,文章勾勒出一条从“快速原型”到“高效协同”再到“自主交付”的进阶路径。核心旨在指导用户利用 AI 工具矩阵打破技术边界,实现从创意描述到工业级交付的生产力飞跃,重塑软件开发全生命周期。","permalink":"/fullstack/ai-coding/resources","coverImg":"https://insight-stack-1252300811.cos.ap-shanghai.myqcloud.com/img/cover/source_sites_bg.png","categories":["资源推荐"],"tags":["资源推荐","AI","AI Coding","Vibe Coding","Agentic Engineering"]},"headers":[],"relativePath":"fullstack/ai-coding/resources.md","filePath":"01.全栈/10.AI 编程实践指南/00.AI编程工具与资源.md"}'),d={name:"fullstack/ai-coding/resources.md"};function i(o,a,r,c,g,_){return n(),l("div",null,[...a[0]||(a[0]=[e("",9),t("div",{class:"container nav-card-container"},[t("div",{class:"nav-card index-auto",style:{"--row-gap":"20px","--column-gap":"20px","--column-min-width":"calc(100% / 4 - 60px)"}},[t("a",{href:"https://bolt.new/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[t("div",{class:"nav-card__item__info"},[t("div",{class:"nav-card__item__img skeleton-image"},[t("img",{src:"https://bolt.new/static/favicon-192x192.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),t("span",{class:"name"},"Bolt.new")]),t("p",{class:"desc"},"StackBlitz 推出的全栈 AI 开发平台,在浏览器中直接生成并运行完整的 React 项目,支持多轮对话迭代,可一键部署到 Netlify / Vercel,零环境配置从描述到上线全链路打通。"),t("span",{class:"VPBadge tip badge"},"一键部署")]),t("a",{href:"https://v0.dev/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[t("div",{class:"nav-card__item__info"},[t("div",{class:"nav-card__item__img skeleton-image"},[t("img",{src:"https://v0.app/assets/icon-dark-32x32.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),t("span",{class:"name"},"v0 (Vercel)")]),t("p",{class:"desc"},"Vercel 推出的 UI 组件生成工具,专注前端界面:用自然语言描述界面,生成 React + Tailwind CSS + shadcn/ui 组件代码,可直接复制进项目,天生与 Next.js 生态无缝衔接,非常适合前端 UI 的快速原型。"),t("span",{class:"VPBadge tip badge"},"UI 生成")]),t("a",{href:"https://lovable.dev/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[t("div",{class:"nav-card__item__info"},[t("div",{class:"nav-card__item__img skeleton-image"},[t("img",{src:"https://lovable.dev/favicon.ico",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),t("span",{class:"name"},"Lovable")]),t("p",{class:"desc"},"面向非技术用户的 AI 全栈应用生成器,输入产品想法生成前后端完整应用,内置 Supabase 数据库集成与一键部署,支持实时预览和多轮对话修改,让没有编程基础的人也能独立做出可上线的 Web 产品。"),t("span",{class:"VPBadge tip badge"},"无代码全栈")]),t("a",{href:"https://replit.com/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[t("div",{class:"nav-card__item__info"},[t("div",{class:"nav-card__item__img skeleton-image"},[t("img",{src:"https://replit.com/public/icons/favicon-prompt-192.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),t("span",{class:"name"},"Replit Agent")]),t("p",{class:"desc"},"云端在线 IDE Replit 内置的 AI Agent,能从需求描述自动生成完整项目、安装依赖、运行调试,全程在浏览器内完成,内置托管与分享功能,零本地环境要求,适合快速原型和在线学习编程。"),t("span",{class:"VPBadge tip badge"},"云端全栈")]),t("a",{href:"https://same.dev/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[t("div",{class:"nav-card__item__info"},[t("div",{class:"nav-card__item__img skeleton-image"},[t("img",{src:"https://same.dev/favicon.ico",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),t("span",{class:"name"},"Same.dev")]),t("p",{class:"desc"},'专注"克隆任意网站 UI"的 AI 编码工具,输入目标网站 URL,AI 自动还原其界面并生成对应前端代码,适合学习参考优秀设计、快速复现竞品界面,以及建站初始模板快速搭建。'),t("span",{class:"VPBadge tip badge"},"UI 克隆")]),t("a",{href:"https://www.miaoda.cn/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[t("div",{class:"nav-card__item__info"},[t("div",{class:"nav-card__item__img skeleton-image"},[t("img",{src:"https://resource-static.cdn.bcebos.com/img/favicon.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),t("span",{class:"name"},"秒哒 Miaoda")]),t("p",{class:"desc"},'百度出品的无代码应用搭建平台,口号"一句话做应用"。在输入框用自然语言描述需求,即可一键生成可部署的 Web 应用或微信小程序;内置深度开发模式、插件市场与风格定制,帮助想法从描述直达成品。配套"应用广场"汇聚社区作品,可浏览、点赞并参考他人案例,适合产品原型快速验证、学习参考与演示展示。'),t("span",{class:"VPBadge tip badge"},"中文体验佳")])])],-1),e("",6),t("div",{class:"container nav-card-container"},[t("div",{class:"nav-card index-auto",style:{"--row-gap":"20px","--column-gap":"20px","--column-min-width":"calc(100% / 4 - 60px)"}},[t("a",{href:"https://www.cursor.com/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[t("div",{class:"nav-card__item__info"},[t("div",{class:"nav-card__item__img skeleton-image"},[t("img",{src:"https://www.cursor.com/favicon.ico",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),t("span",{class:"name"},"Cursor")]),t("p",{class:"desc"},"基于 VS Code 深度改造的 AI 原生 IDE,三大核心能力:① Tab 智能补全(感知上下文多文件);② Cmd+K 行内生成与修改;③ Cursor Agent 可自主规划、读写多文件、运行终端完成复杂任务。是目前口碑最好的 AI 编程工具。"),t("span",{class:"VPBadge tip badge"},"强烈推荐")]),t("a",{href:"https://www.trae.cn/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[t("div",{class:"nav-card__item__info"},[t("div",{class:"nav-card__item__img skeleton-image"},[t("img",{src:"https://lf-cdn.trae.com.cn/obj/trae-com-cn/trae_website_prod_cn/favicon.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),t("span",{class:"name"},"Trae IDE")]),t("p",{class:"desc"},'国内出品的 AI 原生 IDE,"The Real AI Engineer(真正的 AI 工程师)",免费可用。三大核心能力:① 智能补全与对话式改代码;② 多文件 Agent 自主重构,全面对标 Cursor;③ **数据安全优先** — 坚持"本地优先、最小化数据收集"原则,内置隐私模式,代码默认存于本地。另提供 SOLO 在线轻量版供快速体验,适合关注数据主权的国内开发者与有合规要求的企业团队。'),t("span",{class:"VPBadge tip badge"},"国内自主支持")]),t("a",{href:"https://windsurf.com/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[t("div",{class:"nav-card__item__info"},[t("div",{class:"nav-card__item__img skeleton-image"},[t("img",{src:"https://codeium.com/favicon.ico",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),t("span",{class:"name"},"Windsurf")]),t("p",{class:"desc"},'Codeium 出品的 AI 原生 IDE,现已迁至独立域名 windsurf.com,口号"开发者做出最佳工作的地方"。两大核心能力:① **Cascade Agent** — 能前瞻 10 步以上,自动规划、编码、修复 Bug,深度理解整个代码库并串联多步骤任务;② **Windsurf Tab** — 一键补全代码、跳转光标、自动导入依赖,保持开发"心流"不中断。支持 GPT-4.5、Gemini 等主流模型,提供个人免费版与企业版。'),t("span",{class:"VPBadge tip badge"},"分析代码")])])],-1),e("",6),t("div",{class:"container nav-card-container"},[t("div",{class:"nav-card index-auto",style:{"--row-gap":"20px","--column-gap":"20px","--column-min-width":"calc(100% / 4 - 60px)"}},[t("a",{href:"https://claude-update-code.squarespace.com/?gad_source=1&gad_campaignid=23635038607&gbraid=0AAAAADBLX79DSBI8Ftftv8_FSgjubKKve&gclid=CjwKCAiAtq_NBhA_EiwA78nNWBwq9FGhmQLtwZ0ImoSZ5098wJU2cJMAwk8pHy9DtfDpt6Zf_TzDNhoCptgQAvD_BwE",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[t("div",{class:"nav-card__item__info"},[t("div",{class:"nav-card__item__img skeleton-image"},[t("img",{src:"https://claude.ai/favicon.ico",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),t("span",{class:"name"},"Claude Code")]),t("p",{class:"desc"},'Anthropic 官方推出的命令行 AI 编程 Agent,在终端中直接与代码库深度对话,支持多文件读写、执行 Shell 命令、Git 操作,能够完成"读懂整个代码库→制定方案→逐步执行"的完整工程任务流,是最贴近真实工程流程的终端 Agent。'),t("span",{class:"VPBadge tip badge"},"CLI Agent")]),t("a",{href:"https://opencode.ai",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[t("div",{class:"nav-card__item__info"},[t("div",{class:"nav-card__item__img skeleton-image"},[t("img",{src:"https://opencode.ai/favicon.ico",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),t("span",{class:"name"},"opencode")]),t("p",{class:"desc"},"开源 AI 编程代理,Claude Code 的开源平替,内置免费模型,也可配置、连接任意提供商的任意模型,包括 Claude、GPT、Gemini,以及国内模型。"),t("span",{class:"VPBadge tip badge"},"开源 CLI Agent")]),t("a",{href:"https://devin.ai/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[t("div",{class:"nav-card__item__info"},[t("div",{class:"nav-card__item__img skeleton-image"},[t("img",{src:"https://devin.ai/favicon.ico",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),t("span",{class:"name"},"Devin")]),t("p",{class:"desc"},'全球首个商用"AI 软件工程师",能接收 GitHub Issue 或自然语言任务,自主浏览文档、搜索资料、编写代码、运行测试并提交 PR,具备完整工程任务自主执行闭环,是 Agentic Engineering 的行业标杆。'),t("span",{class:"VPBadge tip badge"},"自主 Agent 标杆")]),t("a",{href:"https://github.com/All-Hands-AI/OpenHands",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[t("div",{class:"nav-card__item__info"},[t("div",{class:"nav-card__item__img skeleton-image"},[t("img",{src:"https://github.githubassets.com/favicons/favicon.svg",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),t("span",{class:"name"},"OpenHands")]),t("p",{class:"desc"},"前 OpenDevin,完全开源的 AI 软件工程师平台,Devin 的开源可自托管替代方案,可本地 Docker 部署,支持接入多种 LLM(GPT / Claude / DeepSeek 等),自主执行代码库任务、运行 Shell 命令、浏览网页查阅文档。"),t("span",{class:"VPBadge tip badge"},"开源可自部署")]),t("a",{href:"https://www.augmentcode.com/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[t("div",{class:"nav-card__item__info"},[t("div",{class:"nav-card__item__img skeleton-image"},[t("img",{src:"https://www.augmentcode.com/favicon.ico",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),t("span",{class:"name"},"Augment Code")]),t("p",{class:"desc"},"专为大型代码库设计的 AI 编程 Agent 平台,能深度索引企业级代码库(百万行级别),提供精准的上下文感知补全和 Agent 任务执行,适合中大型团队在已有复杂代码库上进行 AI 辅助开发。"),t("span",{class:"VPBadge tip badge"},"企业级 Agent")])])],-1),e("",3)])])}const m=s(d,[["render",i]]);export{h as __pageData,m as default}; diff --git a/assets/fullstack_ai-engineer-capability.md.DWEvYZ-g.js b/assets/fullstack_ai-engineer-capability.md.DWEvYZ-g.js new file mode 100644 index 00000000..55644fff --- /dev/null +++ b/assets/fullstack_ai-engineer-capability.md.DWEvYZ-g.js @@ -0,0 +1 @@ +import{H as r}from"./chunks/HighLightText.BD5ARcjF.js";import{g as o,h as i,U as a,i as n,S as e,z as s,s as g}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const p=JSON.parse('{"title":"重构开发者:AI 时代下的工程师能力图谱与演进指南","description":"摘要总结:当 AI 极速降低代码编写门槛,单纯的“业务代码翻译器”角色正加速贬值。本文从技术演进与产品思考的交汇点出发,将 AI 时代的开发者能力图谱重新划分为三大核心圈层:产品应用层(Insight Stack)、Agent 开发层与 AI 基础设施层。无论你是深耕视图层交互、精通 Node.js 等服务端架构的开发者,还是致力于技术落地的探索者,都能在这份演进指南中找到打破能力边界、向“超级个体”与“AI 智能体指挥官”跃迁的破局之道。","frontmatter":{"date":"2026-03-02T11:05:50.000Z","title":"重构开发者:AI 时代下的工程师能力图谱与演进指南","description":"摘要总结:当 AI 极速降低代码编写门槛,单纯的“业务代码翻译器”角色正加速贬值。本文从技术演进与产品思考的交汇点出发,将 AI 时代的开发者能力图谱重新划分为三大核心圈层:产品应用层(Insight Stack)、Agent 开发层与 AI 基础设施层。无论你是深耕视图层交互、精通 Node.js 等服务端架构的开发者,还是致力于技术落地的探索者,都能在这份演进指南中找到打破能力边界、向“超级个体”与“AI 智能体指挥官”跃迁的破局之道。","permalink":"/fullstack/ai-engineer-capability","coverImg":"https://insight-stack-1252300811.cos.ap-shanghai.myqcloud.com/img/full-stack/insight_stack.png","top":true,"tags":["全栈","AI"],"categories":["全栈"]},"headers":[],"relativePath":"fullstack/ai-engineer-capability.md","filePath":"01.全栈/01.AI Native 工程思维/02.重构开发者:AI 时代下的工程师能力图谱与演进指南.md"}'),l={name:"fullstack/ai-engineer-capability.md"},I=Object.assign(l,{setup(d){return(h,t)=>(i(),o("div",null,[t[5]||(t[5]=a('

重构开发者:AI 时代下的工程师能力图谱与演进指南

摘要总结:当 AI 极速降低代码编写门槛,单纯的“业务代码翻译器”角色正加速贬值。本文从技术演进与产品思考的交汇点出发,将 AI 时代的开发者能力图谱重新划分为三大核心圈层:产品应用层(Insight Stack)、Agent 开发层与 AI 基础设施层。无论你是深耕视图层交互、精通 Node.js 等服务端架构的开发者,还是致力于技术落地的探索者,都能在这份演进指南中找到打破能力边界、向“超级个体”与“AI 智能体指挥官”跃迁的破局之道。

about site background

如果你对近两年的技术浪潮保持敏感,大概会得出一个有些残酷但无比真实的结论:代码正在发生“通货膨胀”。随着大模型编程能力的指数级跃升,纯粹的“将业务逻辑翻译成代码”这项技能的溢价正在快速衰减。当 AI 能在几秒钟内吐出包含完整类型定义、错误处理和测试用例的后端接口或是 React 组件时,软件工程师的护城河究竟在哪里?

行业的演进给出了答案:开发者的角色正在经历一次彻底的重构。我们正在从“代码的编写者”转变为“系统的架构者”与“AI 智能体的指挥官”。结合当下的工业界实践,我们可以将 AI 时代的工程师图谱清晰地划分为三大核心圈层:产品应用层、Agent 开发层与 AI 基础设施层

1. 产品应用层(Insight Stack):走向“超级个体”的 AI 原生全栈

核心壁垒:技术视野 + 产品敏锐度 + 极速的架构组装能力,能够单枪匹马或带领极小团队,将一个灵感迅速转化为高可用产品。

在 AI 极大地降低了代码编写门槛的今天,“决定做什么”和“如何利用 AI 构建系统”的价值,已经逐渐超越了“纯手工敲击代码”的价值。这或许是传统前端、后端开发者转型最顺滑、也最能释放巨大商业价值的一层。

',8)),n("p",null,[t[1]||(t[1]=e("在这一层,“全栈工程师”的定义被重新改写为“产品工程师(Product Engineer)”。",-1)),t[2]||(t[2]=n("strong",null,"技术栈不再仅仅是前端框架和数据库,而是包含了“产品 Sense”与“商业洞察”的 Insight Stack",-1)),t[3]||(t[3]=e("。全栈工程师也正在进化为“超级个体”或“产品工程师(Product Engineer)”。",-1)),s(r,{type:"note",bold:""},{default:g(()=>[...t[0]||(t[0]=[e("问题发现 -> 创意沉淀 -> AI 辅助技术方案 -> AI 驱动代码生成",-1)])]),_:1}),t[4]||(t[4]=e(" 这一闭环,正是当前最高效的独立开发或小团队敏捷开发范式。",-1))]),t[6]||(t[6]=a('

1.1 产品 Sense 与业务洞察

过去,工程师往往是被动接收 PRD。而在 AI 时代,技术门槛的降低意味着工程师可以随时将生活和工作中的“灵感碎片”与“痛点捕获”转化为产品创意。我们需要具备极其敏锐的 AI 边界认知,明确知道哪些场景适合用传统的 CRUD 解决,哪些必须交由 LLM 去处理模糊与非确定性。

在产品应用层,我们还需要具备数据飞轮意识,注重在应用层设计埋点,收集用户的交互与纠错数据,为后续的 Agentic workflow 优化或模型微调提供高质量数据源。

1.2 Agentic Engineering(智能体工程)

这是一种全新的开发范式,开发者不再逐行手敲代码,而是通过撰写严谨的 Spec、利用 TDD(测试驱动开发)和 Lint 强约束,去“驱动”和“管理” AI 编程助手(如 Claude Code、Cursor),全栈基础设施的范畴也扩展到了跨端轻量化应用(例如利用前端技术栈快速构建高价值的浏览器插件)。

能力维度具体要求
规划、设计与迭代能力• 能够快速响应业务需求,规划产品功能,完成技术架构的调研、选型与整体设计。
• 能借助 AI 进行前端视图层、Node.js 后端核心数据流、业务流程的顶层设计。
• 不但能单枪匹马或带领极小团队中的人,还懂得领导、管理 AI 数字员工。
AI 驱动编程基于 Spec、TDD、Hooks(Lint 检查)等强约束机制,驱动 Claude Code / Copilot 等工具生成高规范度代码。
全栈基础设施熟练掌握传统架构体系(数据库选型、Redis、微服务、消息队列),以及跨端/轻量化形态(如 Chrome 插件生态)的工程搭建。
DevOps现代化的自动化部署、CI/CD 流水线搭建与运维。

1.3 AI-First 的交互哲学

AI 应用的体验与传统软件截然不同。为了对抗大模型的延迟与幻觉,工程师必须掌握流式渲染(Streaming UI)、生成式 UI(Generative UI)等新一代交互模式,用优雅的工程设计兜底 AI 的不确定性。

  • 流式渲染(Streaming UI):优化大模型响应的等待体验。
  • 生成式交互(Generative UI):在前端框架(如 React / Next.js)中,根据 AI 返回的结构化状态实时渲染出最合适的交互组件,而非死板的对话框。
  • 容错与兜底机制:优雅处理大模型幻觉(Hallucination),降低用户的挫败感。

2. Agent 开发层:构建连接物理世界的数字中枢

核心壁垒:标准化模块组装 + 复杂 Agentic Workflow 编排 + 严谨的评测体系,这一层负责为 AI 赋予记忆、手脚和专业领域的知识,是连接“底层模型大脑”与“上层应用交互”的核心枢纽。

如果说大模型是大脑,那么 Agent 工程师就是为这个大脑装上“四肢”、“记忆”和“专业工具”的人,这是一个正在爆发的新兴领域,也是实现 AI 业务落地的核心枢纽

2.1 Agentic Workflow 设计

能力维度具体要求
任务拆解与路由基于 CoT(思维链)等技术工程的任务拆解与路由机制,针对不同复杂度的工作流设计稳健的多 Agent 协作与分发机制。
设计模式与编排熟练应用 ReAct、Plan-and-Execute 等智能体设计模式,针对不同的业务场景(如信息爬取、长文总结过滤等自动化处理),设计稳健的多 Agent 协作与路由流。
主流 Agent 框架的核心机制与实战落地熟悉并掌握如 Claude Agent SDK、LangChain、AutoGen 等主流 Agent 框架的核心机制,能够在实际项目中灵活应用,解决复杂的业务场景。

2.2 记忆机制(Memory Management)

要让 Agent 变得“好用”,必须解决上下文遗忘和知识幻觉的问题。这就要求工程师深谙长期记忆/短期记忆的协同管理,以及复杂文档的切块(Chunking)、向量化(Embedding)和混合检索(Hybrid Search)技术。

  • 短期记忆:精准控制 Context Window,进行 Prompt 截断与摘要,即上下文工程能力。
  • 长期记忆:基于图数据库或向量库,持久化存储用户画像与历史交互状态。

2.3 技能的插件化(Agent Skill)

Agent Skill 是由 Anthropic 提出并推动的一种开放式标准,旨在将特定领域的知识、工作流、指令和脚本打包封装成的标准化、模块化资源包,让 AI Agent 按需动态加载这些技能,实现从通用助手向特定任务专家(如代码审计、法律文件分析)的无缝转变。

  • 结构化封装:以目录形式组织(如含 SKILL.md 的文件夹),包含详细的执行规则。
  • 渐进披露 & 按需调用:Agent 仅在处理相关任务时动态激活这些能力,无需每次提示都包含所有技能。
  • 可重用与组合:技能可多次重复使用,或多个技能组合处理复杂流程。

无论是长文抓取、摘要提取还是打标签,都可以被封装为独立的 Skill,在复杂的 Workflow 中被 Agent 动态挂载,即插即用,在构建特定场景的 Agent(例如专注于技术资讯处理的知识管理助手)时,能够像搭积木一样,根据当前任务的上下文动态加载所需的 Skills,从而大幅提升 Agent 的泛化能力和开发效率。

2.4 从硬编码到标准协议与上下文连接

随着 MCP(Model Context Protocol)等标准化协议的成熟,Agent 开发正在摆脱杂乱的胶水代码。我们可以利用熟悉的后端生态(如 Node.js)构建 MCP Server,让 AI 安全、统一地读取外部 API 或是企业内部知识库,打破信息孤岛。

  • 统一数据接入层:不再需要为每一个数据源(如 Notion、本地文件系统、特定的研发工具或外部 API)手写杂乱的胶水代码。通过实现和接入 MCP Server,为大模型提供一套标准化的双向通信协议。
  • 跨生态与端侧集成:能够利用 Node.js 等熟悉的后端生态快速构建 MCP 服务,让大模型统一、安全地读取多源上下文。这对于开发跨端的 AI 应用(如在浏览器插件中打破沙盒限制,直接与本地或云端知识库联动)至关重要。

2.5 模型选型、路由与可观测性

  • 动态 API 路由:在成本与性能之间取舍,灵活调度国内外大模型(Claude、Gemini、GPT-4,以及国内的 DeepSeek、GLM、MiniMax、Qwen等)。
  • Agent 监控:构建测试集(Eval),监控链路执行过程(Tracing),分析 Token 消耗与步骤延迟。

2.6 EDD(评估驱动开发)重塑工程质量

在 Agent 开发中,大模型的输出具有非确定性,如果说开发 Agent 只是完成了从 0 到 1 的“能用”,那么构建完善的评测体系,就是解决从 1 到 100 的“好用”与“敢用”的核心壁垒。成熟的 Agent 工程师必须建立系统的评测与监控体系(Observability),通过构建黄金测试集(Golden Dataset)、引入 LLM-as-a-Judge,以及精确到 Token 级的链路追踪(Tracing),将“感觉不错”的玄学转化为可量化的工程指标。

能力维度具体要求
自动化评测驱动 (EDD)摒弃"肉眼看效果"的游击战,建立特定场景的 Golden Dataset(基准测试集),熟练引入 Promptfoo、Ragas 等评估框架,将评测无缝融入 CI/CD 流水线。
多维指标体系设计针对具体任务(如长文总结、内容归类),设计并量化诸如事实一致性 (Faithfulness)、答案相关性 (Answer Relevance)、幻觉率 (Hallucination Rate) 等核心指标。
LLM-as-a-Judge 与人工对齐使用强模型(如 Claude 4.6/GPT)来批量自动评测弱模型或 Agent 的输出质量,并在关键节点结合 HITL(Human-in-the-loop,人机协同)进行人工微调与对齐。
链路追踪与归因 (Tracing)面对多 Agent 协作或复杂的 RAG 链路,熟练使用 LangSmith、Langfuse 等可观测性工具,记录每一次工具调用、Prompt 组装耗时和 Token 消耗,精准定位 Bad Case 的根因。

3. AI 基础设施层:算力与模型的重工业底座

核心壁垒:深厚的底层算法素养 + 极致的性能压榨 + 大规模分布式系统经验。这一层是 AI 时代的“重工业”底座,负责打造和打磨基础模型,并提供极致性价比的算力支撑。

技术工程背景的工程师可暂时只关注于模型预备训练、后训练、推理等放面的原理与流程,以及如何在大规模分布式系统上高效部署和运行这些模型,而无需深入理解底层的分布式系统和计算架构。

如果前两层是造车和开车的,这一层就是修路和提炼石油的。这属于 AI 的“重工业”,门槛极高,主要由具备深厚算法背景和底层工程能力的顶级大厂或 AI Native 独角兽主导。

能力维度具体要求
模型精炼与对齐随着开源基座模型的强大,预训练已不再是唯一解。后训练(Post-training)阶段的变得至关重要,通过 RL(强化学习)、SFT(监督微调)、RLHF/DPO(人类偏好对齐),将通用模型打磨成特定领域(如代码生成、逻辑推理)的专家。
极致的推理优化随着模型越大,成本越高。熟练掌握 vLLM 等高性能推理框架,运用量化技术(如 FP8/INT4)、KV Cache 优化(如 PagedAttention),在不牺牲精度的前提下榨干每一滴 GPU 算力。
LLMOps 与算力调度在万卡级别的 GPU 集群上,处理节点故障、实现资源负载均衡和容灾恢复,保障极其昂贵的算力资源不被浪费。

4. 找准自己的生态位

面对这股重塑整个行业的洪流,焦虑是本能,但进阶才是解药。

对于绝大多数有着丰富 Web 开发经验(无论是精通前端交互,还是深谙 Node.js/Golang/Java 等后端架构)的工程师而言,“产品应用层”和“Agent 开发层”不仅是最具性价比的切入点,更是能够最大化杠杆原有技能的沃土

我们不应该将自己局限在“写代码的机器”这一狭窄定义中。尝试用产品 Sense 发现问题,用 AI 编程工具快速实现 MVP,用标准的 Agent skills、MCP 协议和高阶 Agentic workflow 设计赋予应用专业深度。

AI 不会淘汰开发者,只会淘汰那些拒绝使用 AI 来放大自身产品价值的开发者。在技术通缩的时代,唯有洞察力和对业务流的把控力,才能迎来真正的价值膨胀。

',38))]))}});export{p as __pageData,I as default}; diff --git "a/assets/01.\345\205\250\346\240\210_01.AI Native \345\267\245\347\250\213\346\200\235\347\273\264_02.\351\207\215\346\236\204\345\274\200\345\217\221\350\200\205\357\274\232AI \346\227\266\344\273\243\344\270\213\347\232\204\345\267\245\347\250\213\345\270\210\350\203\275\345\212\233\345\233\276\350\260\261\344\270\216\346\274\224\350\277\233\346\214\207\345\215\227.md.BzWlQ04R.lean.js" b/assets/fullstack_ai-engineer-capability.md.DWEvYZ-g.lean.js similarity index 54% rename from "assets/01.\345\205\250\346\240\210_01.AI Native \345\267\245\347\250\213\346\200\235\347\273\264_02.\351\207\215\346\236\204\345\274\200\345\217\221\350\200\205\357\274\232AI \346\227\266\344\273\243\344\270\213\347\232\204\345\267\245\347\250\213\345\270\210\350\203\275\345\212\233\345\233\276\350\260\261\344\270\216\346\274\224\350\277\233\346\214\207\345\215\227.md.BzWlQ04R.lean.js" rename to assets/fullstack_ai-engineer-capability.md.DWEvYZ-g.lean.js index f4083c9e..726e07fb 100644 --- "a/assets/01.\345\205\250\346\240\210_01.AI Native \345\267\245\347\250\213\346\200\235\347\273\264_02.\351\207\215\346\236\204\345\274\200\345\217\221\350\200\205\357\274\232AI \346\227\266\344\273\243\344\270\213\347\232\204\345\267\245\347\250\213\345\270\210\350\203\275\345\212\233\345\233\276\350\260\261\344\270\216\346\274\224\350\277\233\346\214\207\345\215\227.md.BzWlQ04R.lean.js" +++ b/assets/fullstack_ai-engineer-capability.md.DWEvYZ-g.lean.js @@ -1 +1 @@ -import{H as r}from"./chunks/HighLightText.BFsbuOsY.js";import{g as o,h as i,U as a,i as n,S as e,z as s,s as g}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const p=JSON.parse('{"title":"重构开发者:AI 时代下的工程师能力图谱与演进指南","description":"摘要总结:当 AI 极速降低代码编写门槛,单纯的“业务代码翻译器”角色正加速贬值。本文从技术演进与产品思考的交汇点出发,将 AI 时代的开发者能力图谱重新划分为三大核心圈层:产品应用层(Insight Stack)、Agent 开发层与 AI 基础设施层。无论你是深耕视图层交互、精通 Node.js 等服务端架构的开发者,还是致力于技术落地的探索者,都能在这份演进指南中找到打破能力边界、向“超级个体”与“AI 智能体指挥官”跃迁的破局之道。","frontmatter":{"date":"2026-03-02T11:05:50.000Z","title":"重构开发者:AI 时代下的工程师能力图谱与演进指南","description":"摘要总结:当 AI 极速降低代码编写门槛,单纯的“业务代码翻译器”角色正加速贬值。本文从技术演进与产品思考的交汇点出发,将 AI 时代的开发者能力图谱重新划分为三大核心圈层:产品应用层(Insight Stack)、Agent 开发层与 AI 基础设施层。无论你是深耕视图层交互、精通 Node.js 等服务端架构的开发者,还是致力于技术落地的探索者,都能在这份演进指南中找到打破能力边界、向“超级个体”与“AI 智能体指挥官”跃迁的破局之道。","permalink":"/fullstack/ai-engineer-capability","coverImg":"https://insight-stack-1252300811.cos.ap-shanghai.myqcloud.com/img/full-stack/insight_stack.png","top":true,"tags":["全栈","AI"],"categories":["全栈"]},"headers":[],"relativePath":"01.全栈/01.AI Native 工程思维/02.重构开发者:AI 时代下的工程师能力图谱与演进指南.md","filePath":"01.全栈/01.AI Native 工程思维/02.重构开发者:AI 时代下的工程师能力图谱与演进指南.md"}'),d={name:"01.全栈/01.AI Native 工程思维/02.重构开发者:AI 时代下的工程师能力图谱与演进指南.md"},I=Object.assign(d,{setup(l){return(h,t)=>(i(),o("div",null,[t[5]||(t[5]=a("",9)),n("p",null,[t[1]||(t[1]=e("在这一层,“全栈工程师”的定义被重新改写为“产品工程师(Product Engineer)”。",-1)),t[2]||(t[2]=n("strong",null,"技术栈不再仅仅是前端框架和数据库,而是包含了“产品 Sense”与“商业洞察”的 Insight Stack",-1)),t[3]||(t[3]=e("。全栈工程师也正在进化为“超级个体”或“产品工程师(Product Engineer)”。",-1)),s(r,{type:"note",bold:""},{default:g(()=>[...t[0]||(t[0]=[e("问题发现 -> 创意沉淀 -> AI 辅助技术方案 -> AI 驱动代码生成",-1)])]),_:1}),t[4]||(t[4]=e(" 这一闭环,正是当前最高效的独立开发或小团队敏捷开发范式。",-1))]),t[6]||(t[6]=a("",38))]))}});export{p as __pageData,I as default}; +import{H as r}from"./chunks/HighLightText.BD5ARcjF.js";import{g as o,h as i,U as a,i as n,S as e,z as s,s as g}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const p=JSON.parse('{"title":"重构开发者:AI 时代下的工程师能力图谱与演进指南","description":"摘要总结:当 AI 极速降低代码编写门槛,单纯的“业务代码翻译器”角色正加速贬值。本文从技术演进与产品思考的交汇点出发,将 AI 时代的开发者能力图谱重新划分为三大核心圈层:产品应用层(Insight Stack)、Agent 开发层与 AI 基础设施层。无论你是深耕视图层交互、精通 Node.js 等服务端架构的开发者,还是致力于技术落地的探索者,都能在这份演进指南中找到打破能力边界、向“超级个体”与“AI 智能体指挥官”跃迁的破局之道。","frontmatter":{"date":"2026-03-02T11:05:50.000Z","title":"重构开发者:AI 时代下的工程师能力图谱与演进指南","description":"摘要总结:当 AI 极速降低代码编写门槛,单纯的“业务代码翻译器”角色正加速贬值。本文从技术演进与产品思考的交汇点出发,将 AI 时代的开发者能力图谱重新划分为三大核心圈层:产品应用层(Insight Stack)、Agent 开发层与 AI 基础设施层。无论你是深耕视图层交互、精通 Node.js 等服务端架构的开发者,还是致力于技术落地的探索者,都能在这份演进指南中找到打破能力边界、向“超级个体”与“AI 智能体指挥官”跃迁的破局之道。","permalink":"/fullstack/ai-engineer-capability","coverImg":"https://insight-stack-1252300811.cos.ap-shanghai.myqcloud.com/img/full-stack/insight_stack.png","top":true,"tags":["全栈","AI"],"categories":["全栈"]},"headers":[],"relativePath":"fullstack/ai-engineer-capability.md","filePath":"01.全栈/01.AI Native 工程思维/02.重构开发者:AI 时代下的工程师能力图谱与演进指南.md"}'),l={name:"fullstack/ai-engineer-capability.md"},I=Object.assign(l,{setup(d){return(h,t)=>(i(),o("div",null,[t[5]||(t[5]=a("",8)),n("p",null,[t[1]||(t[1]=e("在这一层,“全栈工程师”的定义被重新改写为“产品工程师(Product Engineer)”。",-1)),t[2]||(t[2]=n("strong",null,"技术栈不再仅仅是前端框架和数据库,而是包含了“产品 Sense”与“商业洞察”的 Insight Stack",-1)),t[3]||(t[3]=e("。全栈工程师也正在进化为“超级个体”或“产品工程师(Product Engineer)”。",-1)),s(r,{type:"note",bold:""},{default:g(()=>[...t[0]||(t[0]=[e("问题发现 -> 创意沉淀 -> AI 辅助技术方案 -> AI 驱动代码生成",-1)])]),_:1}),t[4]||(t[4]=e(" 这一闭环,正是当前最高效的独立开发或小团队敏捷开发范式。",-1))]),t[6]||(t[6]=a("",38))]))}});export{p as __pageData,I as default}; diff --git a/assets/fullstack_ai-native.md.DhuHpOPy.js b/assets/fullstack_ai-native.md.DhuHpOPy.js new file mode 100644 index 00000000..0ece9aa1 --- /dev/null +++ b/assets/fullstack_ai-native.md.DhuHpOPy.js @@ -0,0 +1 @@ +import{H as e}from"./chunks/HighLightText.BD5ARcjF.js";import{g as i,h as r,U as n,i as a,S as s,z as l,s as o}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const m="/img/full-stack/insight_stack.png",d={class:"note custom-block"},p={class:"note custom-block"},u=JSON.parse('{"title":"不止于代码:构建 AI 时代全栈工程师的“认知三层塔”","description":"摘要总结:在 AI 重塑软件工程的今天,全栈不再是技术的线性叠加,正在从“技术栈堆砌”转向“认知栈重构”。本文提出 “(工程 + 产品) × AI” 的新公式,助力开发者构建“洞察-架构-杠杆”认知三层塔,利用 AI 杠杆让自己进化为价值创造者。","frontmatter":{"date":"2025-10-24T11:05:50.000Z","title":"不止于代码:构建 AI 时代全栈工程师的“认知三层塔”","description":"摘要总结:在 AI 重塑软件工程的今天,全栈不再是技术的线性叠加,正在从“技术栈堆砌”转向“认知栈重构”。本文提出 “(工程 + 产品) × AI” 的新公式,助力开发者构建“洞察-架构-杠杆”认知三层塔,利用 AI 杠杆让自己进化为价值创造者。","coverImg":"https://insight-stack-1252300811.cos.ap-shanghai.myqcloud.com/img/full-stack/insight_stack.png","permalink":"/fullstack/ai-native","sticky":1,"top":true,"tags":["全栈","AI","产品"],"categories":["全栈"]},"headers":[],"relativePath":"fullstack/ai-native.md","filePath":"01.全栈/01.AI Native 工程思维/01.不止于代码:构建 AI 时代全栈工程师的“认知三层塔”.md"}'),c={name:"fullstack/ai-native.md"},x=Object.assign(c,{setup(h){return(g,t)=>(r(),i("div",null,[t[10]||(t[10]=n('

不止于代码:构建 AI 时代全栈工程师的“认知三层塔”

摘要总结:在 AI 重塑软件工程的今天,全栈不再是技术的线性叠加,正在从“技术栈堆砌”转向“认知栈重构”。本文提出 “(工程 + 产品) × AI” 的新公式,助力开发者构建“洞察-架构-杠杆”认知三层塔,利用 AI 杠杆让自己进化为价值创造者。

1. 引言

在很长一段时间里,当我们谈论“全栈工程师”时,脑海中浮现的往往是一张冗长且令人疲惫的技术工序清单

就像我曾经以为的那样,全栈就是线性的技能叠加与物理式的技术拼接,是一种依靠人力去填补技术鸿沟的“西西弗斯式”努力:

  • 线性的技能叠加:我们被迫成为“全能手”,左手用 React/Vue 构建精美的 UI,右手用 Node/Go 编写高并发 API,中间还要处理数据库的 ACID 事务(整个链路基本是这样的:构建前端 UI 交互 -> 编写后端业务API -> 维护底层数据存储与服务稳定)。
  • 物理式的拼接:我们试图用人力去掩盖技术栈之间的裂痕——用各种 Shell 脚本、Docker 配置、Nginx 转发规则,去粘合一个支离破碎的系统。

那个时候,我认为全栈的护城河在于“掌握编程语言的数量”。只要我能写前端、能写后端、偶尔还能写点 Python 爬虫,我就是全栈。我们都在拼命地做加法,试图把自己打磨成一把无所不能的瑞士军刀。

但在 AI 彻底重构代码生产方式的今天,这个定义显得过时且狭隘。当 GPT5/Claude Code/Cursor 等能够在一分钟内生成高质量的 CRUD 代码,甚至自动完成单元测试时,我们掌握语言、语法的价值又还剩多少?如果一个人就能通过 AI 完成一支团队的工作,那么“全栈”的边界到底在哪里?

真正的全栈,已经从“技能的物理叠加” 进化到了 “价值的化学闭环”。如果一个人通过 AI 就能完成过去一支团队的交付量,那么“全栈”的边界就不再是技术栈(Tech Stack),而是认知栈(Insight Stack)。

维度旧全栈 (Legacy Full Stack)新全栈 (AI-Native Full Stack)
关注点语言、框架、语法 (Tools)问题、场景、价值 (Value)
核心能力纯手工编码 (Coding)架构设计、Prompt 工程、代码审查 (Architecting)
交付边界前端页面 + 后端接口需求洞察 \\rightarrow 产品设计 \\rightarrow 落地运营
AI 的角色辅助工具 (Copilot)核心引擎与分身 (Co-founder)

2. AI 时代的全栈新公式

在重新思考技术演进的逻辑后,笔者思考出了一个更具现代感的全栈价值公式。这不仅仅是技能的组合,更是思维模型的重构:

Full Stack=(Engineering+Product)×AI\\mathbf{Full\\ Stack} \\; = \\; (\\mathbf{Engineering} \\; + \\; \\mathbf{Product}) \\; \\times \\; \\mathbf{AI}

这个公式告诉我们:不要再执着于手里有多少把锤子,而要关注你能构建出怎样的建筑,AI 是那个能够让工程能力和产品思维产生指数级爆炸的乘数。

2.1. Engineering (工程力):从“困于实现”到“敢于设计”

',15)),a("div",d,[t[3]||(t[3]=a("p",{class:"title note-title custom-block-title"},"新旧模式对比:",-1)),t[4]||(t[4]=a("p",null,[a("strong",null,"旧模式"),s(":熟练记忆 API,手写大量样板代码,关注具体的语言和语法细节。")],-1)),a("p",null,[t[1]||(t[1]=a("strong",null,"新模式",-1)),t[2]||(t[2]=s(":",-1)),l(e,{type:"note",bold:""},{default:o(()=>[...t[0]||(t[0]=[s("具备系统级视野,关注架构的健壮性、可维护性以及自动化交付体系。",-1)])]),_:1})])]),t[11]||(t[11]=n('

在 AI 时代,工程力的内核发生了迁移,AI 在逐渐接管 How(怎么写代码),人类必须专注于 What(做什么系统)和 Why(为什么这样设计)。

能力维度核心要点
架构决策当代码生成变得廉价,架构决策变得昂贵。是选择单体还是微服务?是 SQL 还是 NoSQL?这些决定了系统的上限。
代码审计与验收你从"写作者"变成了"编辑"和"审计员",当 AI 帮你写完 80% 的代码后,你是否有能力调试剩下那 20% 最隐蔽的逻辑漏洞?
DevOps 与交付工程力不再止步于 localhost,它意味着你能利用 Docker、K8s、CI/CD 乃至 Serverless,将代码安全、稳定地送达线上,并将产品交付到用户手中。

2.2. Product (产品力):从“需求翻译机”到“价值定义者”

',3)),a("div",p,[t[8]||(t[8]=a("p",{class:"title note-title custom-block-title"},"新旧模式对比:",-1)),t[9]||(t[9]=a("p",null,[a("strong",null,"旧模式"),s(":被动接收需求文档,关注功能的按时上线。")],-1)),a("p",null,[t[6]||(t[6]=a("strong",null,"新模式",-1)),t[7]||(t[7]=s(":",-1)),l(e,{type:"note",bold:""},{default:o(()=>[...t[5]||(t[5]=[s("理解商业模式与用户痛点,能判断“做什么”比“怎么做”更重要。",-1)])]),_:1})])]),t[12]||(t[12]=n('

产品力是技术人员最容易忽视,但在公式中权重极高的变量,它与工程力是相加关系——没有产品力的工程师,只是 AI 的操作员。

维度核心要点
同理心 (Empathy)脱离"技术自嗨",回归"用户感知"。工程师常沉迷于后端架构的完美重构(High Effort),却忽略前端模糊的报错提示(Low Effort)正让用户抓狂。
具备同理心的全栈懂得计算体验 ROI:优先解决阻碍用户达成目标的"可见障碍",而非盲目追求技术实现的"隐性完美"。
MVP 思维 (ROI 意识)精准识别"低成本高价值"的功能。在 AI 辅助下,快速构建最小可行性产品(MVP)验证假设,而非陷入过度设计的泥潭。
业务闭环不仅把功能做出来,还要考虑数据如何回流、用户如何增长。

2.3. AI (AI 杠杆):指数级倍增器

NOTE

旧模式:将 AI 视为搜索引擎的替代品或简单的代码补全工具。

新模式:AI 是你的数字员工、技能分身,是让个人产出这种线性增长变成指数增长的关键变量。

为什么 AI 处于乘数的位置?因为它是对上述两种能力的全方位放大

能力维度核心要点
技能树的补全利用 Cursor/Claude Code 等 AI 编程与 Agentic 工具,后端工程师可以写出像素级完美的前端 CSS,前端工程师可以编写复杂的 SQL 分析语句。AI 抹平了技术栈之间的专业门槛
上下文工程学会如何向 AI 提供高质量的上下文(Context),让 AI 理解你的项目结构、业务逻辑和编码规范,从而生成生产级代码。
时间压缩将从"Idea"到"Demo"的时间从数周压缩到数小时。这让"超级个体(Solo Maker)"成为可能——一个人就是一支队伍。

3. 从 Tech Stack 到 Insight Stack:进阶之路

全栈新时代架构图

过去的“全栈”是指 Tech Stack(技术栈) —— 我们在简历上堆砌的 React、Vue、NestJS、Python、Rust 等名词。

现在的“全栈”是指 Insight Stack(认知栈) —— 我们构建的是一套解决复杂问题的思维模型。

在新的范式下,我们的核心竞争力不再是精通具体的语言特性或掌握庞杂的框架细节——因为 AI 已是最好的“百科全书”与“熟练工”——而是转变为构建以下三层认知模型:

  1. 洞察层:具备 Product Sense,能够发现真实世界中值得解决的问题,并定义清楚需求的边界。
  2. 架构层:具备 Engineering Logic,能够设计出高可用、可扩展的技术方案,并指挥 AI 完成具体的模块实现。
  3. 杠杆层:具备 AI Quotient (AI商),熟练运用 LLM、RAG、Agents 等工具,将上述两层能力指数级放大。

AI 并没有以此消灭全栈工程师,它只是消灭了“平庸的搬运工”。它正在邀请我们,从“代码工人”进化为真正的“价值创造者”。

',13))]))}});export{u as __pageData,x as default}; diff --git a/assets/fullstack_ai-native.md.DhuHpOPy.lean.js b/assets/fullstack_ai-native.md.DhuHpOPy.lean.js new file mode 100644 index 00000000..302259a9 --- /dev/null +++ b/assets/fullstack_ai-native.md.DhuHpOPy.lean.js @@ -0,0 +1 @@ +import{H as e}from"./chunks/HighLightText.BD5ARcjF.js";import{g as i,h as r,U as n,i as a,S as s,z as l,s as o}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const m="/img/full-stack/insight_stack.png",d={class:"note custom-block"},p={class:"note custom-block"},u=JSON.parse('{"title":"不止于代码:构建 AI 时代全栈工程师的“认知三层塔”","description":"摘要总结:在 AI 重塑软件工程的今天,全栈不再是技术的线性叠加,正在从“技术栈堆砌”转向“认知栈重构”。本文提出 “(工程 + 产品) × AI” 的新公式,助力开发者构建“洞察-架构-杠杆”认知三层塔,利用 AI 杠杆让自己进化为价值创造者。","frontmatter":{"date":"2025-10-24T11:05:50.000Z","title":"不止于代码:构建 AI 时代全栈工程师的“认知三层塔”","description":"摘要总结:在 AI 重塑软件工程的今天,全栈不再是技术的线性叠加,正在从“技术栈堆砌”转向“认知栈重构”。本文提出 “(工程 + 产品) × AI” 的新公式,助力开发者构建“洞察-架构-杠杆”认知三层塔,利用 AI 杠杆让自己进化为价值创造者。","coverImg":"https://insight-stack-1252300811.cos.ap-shanghai.myqcloud.com/img/full-stack/insight_stack.png","permalink":"/fullstack/ai-native","sticky":1,"top":true,"tags":["全栈","AI","产品"],"categories":["全栈"]},"headers":[],"relativePath":"fullstack/ai-native.md","filePath":"01.全栈/01.AI Native 工程思维/01.不止于代码:构建 AI 时代全栈工程师的“认知三层塔”.md"}'),c={name:"fullstack/ai-native.md"},x=Object.assign(c,{setup(h){return(g,t)=>(r(),i("div",null,[t[10]||(t[10]=n("",15)),a("div",d,[t[3]||(t[3]=a("p",{class:"title note-title custom-block-title"},"新旧模式对比:",-1)),t[4]||(t[4]=a("p",null,[a("strong",null,"旧模式"),s(":熟练记忆 API,手写大量样板代码,关注具体的语言和语法细节。")],-1)),a("p",null,[t[1]||(t[1]=a("strong",null,"新模式",-1)),t[2]||(t[2]=s(":",-1)),l(e,{type:"note",bold:""},{default:o(()=>[...t[0]||(t[0]=[s("具备系统级视野,关注架构的健壮性、可维护性以及自动化交付体系。",-1)])]),_:1})])]),t[11]||(t[11]=n("",3)),a("div",p,[t[8]||(t[8]=a("p",{class:"title note-title custom-block-title"},"新旧模式对比:",-1)),t[9]||(t[9]=a("p",null,[a("strong",null,"旧模式"),s(":被动接收需求文档,关注功能的按时上线。")],-1)),a("p",null,[t[6]||(t[6]=a("strong",null,"新模式",-1)),t[7]||(t[7]=s(":",-1)),l(e,{type:"note",bold:""},{default:o(()=>[...t[5]||(t[5]=[s("理解商业模式与用户痛点,能判断“做什么”比“怎么做”更重要。",-1)])]),_:1})])]),t[12]||(t[12]=n("",13))]))}});export{u as __pageData,x as default}; diff --git "a/assets/01.\345\205\250\346\240\210_40.\345\211\215\347\253\257\345\267\245\347\250\213_02.CSS\345\267\245\347\250\213\345\214\226.md.DUPhvCof.js" b/assets/fullstack_css-engineering.md.CyF7_CNd.js similarity index 95% rename from "assets/01.\345\205\250\346\240\210_40.\345\211\215\347\253\257\345\267\245\347\250\213_02.CSS\345\267\245\347\250\213\345\214\226.md.DUPhvCof.js" rename to assets/fullstack_css-engineering.md.CyF7_CNd.js index 8417b8f1..e049c862 100644 --- "a/assets/01.\345\205\250\346\240\210_40.\345\211\215\347\253\257\345\267\245\347\250\213_02.CSS\345\267\245\347\250\213\345\214\226.md.DUPhvCof.js" +++ b/assets/fullstack_css-engineering.md.CyF7_CNd.js @@ -1,4 +1,4 @@ -import{_ as i,g as n,h as a,U as l}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const g=JSON.parse('{"title":"从原子化到变体驱动:现代 CSS 工程化的架构演进与混合实践指南","description":"本文系统剖析主流 CSS 工程化方案的底层逻辑,提出“样式资产 ROI”评估模型,并针对 Vue/React 生态给出了面向 AI 时代的企业级混合架构选型建议。","frontmatter":{"date":"2026-03-10T22:05:50.000Z","title":"从原子化到变体驱动:现代 CSS 工程化的架构演进与混合实践指南","description":"本文系统剖析主流 CSS 工程化方案的底层逻辑,提出“样式资产 ROI”评估模型,并针对 Vue/React 生态给出了面向 AI 时代的企业级混合架构选型建议。","permalink":"/full-stack/css-engineering","coverImg":"https://insight-stack-1252300811.cos.ap-shanghai.myqcloud.com/img/full-stack/insight_stack.png","top":true,"categories":["全栈"],"tags":["全栈","CSS","工程化","tailwindcss"]},"headers":[],"relativePath":"01.全栈/40.前端工程/02.CSS工程化.md","filePath":"01.全栈/40.前端工程/02.CSS工程化.md"}'),t={name:"01.全栈/40.前端工程/02.CSS工程化.md"};function p(e,s,h,r,k,d){return a(),n("div",null,[...s[0]||(s[0]=[l(`

从原子化到变体驱动:现代 CSS 工程化的架构演进与混合实践指南

摘要总结:在前端生态日新月异的今天,CSS 工程化早已超越了“如何写样式”的范畴,演变为一场关于开发效率(Velocity)与系统韧性(Resilience)的深度博弈。本文将系统梳理从预处理器、CSS-in-JS、Scoped CSS 到原子化 CSS 的演进脉络,并首次引入 “样式资产 ROI” 模型,深入剖析为何 Tailwind 已成为 AI 时代的基石架构。针对 Vue 与 React 的不同哲学,我们总结出了一套 “原子化为主,工程化局部兜底” 的企业级混合架构方案。无论你是深耕 React 生态、追求全链路类型安全的“变体驱动”先行者,还是在 Vue 生态中寻找极致心智负担平衡的实践者,本文都将为你提供一份清晰的架构决策树,助你规避工程红线,构建真正面向未来的样式资产。

1. 引言:主流 CSS 工程化方案有哪些?

在现代前端开发中,随着项目复杂度的急剧提升,原生 CSS 常常面临全局污染、复用困难、层级嵌套过深以及维护成本极高等问题。为了解决这些痛点,社区多年来不断探索,沉淀出了多种主流的 CSS 工程化方案。

除原生 CSS 之外,主流方案还包括预处理器、CSS-in-JS、CSS Module、Scoped CSS、原子化 CSS 等。BEM 作为一种基于命名约定来规避命名冲突的早期方案,在现代前端工程中已基本不再使用,因此本文不再对其展开详细分析。

CSS 命名规范(BEM):通过严格的命名约定(如 Block__Element--Modifier)来约束作用域,增强代码的可读性和可维护性。BEM 本身是一个优秀的规范,但它高度依赖开发者的自觉性,且会导致类名冗长,难以管理。

2. CSS 预处理器

CSS 预处理器是一种扩展了 CSS 功能的脚本语言,通过添加变量、嵌套、混入(Mixins)和函数等编程特性,让 CSS 更具结构化、可读性和可维护性。它允许开发者用特殊语法编写样式,然后编译成浏览器可读的普通 CSS 文件。 它也是最早也是最基础的工程化方案,核心思想是通过扩展原生 CSS 的语法,赋予其“编程”能力。

维度说明
核心思想增强版 CSS 使用变量统一管理设计令牌(Design Tokens),用嵌套减少重复选择器。
代表技术Sass (SCSS), Less, Stylus
核心特点提供了变量(Variables)、嵌套(Nesting)、混合(Mixins)、继承、函数等功能。
适用场景几乎所有项目。现阶段它通常不作为独立的解决方案,而是与其他方案(如 CSS Modules)结合使用。
局限性编译后的产物依然是普通 CSS,无法从根本上解决全局命名冲突的问题(通常需要配合 BEM 命名规范来缓解)

以 SCSS 为例,示意如下:

scss
/* Button.scss */
+import{_ as i,g as n,h as a,U as l}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const g=JSON.parse('{"title":"从原子化到变体驱动:现代 CSS 工程化的架构演进与混合实践指南","description":"本文系统剖析主流 CSS 工程化方案的底层逻辑,提出“样式资产 ROI”评估模型,并针对 Vue/React 生态给出了面向 AI 时代的企业级混合架构选型建议。","frontmatter":{"date":"2026-03-10T22:05:50.000Z","title":"从原子化到变体驱动:现代 CSS 工程化的架构演进与混合实践指南","description":"本文系统剖析主流 CSS 工程化方案的底层逻辑,提出“样式资产 ROI”评估模型,并针对 Vue/React 生态给出了面向 AI 时代的企业级混合架构选型建议。","permalink":"/fullstack/css-engineering","coverImg":"https://insight-stack-1252300811.cos.ap-shanghai.myqcloud.com/img/full-stack/insight_stack.png","top":true,"categories":["全栈"],"tags":["全栈","CSS","工程化","tailwindcss"]},"headers":[],"relativePath":"fullstack/css-engineering.md","filePath":"01.全栈/40.前端工程/02.CSS工程化.md"}'),t={name:"fullstack/css-engineering.md"};function p(e,s,h,r,k,d){return a(),n("div",null,[...s[0]||(s[0]=[l(`

从原子化到变体驱动:现代 CSS 工程化的架构演进与混合实践指南

摘要总结:在前端生态日新月异的今天,CSS 工程化早已超越了“如何写样式”的范畴,演变为一场关于开发效率(Velocity)与系统韧性(Resilience)的深度博弈。本文将系统梳理从预处理器、CSS-in-JS、Scoped CSS 到原子化 CSS 的演进脉络,并首次引入 “样式资产 ROI” 模型,深入剖析为何 Tailwind 已成为 AI 时代的基石架构。针对 Vue 与 React 的不同哲学,我们总结出了一套 “原子化为主,工程化局部兜底” 的企业级混合架构方案。无论你是深耕 React 生态、追求全链路类型安全的“变体驱动”先行者,还是在 Vue 生态中寻找极致心智负担平衡的实践者,本文都将为你提供一份清晰的架构决策树,助你规避工程红线,构建真正面向未来的样式资产。

1. 引言:主流 CSS 工程化方案有哪些?

在现代前端开发中,随着项目复杂度的急剧提升,原生 CSS 常常面临全局污染、复用困难、层级嵌套过深以及维护成本极高等问题。为了解决这些痛点,社区多年来不断探索,沉淀出了多种主流的 CSS 工程化方案。

除原生 CSS 之外,主流方案还包括预处理器、CSS-in-JS、CSS Module、Scoped CSS、原子化 CSS 等。BEM 作为一种基于命名约定来规避命名冲突的早期方案,在现代前端工程中已基本不再使用,因此本文不再对其展开详细分析。

CSS 命名规范(BEM):通过严格的命名约定(如 Block__Element--Modifier)来约束作用域,增强代码的可读性和可维护性。BEM 本身是一个优秀的规范,但它高度依赖开发者的自觉性,且会导致类名冗长,难以管理。

2. CSS 预处理器

CSS 预处理器是一种扩展了 CSS 功能的脚本语言,通过添加变量、嵌套、混入(Mixins)和函数等编程特性,让 CSS 更具结构化、可读性和可维护性。它允许开发者用特殊语法编写样式,然后编译成浏览器可读的普通 CSS 文件。 它也是最早也是最基础的工程化方案,核心思想是通过扩展原生 CSS 的语法,赋予其“编程”能力。

维度说明
核心思想增强版 CSS 使用变量统一管理设计令牌(Design Tokens),用嵌套减少重复选择器。
代表技术Sass (SCSS), Less, Stylus
核心特点提供了变量(Variables)、嵌套(Nesting)、混合(Mixins)、继承、函数等功能。
适用场景几乎所有项目。现阶段它通常不作为独立的解决方案,而是与其他方案(如 CSS Modules)结合使用。
局限性编译后的产物依然是普通 CSS,无法从根本上解决全局命名冲突的问题(通常需要配合 BEM 命名规范来缓解)

以 SCSS 为例,示意如下:

scss
/* Button.scss */
 
 /* 1. 定义变量 */
 $primary-color: #3b82f6;
@@ -334,4 +334,4 @@ import{_ as i,g as n,h as a,U as l}from"./chunks/vitepress-theme-teek.CqY1sKvl.j
    职责定位:
       - 整个架构的发动机。负责将非标准 CSS 转换为浏览器安全代码,并执行 Tailwind。
       - 将一切非标准语法转化为浏览器可识别的 CSS,是智能化 UI 生成与工程构建的底层基建。
-===================================================================================

8.1 第一层:架构的根基 —— CSS 变量、设计规范与 Design Token

无论上层使用什么技术栈,坚决消灭硬编码(Hardcode)是现代前端架构的第一铁律:

  • 核心策略:将设计规范抽象为 CSS 变量(Custom Properties),以此作为全项目的 Design Token 唯一真理来源。这不仅能够确保设计的一致性,还能在代码中直接引用变量,避免在多个地方重复定义相同的颜色值。
  • 价值:它是实现暗黑模式、SaaS 多租户一键换肤的绝对基石,能完美兼容上层的所有开发模式,还能将研发团队与设计团队的协作效率提升到一个新的水平。
  • 最佳实践
    • 分层定义: 将变量分为“基础令牌 (Primitive)”(如 --blue-500: 221 83% 53%)和“语义令牌 (Semantic)”(如 --color-primary: var(--blue-500))。
    • 拥抱 HSL/RGB 通道: 变量只存数字通道,不存色值格式。
    • 桥接 Tailwind: 在 tailwind.config.js 中使用 <alpha-value> 将语义变量映射给 Tailwind,赋予其透明度计算能力。

8.2 第二层:生产力基石与标准协议 —— 占比 90% 的主力构建层

在日常业务开发中,我们必须将思维从“写自定义 CSS”转变为“用标准化工具类拼装 UI”。这一层是整个工程提效的核心发动机。

  • 核心策略:全面拥抱 Utility-first(实用优先)理念,将绝大部分(约 90%)的布局、间距、字体排版和基础色彩交给 Tailwind CSS 等原子化 CSS 引擎来处理。

  • 价值

    • 极速交付与零膨胀:免去了在 HTML 和 CSS 文件间反复横跳的低效,且得益于 JIT 引擎,无论项目多大,CSS 产物体积始终保持极小。
    • 强力约束与 AI 友好:通过类名强制约束团队遵循第一层定义的 Design Token,避免“自由发挥”导致的样式碎片化;同时,这种高度内聚在 HTML/JSX 中的范式,对 AI Coding Agent 等大模型辅助生成代码极度友好。
  • 最佳实践

    • 拥抱长类名,抽离组件而非样式:不要害怕 HTML 类名过长,坚决抵制为了“看起来干净”而滥用 @apply 重新创建 .card、.btn 的反模式。复用的单位应该是 Vue/React 组件。
    • 引入 CVA (变体驱动原子化):针对 React 团队或复杂自研 UI 组件库,彻底抛弃外部 CSS 文件,使用 cva 配合 TypeScript 构建强类型的枚举接口,将 UI 的不同状态完美映射为 Tailwind 类名组合。

8.3 第三层:兜底封装与高级逻辑 —— 占比 10% 的边界“逃生舱”

原子化并非万能,剩下的 10% 业务边界和极端场景,需要用更具工程表达能力的预处理器(如 SCSS 等)结合框架原生的隔离机制来解决。

  • 核心策略:将 CSS 预处理器从“全局样式管理器”降级为“局部增强利器”。针对原子类难以描述的复杂场景,在安全的局部作用域内进行逻辑封装与样式覆写。
  • 价值:弥补 Tailwind 在处理复杂 CSS 动效、伪元素组合以及第三方黑盒组件时的短板,为开发者提供一个安全、可控的“逃生舱”,且保证不污染全局环境。
  • 最佳实践
    • 因地制宜的隔离方案
      • Vue 生态:毫不犹豫地使用 <style scoped lang="scss"> 。这是心智负担最低的方案,坚决避开在 Vue 中使用 CSS Modules 带来的语法噪音。
      • React 生态:使用 CSS Modules (.module.scss),通过 clsx 工具库在 JSX 中将 Tailwind 基础类与 Module 兜底类优雅拼装。
    • 深度覆写第三方库:当需要修改 Element Plus 或 Ant Design 内部样式时,结合 SCSS 的嵌套语法(&),在 Vue 中使用 :deep(),在 React (Modules) 中使用 :global() 进行穿透定位。
    • 扁平化原则:即使在隔离环境中,SCSS 的嵌套也不应超过 3 层,避免选择器权重过高导致后期的维护灾难。

8.4 底部构建环境:PostCSS 编译管道 (Pipeline)

这是整个样式架构“看不见”但至关重要的基石。它将我们在上面三层编写的所有代码,统一转化为浏览器能够安全、高效运行的最终产物。

  • 核心策略:将 CSS 视为数据(抽象语法树 AST),通过标准化的插件流水线对其进行转化、加工和压缩。
  • 价值:它是实现 Tailwind 实时编译(JIT)、自动化处理浏览器兼容性、以及未来对接智能化 UI 代码生成(D2C)等高阶工程化链路的唯一底层载体。
  • 最佳实践
    • 严格的执行秩序:在 postcss.config.js 中,插件顺序决定了编译结果。必须确保工作流为:构建原子层 (tailwindcss) -> 处理兼容前缀 (autoprefixer) -> 极限压缩树结构 (cssnano)。
    • 区分预处理与后处理的边界:切忌混淆两者的定位。SCSS(预处理)只负责提供更爽的编写体验(如嵌套、混入);PostCSS(后处理)则全权负责产物加工与工程化转化。团队不应在构建管道中添加过多臃肿的自定义插件,保持流水线的纯粹与高效。

8.5 架构红线 —— 一些必须规避的反模式

CSS 工程化解决方案和工具繁多,在将这些工具组合时,稍有不慎就会导致项目变得比原来更难维护。以下是实战中必须拉响警报的红线:

红线症状诊断
红线一:在 Vue 中强行使用 CSS Modules + Tailwind模板中充斥着 :class="[$style.card, 'flex p-4 mt-2']" 这种视觉噪音极大的代码。框架自带的 Scoped 已经实现了优雅的隔离,引入 Modules 纯属“过度设计”,不仅剥夺了 Tailwind 的书写快感,还增加了运行时的解析成本。
红线二:滥用 @apply 将 Tailwind 退化为预处理器.btn { @apply px-4 py-2 bg-blue-500 rounded; } 满天飞。这是新手转型 Tailwind 时最容易犯的错。它会导致 CSS 产物体积爆炸,失去了 Utility-First 的核心优势。正确做法是抽离 Framework 框架层面的组件 (如 React/Vue Component),而不是抽离 CSS 类。
红线三:在 CSS 变量中硬编码 HEX/RGB 格式:root { --primary: #ff0000; }这会彻底干掉 Tailwind 非常实用的透明度修饰符(如 bg-primary/50)。必须严格遵循“只存通道值,配合 <alpha-value>”的规范。
红线四:CSS Modules 中嵌套层级过深 (Nesting Hell)SCSS Module 中嵌套了 5 层以上的选择器。即使是 Modules,过深的嵌套也会导致 CSS 产物体积变大,且覆盖优先级极难控制。应保持扁平化,最多不超过 3 层。

9. 结语:从手工精雕到 AI 增强的架构跃迁

CSS 工程化早已超越了单纯的“页面美化”,它本质上是一场对抗系统熵增的架构实践。我们在评估各种眼花缭乱的方案时,其底层逻辑无非是在做一道关于产品感的算术题:用架构引入的合理复杂度,去换取前端资产的长期可维护性与业务交付的极速 ROI。

纵观前文,在应对复杂业务的挑战时,单一方案往往独木难支。基于不同生态的特性,我们沉淀出了三种走向成熟的混合架构范式,前两种是 Vue 生态和 React 生态中常用且成熟的实践模式:

模式架构分工AI 友好度
Vue 生态:Scoped + SCSS + TailwindCSS90% (TailwindCSS): 负责页面布局、间距、字体、颜色排布。极大提升复用率和开发速度。
10% (Scoped + SCSS): 作为“逃生舱”。负责覆写 Element/AntD 等第三方 UI 库(借助 :deep())、编写极其复杂的关键帧动画(@keyframes)、以及处理 Tailwind 难以描述的极端伪元素逻辑。
极高,可以直接把大模型生成的 Tailwind HTML 片段丢进 Vue 的 <template> 中无缝运行,遇到复杂的业务定制样式,再让大模型输出一段 Scoped SCSS 补充在底部。
React 生态:CSS Modules + SCSS + TailwindCSS90% (TailwindCSS): 同上,处理所有标准化 UI 搭建。
10% (Modules + SCSS): 由于 React 没有 Scoped,通过引入 xxx.module.scss 配合 clsx 库来实现第三方样式覆盖和复杂逻辑的物理隔离。
,虽然 JSX 中混写 Module 变量(styles.wrapper)和 Tailwind 字符串需要用到 clsx 拼接,但目前的主流代码模型已经能非常熟练地处理这种拼接范式。

第三种最佳实践模式是前沿的组件化范式 —— 变体驱动 (CVA + TailwindCSS)。它是 React 生态下更完美的实践模式,因为它将 CSS 视作组件的状态函数,通过 TypeScript 强类型定义 UI 的 Variants(变体),从而实现高度的可维护性和可扩展性。它不仅是值得探索的领域,还已经成为目前顶级 React 开发者(特别是 Next.js 生态)的事实标准:

维度说明
架构思想彻底干掉 CSS 文件,将 CSS 视作组件的 “状态函数”。通过 TypeScript 强类型定义 UI 的 Variants(变体)。
对 AI 的友好度评估极其完美(史诗级增强),传统 CSS 对 AI 是一个“开放的无限空间”,容易出现幻觉。而 CVA 结合 TypeScript,给大模型提供了一个“封闭的枚举上下文”
实战场景当 AI 生成 UI 组件时,它需要根据你的 CVA 接口定义,自动推导出必须输出的组件。
例如,当你让 AI “生成一个警告按钮”时,AI 不需要去猜应该用什么 Tailwind 颜色,它只要看一眼你的 CVA 接口定义,就会自动推导出必须输出 <Button variant="destructive" />。诸如 v0.dev 这样的 AI 生成神器,其底层输出的完全就是这一套架构,它让 AI 产出的代码具备了企业级的稳定性。

在这个从“纯手工编码”全面迈向“AI 增强构建”的转折点上,我们需要的不再是花哨的样式技巧,而是具备高度确定性的工程基建。希望这份 CSS 工程化指南,能成为你知识体系中一块有价值的拼图,在下一次重构或开启新项目时,帮你找到开发效率与架构韧性之间的最佳杠杆。

`,80)])])}const c=i(t,[["render",p]]);export{g as __pageData,c as default}; +===================================================================================

8.1 第一层:架构的根基 —— CSS 变量、设计规范与 Design Token

无论上层使用什么技术栈,坚决消灭硬编码(Hardcode)是现代前端架构的第一铁律:

  • 核心策略:将设计规范抽象为 CSS 变量(Custom Properties),以此作为全项目的 Design Token 唯一真理来源。这不仅能够确保设计的一致性,还能在代码中直接引用变量,避免在多个地方重复定义相同的颜色值。
  • 价值:它是实现暗黑模式、SaaS 多租户一键换肤的绝对基石,能完美兼容上层的所有开发模式,还能将研发团队与设计团队的协作效率提升到一个新的水平。
  • 最佳实践
    • 分层定义: 将变量分为“基础令牌 (Primitive)”(如 --blue-500: 221 83% 53%)和“语义令牌 (Semantic)”(如 --color-primary: var(--blue-500))。
    • 拥抱 HSL/RGB 通道: 变量只存数字通道,不存色值格式。
    • 桥接 Tailwind: 在 tailwind.config.js 中使用 <alpha-value> 将语义变量映射给 Tailwind,赋予其透明度计算能力。

8.2 第二层:生产力基石与标准协议 —— 占比 90% 的主力构建层

在日常业务开发中,我们必须将思维从“写自定义 CSS”转变为“用标准化工具类拼装 UI”。这一层是整个工程提效的核心发动机。

  • 核心策略:全面拥抱 Utility-first(实用优先)理念,将绝大部分(约 90%)的布局、间距、字体排版和基础色彩交给 Tailwind CSS 等原子化 CSS 引擎来处理。

  • 价值

    • 极速交付与零膨胀:免去了在 HTML 和 CSS 文件间反复横跳的低效,且得益于 JIT 引擎,无论项目多大,CSS 产物体积始终保持极小。
    • 强力约束与 AI 友好:通过类名强制约束团队遵循第一层定义的 Design Token,避免“自由发挥”导致的样式碎片化;同时,这种高度内聚在 HTML/JSX 中的范式,对 AI Coding Agent 等大模型辅助生成代码极度友好。
  • 最佳实践

    • 拥抱长类名,抽离组件而非样式:不要害怕 HTML 类名过长,坚决抵制为了“看起来干净”而滥用 @apply 重新创建 .card、.btn 的反模式。复用的单位应该是 Vue/React 组件。
    • 引入 CVA (变体驱动原子化):针对 React 团队或复杂自研 UI 组件库,彻底抛弃外部 CSS 文件,使用 cva 配合 TypeScript 构建强类型的枚举接口,将 UI 的不同状态完美映射为 Tailwind 类名组合。

8.3 第三层:兜底封装与高级逻辑 —— 占比 10% 的边界“逃生舱”

原子化并非万能,剩下的 10% 业务边界和极端场景,需要用更具工程表达能力的预处理器(如 SCSS 等)结合框架原生的隔离机制来解决。

  • 核心策略:将 CSS 预处理器从“全局样式管理器”降级为“局部增强利器”。针对原子类难以描述的复杂场景,在安全的局部作用域内进行逻辑封装与样式覆写。
  • 价值:弥补 Tailwind 在处理复杂 CSS 动效、伪元素组合以及第三方黑盒组件时的短板,为开发者提供一个安全、可控的“逃生舱”,且保证不污染全局环境。
  • 最佳实践
    • 因地制宜的隔离方案
      • Vue 生态:毫不犹豫地使用 <style scoped lang="scss"> 。这是心智负担最低的方案,坚决避开在 Vue 中使用 CSS Modules 带来的语法噪音。
      • React 生态:使用 CSS Modules (.module.scss),通过 clsx 工具库在 JSX 中将 Tailwind 基础类与 Module 兜底类优雅拼装。
    • 深度覆写第三方库:当需要修改 Element Plus 或 Ant Design 内部样式时,结合 SCSS 的嵌套语法(&),在 Vue 中使用 :deep(),在 React (Modules) 中使用 :global() 进行穿透定位。
    • 扁平化原则:即使在隔离环境中,SCSS 的嵌套也不应超过 3 层,避免选择器权重过高导致后期的维护灾难。

8.4 底部构建环境:PostCSS 编译管道 (Pipeline)

这是整个样式架构“看不见”但至关重要的基石。它将我们在上面三层编写的所有代码,统一转化为浏览器能够安全、高效运行的最终产物。

  • 核心策略:将 CSS 视为数据(抽象语法树 AST),通过标准化的插件流水线对其进行转化、加工和压缩。
  • 价值:它是实现 Tailwind 实时编译(JIT)、自动化处理浏览器兼容性、以及未来对接智能化 UI 代码生成(D2C)等高阶工程化链路的唯一底层载体。
  • 最佳实践
    • 严格的执行秩序:在 postcss.config.js 中,插件顺序决定了编译结果。必须确保工作流为:构建原子层 (tailwindcss) -> 处理兼容前缀 (autoprefixer) -> 极限压缩树结构 (cssnano)。
    • 区分预处理与后处理的边界:切忌混淆两者的定位。SCSS(预处理)只负责提供更爽的编写体验(如嵌套、混入);PostCSS(后处理)则全权负责产物加工与工程化转化。团队不应在构建管道中添加过多臃肿的自定义插件,保持流水线的纯粹与高效。

8.5 架构红线 —— 一些必须规避的反模式

CSS 工程化解决方案和工具繁多,在将这些工具组合时,稍有不慎就会导致项目变得比原来更难维护。以下是实战中必须拉响警报的红线:

红线症状诊断
红线一:在 Vue 中强行使用 CSS Modules + Tailwind模板中充斥着 :class="[$style.card, 'flex p-4 mt-2']" 这种视觉噪音极大的代码。框架自带的 Scoped 已经实现了优雅的隔离,引入 Modules 纯属“过度设计”,不仅剥夺了 Tailwind 的书写快感,还增加了运行时的解析成本。
红线二:滥用 @apply 将 Tailwind 退化为预处理器.btn { @apply px-4 py-2 bg-blue-500 rounded; } 满天飞。这是新手转型 Tailwind 时最容易犯的错。它会导致 CSS 产物体积爆炸,失去了 Utility-First 的核心优势。正确做法是抽离 Framework 框架层面的组件 (如 React/Vue Component),而不是抽离 CSS 类。
红线三:在 CSS 变量中硬编码 HEX/RGB 格式:root { --primary: #ff0000; }这会彻底干掉 Tailwind 非常实用的透明度修饰符(如 bg-primary/50)。必须严格遵循“只存通道值,配合 <alpha-value>”的规范。
红线四:CSS Modules 中嵌套层级过深 (Nesting Hell)SCSS Module 中嵌套了 5 层以上的选择器。即使是 Modules,过深的嵌套也会导致 CSS 产物体积变大,且覆盖优先级极难控制。应保持扁平化,最多不超过 3 层。

9. 结语:从手工精雕到 AI 增强的架构跃迁

CSS 工程化早已超越了单纯的“页面美化”,它本质上是一场对抗系统熵增的架构实践。我们在评估各种眼花缭乱的方案时,其底层逻辑无非是在做一道关于产品感的算术题:用架构引入的合理复杂度,去换取前端资产的长期可维护性与业务交付的极速 ROI。

纵观前文,在应对复杂业务的挑战时,单一方案往往独木难支。基于不同生态的特性,我们沉淀出了三种走向成熟的混合架构范式,前两种是 Vue 生态和 React 生态中常用且成熟的实践模式:

模式架构分工AI 友好度
Vue 生态:Scoped + SCSS + TailwindCSS90% (TailwindCSS): 负责页面布局、间距、字体、颜色排布。极大提升复用率和开发速度。
10% (Scoped + SCSS): 作为“逃生舱”。负责覆写 Element/AntD 等第三方 UI 库(借助 :deep())、编写极其复杂的关键帧动画(@keyframes)、以及处理 Tailwind 难以描述的极端伪元素逻辑。
极高,可以直接把大模型生成的 Tailwind HTML 片段丢进 Vue 的 <template> 中无缝运行,遇到复杂的业务定制样式,再让大模型输出一段 Scoped SCSS 补充在底部。
React 生态:CSS Modules + SCSS + TailwindCSS90% (TailwindCSS): 同上,处理所有标准化 UI 搭建。
10% (Modules + SCSS): 由于 React 没有 Scoped,通过引入 xxx.module.scss 配合 clsx 库来实现第三方样式覆盖和复杂逻辑的物理隔离。
,虽然 JSX 中混写 Module 变量(styles.wrapper)和 Tailwind 字符串需要用到 clsx 拼接,但目前的主流代码模型已经能非常熟练地处理这种拼接范式。

第三种最佳实践模式是前沿的组件化范式 —— 变体驱动 (CVA + TailwindCSS)。它是 React 生态下更完美的实践模式,因为它将 CSS 视作组件的状态函数,通过 TypeScript 强类型定义 UI 的 Variants(变体),从而实现高度的可维护性和可扩展性。它不仅是值得探索的领域,还已经成为目前顶级 React 开发者(特别是 Next.js 生态)的事实标准:

维度说明
架构思想彻底干掉 CSS 文件,将 CSS 视作组件的 “状态函数”。通过 TypeScript 强类型定义 UI 的 Variants(变体)。
对 AI 的友好度评估极其完美(史诗级增强),传统 CSS 对 AI 是一个“开放的无限空间”,容易出现幻觉。而 CVA 结合 TypeScript,给大模型提供了一个“封闭的枚举上下文”
实战场景当 AI 生成 UI 组件时,它需要根据你的 CVA 接口定义,自动推导出必须输出的组件。
例如,当你让 AI “生成一个警告按钮”时,AI 不需要去猜应该用什么 Tailwind 颜色,它只要看一眼你的 CVA 接口定义,就会自动推导出必须输出 <Button variant="destructive" />。诸如 v0.dev 这样的 AI 生成神器,其底层输出的完全就是这一套架构,它让 AI 产出的代码具备了企业级的稳定性。

在这个从“纯手工编码”全面迈向“AI 增强构建”的转折点上,我们需要的不再是花哨的样式技巧,而是具备高度确定性的工程基建。希望这份 CSS 工程化指南,能成为你知识体系中一块有价值的拼图,在下一次重构或开启新项目时,帮你找到开发效率与架构韧性之间的最佳杠杆。

`,79)])])}const c=i(t,[["render",p]]);export{g as __pageData,c as default}; diff --git "a/assets/01.\345\205\250\346\240\210_40.\345\211\215\347\253\257\345\267\245\347\250\213_02.CSS\345\267\245\347\250\213\345\214\226.md.DUPhvCof.lean.js" b/assets/fullstack_css-engineering.md.CyF7_CNd.lean.js similarity index 52% rename from "assets/01.\345\205\250\346\240\210_40.\345\211\215\347\253\257\345\267\245\347\250\213_02.CSS\345\267\245\347\250\213\345\214\226.md.DUPhvCof.lean.js" rename to assets/fullstack_css-engineering.md.CyF7_CNd.lean.js index b6b3af49..30548cbd 100644 --- "a/assets/01.\345\205\250\346\240\210_40.\345\211\215\347\253\257\345\267\245\347\250\213_02.CSS\345\267\245\347\250\213\345\214\226.md.DUPhvCof.lean.js" +++ b/assets/fullstack_css-engineering.md.CyF7_CNd.lean.js @@ -1 +1 @@ -import{_ as i,g as n,h as a,U as l}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const g=JSON.parse('{"title":"从原子化到变体驱动:现代 CSS 工程化的架构演进与混合实践指南","description":"本文系统剖析主流 CSS 工程化方案的底层逻辑,提出“样式资产 ROI”评估模型,并针对 Vue/React 生态给出了面向 AI 时代的企业级混合架构选型建议。","frontmatter":{"date":"2026-03-10T22:05:50.000Z","title":"从原子化到变体驱动:现代 CSS 工程化的架构演进与混合实践指南","description":"本文系统剖析主流 CSS 工程化方案的底层逻辑,提出“样式资产 ROI”评估模型,并针对 Vue/React 生态给出了面向 AI 时代的企业级混合架构选型建议。","permalink":"/full-stack/css-engineering","coverImg":"https://insight-stack-1252300811.cos.ap-shanghai.myqcloud.com/img/full-stack/insight_stack.png","top":true,"categories":["全栈"],"tags":["全栈","CSS","工程化","tailwindcss"]},"headers":[],"relativePath":"01.全栈/40.前端工程/02.CSS工程化.md","filePath":"01.全栈/40.前端工程/02.CSS工程化.md"}'),t={name:"01.全栈/40.前端工程/02.CSS工程化.md"};function p(e,s,h,r,k,d){return a(),n("div",null,[...s[0]||(s[0]=[l("",80)])])}const c=i(t,[["render",p]]);export{g as __pageData,c as default}; +import{_ as i,g as n,h as a,U as l}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const g=JSON.parse('{"title":"从原子化到变体驱动:现代 CSS 工程化的架构演进与混合实践指南","description":"本文系统剖析主流 CSS 工程化方案的底层逻辑,提出“样式资产 ROI”评估模型,并针对 Vue/React 生态给出了面向 AI 时代的企业级混合架构选型建议。","frontmatter":{"date":"2026-03-10T22:05:50.000Z","title":"从原子化到变体驱动:现代 CSS 工程化的架构演进与混合实践指南","description":"本文系统剖析主流 CSS 工程化方案的底层逻辑,提出“样式资产 ROI”评估模型,并针对 Vue/React 生态给出了面向 AI 时代的企业级混合架构选型建议。","permalink":"/fullstack/css-engineering","coverImg":"https://insight-stack-1252300811.cos.ap-shanghai.myqcloud.com/img/full-stack/insight_stack.png","top":true,"categories":["全栈"],"tags":["全栈","CSS","工程化","tailwindcss"]},"headers":[],"relativePath":"fullstack/css-engineering.md","filePath":"01.全栈/40.前端工程/02.CSS工程化.md"}'),t={name:"fullstack/css-engineering.md"};function p(e,s,h,r,k,d){return a(),n("div",null,[...s[0]||(s[0]=[l("",79)])])}const c=i(t,[["render",p]]);export{g as __pageData,c as default}; diff --git "a/assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_3.ES Modules \346\240\270\345\277\203\350\247\204\350\214\203\344\270\216\345\256\236\350\267\265\350\247\243\346\236\220.md.fPkWGUxd.js" b/assets/fullstack_decode-es-modules.md.D2FiEXNA.js similarity index 96% rename from "assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_3.ES Modules \346\240\270\345\277\203\350\247\204\350\214\203\344\270\216\345\256\236\350\267\265\350\247\243\346\236\220.md.fPkWGUxd.js" rename to assets/fullstack_decode-es-modules.md.D2FiEXNA.js index 25b8724c..06644096 100644 --- "a/assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_3.ES Modules \346\240\270\345\277\203\350\247\204\350\214\203\344\270\216\345\256\236\350\267\265\350\247\243\346\236\220.md.fPkWGUxd.js" +++ b/assets/fullstack_decode-es-modules.md.D2FiEXNA.js @@ -1,4 +1,4 @@ -import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const g=JSON.parse('{"title":"回归标准,拥抱原生:ES Modules 核心规范与实践解析","description":"深度解析 ES Modules 命名导出/导入、默认导出、动态导入等语法,以及模块执行顺序、循环依赖处理与编译时优化机制。","frontmatter":{"date":"2024-05-14T22:29:32.000Z","title":"回归标准,拥抱原生:ES Modules 核心规范与实践解析","tldr":"ES Modules 核心语法与执行模型:静态分析如何重塑前端构建效率。","description":"深度解析 ES Modules 命名导出/导入、默认导出、动态导入等语法,以及模块执行顺序、循环依赖处理与编译时优化机制。","permalink":"/fullstack/decode-es-modules","tags":["concept","ESM","static-analysis","Tree-Shaking","circular-dependency"],"categories":["全栈","全栈基础素养","模块化编程实践指南"]},"headers":[],"relativePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/3.ES Modules 核心规范与实践解析.md","filePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/3.ES Modules 核心规范与实践解析.md"}'),p={name:"01.全栈/80.全栈基础素养/20.模块化编程实践指南/3.ES Modules 核心规范与实践解析.md"};function h(k,s,e,t,r,E){return n(),a("div",null,[...s[0]||(s[0]=[l(`

回归标准,拥抱原生:ES Modules 核心规范与实践解析

如果说 CommonJS 是“草根英雄”,那么 ES Modules 就是“名门正派”。它是 ECMAScript 官方定义的模块系统,旨在为所有 JavaScript 环境提供统一、高效、且可静态分析的模块化方案。

理解 ESM,不仅仅是学会 import 和 export,更重要的是理解它如何通过编译时优化彻底改变了前端构建的效率。

1. 命名导出与导入:精准的代码引用

命名导出(Named Exports)是 ESM 最常用的形式,它允许一个模块暴露多个成员。其核心优势在于:导入方可以按需引入,且 IDE 能提供精准的补全。

语法实践:

javascript
// math.js - 命名导出
+import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const g=JSON.parse('{"title":"回归标准,拥抱原生:ES Modules 核心规范与实践解析","description":"深度解析 ES Modules 命名导出/导入、默认导出、动态导入等语法,以及模块执行顺序、循环依赖处理与编译时优化机制。","frontmatter":{"date":"2024-05-14T22:29:32.000Z","title":"回归标准,拥抱原生:ES Modules 核心规范与实践解析","tldr":"ES Modules 核心语法与执行模型:静态分析如何重塑前端构建效率。","description":"深度解析 ES Modules 命名导出/导入、默认导出、动态导入等语法,以及模块执行顺序、循环依赖处理与编译时优化机制。","permalink":"/fullstack/decode-es-modules","tags":["concept","ESM","static-analysis","Tree-Shaking","circular-dependency"],"categories":["全栈","全栈基础素养","模块化编程实践指南"]},"headers":[],"relativePath":"fullstack/decode-es-modules.md","filePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/3.ES Modules 核心规范与实践解析.md"}'),p={name:"fullstack/decode-es-modules.md"};function h(k,s,e,t,r,E){return n(),a("div",null,[...s[0]||(s[0]=[l(`

回归标准,拥抱原生:ES Modules 核心规范与实践解析

如果说 CommonJS 是“草根英雄”,那么 ES Modules 就是“名门正派”。它是 ECMAScript 官方定义的模块系统,旨在为所有 JavaScript 环境提供统一、高效、且可静态分析的模块化方案。

理解 ESM,不仅仅是学会 import 和 export,更重要的是理解它如何通过编译时优化彻底改变了前端构建的效率。

1. 命名导出与导入:精准的代码引用

命名导出(Named Exports)是 ESM 最常用的形式,它允许一个模块暴露多个成员。其核心优势在于:导入方可以按需引入,且 IDE 能提供精准的补全。

语法实践:

javascript
// math.js - 命名导出
 // 行内导出
 export const PI = 3.14159;
 
@@ -175,4 +175,4 @@ import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.CqY1sKvl.j
   console.log('b.js received a:', a);
 });
 
-eventBus.emit('b-ready', 'b');

7. 结语:在标准规范中寻求最优解

从 ESM 的核心语法我们可以看到,它不仅解决了“代码怎么写”的问题,更通过静态性为现代前端工程化铺平了道路。没有 ESM,就没有如此高效的 HMR(热更新),也没有精准的 Tree Shaking。

ESM 不再仅仅是一个模块协议,它已成为 JavaScript 生态的通用标准,让全栈代码同构变得轻而易举,也让复杂的依赖治理变得有迹可循。

掌握 ESM,本质上是在掌握一种确定性**——无论是在浏览器端、服务端,还是日益兴起的 AI-native 场景中,这种标准化都是构建大规模复杂系统应用的基础。

`,51)])])}const c=i(p,[["render",h]]);export{g as __pageData,c as default}; +eventBus.emit('b-ready', 'b');

7. 结语:在标准规范中寻求最优解

从 ESM 的核心语法我们可以看到,它不仅解决了“代码怎么写”的问题,更通过静态性为现代前端工程化铺平了道路。没有 ESM,就没有如此高效的 HMR(热更新),也没有精准的 Tree Shaking。

ESM 不再仅仅是一个模块协议,它已成为 JavaScript 生态的通用标准,让全栈代码同构变得轻而易举,也让复杂的依赖治理变得有迹可循。

掌握 ESM,本质上是在掌握一种确定性**——无论是在浏览器端、服务端,还是日益兴起的 AI-native 场景中,这种标准化都是构建大规模复杂系统应用的基础。

`,50)])])}const c=i(p,[["render",h]]);export{g as __pageData,c as default}; diff --git "a/assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_3.ES Modules \346\240\270\345\277\203\350\247\204\350\214\203\344\270\216\345\256\236\350\267\265\350\247\243\346\236\220.md.fPkWGUxd.lean.js" b/assets/fullstack_decode-es-modules.md.D2FiEXNA.lean.js similarity index 60% rename from "assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_3.ES Modules \346\240\270\345\277\203\350\247\204\350\214\203\344\270\216\345\256\236\350\267\265\350\247\243\346\236\220.md.fPkWGUxd.lean.js" rename to assets/fullstack_decode-es-modules.md.D2FiEXNA.lean.js index 50cf8dfe..ed412960 100644 --- "a/assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_3.ES Modules \346\240\270\345\277\203\350\247\204\350\214\203\344\270\216\345\256\236\350\267\265\350\247\243\346\236\220.md.fPkWGUxd.lean.js" +++ b/assets/fullstack_decode-es-modules.md.D2FiEXNA.lean.js @@ -1 +1 @@ -import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const g=JSON.parse('{"title":"回归标准,拥抱原生:ES Modules 核心规范与实践解析","description":"深度解析 ES Modules 命名导出/导入、默认导出、动态导入等语法,以及模块执行顺序、循环依赖处理与编译时优化机制。","frontmatter":{"date":"2024-05-14T22:29:32.000Z","title":"回归标准,拥抱原生:ES Modules 核心规范与实践解析","tldr":"ES Modules 核心语法与执行模型:静态分析如何重塑前端构建效率。","description":"深度解析 ES Modules 命名导出/导入、默认导出、动态导入等语法,以及模块执行顺序、循环依赖处理与编译时优化机制。","permalink":"/fullstack/decode-es-modules","tags":["concept","ESM","static-analysis","Tree-Shaking","circular-dependency"],"categories":["全栈","全栈基础素养","模块化编程实践指南"]},"headers":[],"relativePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/3.ES Modules 核心规范与实践解析.md","filePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/3.ES Modules 核心规范与实践解析.md"}'),p={name:"01.全栈/80.全栈基础素养/20.模块化编程实践指南/3.ES Modules 核心规范与实践解析.md"};function h(k,s,e,t,r,E){return n(),a("div",null,[...s[0]||(s[0]=[l("",51)])])}const c=i(p,[["render",h]]);export{g as __pageData,c as default}; +import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const g=JSON.parse('{"title":"回归标准,拥抱原生:ES Modules 核心规范与实践解析","description":"深度解析 ES Modules 命名导出/导入、默认导出、动态导入等语法,以及模块执行顺序、循环依赖处理与编译时优化机制。","frontmatter":{"date":"2024-05-14T22:29:32.000Z","title":"回归标准,拥抱原生:ES Modules 核心规范与实践解析","tldr":"ES Modules 核心语法与执行模型:静态分析如何重塑前端构建效率。","description":"深度解析 ES Modules 命名导出/导入、默认导出、动态导入等语法,以及模块执行顺序、循环依赖处理与编译时优化机制。","permalink":"/fullstack/decode-es-modules","tags":["concept","ESM","static-analysis","Tree-Shaking","circular-dependency"],"categories":["全栈","全栈基础素养","模块化编程实践指南"]},"headers":[],"relativePath":"fullstack/decode-es-modules.md","filePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/3.ES Modules 核心规范与实践解析.md"}'),p={name:"fullstack/decode-es-modules.md"};function h(k,s,e,t,r,E){return n(),a("div",null,[...s[0]||(s[0]=[l("",50)])])}const c=i(p,[["render",h]]);export{g as __pageData,c as default}; diff --git "a/assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_2.\344\270\215\345\220\214\346\250\241\345\235\227\345\214\226\350\247\204\350\214\203\346\242\263\347\220\206.md.CRGmbaTn.js" b/assets/fullstack_different-module-programming-specifications.md.471jsJdi.js similarity index 90% rename from "assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_2.\344\270\215\345\220\214\346\250\241\345\235\227\345\214\226\350\247\204\350\214\203\346\242\263\347\220\206.md.CRGmbaTn.js" rename to assets/fullstack_different-module-programming-specifications.md.471jsJdi.js index 2385dbd2..75132851 100644 --- "a/assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_2.\344\270\215\345\220\214\346\250\241\345\235\227\345\214\226\350\247\204\350\214\203\346\242\263\347\220\206.md.CRGmbaTn.js" +++ b/assets/fullstack_different-module-programming-specifications.md.471jsJdi.js @@ -1,4 +1,4 @@ -import{_ as i,g as a,h as n,U as t}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const g=JSON.parse('{"title":"JavaScript 模块化规范全景图:从 CJS 到 ESM","description":"全面梳理 CommonJS、AMD、UMD、ES Modules 四大模块化规范的核心语法与适用场景,解析各规范的关键差异,并提供从旧规范向 ESM 迁移的实操策略。","frontmatter":{"date":"2024-05-14T22:26:06.000Z","title":"JavaScript 模块化规范全景图:从 CJS 到 ESM","tldr":"全面梳理 CommonJS、AMD、UMD、ES Modules 等核心规范,附现代迁移策略。","description":"全面梳理 CommonJS、AMD、UMD、ES Modules 四大模块化规范的核心语法与适用场景,解析各规范的关键差异,并提供从旧规范向 ESM 迁移的实操策略。","permalink":"/fullstack/different-module-programming-specifications","tags":["tutorial","CommonJS","AMD","UMD","ESM"],"categories":["全栈","全栈基础素养","模块化编程实践指南"]},"headers":[],"relativePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/2.不同模块化规范梳理.md","filePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/2.不同模块化规范梳理.md"}'),l={name:"01.全栈/80.全栈基础素养/20.模块化编程实践指南/2.不同模块化规范梳理.md"};function h(p,s,k,e,r,d){return n(),a("div",null,[...s[0]||(s[0]=[t(`

JavaScript 模块化规范全景图:从 CJS 到 ESM

摘要总结: 本文横向对比 JavaScript 四大模块化规范:CommonJS、AMD、UMD、ES Modules。通过代码示例展示各规范的核心语法,并提供从 CommonJS 迁移到 ESM 的具体步骤,以及从 AMD 向 ESM 迁移的构建工具策略。最后以对比表格收尾,阐明 ESM 作为现代开发唯一推荐标准的地位。

在 JavaScript 进化史上,“模块化”始终是一个核心命题。从早期 script 标签满天飞的“混沌时代”,到各路规范群雄逐鹿的“战国时代”,再到如今 ES Modules 定于一尊,开发者们在解决依赖管理、作用域污染和异步加载等问题上付出了巨大的努力。

本文将带你梳理 JavaScript 历史上最重要的几种模块化规范,便于构建起全栈开发的底层知识图谱。

1. CommonJS 规范:Node.js 生态的基石

CommonJS 是伴随 Node.js 诞生的规范,由 Kevin Dangoor 提出,初衷是让 JavaScript 脱离浏览器也能构建复杂的系统应用。它是 Node.js 成功的关键因素之一,在它出现之前,JavaScript 缺乏在服务器端运行所需的组织结构。它规定每个文件都是一个独立的模块,拥有私有的作用域,不会污染全局空间。

核心逻辑:

  • 导出:通过 module.exportsexports 对象暴露成员。
  • 导入:使用同步的 require() 函数加载模块。

示例代码:

javascript
// 导出模块(module.exports)
+import{_ as i,g as a,h as n,U as t}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const g=JSON.parse('{"title":"JavaScript 模块化规范全景图:从 CJS 到 ESM","description":"全面梳理 CommonJS、AMD、UMD、ES Modules 四大模块化规范的核心语法与适用场景,解析各规范的关键差异,并提供从旧规范向 ESM 迁移的实操策略。","frontmatter":{"date":"2024-05-14T22:26:06.000Z","title":"JavaScript 模块化规范全景图:从 CJS 到 ESM","tldr":"全面梳理 CommonJS、AMD、UMD、ES Modules 等核心规范,附现代迁移策略。","description":"全面梳理 CommonJS、AMD、UMD、ES Modules 四大模块化规范的核心语法与适用场景,解析各规范的关键差异,并提供从旧规范向 ESM 迁移的实操策略。","permalink":"/fullstack/different-module-programming-specifications","tags":["tutorial","CommonJS","AMD","UMD","ESM"],"categories":["全栈","全栈基础素养","模块化编程实践指南"]},"headers":[],"relativePath":"fullstack/different-module-programming-specifications.md","filePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/2.不同模块化规范梳理.md"}'),l={name:"fullstack/different-module-programming-specifications.md"};function h(p,s,k,e,r,d){return n(),a("div",null,[...s[0]||(s[0]=[t(`

JavaScript 模块化规范全景图:从 CJS 到 ESM

摘要总结: 本文横向对比 JavaScript 四大模块化规范:CommonJS、AMD、UMD、ES Modules。通过代码示例展示各规范的核心语法,并提供从 CommonJS 迁移到 ESM 的具体步骤,以及从 AMD 向 ESM 迁移的构建工具策略。最后以对比表格收尾,阐明 ESM 作为现代开发唯一推荐标准的地位。

在 JavaScript 进化史上,“模块化”始终是一个核心命题。从早期 script 标签满天飞的“混沌时代”,到各路规范群雄逐鹿的“战国时代”,再到如今 ES Modules 定于一尊,开发者们在解决依赖管理、作用域污染和异步加载等问题上付出了巨大的努力。

本文将带你梳理 JavaScript 历史上最重要的几种模块化规范,便于构建起全栈开发的底层知识图谱。

1. CommonJS 规范:Node.js 生态的基石

CommonJS 是伴随 Node.js 诞生的规范,由 Kevin Dangoor 提出,初衷是让 JavaScript 脱离浏览器也能构建复杂的系统应用。它是 Node.js 成功的关键因素之一,在它出现之前,JavaScript 缺乏在服务器端运行所需的组织结构。它规定每个文件都是一个独立的模块,拥有私有的作用域,不会污染全局空间。

核心逻辑:

  • 导出:通过 module.exportsexports 对象暴露成员。
  • 导入:使用同步的 require() 函数加载模块。

示例代码:

javascript
// 导出模块(module.exports)
 const add = (a, b) => a + b;
 const subtract = (a, b) => a - b;
 
@@ -49,4 +49,4 @@ import{_ as i,g as a,h as n,U as t}from"./chunks/vitepress-theme-teek.CqY1sKvl.j
 // 导入模块
 import mathDefault, { add, subtract } from './math.js';
 console.log(add(1, 2)); // 输出:3
-console.log(mathDefault.multiply(2, 3)); // 输出:6
关键特性说明
静态分析与 CommonJS 的运行时加载不同,ESM 在代码编译阶段就能确定依赖关系。这使得 Tree Shaking(剔除未使用的代码)成为可能。
异步加载支持天然适配浏览器。
官方标准现代浏览器及 Node.js(v12+)均已原生支持。

5. 规范对比与现代迁移指南

为了更直观地理解,我们将四种规范进行横向对比:

规范主要环境加载方式核心优势现状
CommonJSNode.js同步简单高效,生态极其丰富存量项目主流,正向 ESM 转型
AMD浏览器异步解决浏览器阻塞问题已淡出历史舞台
UMD跨平台兼容一份代码,到处运行仅在需要兼容老旧环境时使用
ES Modules全栈静态语言标准,支持 Tree Shaking现代开发的唯一推荐标准

迁移策略建议

  1. 全面拥抱 ESM:新项目应直接在 package.json 中设置 "type": "module"。
  2. 从 CommonJS 迁移到 ES Modules:可以将 .js 逐步重命名为 .mjs,或利用 esbuild 等工具进行平滑转译。
    • 使用 .mjs 扩展名或在 package.json 中设置 "type": "module"
    • require() 替换为 import
    • module.exports 替换为 exportexport default
  3. 从 AMD 迁移到 ES Modules
    • 使用现代构建工具(如 Webpack、Vite)处理模块加载
    • define() 替换为 ES Modules 语法
    • 利用构建工具的代码分割功能实现按需加载
    • 移除对 RequireJS 的依赖
  4. 构建工具的妙用:利用 ViteTurbopack,我们完全可以用 ESM 编写代码,由工具链自动处理老旧环境的兼容。

6. 结语:在标准之上构建未来

从 CommonJS 的探索到 ESM 的大一统,模块化规范的演进本质上是 JavaScript 从一种“脚本语言”向“工业级编程语言”蜕变的过程

理解这些规范不仅是为了应付面试或处理老旧代码,更是为了让我们在面对复杂的全栈架构时,能对代码的加载、执行和构建有更深层的掌控力。在 AI 辅助编程普及的今天,清晰的模块化思维更是构建可靠 Prompt 和 Agentic 流程的基石,希望这篇梳理能为你夯实全栈基础。

`,42)])])}const o=i(l,[["render",h]]);export{g as __pageData,o as default}; +console.log(mathDefault.multiply(2, 3)); // 输出:6
关键特性说明
静态分析与 CommonJS 的运行时加载不同,ESM 在代码编译阶段就能确定依赖关系。这使得 Tree Shaking(剔除未使用的代码)成为可能。
异步加载支持天然适配浏览器。
官方标准现代浏览器及 Node.js(v12+)均已原生支持。

5. 规范对比与现代迁移指南

为了更直观地理解,我们将四种规范进行横向对比:

规范主要环境加载方式核心优势现状
CommonJSNode.js同步简单高效,生态极其丰富存量项目主流,正向 ESM 转型
AMD浏览器异步解决浏览器阻塞问题已淡出历史舞台
UMD跨平台兼容一份代码,到处运行仅在需要兼容老旧环境时使用
ES Modules全栈静态语言标准,支持 Tree Shaking现代开发的唯一推荐标准

迁移策略建议

  1. 全面拥抱 ESM:新项目应直接在 package.json 中设置 "type": "module"。
  2. 从 CommonJS 迁移到 ES Modules:可以将 .js 逐步重命名为 .mjs,或利用 esbuild 等工具进行平滑转译。
    • 使用 .mjs 扩展名或在 package.json 中设置 "type": "module"
    • require() 替换为 import
    • module.exports 替换为 exportexport default
  3. 从 AMD 迁移到 ES Modules
    • 使用现代构建工具(如 Webpack、Vite)处理模块加载
    • define() 替换为 ES Modules 语法
    • 利用构建工具的代码分割功能实现按需加载
    • 移除对 RequireJS 的依赖
  4. 构建工具的妙用:利用 ViteTurbopack,我们完全可以用 ESM 编写代码,由工具链自动处理老旧环境的兼容。

6. 结语:在标准之上构建未来

从 CommonJS 的探索到 ESM 的大一统,模块化规范的演进本质上是 JavaScript 从一种“脚本语言”向“工业级编程语言”蜕变的过程

理解这些规范不仅是为了应付面试或处理老旧代码,更是为了让我们在面对复杂的全栈架构时,能对代码的加载、执行和构建有更深层的掌控力。在 AI 辅助编程普及的今天,清晰的模块化思维更是构建可靠 Prompt 和 Agentic 流程的基石,希望这篇梳理能为你夯实全栈基础。

`,41)])])}const o=i(l,[["render",h]]);export{g as __pageData,o as default}; diff --git "a/assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_2.\344\270\215\345\220\214\346\250\241\345\235\227\345\214\226\350\247\204\350\214\203\346\242\263\347\220\206.md.CRGmbaTn.lean.js" b/assets/fullstack_different-module-programming-specifications.md.471jsJdi.lean.js similarity index 60% rename from "assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_2.\344\270\215\345\220\214\346\250\241\345\235\227\345\214\226\350\247\204\350\214\203\346\242\263\347\220\206.md.CRGmbaTn.lean.js" rename to assets/fullstack_different-module-programming-specifications.md.471jsJdi.lean.js index 2a383a44..e39c008b 100644 --- "a/assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_2.\344\270\215\345\220\214\346\250\241\345\235\227\345\214\226\350\247\204\350\214\203\346\242\263\347\220\206.md.CRGmbaTn.lean.js" +++ b/assets/fullstack_different-module-programming-specifications.md.471jsJdi.lean.js @@ -1 +1 @@ -import{_ as i,g as a,h as n,U as t}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const g=JSON.parse('{"title":"JavaScript 模块化规范全景图:从 CJS 到 ESM","description":"全面梳理 CommonJS、AMD、UMD、ES Modules 四大模块化规范的核心语法与适用场景,解析各规范的关键差异,并提供从旧规范向 ESM 迁移的实操策略。","frontmatter":{"date":"2024-05-14T22:26:06.000Z","title":"JavaScript 模块化规范全景图:从 CJS 到 ESM","tldr":"全面梳理 CommonJS、AMD、UMD、ES Modules 等核心规范,附现代迁移策略。","description":"全面梳理 CommonJS、AMD、UMD、ES Modules 四大模块化规范的核心语法与适用场景,解析各规范的关键差异,并提供从旧规范向 ESM 迁移的实操策略。","permalink":"/fullstack/different-module-programming-specifications","tags":["tutorial","CommonJS","AMD","UMD","ESM"],"categories":["全栈","全栈基础素养","模块化编程实践指南"]},"headers":[],"relativePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/2.不同模块化规范梳理.md","filePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/2.不同模块化规范梳理.md"}'),l={name:"01.全栈/80.全栈基础素养/20.模块化编程实践指南/2.不同模块化规范梳理.md"};function h(p,s,k,e,r,d){return n(),a("div",null,[...s[0]||(s[0]=[t("",42)])])}const o=i(l,[["render",h]]);export{g as __pageData,o as default}; +import{_ as i,g as a,h as n,U as t}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const g=JSON.parse('{"title":"JavaScript 模块化规范全景图:从 CJS 到 ESM","description":"全面梳理 CommonJS、AMD、UMD、ES Modules 四大模块化规范的核心语法与适用场景,解析各规范的关键差异,并提供从旧规范向 ESM 迁移的实操策略。","frontmatter":{"date":"2024-05-14T22:26:06.000Z","title":"JavaScript 模块化规范全景图:从 CJS 到 ESM","tldr":"全面梳理 CommonJS、AMD、UMD、ES Modules 等核心规范,附现代迁移策略。","description":"全面梳理 CommonJS、AMD、UMD、ES Modules 四大模块化规范的核心语法与适用场景,解析各规范的关键差异,并提供从旧规范向 ESM 迁移的实操策略。","permalink":"/fullstack/different-module-programming-specifications","tags":["tutorial","CommonJS","AMD","UMD","ESM"],"categories":["全栈","全栈基础素养","模块化编程实践指南"]},"headers":[],"relativePath":"fullstack/different-module-programming-specifications.md","filePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/2.不同模块化规范梳理.md"}'),l={name:"fullstack/different-module-programming-specifications.md"};function h(p,s,k,e,r,d){return n(),a("div",null,[...s[0]||(s[0]=[t("",41)])])}const o=i(l,[["render",h]]);export{g as __pageData,o as default}; diff --git "a/assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_1.\345\211\215\347\253\257\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\237\272\347\241\200.md.BVmOGo8x.js" b/assets/fullstack_frontend-module-programming-basic.md.CYF2zgUz.js similarity index 92% rename from "assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_1.\345\211\215\347\253\257\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\237\272\347\241\200.md.BVmOGo8x.js" rename to assets/fullstack_frontend-module-programming-basic.md.CYF2zgUz.js index 70a0e75f..d61422c6 100644 --- "a/assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_1.\345\211\215\347\253\257\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\237\272\347\241\200.md.BVmOGo8x.js" +++ b/assets/fullstack_frontend-module-programming-basic.md.CYF2zgUz.js @@ -1,4 +1,4 @@ -import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const g=JSON.parse('{"title":"模块化编程初体验:概念、演进与设计模式","description":"系统讲解 JavaScript 模块化编程基础,涵盖 IIFE、CommonJS、ES Modules 规范演进,以及工厂、单例、观察者等设计模式与模块化的结合。","frontmatter":{"date":"2024-05-12T22:43:28.000Z","title":"模块化编程初体验:概念、演进与设计模式","tldr":"从全局变量到 ES Modules:JavaScript 模块化演进与工厂、单例、观察者等设计模式实践。","description":"系统讲解 JavaScript 模块化编程基础,涵盖 IIFE、CommonJS、ES Modules 规范演进,以及工厂、单例、观察者等设计模式与模块化的结合。","permalink":"/fullstack/frontend-module-programming-basic","tags":["tutorial","javascript","modularization","esm","design-patterns"],"categories":["全栈","全栈基础素养","模块化编程实践指南"]},"headers":[],"relativePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/1.前端模块化编程基础.md","filePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/1.前端模块化编程基础.md"}'),h={name:"01.全栈/80.全栈基础素养/20.模块化编程实践指南/1.前端模块化编程基础.md"};function p(t,s,k,e,r,E){return n(),a("div",null,[...s[0]||(s[0]=[l(`

模块化编程初体验:概念、演进与设计模式

摘要总结: 本文系统讲解 JavaScript 模块化编程基础,涵盖 IIFE、CommonJS、ES Modules 规范演进,以及工厂、单例、观察者等设计模式与模块化的结合。从模块化的核心痛点出发——全局变量污染、依赖关系混乱、加载性能瓶颈——逐步展开模块化编程的知识图谱。实践层面结合工厂模式(批量创建相似对象)、单例模式(全局唯一实例,如数据库连接)、观察者/发布订阅模式(模块间松耦合通信)三种经典设计模式,展示模块化与设计模式的有机结合。

1. 引言

随着项目规模日益膨胀,代码量从几千行迅速增长到数万甚至数十万行,将所有逻辑塞进少数几个文件的做法早已难以为继。在这样的背景下,模块化编程应运而生,成为现代前端开发的标配。

它的核心理念简洁而优雅:像搭积木一样,将庞大复杂的系统拆解为一个个独立、功能单一且可复用的模块,让每个模块各司其职,再通过标准接口灵活组合。

2. 模块化编程初体验

在深入理论之前,让我们先通过一个简单的 JavaScript 示例,直观地感受一下什么是模块化。假设我们需要处理一些数学运算,我们可以将其封装成一个独立的工具模块:

javascript
// math.js - 定义一个数学工具模块
+import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const g=JSON.parse('{"title":"模块化编程初体验:概念、演进与设计模式","description":"系统讲解 JavaScript 模块化编程基础,涵盖 IIFE、CommonJS、ES Modules 规范演进,以及工厂、单例、观察者等设计模式与模块化的结合。","frontmatter":{"date":"2024-05-12T22:43:28.000Z","title":"模块化编程初体验:概念、演进与设计模式","tldr":"从全局变量到 ES Modules:JavaScript 模块化演进与工厂、单例、观察者等设计模式实践。","description":"系统讲解 JavaScript 模块化编程基础,涵盖 IIFE、CommonJS、ES Modules 规范演进,以及工厂、单例、观察者等设计模式与模块化的结合。","permalink":"/fullstack/frontend-module-programming-basic","tags":["tutorial","javascript","modularization","esm","design-patterns"],"categories":["全栈","全栈基础素养","模块化编程实践指南"]},"headers":[],"relativePath":"fullstack/frontend-module-programming-basic.md","filePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/1.前端模块化编程基础.md"}'),h={name:"fullstack/frontend-module-programming-basic.md"};function p(t,s,k,e,r,E){return n(),a("div",null,[...s[0]||(s[0]=[l(`

模块化编程初体验:概念、演进与设计模式

摘要总结: 本文系统讲解 JavaScript 模块化编程基础,涵盖 IIFE、CommonJS、ES Modules 规范演进,以及工厂、单例、观察者等设计模式与模块化的结合。从模块化的核心痛点出发——全局变量污染、依赖关系混乱、加载性能瓶颈——逐步展开模块化编程的知识图谱。实践层面结合工厂模式(批量创建相似对象)、单例模式(全局唯一实例,如数据库连接)、观察者/发布订阅模式(模块间松耦合通信)三种经典设计模式,展示模块化与设计模式的有机结合。

1. 引言

随着项目规模日益膨胀,代码量从几千行迅速增长到数万甚至数十万行,将所有逻辑塞进少数几个文件的做法早已难以为继。在这样的背景下,模块化编程应运而生,成为现代前端开发的标配。

它的核心理念简洁而优雅:像搭积木一样,将庞大复杂的系统拆解为一个个独立、功能单一且可复用的模块,让每个模块各司其职,再通过标准接口灵活组合。

2. 模块化编程初体验

在深入理论之前,让我们先通过一个简单的 JavaScript 示例,直观地感受一下什么是模块化。假设我们需要处理一些数学运算,我们可以将其封装成一个独立的工具模块:

javascript
// math.js - 定义一个数学工具模块
 export const PI = 3.14159;
 
 export function add(a, b) {
@@ -71,4 +71,4 @@ import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.CqY1sKvl.j
 import { EventEmitter } from './observer.js';
 const emitter = new EventEmitter();
 emitter.on('message', (data) => console.log('Received:', data));
-emitter.emit('message', 'Hello Observer!');

4. 结语:在秩序与复杂中寻找平衡

至此,我们已经推开了模块化编程的大门。从最直观的代码抽离切入,你会发现,模块化从来不仅仅是 import 和 export 的语法糖,它更像是一种对抗软件生命周期中“熵增”的工程哲学。

前端生态历经十余年,从早期 IIFE 的暗夜摸索,到 CommonJS 与 AMD 的百家争鸣,再到如今 ES Modules 的一统江湖,这条演进之路的背后,本质上是整个工程界对于“如何驾驭日益庞大的系统复杂度”这一命题的持续作答。它不仅抹平了命名冲突、依赖混乱的深坑,更为现代团队的高效协作铺设了最底层的基建。

当你开始熟练地运用“高内聚、低耦合”的思维边界,并将工厂、单例、观察者等经典设计模式自然地融入日常开发时,你就不再只是一个单纯的“代码编写者”,而是进阶为了一名掌控全局的“系统构建者”。

代码的物理边界终会在打包工具的运转下被抹平或重组,但留在你脑海中那道划分模块职责的逻辑边界,才是决定一个项目能走多远、多稳的真正基石。希望这次的模块化初体验,能为你未来的工程实践铺垫好最坚实的底色。

`,39)])])}const y=i(h,[["render",p]]);export{g as __pageData,y as default}; +emitter.emit('message', 'Hello Observer!');

4. 结语:在秩序与复杂中寻找平衡

至此,我们已经推开了模块化编程的大门。从最直观的代码抽离切入,你会发现,模块化从来不仅仅是 import 和 export 的语法糖,它更像是一种对抗软件生命周期中“熵增”的工程哲学。

前端生态历经十余年,从早期 IIFE 的暗夜摸索,到 CommonJS 与 AMD 的百家争鸣,再到如今 ES Modules 的一统江湖,这条演进之路的背后,本质上是整个工程界对于“如何驾驭日益庞大的系统复杂度”这一命题的持续作答。它不仅抹平了命名冲突、依赖混乱的深坑,更为现代团队的高效协作铺设了最底层的基建。

当你开始熟练地运用“高内聚、低耦合”的思维边界,并将工厂、单例、观察者等经典设计模式自然地融入日常开发时,你就不再只是一个单纯的“代码编写者”,而是进阶为了一名掌控全局的“系统构建者”。

代码的物理边界终会在打包工具的运转下被抹平或重组,但留在你脑海中那道划分模块职责的逻辑边界,才是决定一个项目能走多远、多稳的真正基石。希望这次的模块化初体验,能为你未来的工程实践铺垫好最坚实的底色。

`,38)])])}const y=i(h,[["render",p]]);export{g as __pageData,y as default}; diff --git "a/assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_1.\345\211\215\347\253\257\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\237\272\347\241\200.md.BVmOGo8x.lean.js" b/assets/fullstack_frontend-module-programming-basic.md.CYF2zgUz.lean.js similarity index 64% rename from "assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_1.\345\211\215\347\253\257\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\237\272\347\241\200.md.BVmOGo8x.lean.js" rename to assets/fullstack_frontend-module-programming-basic.md.CYF2zgUz.lean.js index fcad02b7..76c8e9fd 100644 --- "a/assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_1.\345\211\215\347\253\257\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\237\272\347\241\200.md.BVmOGo8x.lean.js" +++ b/assets/fullstack_frontend-module-programming-basic.md.CYF2zgUz.lean.js @@ -1 +1 @@ -import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const g=JSON.parse('{"title":"模块化编程初体验:概念、演进与设计模式","description":"系统讲解 JavaScript 模块化编程基础,涵盖 IIFE、CommonJS、ES Modules 规范演进,以及工厂、单例、观察者等设计模式与模块化的结合。","frontmatter":{"date":"2024-05-12T22:43:28.000Z","title":"模块化编程初体验:概念、演进与设计模式","tldr":"从全局变量到 ES Modules:JavaScript 模块化演进与工厂、单例、观察者等设计模式实践。","description":"系统讲解 JavaScript 模块化编程基础,涵盖 IIFE、CommonJS、ES Modules 规范演进,以及工厂、单例、观察者等设计模式与模块化的结合。","permalink":"/fullstack/frontend-module-programming-basic","tags":["tutorial","javascript","modularization","esm","design-patterns"],"categories":["全栈","全栈基础素养","模块化编程实践指南"]},"headers":[],"relativePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/1.前端模块化编程基础.md","filePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/1.前端模块化编程基础.md"}'),h={name:"01.全栈/80.全栈基础素养/20.模块化编程实践指南/1.前端模块化编程基础.md"};function p(t,s,k,e,r,E){return n(),a("div",null,[...s[0]||(s[0]=[l("",39)])])}const y=i(h,[["render",p]]);export{g as __pageData,y as default}; +import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const g=JSON.parse('{"title":"模块化编程初体验:概念、演进与设计模式","description":"系统讲解 JavaScript 模块化编程基础,涵盖 IIFE、CommonJS、ES Modules 规范演进,以及工厂、单例、观察者等设计模式与模块化的结合。","frontmatter":{"date":"2024-05-12T22:43:28.000Z","title":"模块化编程初体验:概念、演进与设计模式","tldr":"从全局变量到 ES Modules:JavaScript 模块化演进与工厂、单例、观察者等设计模式实践。","description":"系统讲解 JavaScript 模块化编程基础,涵盖 IIFE、CommonJS、ES Modules 规范演进,以及工厂、单例、观察者等设计模式与模块化的结合。","permalink":"/fullstack/frontend-module-programming-basic","tags":["tutorial","javascript","modularization","esm","design-patterns"],"categories":["全栈","全栈基础素养","模块化编程实践指南"]},"headers":[],"relativePath":"fullstack/frontend-module-programming-basic.md","filePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/1.前端模块化编程基础.md"}'),h={name:"fullstack/frontend-module-programming-basic.md"};function p(t,s,k,e,r,E){return n(),a("div",null,[...s[0]||(s[0]=[l("",38)])])}const y=i(h,[["render",p]]);export{g as __pageData,y as default}; diff --git a/assets/fullstack_full-stack-resources.md.CsBwRi3-.js b/assets/fullstack_full-stack-resources.md.CsBwRi3-.js new file mode 100644 index 00000000..bbd17a69 --- /dev/null +++ b/assets/fullstack_full-stack-resources.md.CsBwRi3-.js @@ -0,0 +1 @@ +import{_ as d,g as i,h as c,U as e,i as a,S as s}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const v=JSON.parse('{"title":"全栈技术资源推荐","description":"摘要总结:本文系统梳理了现代全栈开发的完整技术图谱与演进范式,为开发者提供了一站式的技术选型指南。文章从基石出发,覆盖 Web 核心语言(JS/TS) 与 主流 UI 框架(React/Vue/Svelte),并推荐以 Tailwind CSS 和 shadcn/ui 为代表的现代样式与组件原语。在核心业务逻辑层,深度对比了轻量化状态管理方案(首推 Zustand/Jotai),并重点解析了数据交互的三大现代架构范式:从基础 Axios 到 React Query 状态调度,再到 tRPC 和 GraphQL 带来的全栈类型安全与多端聚合。在工程化与服务端模块,文章全面拥抱 Vite、Rsbuild 等极速构建工具,并剖析了 Next.js/Nuxt 同构元框架与 NestJS 企业级 Node 服务的最佳适用场景。最后,辅以 Vercel 等现代边缘部署平台及丰富的开源社区学习资源。","frontmatter":{"date":"2026-02-06T15:58:53.000Z","title":"全栈技术资源推荐","description":"摘要总结:本文系统梳理了现代全栈开发的完整技术图谱与演进范式,为开发者提供了一站式的技术选型指南。文章从基石出发,覆盖 Web 核心语言(JS/TS) 与 主流 UI 框架(React/Vue/Svelte),并推荐以 Tailwind CSS 和 shadcn/ui 为代表的现代样式与组件原语。在核心业务逻辑层,深度对比了轻量化状态管理方案(首推 Zustand/Jotai),并重点解析了数据交互的三大现代架构范式:从基础 Axios 到 React Query 状态调度,再到 tRPC 和 GraphQL 带来的全栈类型安全与多端聚合。在工程化与服务端模块,文章全面拥抱 Vite、Rsbuild 等极速构建工具,并剖析了 Next.js/Nuxt 同构元框架与 NestJS 企业级 Node 服务的最佳适用场景。最后,辅以 Vercel 等现代边缘部署平台及丰富的开源社区学习资源。","permalink":"/fullstack/full-stack-resources","categories":["资源推荐"],"tags":["资源推荐","全栈"]},"headers":[],"relativePath":"fullstack/full-stack-resources.md","filePath":"01.全栈/90.工具与资源推荐/90.全栈技术资源推荐.md"}'),l={name:"fullstack/full-stack-resources.md"};function n(o,t,r,p,_,m){return c(),i("div",null,[...t[0]||(t[0]=[e('

全栈技术资源推荐

摘要总结:本文系统梳理了现代全栈开发的完整技术图谱与演进范式,不仅是一份全栈工具检索目录,更是一份指导开发者从全局视角构建高性能、类型安全、且极具工程化思维的现代 Web 应用的最佳实践指南。

  • 文章从基石出发,覆盖 Web 核心语言(JS/TS) 与 主流 UI 框架(React/Vue/Svelte),并推荐以 Tailwind CSS 和 shadcn/ui 为代表的现代样式与组件原语。
  • 在核心业务逻辑层,深度对比了轻量化状态管理方案(首推 Zustand/Jotai),并重点解析了数据交互的三大现代架构范式:从基础 Axios 到 React Query 状态调度,再到 tRPC 和 GraphQL 带来的全栈类型安全与多端聚合。
  • 在工程化与服务端模块,文章全面拥抱 Vite、Rsbuild 等极速构建工具,并剖析了 Next.js/Nuxt 同构元框架与 NestJS 企业级 Node 服务的最佳适用场景。最后,辅以 Vercel 等现代边缘部署平台及丰富的开源社区学习资源。

1. 基本语言与环境

',3),a("div",{class:"container nav-card-container"},[a("div",{class:"nav-card index-auto",style:{"--row-gap":"20px","--column-gap":"20px","--column-min-width":"calc(100% / 4 - 60px)"}},[a("a",{href:"https://developer.mozilla.org/zh-CN/docs/Web/HTML",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://upload.wikimedia.org/wikipedia/commons/thumb/6/61/HTML5_logo_and_wordmark.svg/1200px-HTML5_logo_and_wordmark.svg.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"HTML")]),a("p",{class:"desc"},"HTML (HyperText Markup Language) 是用于创建网页的标准标记语言,用于描述网页的结构和内容。它使用标签来定义文档的不同部分,如标题、段落、图像、链接等。HTML 是构建 Web 页面的基础,也是所有前端开发的起点。"),a("span",{class:"VPBadge tip badge"},"标记语言")]),a("a",{href:"https://developer.mozilla.org/zh-CN/docs/Web/CSS",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://upload.wikimedia.org/wikipedia/commons/thumb/d/d5/CSS3_logo_and_wordmark.svg/1200px-CSS3_logo_and_wordmark.svg.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"CSS")]),a("p",{class:"desc"},"CSS (Cascading Style Sheets) 是用于描述网页样式和布局的样式表语言。它定义了文档的外观,包括字体、颜色、间距、布局等。CSS 与 HTML 结合使用,实现了网页的结构与样式的分离,使得网页设计更加灵活和可维护。"),a("span",{class:"VPBadge tip badge"},"样式表")]),a("a",{href:"https://developer.mozilla.org/zh-CN/docs/Web/JavaScript",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://upload.wikimedia.org/wikipedia/commons/thumb/6/6a/JavaScript-logo.png/1200px-JavaScript-logo.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"JavaScript")]),a("p",{class:"desc"},"JavaScript 是一种动态、弱类型的脚本语言,用于在 Web 浏览器中实现交互性和动态内容。它是 Web 开发的基础,也是前端开发的核心语言。"),a("span",{class:"VPBadge tip badge"},"脚本语言")]),a("a",{href:"https://www.typescriptlang.org/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://upload.wikimedia.org/wikipedia/commons/thumb/4/4c/Typescript_logo_2020.svg/1200px-Typescript_logo_2020.svg.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"TypeScript")]),a("p",{class:"desc"},"TypeScript 是 JavaScript 的一个超集,添加了静态类型检查和其他高级功能,使得代码更加可靠和可维护。它在前端开发中得到广泛应用,尤其在 React 项目中。"),a("span",{class:"VPBadge tip badge"},"静态类型")]),a("a",{href:"https://webkit.org/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://webkit.org/wp-content/themes/webkit/images/webkit.svg",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"webkit")]),a("p",{class:"desc"},"WebKit 是一个开源的浏览器引擎,用于渲染网页内容。它是 Safari 浏览器的引擎,也是 Chrome 浏览器的一部分。WebKit 提供了高性能的网页渲染和交互功能,是构建现代 Web 应用的基础。"),a("span",{class:"VPBadge tip badge"},"浏览器引擎")]),a("a",{href:"https://nodejs.org/zh-cn/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://upload.wikimedia.org/wikipedia/commons/thumb/d/d9/Node.js_logo.svg/1200px-Node.js_logo.svg.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"Node.js")]),a("p",{class:"desc"},"Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时环境,用于在服务器端执行 JavaScript 代码。它允许开发者使用 JavaScript 构建高性能的网络应用程序,如服务器端渲染、实时应用程序和 API 服务。"),a("span",{class:"VPBadge tip badge"},"服务器端")])])],-1),a("h2",{id:"_2-核心-ui-框架",tabindex:"-1"},[s("2. 核心 UI 框架 "),a("a",{class:"header-anchor",href:"#_2-核心-ui-框架","aria-label":"Permalink to “2. 核心 UI 框架”"},"​")],-1),a("div",{class:"container nav-card-container"},[a("div",{class:"nav-card index-auto",style:{"--row-gap":"20px","--column-gap":"20px","--column-min-width":"calc(100% / 4 - 60px)"}},[a("a",{href:"https://react.dev/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://upload.wikimedia.org/wikipedia/commons/thumb/a/a7/React-icon.svg/1200px-React-icon.svg.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"React")]),a("p",{class:"desc"},"React 是 Facebook 开发的用于构建用户界面的声明式 JavaScript 库,采用组件化架构,支持服务器端渲染和客户端交互。它允许开发者设计简单的视图,并根据数据变化高效更新渲染组件。"),a("span",{class:"VPBadge tip badge"},"声明式")]),a("a",{href:"https://vuejs.org/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://upload.wikimedia.org/wikipedia/commons/thumb/9/95/Vue.js_Logo_2.svg/1200px-Vue.js_Logo_2.svg.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"Vue")]),a("p",{class:"desc"},"Vue.js 是一套用于构建用户界面的渐进式框架,采用组件化架构,支持服务器端渲染和客户端交互。强调易用性和高性能。其生态包含官方路由 (Vue Router) 和状态管理库 (Pinia)。"),a("span",{class:"VPBadge tip badge"},"渐进式")]),a("a",{href:"https://svelte.dev/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://upload.wikimedia.org/wikipedia/commons/thumb/1/1b/Svelte_Logo.svg/1200px-Svelte_Logo.svg.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"Svelte")]),a("p",{class:"desc"},"Svelte 是一种全新的构建 Web 应用的方式,作为编译器将声明式组件转换为高效且能直接操作 DOM 的 JavaScript 代码,运行时开销极小。它强调组件化开发,开发者可以直接在 HTML 中编写组件逻辑,无需额外的运行时支持。"),a("span",{class:"VPBadge tip badge"},"编译时")])])],-1),a("h2",{id:"_3-样式与-ui-组件库-styling-component-libraries",tabindex:"-1"},[s("3. 样式与 UI 组件库 (Styling & Component Libraries) "),a("a",{class:"header-anchor",href:"#_3-样式与-ui-组件库-styling-component-libraries","aria-label":"Permalink to “3. 样式与 UI 组件库 (Styling & Component Libraries)”"},"​")],-1),a("div",{class:"container nav-card-container"},[a("div",{class:"nav-card index-auto",style:{"--row-gap":"20px","--column-gap":"20px","--column-min-width":"calc(100% / 4 - 60px)"}},[a("a",{href:"https://tailwindcss.com/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://upload.wikimedia.org/wikipedia/commons/thumb/d/d5/Tailwind_CSS_Logo.svg/1200px-Tailwind_CSS_Logo.svg.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"Tailwind CSS")]),a("p",{class:"desc"},"现代前端首选的实用优先 (Utility-first) CSS 框架,通过类名组合实现样式,无需编写自定义 CSS。"),a("span",{class:"VPBadge tip badge"},"实用优先")]),a("a",{href:"https://daisyui.com/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://img.daisyui.com/images/daisyui/mark.svg",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"Daisy UI")]),a("p",{class:"desc"},"是一个基于 Tailwind CSS 的热门开源UI组件库,通过添加语义化类名(如 btn, card)来解决 Tailwind 冗长的代码问题,能帮开发者用更少的代码、更快地构建出干净、美观、响应式且支持主题自定义的 Web 界面。"),a("span",{class:"VPBadge tip badge"},"tailwind 插件")]),a("a",{href:"https://ui.shadcn.com/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://ui.shadcn.com/favicon.ico",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"shadcn/ui")]),a("p",{class:"desc"},"shadcn/ui 不是一个传统的组件库,而是一种构建你自己的组件库的方法。它提供了一套精心设计、可访问的组件和代码分发平台,兼容你喜欢的框架和 AI 模型。"),a("span",{class:"VPBadge tip badge"},"组件原语")]),a("a",{href:"https://ant.design/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://gw.alipayobjects.com/zos/rmsportal/rlpTLlbMzTNYuZGGCVYM.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"Ant Design")]),a("p",{class:"desc"},"AI 友好的「设计系统」,让美与智能并进,让工作充满「灵感」与「快乐」。"),a("span",{class:"VPBadge tip badge"},"组件库")]),a("a",{href:"https://element-plus.org/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://element-plus.org/images/element-plus-logo-small.svg",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"element-plus")]),a("p",{class:"desc"},"Element Plus 是一个基于 Vue 3 设计的组件库,提供丰富的组件和样式,常用于构建后台管理系统。"),a("span",{class:"VPBadge tip badge"},"组件库")]),a("a",{href:"https://vuetifyjs.com/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://vuetifyjs.com/favicon.ico",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"Vuetify")]),a("p",{class:"desc"},"为 Vue 3 设计的成熟 UI 库,常用于构建后台管理系统,提供丰富的组件和样式。"),a("span",{class:"VPBadge tip badge"},"组件库")])])],-1),a("h2",{id:"_4-路由与状态管理",tabindex:"-1"},[s("4. 路由与状态管理 "),a("a",{class:"header-anchor",href:"#_4-路由与状态管理","aria-label":"Permalink to “4. 路由与状态管理”"},"​")],-1),a("div",{class:"container nav-card-container"},[a("div",{class:"nav-card index-auto",style:{"--row-gap":"20px","--column-gap":"20px","--column-min-width":"calc(100% / 4 - 60px)"}},[a("a",{href:"https://reactrouter.com/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://reactrouter.com/favicon-dark.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"React Router")]),a("p",{class:"desc"},"React Router 是 React 官方的路由管理器,用于构建单页应用 (SPA),提供动态路由匹配、嵌套路由、路由守卫等功能。"),a("span",{class:"VPBadge tip badge"},"路由管理器")]),a("a",{href:"https://router.vuejs.org/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://upload.wikimedia.org/wikipedia/commons/thumb/9/95/Vue.js_Logo_2.svg/1200px-Vue.js_Logo_2.svg.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"Vue Router")]),a("p",{class:"desc"},"Vue.js 官方的路由管理器,用于构建单页应用 (SPA),提供动态路由匹配、嵌套路由、路由守卫等功能。"),a("span",{class:"VPBadge tip badge"},"路由管理器")]),a("a",{href:"https://github.com/pmndrs/zustand",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://avatars.githubusercontent.com/u/45790596?s=48&v=4",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"Zustand")]),a("p",{class:"desc"},"pmndrs 社区出品,是 Redux 的现代化、极简主义精神继承者(自上而下的全局 Store),提供了一种简单的方式来管理全局状态。"),a("span",{class:"VPBadge tip badge"},"状态管理")]),a("a",{href:"https://github.com/pmndrs/jotai",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://avatars.githubusercontent.com/u/45790596?s=48&v=4",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"Jotai")]),a("p",{class:"desc"},"pmndrs 社区出品,是 Recoil 的轻量化、高性能替代者(自下而上的原子化状态)。"),a("span",{class:"VPBadge tip badge"},"状态管理")]),a("a",{href:"https://redux.js.org/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://redux.js.org/img/favicon/favicon.ico",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"Redux")]),a("p",{class:"desc"},"Redux 是一个预测性的状态容器,用于管理应用的全局状态,提供一致的状态更新和可预测的行为。"),a("span",{class:"VPBadge tip badge"},"不再推荐")]),a("a",{href:"https://pinia.vuejs.org/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://pinia.vuejs.org/logo.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"Pinia")]),a("p",{class:"desc"},"Vue.js 官方推荐的状态管理库,基于 Vue 3 Composition API 设计,提供简单、灵活的状态管理解决方案。"),a("span",{class:"VPBadge tip badge"},"状态管理")])])],-1),e('

React 状态管理库横向对比分析:

特性/库Zustand 大部分项目的首选Jotai 编辑比较频繁的建议使用Redux 不再推荐
核心思想自上而下的全局状态管理自下而上的原子化状态管理单向数据流、集中式全局状态
适用场景中大型应用全局状态、偏好轻量方案组件间状态共享、细粒度更新、贴近React思维超大型复杂应用、强可预测性需求
学习曲线平缓,API 简洁平缓,原子概念容易理解陡峭,需理解中间件、Redux Toolkit 等
代码风格简洁,类似轻量版 Redux原子化,分散定义状态相对冗长,需定义 Action、Reducer
性能优化支持组件精准订阅状态天然细粒度更新,避免不必要重渲染需配合 Reselect 等工具优化
社区生态生态稳定,常用插件完善生态活跃,适合实验性场景生态庞大,工具链成熟

5. 数据获取与 API 集成 (Data Fetching & API)

',3),a("div",{class:"container nav-card-container"},[a("div",{class:"nav-card index-auto",style:{"--row-gap":"20px","--column-gap":"20px","--column-min-width":"calc(100% / 4 - 60px)"}},[a("a",{href:"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("span",{class:"name"},"Fetch API")]),a("p",{class:"desc"},"Fetch 是一个基于 Promise 的现代 JavaScript API,用于在浏览器中发起 HTTP 请求(AJAX),是 XMLHttpRequest (XHR) 的更简洁、更强大的替代方案。它允许页面在不重载的情况下从服务器获取数据,支持 GET、POST 等请求方法,并广泛应用于处理网络数据交互。"),a("span",{class:"VPBadge tip badge"},"原生 API")]),a("a",{href:"https://axios-http.com/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://axios-http.com/assets/favicon.ico",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"Axios")]),a("p",{class:"desc"},"Axios 是一个基于 Promise 的 HTTP 请求库,可运行在浏览器和 Node.js 环境中。它支持拦截请求和响应、转换数据、取消请求等功能,是前端开发中常用的 HTTP 请求库。"),a("span",{class:"VPBadge tip badge"},"全能请求库")]),a("a",{href:"https://swr.vercel.app/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://swr.vercel.app/favicon.ico",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"SWR")]),a("p",{class:"desc"},'SWR 是由 Vercel 开发的一个基于 React Hooks 的轻量级数据请求库。它基于 "stale-while-revalidate" 策略,先返回缓存数据,再在后台请求最新数据,保证 UI 快速响应且数据保持更新。特点:极简主义,越轻越好,开箱即用,专注于 HTTP 缓存策略。'),a("span",{class:"VPBadge tip badge"},"按需验证缓存")]),a("a",{href:"https://tanstack.com/query/latest",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://tanstack.com/favicon-32x32.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"React Query")]),a("p",{class:"desc"},"React Query (现更名为 TanStack Query) 是一个功能强大的 React 服务端状态管理库。它专注于处理异步数据的获取、缓存、同步和更新,开箱即用地简化了 API 请求、缓存处理、数据过期更新和加载/错误状态管理。特点:功能主义大而全,不仅是 HTTP,可用于任何异步 Promise 管理。"),a("span",{class:"VPBadge tip badge"},"服务端状态管理")]),a("a",{href:"https://graphql.org/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://graphql.org/_next/static/media/logo-blurred.94c9eff4.webp",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"GraphQL")]),a("p",{class:"desc"},"GraphQL 是一个用于 API 的查询语言、一种描述请求数据方法的语法,通常用于客户端从服务端加载数据,主要是为了解决 REST API 中过度获取和获取不足的问题。"),a("span",{class:"VPBadge tip badge"},"按需声明式查询")]),a("a",{href:"https://trpc.io/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://trpc.io/img/favicon.ico",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"tRPC")]),a("p",{class:"desc"},"tRPC 是基于插件化理念设计的一款支持多语言、高性能的 RPC 开发框架,旨在无需定义专门 API Schema(如 Swagger/GraphQL)的情况下,实现前后端无缝、全栈类型安全的 API 调用。它让前端能像调用本地函数一样调用后端远程函数,大大提升开发效率。"),a("span",{class:"VPBadge tip badge"},"端到端类型安全")])])],-1),e('
技术/工具核心定位与特征核心优势 (能解决什么痛点)局限性与妥协最佳实践与适用场景
Fetch API 通信基建浏览器原生标准协议无需安装第三方包、天然融入现代 Web 标准。在 Edge Runtime 环境下表现最佳。默认不抛出 HTTP 错误状态码(需手动拦截);处理 JSON 和参数拼接繁琐、缺少请求取消机制。极简场景/底层封装:不需要复杂拦截器的轻量级页面;作为更高级架构的底层引擎,如 Next.js 内部的 fetch 扩展。
Axios
通信基建
全能型同构请求体API 极其友好、请求/响应拦截器(处理全局 Token、统一错误提示的利器)、自动转换 JSON 数据。增加了一定的打包体积;基于 XHR(尽管现代版本已支持 fetch 底层),在某些最新的服务端边缘计算环境中可能受限。重度依赖 RESTful 的项目:需要精细化控制请求头、进行全局鉴权拦截、处理复杂文件上传的传统全栈或中后台系统。
SWR
状态调度
按需验证的轻量级缓存极致的轻量与简单;焦点聚焦时自动刷新、网络恢复时重试;带来极佳的“UI 瞬间响应”体验。面对极其复杂的异步状态流转(如互相依赖的串行请求、精细的离线修改回滚)时,显得心有余而力不足。内容驱动型应用:注重阅读体验的博客站点、数据实时性要求中等的数据看板。配置极简,非常适合快速迭代的产品。
React Query
状态调度
大而全的异步状态接管强大的缓存生命周期管理;优雅的 Mutations(数据变更)处理与乐观更新;极好的开发调试工具。学习曲线较陡峭;默认配置下有时会导致意料之外的组件重渲染;体积相对较大。复杂交互型 SaaS / 强业务逻辑系统:需要处理大量表单提交、列表无限滚动、精细化缓存控制的重型单页应用(SPA)。
GraphQL 协议契约声明式的图谱查询彻底解决 Over-fetching;前端拥有极高的数据按需组合自由度;自带强类型的 Schema 文档。后端开发成本极高(需编写大量 Resolver 函数);容易产生 N+1 查询性能问题;HTTP 缓存机制难以直接利用。多端复用型大中型产品:后端需要同时服务于 Web、iOS、Android 甚至第三方开发者;业务实体关系高度复杂的系统。
tRPC
协议契约
端到端的全栈类型推导前后端类型零成本共享;重构时的代码安全性极高;完全不需要手写接口文档或 Schema。强绑定 Node.js/TypeScript 技术栈;如果前端项目和后端代码没有在一个 Monorepo 中,威力大打折扣。敏捷全栈/单人作战团队:采用 Node.js + 前端框架(React/Vue)构建的全栈项目。极度追求开发效率和产品迭代速度的团队。

现代 Web 数据流架构范式:

1、标准前后端分离架构:Axios + React Query(或 SWR)

  • 适用场景: 异构系统(如前端使用 React/Vue,后端使用 Java/Go/Python 等非 JS 语言);高度依赖传统 RESTful API 规范、需要精细化控制网络请求拦截器的中大型企业级项目。
  • 架构机制:将网络请求的“底层通道”与“上层状态”严格解耦。Axios 专注于基础通信层的治理,负责全局请求头注入(如 Bearer Token)、统一的 HTTP 状态码拦截与静默错误上报;React Query / SWR 则专注于表现层的状态调度,接管数据的缓存生命周期、请求去重(Deduplication)以及乐观更新(Optimistic UI)。
  • 工程价值:具备极高的稳健性与技术栈包容性。前后端边界清晰,互不干扰。

2、全栈类型安全架构:tRPC + React Query

  • 适用场景: 采用 Monorepo 架构管理的纯 TypeScript/Node.js 全栈项目;追求敏捷开发、极速交付以及需要频繁进行业务重构的 SaaS 产品或内部系统。
  • 架构机制:基于 TypeScript 的强类型推导系统,打通前后端数据流。tRPC 官方深度集成了 React Query(@trpc/react-query),在保留了完整的现代前端缓存调度能力的同时,彻底免去了手动维护 API 接口文档和 Schema 编译生成的中间环节。后端的类型变更会即刻反映为前端编译期的静态类型检查报错。
  • 工程价值:极致的研发效能与结构安全性。对于专注于产品迭代与业务增长的 Node.js 全栈开发者而言,这种组合完美契合了“以更少投入获得更大收益”的工程哲学。它直接消灭了“接口联调”这一无效耗时环节,让开发者能将核心精力聚焦于产品逻辑本身。

3、多端数据聚合 BFF 架构:GraphQL + Apollo Client

  • 适用场景: 数据来源庞杂且分散的大型业务系统;需要同时为多种不同客户端提供高灵活性 API,且前后端团队规模较大、需要高度并行的项目。
  • 架构机制:引入 BFF(Backend For Frontend,服务于前端的后端)理念。GraphQL 作为中间件层,负责将底层分散的微服务、数据库或第三方 API 进行聚合与编排(Data Orchestration)。前端通过 Apollo Client 发起声明式查询,精准获取 UI 组件所需的数据切片,并利用 Apollo 强大的标准化缓存(Normalized Cache)管理复杂实体关系。
  • 工程价值:彻底解决多端设备(Web、iOS、Android)面临的过度获取(Over-fetching)与碎片化接口治理问题,实现了数据消费端的高度自治。

6. 构建工具与工作流 (Build Tools & Workflow)

',9),a("div",{class:"container nav-card-container"},[a("div",{class:"nav-card index-auto",style:{"--row-gap":"20px","--column-gap":"20px","--column-min-width":"calc(100% / 4 - 60px)"}},[a("a",{href:"https://cn.vite.dev/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://cn.vite.dev/logo-without-border.svg",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"Vite")]),a("p",{class:"desc"},"Vite 是一款速度极快的前端构建工具,为下一代 Web 应用程序提供支持,它摒弃了“先打包,再启动”的模式,开启了“原生 ESM”开发的新时代。"),a("span",{class:"VPBadge tip badge"},"极速 ESM 构建")]),a("a",{href:"https://rsbuild.rs/zh/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://assets.rspack.rs/rsbuild/favicon-128x128.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"Rsbuild")]),a("p",{class:"desc"},"Rsbuild 是一个由字节跳动 Web Infra 团队开源、基于 Rust 语言编写的 Rspack 驱动的高性能构建工具。它专注于为 Web 项目提供开箱即用的开发体验,通过内置的高性能工具(如 SWC、Lightning CSS)实现极快的构建速度,并提供类似 Vite/Webpack 的零配置或低配置体验。"),a("span",{class:"VPBadge tip badge"},"Rust 高性能构建")]),a("a",{href:"https://nextjscn.org/docs/app/api-reference/turbopack",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("span",{class:"name"},"Turbopack")]),a("p",{class:"desc"},"Turbopack 是由 Vercel 开发、基于 Rust 编写的高性能增量打包工具,专为 JavaScript 和 TypeScript 优化。它被设计为 Webpack 的继任者,旨在通过优化的机器代码和高度增量计算能力,提供比 Vite 快 10 倍、比 Webpack 快 700 倍的本地开发体验,主要内置于 Next.js。"),a("span",{class:"VPBadge tip badge"},"增量极速打包")]),a("a",{href:"https://webpack.docschina.org/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://webpack.docschina.org/favicon.f326220248556af65f41.ico",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"Webpack")]),a("p",{class:"desc"},"Webpack 是一个现代 JavaScript 应用程序的静态模块打包工具。它在内部构建依赖图,将项目中的各种资源(如 JS、CSS、图片、TypeScript 等)视为模块,并最终打包成浏览器可直接运行的静态文件。通过 Loader 和 Plugin,它能处理复杂的开发需求。"),a("span",{class:"VPBadge tip badge"},"经典模块打包")]),a("a",{href:"https://github.com/features/actions",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://github.com/fluidicon.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"GitHub Actions")]),a("p",{class:"desc"},"GitHub Actions 是 GitHub 推出的持续集成和持续交付 (CI/CD) 平台,旨在帮助开发者自动执行软件开发工作流。它允许在代码仓库中直接定义自动化流程(如构建、测试、部署),支持事件触发(如提交代码),并提供虚拟机环境(Ubuntu、Windows、macOS)运行任务,使开发更高效。"),a("span",{class:"VPBadge tip badge"},"CI/CD 自动化")])])],-1),a("h2",{id:"_7-全栈框架",tabindex:"-1"},[s("7. 全栈框架 "),a("a",{class:"header-anchor",href:"#_7-全栈框架","aria-label":"Permalink to “7. 全栈框架”"},"​")],-1),a("blockquote",null,[a("p",null,[a("strong",null,"同构元框架:Next.js、Nuxt"),s(",现代全栈开发倾向于使用“元框架”,它们模糊了客户端和服务器的界限,提供一体化的开发体验。")]),a("p",null,[a("strong",null,"企业级 Node 服务端框架:NestJS"),s(",一个用于构建高效、可扩展的 Node.js 服务器端应用程序的框架,它采用现代 TypeScript 编写,并完全支持它(同时也支持纯 JavaScript)。它融合了 OOP(面向对象编程)、FP(函数式编程)和 FRP(函数响应式编程)的理念。其设计深受 Angular 启发,内置了依赖注入(DI)、模块化和分层架构等强主张特性,被称为 Node.js 版的 Spring 框架。")])],-1),a("div",{class:"container nav-card-container"},[a("div",{class:"nav-card index-auto",style:{"--row-gap":"20px","--column-gap":"20px","--column-min-width":"calc(100% / 4 - 60px)"}},[a("a",{href:"https://nextjs.org/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://nextjs.org/favicon.ico?favicon.3fc65821.ico",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"Next.js")]),a("p",{class:"desc"},"Next.js 是一个基于 React、Node.js 的全栈 Web 开发框架,由 Vercel 公司维护,专为生产环境设计。它通过内置的服务器端渲染 (SSR)、静态站点生成 (SSG) 和增量静态再生成 (ISR) 技术,解决了传统 React 应用的 SEO 优化差 和首屏加载慢的问题,是目前最受欢迎的 React 应用开发框架之一。"),a("span",{class:"VPBadge tip badge"},"SSR/SSG/ISR")]),a("a",{href:"https://nuxtjs.org/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://nuxt.com/icon.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"Nuxt")]),a("p",{class:"desc"},"是一个基于 Vue.js 的开源、免费的 Web 开发元框架(Meta-framework),专为构建高性能的服务端渲染(SSR)、静态站点生成(SSG)和单页应用(SPA)而设计。它集成了 Vite、Vue 3 和 Nitro 服务端引擎,旨在简化开发流程,提供卓越的 SEO 优化和开发人员体验"),a("span",{class:"VPBadge tip badge"},"SSR/SSG/ISR")]),a("a",{href:"https://nestjs.com/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://nestjs.com/favicon-32x32.a39d94f4.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"NestJS")]),a("p",{class:"desc"},"NestJS 是一个用于构建高效、可扩展的 Node.js 服务器端应用程序的框架,它采用现代 TypeScript 编写,并完全支持它(同时也支持纯 JavaScript)。它融合了 OOP(面向对象编程)、FP(函数式编程)和 FRP(函数响应式编程)的理念。其设计深受 Angular 启发,内置了依赖注入(DI)、模块化和分层架构等强主张特性,被称为 Node.js 版的 Spring 框架."),a("span",{class:"VPBadge tip badge"},"企业级 Node 框架")])])],-1),e('
对比维度Next.jsNuxtNestJS
框架定位React 全栈框架
(Isomorphic Meta-framework)
Vue 全栈框架
(Isomorphic Meta-framework)
企业级 Node.js 服务端框架
(Backend Framework)
底层驱动Webpack / Turbopack
React Server Components
Vite / Nitro 引擎
Vue3
Express / Fastify (底层可插拔)
纯 TypeScript
核心工程特性混合渲染 (SSR/SSG/ISR)
Server Actions (无缝 RPC)
边缘计算路由
混合渲染与预渲染
极致的自动导入 (Auto-imports)
开箱即用的模块化生态
依赖注入 (DI) / 控制反转 (IoC)
面向切面编程 (AOP)
强主张的模块化目录
数据流职责视图层渲染、BFF (服务于前端的后端)、轻量级聚合 API。视图层渲染、BFF (服务于前端的后端)、轻量级聚合 API。纯后端业务逻辑处理、微服务通信与编排、统一 API 供应。
最佳业务场景重 SEO 的 C 端产品 (电商、内容站); 敏捷迭代的 SaaS; 单仓库极速交付。重交互体验的 Web 应用; Vue 技术团队的全栈转型; 独立开发者建站。复杂领域驱动设计 (DDD) 系统; 多端复用的 API 中台; 庞大的微服务集群。
需规避的反模式承载高并发 CPU 密集型计算; 极其复杂的跨服务分布式事务。承载高并发 CPU 密集型计算; 极其复杂的跨服务分布式事务。仅需极简 CRUD 的小型外包项目; 强依赖首屏 HTML 直出的纯展示网页。
团队协作模型前端主导的敏捷全栈小队, 或追求“单兵作战”的极客团队。前端主导的敏捷全栈小队, 或 Vue 生态重度依赖团队。后端主导的中大型团队, 前后端物理分离的标准化开发流水线。

8. 部署与托管 (Deployment & Hosting)

',2),a("div",{class:"container nav-card-container"},[a("div",{class:"nav-card index-auto",style:{"--row-gap":"20px","--column-gap":"20px","--column-min-width":"calc(100% / 4 - 60px)"}},[a("a",{href:"https://vercel.com/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://assets.vercel.com/image/upload/front/favicon/vercel/apple-touch-icon-256x256.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"Vercel")]),a("p",{class:"desc"},"Vercel 是一个现代前端项目的理想部署平台,它零配置、支持自动部署和预览、拥有全球加速节点,广泛用于开源项目、个人作品集、企业网站等。 无论你是用React、Vue、Svelte 还是静态HTML,只需几步就可以将项目上线。"),a("span",{class:"VPBadge tip badge"},"前端边缘托管")]),a("a",{href:"https://www.netlify.com/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://www.netlify.com/favicon/favicon.ico",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"Netlify")]),a("p",{class:"desc"},"与 Vercel 类似,功能更全面:支持更多的框架和静态站点生成器,有表单处理、无服务器函数等功能,免费额度更大、还支持 A/B 测试和分析。Netlify 是一个基于云计算的网站部署和托管平台,专注于为开发者提供便捷的静态网站和Jamstack 应用部署服务。 它的核心优势在于将网站构建、部署、托管以及持续集成/ 持续部署(CI/CD)流程高度集成,极大地简化了开发和运维的复杂程度"),a("span",{class:"VPBadge tip badge"},"Jamstack 平台")]),a("a",{href:"https://pages.github.com/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://github.com/fluidicon.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"GitHub Pages")]),a("p",{class:"desc"},"GitHub Pages 是一个由 GitHub 提供的、免费的静态网站托管服务。它允许用户直接从 GitHub 仓库(Repository)获取 HTML、CSS 和 JavaScript 文件,无需额外配置服务器即可快速部署个人主页、项目文档或博客。"),a("span",{class:"VPBadge tip badge"},"纯静态托管")])])],-1),a("h2",{id:"_9-学习资源与社区-learning-community",tabindex:"-1"},[s("9. 学习资源与社区 (Learning & Community) "),a("a",{class:"header-anchor",href:"#_9-学习资源与社区-learning-community","aria-label":"Permalink to “9. 学习资源与社区 (Learning & Community)”"},"​")],-1),a("div",{class:"container nav-card-container"},[a("div",{class:"nav-card index-auto",style:{"--row-gap":"20px","--column-gap":"20px","--column-min-width":"calc(100% / 4 - 60px)"}},[a("a",{href:"https://javascriptweekly.com/issues",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("span",{class:"name"},"JavaScript Weekly")]),a("p",{class:"desc"},"每周分享最新的 JavaScript 相关技术文章、库、工具和趋势"),a("span",{class:"VPBadge tip badge"},"技术周刊")]),a("a",{href:"https://nodeweekly.com/issues",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("span",{class:"name"},"Node Weekly")]),a("p",{class:"desc"},"每周分享最新的 Node.js 相关技术文章、库、工具和趋势。"),a("span",{class:"VPBadge tip badge"},"技术周刊")]),a("a",{href:"https://www.ruanyifeng.com/blog/weekly/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("span",{class:"name"},"阮一峰网络日志")]),a("p",{class:"desc"},"阮一峰的网络日志,每周五发布,分享最新的前端技术文章、库、工具和趋势等。"),a("span",{class:"VPBadge tip badge"},"技术周刊")]),a("a",{href:"https://fed.chanceyu.com/?q=%5B%E6%9D%A5%E6%BA%90%5D%20%E5%89%8D%E7%AB%AF%E6%97%A9%E8%AF%BB%E8%AF%BE",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://res.wx.qq.com/a/wx_fed/assets/res/OTE0YTAw.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"前端早读课")]),a("p",{class:"desc"},"前端领域专业的微信公众号,发布一些与前端相关的深度技术文章、库、工具和趋势等。"),a("span",{class:"VPBadge tip badge"},"专业公众号")]),a("a",{href:"https://fed.chanceyu.com/?q=%5B%E6%9D%A5%E6%BA%90%5D%20%E5%89%8D%E7%AB%AF%E4%B9%8B%E5%B7%85",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://res.wx.qq.com/a/wx_fed/assets/res/OTE0YTAw.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"前端之巅")]),a("p",{class:"desc"},"前端领域专业的微信公众号,发布一些与前端相关的深度技术文章、库、工具和趋势等。"),a("span",{class:"VPBadge tip badge"},"专业公众号")]),a("a",{href:"https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzIxMzExMjYwOQ==&action=getalbum&album_id=1369610438157369345#wechat_redirect",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://res.wx.qq.com/a/wx_fed/assets/res/OTE0YTAw.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"凹凸实验室")]),a("p",{class:"desc"},"蒲公英·JELLY技术周刊,由京东·凹凸实验室维护整理的技术周刊,从团队专注的研究技术方向出发,深入挖掘业界热点,聚焦技术动态。技术周刊内容分类主要包括如下:基础技术、工程化、跨端框架技术、图形编程、服务端开发、桌面开发、人工智能等。"),a("span",{class:"VPBadge tip badge"},"技术周刊")]),a("a",{href:"https://fed.chanceyu.com/?q=%5B%E6%9D%A5%E6%BA%90%5D%20%E5%89%8D%E7%AB%AF%E5%A4%A7%E5%85%A8",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://res.wx.qq.com/a/wx_fed/assets/res/OTE0YTAw.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"前端大全")]),a("p",{class:"desc"},"前端大全,分享最新的前端技术文章、库、工具和趋势"),a("span",{class:"VPBadge tip badge"},"专业公众号")]),a("a",{href:"https://fed.chanceyu.com/?q=%5B%E6%9D%A5%E6%BA%90%5D%20%E5%89%8D%E7%AB%AF%E4%B9%8B%E7%A5%9E",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://res.wx.qq.com/a/wx_fed/assets/res/OTE0YTAw.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"前端之神")]),a("p",{class:"desc"},"前端之神,分享最新的前端技术文章、库、工具和趋势"),a("span",{class:"VPBadge tip badge"},"专业公众号")]),a("a",{href:"https://fed.chanceyu.com/?q=%5B%E6%9D%A5%E6%BA%90%5D%20%E7%A8%8B%E5%BA%8F%E5%91%98%E6%88%90%E9%95%BF%E6%8C%87%E5%8C%97",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://res.wx.qq.com/a/wx_fed/assets/res/OTE0YTAw.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"程序员成长指北")]),a("p",{class:"desc"},"前端领域专业的微信公众号,发布一些与前端相关的深度技术文章、库、工具和趋势等。"),a("span",{class:"VPBadge tip badge"},"专业公众号")]),a("a",{href:"https://fed.chanceyu.com/?q=%5B%E6%9D%A5%E6%BA%90%5D%20%E5%AD%97%E8%8A%82%E5%89%8D%E7%AB%AF-ByteFE",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://res.wx.qq.com/a/wx_fed/assets/res/OTE0YTAw.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"ByteFE")]),a("p",{class:"desc"},"字节跳动前端团队维护的专业微信公众号,分享技术前沿、文章分享、实践干货等。"),a("span",{class:"VPBadge tip badge"},"专业公众号")]),a("a",{href:"https://fed.chanceyu.com/?q=%5B%E6%9D%A5%E6%BA%90%5D%20%E5%89%8D%E7%AB%AF%E4%BB%8E%E8%BF%9B%E9%98%B6%E5%88%B0%E5%85%A5%E9%99%A2",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://res.wx.qq.com/a/wx_fed/assets/res/OTE0YTAw.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"前端从进阶到入院")]),a("p",{class:"desc"},"前端从进阶到入院,分享最新的前端技术文章、库、工具和趋势"),a("span",{class:"VPBadge tip badge"},"专业公众号")]),a("a",{href:"https://www.zhangxinxu.com/wordpress/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("span",{class:"name"},"张鑫旭-鑫空间-鑫生活")]),a("p",{class:"desc"},"张鑫旭的个人博客,分享最新的前端技术文章、库、工具和趋势等。"),a("span",{class:"VPBadge tip badge"},"网络博客")]),a("a",{href:"https://fed.chanceyu.com/?q=%5B%E6%9D%A5%E6%BA%90%5D%20%E6%B7%98%E7%B3%BB%E5%89%8D%E7%AB%AF%E5%9B%A2%E9%98%9F",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://res.wx.qq.com/a/wx_fed/assets/res/OTE0YTAw.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"淘系前端团队")]),a("p",{class:"desc"},"淘宝前端团队,分享最新的前端技术文章、库、工具和趋势等。"),a("span",{class:"VPBadge tip badge"},"专业公众号")])])],-1)])])}const h=d(l,[["render",n]]);export{v as __pageData,h as default}; diff --git a/assets/fullstack_full-stack-resources.md.CsBwRi3-.lean.js b/assets/fullstack_full-stack-resources.md.CsBwRi3-.lean.js new file mode 100644 index 00000000..114f2500 --- /dev/null +++ b/assets/fullstack_full-stack-resources.md.CsBwRi3-.lean.js @@ -0,0 +1 @@ +import{_ as d,g as i,h as c,U as e,i as a,S as s}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const v=JSON.parse('{"title":"全栈技术资源推荐","description":"摘要总结:本文系统梳理了现代全栈开发的完整技术图谱与演进范式,为开发者提供了一站式的技术选型指南。文章从基石出发,覆盖 Web 核心语言(JS/TS) 与 主流 UI 框架(React/Vue/Svelte),并推荐以 Tailwind CSS 和 shadcn/ui 为代表的现代样式与组件原语。在核心业务逻辑层,深度对比了轻量化状态管理方案(首推 Zustand/Jotai),并重点解析了数据交互的三大现代架构范式:从基础 Axios 到 React Query 状态调度,再到 tRPC 和 GraphQL 带来的全栈类型安全与多端聚合。在工程化与服务端模块,文章全面拥抱 Vite、Rsbuild 等极速构建工具,并剖析了 Next.js/Nuxt 同构元框架与 NestJS 企业级 Node 服务的最佳适用场景。最后,辅以 Vercel 等现代边缘部署平台及丰富的开源社区学习资源。","frontmatter":{"date":"2026-02-06T15:58:53.000Z","title":"全栈技术资源推荐","description":"摘要总结:本文系统梳理了现代全栈开发的完整技术图谱与演进范式,为开发者提供了一站式的技术选型指南。文章从基石出发,覆盖 Web 核心语言(JS/TS) 与 主流 UI 框架(React/Vue/Svelte),并推荐以 Tailwind CSS 和 shadcn/ui 为代表的现代样式与组件原语。在核心业务逻辑层,深度对比了轻量化状态管理方案(首推 Zustand/Jotai),并重点解析了数据交互的三大现代架构范式:从基础 Axios 到 React Query 状态调度,再到 tRPC 和 GraphQL 带来的全栈类型安全与多端聚合。在工程化与服务端模块,文章全面拥抱 Vite、Rsbuild 等极速构建工具,并剖析了 Next.js/Nuxt 同构元框架与 NestJS 企业级 Node 服务的最佳适用场景。最后,辅以 Vercel 等现代边缘部署平台及丰富的开源社区学习资源。","permalink":"/fullstack/full-stack-resources","categories":["资源推荐"],"tags":["资源推荐","全栈"]},"headers":[],"relativePath":"fullstack/full-stack-resources.md","filePath":"01.全栈/90.工具与资源推荐/90.全栈技术资源推荐.md"}'),l={name:"fullstack/full-stack-resources.md"};function n(o,t,r,p,_,m){return c(),i("div",null,[...t[0]||(t[0]=[e("",3),a("div",{class:"container nav-card-container"},[a("div",{class:"nav-card index-auto",style:{"--row-gap":"20px","--column-gap":"20px","--column-min-width":"calc(100% / 4 - 60px)"}},[a("a",{href:"https://developer.mozilla.org/zh-CN/docs/Web/HTML",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://upload.wikimedia.org/wikipedia/commons/thumb/6/61/HTML5_logo_and_wordmark.svg/1200px-HTML5_logo_and_wordmark.svg.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"HTML")]),a("p",{class:"desc"},"HTML (HyperText Markup Language) 是用于创建网页的标准标记语言,用于描述网页的结构和内容。它使用标签来定义文档的不同部分,如标题、段落、图像、链接等。HTML 是构建 Web 页面的基础,也是所有前端开发的起点。"),a("span",{class:"VPBadge tip badge"},"标记语言")]),a("a",{href:"https://developer.mozilla.org/zh-CN/docs/Web/CSS",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://upload.wikimedia.org/wikipedia/commons/thumb/d/d5/CSS3_logo_and_wordmark.svg/1200px-CSS3_logo_and_wordmark.svg.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"CSS")]),a("p",{class:"desc"},"CSS (Cascading Style Sheets) 是用于描述网页样式和布局的样式表语言。它定义了文档的外观,包括字体、颜色、间距、布局等。CSS 与 HTML 结合使用,实现了网页的结构与样式的分离,使得网页设计更加灵活和可维护。"),a("span",{class:"VPBadge tip badge"},"样式表")]),a("a",{href:"https://developer.mozilla.org/zh-CN/docs/Web/JavaScript",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://upload.wikimedia.org/wikipedia/commons/thumb/6/6a/JavaScript-logo.png/1200px-JavaScript-logo.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"JavaScript")]),a("p",{class:"desc"},"JavaScript 是一种动态、弱类型的脚本语言,用于在 Web 浏览器中实现交互性和动态内容。它是 Web 开发的基础,也是前端开发的核心语言。"),a("span",{class:"VPBadge tip badge"},"脚本语言")]),a("a",{href:"https://www.typescriptlang.org/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://upload.wikimedia.org/wikipedia/commons/thumb/4/4c/Typescript_logo_2020.svg/1200px-Typescript_logo_2020.svg.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"TypeScript")]),a("p",{class:"desc"},"TypeScript 是 JavaScript 的一个超集,添加了静态类型检查和其他高级功能,使得代码更加可靠和可维护。它在前端开发中得到广泛应用,尤其在 React 项目中。"),a("span",{class:"VPBadge tip badge"},"静态类型")]),a("a",{href:"https://webkit.org/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://webkit.org/wp-content/themes/webkit/images/webkit.svg",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"webkit")]),a("p",{class:"desc"},"WebKit 是一个开源的浏览器引擎,用于渲染网页内容。它是 Safari 浏览器的引擎,也是 Chrome 浏览器的一部分。WebKit 提供了高性能的网页渲染和交互功能,是构建现代 Web 应用的基础。"),a("span",{class:"VPBadge tip badge"},"浏览器引擎")]),a("a",{href:"https://nodejs.org/zh-cn/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://upload.wikimedia.org/wikipedia/commons/thumb/d/d9/Node.js_logo.svg/1200px-Node.js_logo.svg.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"Node.js")]),a("p",{class:"desc"},"Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时环境,用于在服务器端执行 JavaScript 代码。它允许开发者使用 JavaScript 构建高性能的网络应用程序,如服务器端渲染、实时应用程序和 API 服务。"),a("span",{class:"VPBadge tip badge"},"服务器端")])])],-1),a("h2",{id:"_2-核心-ui-框架",tabindex:"-1"},[s("2. 核心 UI 框架 "),a("a",{class:"header-anchor",href:"#_2-核心-ui-框架","aria-label":"Permalink to “2. 核心 UI 框架”"},"​")],-1),a("div",{class:"container nav-card-container"},[a("div",{class:"nav-card index-auto",style:{"--row-gap":"20px","--column-gap":"20px","--column-min-width":"calc(100% / 4 - 60px)"}},[a("a",{href:"https://react.dev/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://upload.wikimedia.org/wikipedia/commons/thumb/a/a7/React-icon.svg/1200px-React-icon.svg.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"React")]),a("p",{class:"desc"},"React 是 Facebook 开发的用于构建用户界面的声明式 JavaScript 库,采用组件化架构,支持服务器端渲染和客户端交互。它允许开发者设计简单的视图,并根据数据变化高效更新渲染组件。"),a("span",{class:"VPBadge tip badge"},"声明式")]),a("a",{href:"https://vuejs.org/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://upload.wikimedia.org/wikipedia/commons/thumb/9/95/Vue.js_Logo_2.svg/1200px-Vue.js_Logo_2.svg.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"Vue")]),a("p",{class:"desc"},"Vue.js 是一套用于构建用户界面的渐进式框架,采用组件化架构,支持服务器端渲染和客户端交互。强调易用性和高性能。其生态包含官方路由 (Vue Router) 和状态管理库 (Pinia)。"),a("span",{class:"VPBadge tip badge"},"渐进式")]),a("a",{href:"https://svelte.dev/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://upload.wikimedia.org/wikipedia/commons/thumb/1/1b/Svelte_Logo.svg/1200px-Svelte_Logo.svg.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"Svelte")]),a("p",{class:"desc"},"Svelte 是一种全新的构建 Web 应用的方式,作为编译器将声明式组件转换为高效且能直接操作 DOM 的 JavaScript 代码,运行时开销极小。它强调组件化开发,开发者可以直接在 HTML 中编写组件逻辑,无需额外的运行时支持。"),a("span",{class:"VPBadge tip badge"},"编译时")])])],-1),a("h2",{id:"_3-样式与-ui-组件库-styling-component-libraries",tabindex:"-1"},[s("3. 样式与 UI 组件库 (Styling & Component Libraries) "),a("a",{class:"header-anchor",href:"#_3-样式与-ui-组件库-styling-component-libraries","aria-label":"Permalink to “3. 样式与 UI 组件库 (Styling & Component Libraries)”"},"​")],-1),a("div",{class:"container nav-card-container"},[a("div",{class:"nav-card index-auto",style:{"--row-gap":"20px","--column-gap":"20px","--column-min-width":"calc(100% / 4 - 60px)"}},[a("a",{href:"https://tailwindcss.com/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://upload.wikimedia.org/wikipedia/commons/thumb/d/d5/Tailwind_CSS_Logo.svg/1200px-Tailwind_CSS_Logo.svg.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"Tailwind CSS")]),a("p",{class:"desc"},"现代前端首选的实用优先 (Utility-first) CSS 框架,通过类名组合实现样式,无需编写自定义 CSS。"),a("span",{class:"VPBadge tip badge"},"实用优先")]),a("a",{href:"https://daisyui.com/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://img.daisyui.com/images/daisyui/mark.svg",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"Daisy UI")]),a("p",{class:"desc"},"是一个基于 Tailwind CSS 的热门开源UI组件库,通过添加语义化类名(如 btn, card)来解决 Tailwind 冗长的代码问题,能帮开发者用更少的代码、更快地构建出干净、美观、响应式且支持主题自定义的 Web 界面。"),a("span",{class:"VPBadge tip badge"},"tailwind 插件")]),a("a",{href:"https://ui.shadcn.com/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://ui.shadcn.com/favicon.ico",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"shadcn/ui")]),a("p",{class:"desc"},"shadcn/ui 不是一个传统的组件库,而是一种构建你自己的组件库的方法。它提供了一套精心设计、可访问的组件和代码分发平台,兼容你喜欢的框架和 AI 模型。"),a("span",{class:"VPBadge tip badge"},"组件原语")]),a("a",{href:"https://ant.design/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://gw.alipayobjects.com/zos/rmsportal/rlpTLlbMzTNYuZGGCVYM.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"Ant Design")]),a("p",{class:"desc"},"AI 友好的「设计系统」,让美与智能并进,让工作充满「灵感」与「快乐」。"),a("span",{class:"VPBadge tip badge"},"组件库")]),a("a",{href:"https://element-plus.org/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://element-plus.org/images/element-plus-logo-small.svg",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"element-plus")]),a("p",{class:"desc"},"Element Plus 是一个基于 Vue 3 设计的组件库,提供丰富的组件和样式,常用于构建后台管理系统。"),a("span",{class:"VPBadge tip badge"},"组件库")]),a("a",{href:"https://vuetifyjs.com/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://vuetifyjs.com/favicon.ico",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"Vuetify")]),a("p",{class:"desc"},"为 Vue 3 设计的成熟 UI 库,常用于构建后台管理系统,提供丰富的组件和样式。"),a("span",{class:"VPBadge tip badge"},"组件库")])])],-1),a("h2",{id:"_4-路由与状态管理",tabindex:"-1"},[s("4. 路由与状态管理 "),a("a",{class:"header-anchor",href:"#_4-路由与状态管理","aria-label":"Permalink to “4. 路由与状态管理”"},"​")],-1),a("div",{class:"container nav-card-container"},[a("div",{class:"nav-card index-auto",style:{"--row-gap":"20px","--column-gap":"20px","--column-min-width":"calc(100% / 4 - 60px)"}},[a("a",{href:"https://reactrouter.com/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://reactrouter.com/favicon-dark.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"React Router")]),a("p",{class:"desc"},"React Router 是 React 官方的路由管理器,用于构建单页应用 (SPA),提供动态路由匹配、嵌套路由、路由守卫等功能。"),a("span",{class:"VPBadge tip badge"},"路由管理器")]),a("a",{href:"https://router.vuejs.org/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://upload.wikimedia.org/wikipedia/commons/thumb/9/95/Vue.js_Logo_2.svg/1200px-Vue.js_Logo_2.svg.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"Vue Router")]),a("p",{class:"desc"},"Vue.js 官方的路由管理器,用于构建单页应用 (SPA),提供动态路由匹配、嵌套路由、路由守卫等功能。"),a("span",{class:"VPBadge tip badge"},"路由管理器")]),a("a",{href:"https://github.com/pmndrs/zustand",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://avatars.githubusercontent.com/u/45790596?s=48&v=4",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"Zustand")]),a("p",{class:"desc"},"pmndrs 社区出品,是 Redux 的现代化、极简主义精神继承者(自上而下的全局 Store),提供了一种简单的方式来管理全局状态。"),a("span",{class:"VPBadge tip badge"},"状态管理")]),a("a",{href:"https://github.com/pmndrs/jotai",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://avatars.githubusercontent.com/u/45790596?s=48&v=4",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"Jotai")]),a("p",{class:"desc"},"pmndrs 社区出品,是 Recoil 的轻量化、高性能替代者(自下而上的原子化状态)。"),a("span",{class:"VPBadge tip badge"},"状态管理")]),a("a",{href:"https://redux.js.org/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://redux.js.org/img/favicon/favicon.ico",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"Redux")]),a("p",{class:"desc"},"Redux 是一个预测性的状态容器,用于管理应用的全局状态,提供一致的状态更新和可预测的行为。"),a("span",{class:"VPBadge tip badge"},"不再推荐")]),a("a",{href:"https://pinia.vuejs.org/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://pinia.vuejs.org/logo.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"Pinia")]),a("p",{class:"desc"},"Vue.js 官方推荐的状态管理库,基于 Vue 3 Composition API 设计,提供简单、灵活的状态管理解决方案。"),a("span",{class:"VPBadge tip badge"},"状态管理")])])],-1),e("",3),a("div",{class:"container nav-card-container"},[a("div",{class:"nav-card index-auto",style:{"--row-gap":"20px","--column-gap":"20px","--column-min-width":"calc(100% / 4 - 60px)"}},[a("a",{href:"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("span",{class:"name"},"Fetch API")]),a("p",{class:"desc"},"Fetch 是一个基于 Promise 的现代 JavaScript API,用于在浏览器中发起 HTTP 请求(AJAX),是 XMLHttpRequest (XHR) 的更简洁、更强大的替代方案。它允许页面在不重载的情况下从服务器获取数据,支持 GET、POST 等请求方法,并广泛应用于处理网络数据交互。"),a("span",{class:"VPBadge tip badge"},"原生 API")]),a("a",{href:"https://axios-http.com/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://axios-http.com/assets/favicon.ico",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"Axios")]),a("p",{class:"desc"},"Axios 是一个基于 Promise 的 HTTP 请求库,可运行在浏览器和 Node.js 环境中。它支持拦截请求和响应、转换数据、取消请求等功能,是前端开发中常用的 HTTP 请求库。"),a("span",{class:"VPBadge tip badge"},"全能请求库")]),a("a",{href:"https://swr.vercel.app/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://swr.vercel.app/favicon.ico",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"SWR")]),a("p",{class:"desc"},'SWR 是由 Vercel 开发的一个基于 React Hooks 的轻量级数据请求库。它基于 "stale-while-revalidate" 策略,先返回缓存数据,再在后台请求最新数据,保证 UI 快速响应且数据保持更新。特点:极简主义,越轻越好,开箱即用,专注于 HTTP 缓存策略。'),a("span",{class:"VPBadge tip badge"},"按需验证缓存")]),a("a",{href:"https://tanstack.com/query/latest",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://tanstack.com/favicon-32x32.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"React Query")]),a("p",{class:"desc"},"React Query (现更名为 TanStack Query) 是一个功能强大的 React 服务端状态管理库。它专注于处理异步数据的获取、缓存、同步和更新,开箱即用地简化了 API 请求、缓存处理、数据过期更新和加载/错误状态管理。特点:功能主义大而全,不仅是 HTTP,可用于任何异步 Promise 管理。"),a("span",{class:"VPBadge tip badge"},"服务端状态管理")]),a("a",{href:"https://graphql.org/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://graphql.org/_next/static/media/logo-blurred.94c9eff4.webp",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"GraphQL")]),a("p",{class:"desc"},"GraphQL 是一个用于 API 的查询语言、一种描述请求数据方法的语法,通常用于客户端从服务端加载数据,主要是为了解决 REST API 中过度获取和获取不足的问题。"),a("span",{class:"VPBadge tip badge"},"按需声明式查询")]),a("a",{href:"https://trpc.io/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://trpc.io/img/favicon.ico",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"tRPC")]),a("p",{class:"desc"},"tRPC 是基于插件化理念设计的一款支持多语言、高性能的 RPC 开发框架,旨在无需定义专门 API Schema(如 Swagger/GraphQL)的情况下,实现前后端无缝、全栈类型安全的 API 调用。它让前端能像调用本地函数一样调用后端远程函数,大大提升开发效率。"),a("span",{class:"VPBadge tip badge"},"端到端类型安全")])])],-1),e("",9),a("div",{class:"container nav-card-container"},[a("div",{class:"nav-card index-auto",style:{"--row-gap":"20px","--column-gap":"20px","--column-min-width":"calc(100% / 4 - 60px)"}},[a("a",{href:"https://cn.vite.dev/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://cn.vite.dev/logo-without-border.svg",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"Vite")]),a("p",{class:"desc"},"Vite 是一款速度极快的前端构建工具,为下一代 Web 应用程序提供支持,它摒弃了“先打包,再启动”的模式,开启了“原生 ESM”开发的新时代。"),a("span",{class:"VPBadge tip badge"},"极速 ESM 构建")]),a("a",{href:"https://rsbuild.rs/zh/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://assets.rspack.rs/rsbuild/favicon-128x128.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"Rsbuild")]),a("p",{class:"desc"},"Rsbuild 是一个由字节跳动 Web Infra 团队开源、基于 Rust 语言编写的 Rspack 驱动的高性能构建工具。它专注于为 Web 项目提供开箱即用的开发体验,通过内置的高性能工具(如 SWC、Lightning CSS)实现极快的构建速度,并提供类似 Vite/Webpack 的零配置或低配置体验。"),a("span",{class:"VPBadge tip badge"},"Rust 高性能构建")]),a("a",{href:"https://nextjscn.org/docs/app/api-reference/turbopack",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("span",{class:"name"},"Turbopack")]),a("p",{class:"desc"},"Turbopack 是由 Vercel 开发、基于 Rust 编写的高性能增量打包工具,专为 JavaScript 和 TypeScript 优化。它被设计为 Webpack 的继任者,旨在通过优化的机器代码和高度增量计算能力,提供比 Vite 快 10 倍、比 Webpack 快 700 倍的本地开发体验,主要内置于 Next.js。"),a("span",{class:"VPBadge tip badge"},"增量极速打包")]),a("a",{href:"https://webpack.docschina.org/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://webpack.docschina.org/favicon.f326220248556af65f41.ico",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"Webpack")]),a("p",{class:"desc"},"Webpack 是一个现代 JavaScript 应用程序的静态模块打包工具。它在内部构建依赖图,将项目中的各种资源(如 JS、CSS、图片、TypeScript 等)视为模块,并最终打包成浏览器可直接运行的静态文件。通过 Loader 和 Plugin,它能处理复杂的开发需求。"),a("span",{class:"VPBadge tip badge"},"经典模块打包")]),a("a",{href:"https://github.com/features/actions",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://github.com/fluidicon.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"GitHub Actions")]),a("p",{class:"desc"},"GitHub Actions 是 GitHub 推出的持续集成和持续交付 (CI/CD) 平台,旨在帮助开发者自动执行软件开发工作流。它允许在代码仓库中直接定义自动化流程(如构建、测试、部署),支持事件触发(如提交代码),并提供虚拟机环境(Ubuntu、Windows、macOS)运行任务,使开发更高效。"),a("span",{class:"VPBadge tip badge"},"CI/CD 自动化")])])],-1),a("h2",{id:"_7-全栈框架",tabindex:"-1"},[s("7. 全栈框架 "),a("a",{class:"header-anchor",href:"#_7-全栈框架","aria-label":"Permalink to “7. 全栈框架”"},"​")],-1),a("blockquote",null,[a("p",null,[a("strong",null,"同构元框架:Next.js、Nuxt"),s(",现代全栈开发倾向于使用“元框架”,它们模糊了客户端和服务器的界限,提供一体化的开发体验。")]),a("p",null,[a("strong",null,"企业级 Node 服务端框架:NestJS"),s(",一个用于构建高效、可扩展的 Node.js 服务器端应用程序的框架,它采用现代 TypeScript 编写,并完全支持它(同时也支持纯 JavaScript)。它融合了 OOP(面向对象编程)、FP(函数式编程)和 FRP(函数响应式编程)的理念。其设计深受 Angular 启发,内置了依赖注入(DI)、模块化和分层架构等强主张特性,被称为 Node.js 版的 Spring 框架。")])],-1),a("div",{class:"container nav-card-container"},[a("div",{class:"nav-card index-auto",style:{"--row-gap":"20px","--column-gap":"20px","--column-min-width":"calc(100% / 4 - 60px)"}},[a("a",{href:"https://nextjs.org/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://nextjs.org/favicon.ico?favicon.3fc65821.ico",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"Next.js")]),a("p",{class:"desc"},"Next.js 是一个基于 React、Node.js 的全栈 Web 开发框架,由 Vercel 公司维护,专为生产环境设计。它通过内置的服务器端渲染 (SSR)、静态站点生成 (SSG) 和增量静态再生成 (ISR) 技术,解决了传统 React 应用的 SEO 优化差 和首屏加载慢的问题,是目前最受欢迎的 React 应用开发框架之一。"),a("span",{class:"VPBadge tip badge"},"SSR/SSG/ISR")]),a("a",{href:"https://nuxtjs.org/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://nuxt.com/icon.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"Nuxt")]),a("p",{class:"desc"},"是一个基于 Vue.js 的开源、免费的 Web 开发元框架(Meta-framework),专为构建高性能的服务端渲染(SSR)、静态站点生成(SSG)和单页应用(SPA)而设计。它集成了 Vite、Vue 3 和 Nitro 服务端引擎,旨在简化开发流程,提供卓越的 SEO 优化和开发人员体验"),a("span",{class:"VPBadge tip badge"},"SSR/SSG/ISR")]),a("a",{href:"https://nestjs.com/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://nestjs.com/favicon-32x32.a39d94f4.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"NestJS")]),a("p",{class:"desc"},"NestJS 是一个用于构建高效、可扩展的 Node.js 服务器端应用程序的框架,它采用现代 TypeScript 编写,并完全支持它(同时也支持纯 JavaScript)。它融合了 OOP(面向对象编程)、FP(函数式编程)和 FRP(函数响应式编程)的理念。其设计深受 Angular 启发,内置了依赖注入(DI)、模块化和分层架构等强主张特性,被称为 Node.js 版的 Spring 框架."),a("span",{class:"VPBadge tip badge"},"企业级 Node 框架")])])],-1),e("",2),a("div",{class:"container nav-card-container"},[a("div",{class:"nav-card index-auto",style:{"--row-gap":"20px","--column-gap":"20px","--column-min-width":"calc(100% / 4 - 60px)"}},[a("a",{href:"https://vercel.com/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://assets.vercel.com/image/upload/front/favicon/vercel/apple-touch-icon-256x256.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"Vercel")]),a("p",{class:"desc"},"Vercel 是一个现代前端项目的理想部署平台,它零配置、支持自动部署和预览、拥有全球加速节点,广泛用于开源项目、个人作品集、企业网站等。 无论你是用React、Vue、Svelte 还是静态HTML,只需几步就可以将项目上线。"),a("span",{class:"VPBadge tip badge"},"前端边缘托管")]),a("a",{href:"https://www.netlify.com/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://www.netlify.com/favicon/favicon.ico",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"Netlify")]),a("p",{class:"desc"},"与 Vercel 类似,功能更全面:支持更多的框架和静态站点生成器,有表单处理、无服务器函数等功能,免费额度更大、还支持 A/B 测试和分析。Netlify 是一个基于云计算的网站部署和托管平台,专注于为开发者提供便捷的静态网站和Jamstack 应用部署服务。 它的核心优势在于将网站构建、部署、托管以及持续集成/ 持续部署(CI/CD)流程高度集成,极大地简化了开发和运维的复杂程度"),a("span",{class:"VPBadge tip badge"},"Jamstack 平台")]),a("a",{href:"https://pages.github.com/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://github.com/fluidicon.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"GitHub Pages")]),a("p",{class:"desc"},"GitHub Pages 是一个由 GitHub 提供的、免费的静态网站托管服务。它允许用户直接从 GitHub 仓库(Repository)获取 HTML、CSS 和 JavaScript 文件,无需额外配置服务器即可快速部署个人主页、项目文档或博客。"),a("span",{class:"VPBadge tip badge"},"纯静态托管")])])],-1),a("h2",{id:"_9-学习资源与社区-learning-community",tabindex:"-1"},[s("9. 学习资源与社区 (Learning & Community) "),a("a",{class:"header-anchor",href:"#_9-学习资源与社区-learning-community","aria-label":"Permalink to “9. 学习资源与社区 (Learning & Community)”"},"​")],-1),a("div",{class:"container nav-card-container"},[a("div",{class:"nav-card index-auto",style:{"--row-gap":"20px","--column-gap":"20px","--column-min-width":"calc(100% / 4 - 60px)"}},[a("a",{href:"https://javascriptweekly.com/issues",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("span",{class:"name"},"JavaScript Weekly")]),a("p",{class:"desc"},"每周分享最新的 JavaScript 相关技术文章、库、工具和趋势"),a("span",{class:"VPBadge tip badge"},"技术周刊")]),a("a",{href:"https://nodeweekly.com/issues",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("span",{class:"name"},"Node Weekly")]),a("p",{class:"desc"},"每周分享最新的 Node.js 相关技术文章、库、工具和趋势。"),a("span",{class:"VPBadge tip badge"},"技术周刊")]),a("a",{href:"https://www.ruanyifeng.com/blog/weekly/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("span",{class:"name"},"阮一峰网络日志")]),a("p",{class:"desc"},"阮一峰的网络日志,每周五发布,分享最新的前端技术文章、库、工具和趋势等。"),a("span",{class:"VPBadge tip badge"},"技术周刊")]),a("a",{href:"https://fed.chanceyu.com/?q=%5B%E6%9D%A5%E6%BA%90%5D%20%E5%89%8D%E7%AB%AF%E6%97%A9%E8%AF%BB%E8%AF%BE",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://res.wx.qq.com/a/wx_fed/assets/res/OTE0YTAw.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"前端早读课")]),a("p",{class:"desc"},"前端领域专业的微信公众号,发布一些与前端相关的深度技术文章、库、工具和趋势等。"),a("span",{class:"VPBadge tip badge"},"专业公众号")]),a("a",{href:"https://fed.chanceyu.com/?q=%5B%E6%9D%A5%E6%BA%90%5D%20%E5%89%8D%E7%AB%AF%E4%B9%8B%E5%B7%85",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://res.wx.qq.com/a/wx_fed/assets/res/OTE0YTAw.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"前端之巅")]),a("p",{class:"desc"},"前端领域专业的微信公众号,发布一些与前端相关的深度技术文章、库、工具和趋势等。"),a("span",{class:"VPBadge tip badge"},"专业公众号")]),a("a",{href:"https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzIxMzExMjYwOQ==&action=getalbum&album_id=1369610438157369345#wechat_redirect",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://res.wx.qq.com/a/wx_fed/assets/res/OTE0YTAw.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"凹凸实验室")]),a("p",{class:"desc"},"蒲公英·JELLY技术周刊,由京东·凹凸实验室维护整理的技术周刊,从团队专注的研究技术方向出发,深入挖掘业界热点,聚焦技术动态。技术周刊内容分类主要包括如下:基础技术、工程化、跨端框架技术、图形编程、服务端开发、桌面开发、人工智能等。"),a("span",{class:"VPBadge tip badge"},"技术周刊")]),a("a",{href:"https://fed.chanceyu.com/?q=%5B%E6%9D%A5%E6%BA%90%5D%20%E5%89%8D%E7%AB%AF%E5%A4%A7%E5%85%A8",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://res.wx.qq.com/a/wx_fed/assets/res/OTE0YTAw.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"前端大全")]),a("p",{class:"desc"},"前端大全,分享最新的前端技术文章、库、工具和趋势"),a("span",{class:"VPBadge tip badge"},"专业公众号")]),a("a",{href:"https://fed.chanceyu.com/?q=%5B%E6%9D%A5%E6%BA%90%5D%20%E5%89%8D%E7%AB%AF%E4%B9%8B%E7%A5%9E",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://res.wx.qq.com/a/wx_fed/assets/res/OTE0YTAw.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"前端之神")]),a("p",{class:"desc"},"前端之神,分享最新的前端技术文章、库、工具和趋势"),a("span",{class:"VPBadge tip badge"},"专业公众号")]),a("a",{href:"https://fed.chanceyu.com/?q=%5B%E6%9D%A5%E6%BA%90%5D%20%E7%A8%8B%E5%BA%8F%E5%91%98%E6%88%90%E9%95%BF%E6%8C%87%E5%8C%97",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://res.wx.qq.com/a/wx_fed/assets/res/OTE0YTAw.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"程序员成长指北")]),a("p",{class:"desc"},"前端领域专业的微信公众号,发布一些与前端相关的深度技术文章、库、工具和趋势等。"),a("span",{class:"VPBadge tip badge"},"专业公众号")]),a("a",{href:"https://fed.chanceyu.com/?q=%5B%E6%9D%A5%E6%BA%90%5D%20%E5%AD%97%E8%8A%82%E5%89%8D%E7%AB%AF-ByteFE",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://res.wx.qq.com/a/wx_fed/assets/res/OTE0YTAw.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"ByteFE")]),a("p",{class:"desc"},"字节跳动前端团队维护的专业微信公众号,分享技术前沿、文章分享、实践干货等。"),a("span",{class:"VPBadge tip badge"},"专业公众号")]),a("a",{href:"https://fed.chanceyu.com/?q=%5B%E6%9D%A5%E6%BA%90%5D%20%E5%89%8D%E7%AB%AF%E4%BB%8E%E8%BF%9B%E9%98%B6%E5%88%B0%E5%85%A5%E9%99%A2",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://res.wx.qq.com/a/wx_fed/assets/res/OTE0YTAw.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"前端从进阶到入院")]),a("p",{class:"desc"},"前端从进阶到入院,分享最新的前端技术文章、库、工具和趋势"),a("span",{class:"VPBadge tip badge"},"专业公众号")]),a("a",{href:"https://www.zhangxinxu.com/wordpress/",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("span",{class:"name"},"张鑫旭-鑫空间-鑫生活")]),a("p",{class:"desc"},"张鑫旭的个人博客,分享最新的前端技术文章、库、工具和趋势等。"),a("span",{class:"VPBadge tip badge"},"网络博客")]),a("a",{href:"https://fed.chanceyu.com/?q=%5B%E6%9D%A5%E6%BA%90%5D%20%E6%B7%98%E7%B3%BB%E5%89%8D%E7%AB%AF%E5%9B%A2%E9%98%9F",target:"_blank",class:"nav-card__item row-4",style:{"--desc-line-clamp":"2"}},[a("div",{class:"nav-card__item__info"},[a("div",{class:"nav-card__item__img skeleton-image"},[a("img",{src:"https://res.wx.qq.com/a/wx_fed/assets/res/OTE0YTAw.png",class:"no-preview",onload:"this.classList.add('loaded')",onerror:"this.classList.add('loaded')"})]),a("span",{class:"name"},"淘系前端团队")]),a("p",{class:"desc"},"淘宝前端团队,分享最新的前端技术文章、库、工具和趋势等。"),a("span",{class:"VPBadge tip badge"},"专业公众号")])])],-1)])])}const h=d(l,[["render",n]]);export{v as __pageData,h as default}; diff --git "a/assets/01.\345\205\250\346\240\210_40.\345\211\215\347\253\257\345\267\245\347\250\213_03.JAMStack \346\242\263\347\220\206\344\270\216\345\256\236\350\267\265\346\214\207\345\215\227.md.CdkgDOAk.js" b/assets/fullstack_jamstack.md.BHwDJOwo.js similarity index 87% rename from "assets/01.\345\205\250\346\240\210_40.\345\211\215\347\253\257\345\267\245\347\250\213_03.JAMStack \346\242\263\347\220\206\344\270\216\345\256\236\350\267\265\346\214\207\345\215\227.md.CdkgDOAk.js" rename to assets/fullstack_jamstack.md.BHwDJOwo.js index 9b05b72d..8c5d6622 100644 --- "a/assets/01.\345\205\250\346\240\210_40.\345\211\215\347\253\257\345\267\245\347\250\213_03.JAMStack \346\242\263\347\220\206\344\270\216\345\256\236\350\267\265\346\214\207\345\215\227.md.CdkgDOAk.js" +++ b/assets/fullstack_jamstack.md.BHwDJOwo.js @@ -1,4 +1,4 @@ -import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const g=JSON.parse('{"title":"JAMStack 梳理与实践指南","description":"从核心概念、工具链选型(Next.js/Vercel/Supabase/Contentful)到从 0 搭建博客的完整实践,覆盖 JAMStack 适用与不适用场景,帮助判断何时选用该架构。","frontmatter":{"date":"2025-11-14T22:33:39.000Z","title":"JAMStack 梳理与实践指南","aliases":["静态站点生成器","SSG"],"tldr":"预渲染静态页面 + 动态 API,CDN 分发全球,替代传统动态网站的开发部署范式","description":"从核心概念、工具链选型(Next.js/Vercel/Supabase/Contentful)到从 0 搭建博客的完整实践,覆盖 JAMStack 适用与不适用场景,帮助判断何时选用该架构。","permalink":"/fullstack/jamstack","tags":["tutorial","jamstack","frontend-architecture","next.js","static-site-generator"],"categories":["全栈","前端工程"]},"headers":[],"relativePath":"01.全栈/40.前端工程/03.JAMStack 梳理与实践指南.md","filePath":"01.全栈/40.前端工程/03.JAMStack 梳理与实践指南.md"}'),t={name:"01.全栈/40.前端工程/03.JAMStack 梳理与实践指南.md"};function p(h,s,k,e,r,E){return n(),a("div",null,[...s[0]||(s[0]=[l(`

JAMStack 梳理与实践指南

摘要总结:JAMStack 是一种以"预构建静态资产 + 客户端动态交互 + API 数据集成"为核心的 web 开发范式,名称源自 JavaScript、APIs、Markup 三个核心技术缩写。

其核心机制是在构建时将页面预渲染为静态 HTML/CSS/JS,部署至 CDN 供用户就近加载,仅在需要动态数据时通过 JavaScript 调用 API 获取。相较于传统动态网站,JAMStack 在性能、可靠性、扩展性、安全性及运维成本上具有显著优势。

本文梳理了主流构建工具(Gatsby、Next.js、Nuxt.js、11ty)、静态托管平台(Vercel、Netlify、Cloudflare Pages)、API/BaaS 服务(Supabase、Firebase、Auth0)及无头 CMS(Contentful、Sanity、Strapi)的选型策略,并通过 Next.js + Vercel + Supabase + Contentful 的实战案例,完整演示了从项目初始化、内容配置、SSG 预渲染、动态评论集成到自动化部署的全流程。

JAMStack 是近几年前端领域备受关注的架构理念,它并非单一技术,而是一套以“高性能、高可靠、易扩展”为核心的开发范式。其名称源于三个核心技术的缩写:JavaScript(客户端交互逻辑)、APIs(通过第三方/自建接口获取数据)、Markup(预渲染的静态标记,如 HTML)。本质是“预渲染静态页面 + 客户端动态交互 + 接口数据集成”的架构模式,彻底改变了传统动态网站的部署与运行方式。

1. JAMStack 核心概念与核心特性

1.1 核心定义

JAMStack 的核心是“预构建静态资产”——网站部署前,所有页面已通过构建工具(如 Gatsby、Next.js)渲染为静态 HTML、CSS、JS 文件,部署时仅需将这些静态文件托管到 CDN 即可。用户访问时,直接从 CDN 加载静态资源,无需后端服务器动态生成页面,仅在需要时通过 API 调用获取动态数据(如用户信息、实时数据)。

1.2 核心特性(与传统动态网站对比)

特性JAMStack传统动态网站(如 PHP/Java 后端渲染)
页面生成时机构建时预渲染(部署前完成)请求时动态生成(用户访问时后端计算)
服务器依赖无(仅需 CDN 托管静态资源)强依赖后端服务器(需运行应用服务)
性能极高(CDN 全球分发,就近加载)中等(受服务器性能、网络延迟影响)
可靠性极高(静态资源无单点故障)中等(依赖后端服务器稳定性)
扩展性天然支持(CDN 弹性扩容)需配置服务器集群、负载均衡,成本高
安全性高(无服务器端代码,攻击面极小)较低(需防护 SQL 注入、XSS 等攻击)
开发/部署成本低(静态托管免费/低成本,无需运维服务器)高(需服务器运维、扩容、安全防护)

1.3 关键误区澄清

  • ❌ 误区1:JAMStack = 纯静态网站(无动态交互)

    ✅ 正解:JAMStack 支持动态交互,只是“页面骨架”预渲染为静态,动态数据通过 JavaScript 调用 API 实现(如登录、评论、实时数据展示)。

  • ❌ 误区2:JAMStack 只能做博客/文档类网站

    ✅ 正解:可覆盖绝大多数场景,包括电商网站、管理后台、SaaS 应用(如 Netlify、Vercel 本身就是基于 JAMStack 构建的)。

  • ❌ 误区3:JAMStack 不需要后端

    ✅ 正解:需要后端,但后端仅提供 API 接口(无页面渲染逻辑),可使用第三方 BaaS 服务(如 Firebase、Supabase)替代自建后端,降低开发成本。

2. JAMStack 核心技术栈(工具链选型)

JAMStack 的实现依赖“构建工具 + 静态托管 + API/BaaS + 可选的无头 CMS”,以下是主流工具选型推荐:

2.1 核心构建工具(静态站点生成器 SSG)

负责将源码(Markdown、组件、数据)预渲染为静态 HTML,是 JAMStack 的核心工具:

工具核心优势适用场景技术栈依赖
Next.js支持 SSG/SSR/ISR 混合渲染,React 生态,灵活度高复杂应用(电商、SaaS、管理后台)React
GatsbyGraphQL 数据层,插件生态丰富,优化极致博客、文档、营销网站React
Nuxt.jsVue 生态,支持 SSG/SSR,易用性强全场景 Vue 项目Vue
11ty(Eleventy)轻量无依赖,原生支持 Markdown,配置简单小型博客、静态文档原生 JS/模板引擎

2.2 静态资源托管(部署平台)

无需自建服务器,直接托管预构建的静态文件,提供全球 CDN 分发:

  • 主流平台:Vercel(Next.js 官方推荐,免费入门,一键部署)、Netlify(JAMStack 先驱,功能全面,支持表单/无服务器函数)、Cloudflare Pages(免费、CDN 速度快)、GitHub Pages(适合小型项目,免费无广告)。
  • 自建方案:将静态文件上传到阿里云 OSS + CDN、腾讯云 COS + CDN,适合需要私有化部署的场景。

2.3 API/BaaS 服务(后端能力补充)

JAMStack 无自建后端,需通过 API 获取动态能力(如数据库操作、用户认证):

  • 用户认证:Auth0、NextAuth.js(Next.js 专属)、Firebase Auth。
  • 数据库/存储:Supabase(开源 Firebase 替代方案,支持 PostgreSQL + 存储 + 认证)、Firebase Firestore、MongoDB Atlas。
  • 无服务器函数(Serverless Functions):Vercel Functions、Netlify Functions(无需部署独立 API 服务,在静态项目中直接编写 Node.js 函数,处理后端逻辑)。
  • 第三方 API:支付(Stripe)、邮件(SendGrid)、地图(高德/谷歌地图 API)等。

2.4 无头 CMS(内容管理)

适合非技术人员维护内容(如博客文章、产品信息),提供 API 供构建工具拉取数据:

  • 主流选择:Contentful、Sanity、Strapi(开源,可自建)、Ghost(专注博客)。
  • 核心作用:内容与代码分离,编辑者在 CMS 中修改内容后,触发构建工具重新预渲染静态页面(或通过 ISR 增量更新)。

3. JAMStack 项目实践:从 0 到 1 搭建博客网站

以“Next.js + Vercel + Supabase + Contentful”为例,搭建一个支持内容管理、用户评论的博客网站,步骤如下:

3.1 技术栈选型

  • 构建工具:Next.js(支持 SSG 预渲染,方便后续扩展动态功能)。
  • 托管平台:Vercel(一键部署,自动构建,全球 CDN)。
  • 内容管理:Contentful(免费版足够个人博客使用,API 友好)。
  • 动态功能:Supabase(提供 PostgreSQL 数据库,存储用户评论;Auth 功能实现评论登录)。
  • 样式方案:Tailwind CSS(快速开发,响应式设计)。

3.2 具体实施步骤

步骤 1:初始化 Next.js 项目(SSG 模式)

首先创建 Next.js 项目,开启 SSG 预渲染模式(Next.js 13+ 推荐 App Router):

bash
# 1. 创建项目
+import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const g=JSON.parse('{"title":"JAMStack 梳理与实践指南","description":"从核心概念、工具链选型(Next.js/Vercel/Supabase/Contentful)到从 0 搭建博客的完整实践,覆盖 JAMStack 适用与不适用场景,帮助判断何时选用该架构。","frontmatter":{"date":"2025-11-14T22:33:39.000Z","title":"JAMStack 梳理与实践指南","aliases":["静态站点生成器","SSG"],"tldr":"预渲染静态页面 + 动态 API,CDN 分发全球,替代传统动态网站的开发部署范式","description":"从核心概念、工具链选型(Next.js/Vercel/Supabase/Contentful)到从 0 搭建博客的完整实践,覆盖 JAMStack 适用与不适用场景,帮助判断何时选用该架构。","permalink":"/fullstack/jamstack","tags":["tutorial","jamstack","frontend-architecture","next.js","static-site-generator"],"categories":["全栈","前端工程"]},"headers":[],"relativePath":"fullstack/jamstack.md","filePath":"01.全栈/40.前端工程/03.JAMStack 梳理与实践指南.md"}'),t={name:"fullstack/jamstack.md"};function p(h,s,k,e,r,E){return n(),a("div",null,[...s[0]||(s[0]=[l(`

JAMStack 梳理与实践指南

摘要总结:JAMStack 是一种以"预构建静态资产 + 客户端动态交互 + API 数据集成"为核心的 web 开发范式,名称源自 JavaScript、APIs、Markup 三个核心技术缩写。

其核心机制是在构建时将页面预渲染为静态 HTML/CSS/JS,部署至 CDN 供用户就近加载,仅在需要动态数据时通过 JavaScript 调用 API 获取。相较于传统动态网站,JAMStack 在性能、可靠性、扩展性、安全性及运维成本上具有显著优势。

本文梳理了主流构建工具(Gatsby、Next.js、Nuxt.js、11ty)、静态托管平台(Vercel、Netlify、Cloudflare Pages)、API/BaaS 服务(Supabase、Firebase、Auth0)及无头 CMS(Contentful、Sanity、Strapi)的选型策略,并通过 Next.js + Vercel + Supabase + Contentful 的实战案例,完整演示了从项目初始化、内容配置、SSG 预渲染、动态评论集成到自动化部署的全流程。

JAMStack 是近几年前端领域备受关注的架构理念,它并非单一技术,而是一套以“高性能、高可靠、易扩展”为核心的开发范式。其名称源于三个核心技术的缩写:JavaScript(客户端交互逻辑)、APIs(通过第三方/自建接口获取数据)、Markup(预渲染的静态标记,如 HTML)。本质是“预渲染静态页面 + 客户端动态交互 + 接口数据集成”的架构模式,彻底改变了传统动态网站的部署与运行方式。

1. JAMStack 核心概念与核心特性

1.1 核心定义

JAMStack 的核心是“预构建静态资产”——网站部署前,所有页面已通过构建工具(如 Gatsby、Next.js)渲染为静态 HTML、CSS、JS 文件,部署时仅需将这些静态文件托管到 CDN 即可。用户访问时,直接从 CDN 加载静态资源,无需后端服务器动态生成页面,仅在需要时通过 API 调用获取动态数据(如用户信息、实时数据)。

1.2 核心特性(与传统动态网站对比)

特性JAMStack传统动态网站(如 PHP/Java 后端渲染)
页面生成时机构建时预渲染(部署前完成)请求时动态生成(用户访问时后端计算)
服务器依赖无(仅需 CDN 托管静态资源)强依赖后端服务器(需运行应用服务)
性能极高(CDN 全球分发,就近加载)中等(受服务器性能、网络延迟影响)
可靠性极高(静态资源无单点故障)中等(依赖后端服务器稳定性)
扩展性天然支持(CDN 弹性扩容)需配置服务器集群、负载均衡,成本高
安全性高(无服务器端代码,攻击面极小)较低(需防护 SQL 注入、XSS 等攻击)
开发/部署成本低(静态托管免费/低成本,无需运维服务器)高(需服务器运维、扩容、安全防护)

1.3 关键误区澄清

  • ❌ 误区1:JAMStack = 纯静态网站(无动态交互)

    ✅ 正解:JAMStack 支持动态交互,只是“页面骨架”预渲染为静态,动态数据通过 JavaScript 调用 API 实现(如登录、评论、实时数据展示)。

  • ❌ 误区2:JAMStack 只能做博客/文档类网站

    ✅ 正解:可覆盖绝大多数场景,包括电商网站、管理后台、SaaS 应用(如 Netlify、Vercel 本身就是基于 JAMStack 构建的)。

  • ❌ 误区3:JAMStack 不需要后端

    ✅ 正解:需要后端,但后端仅提供 API 接口(无页面渲染逻辑),可使用第三方 BaaS 服务(如 Firebase、Supabase)替代自建后端,降低开发成本。

2. JAMStack 核心技术栈(工具链选型)

JAMStack 的实现依赖“构建工具 + 静态托管 + API/BaaS + 可选的无头 CMS”,以下是主流工具选型推荐:

2.1 核心构建工具(静态站点生成器 SSG)

负责将源码(Markdown、组件、数据)预渲染为静态 HTML,是 JAMStack 的核心工具:

工具核心优势适用场景技术栈依赖
Next.js支持 SSG/SSR/ISR 混合渲染,React 生态,灵活度高复杂应用(电商、SaaS、管理后台)React
GatsbyGraphQL 数据层,插件生态丰富,优化极致博客、文档、营销网站React
Nuxt.jsVue 生态,支持 SSG/SSR,易用性强全场景 Vue 项目Vue
11ty(Eleventy)轻量无依赖,原生支持 Markdown,配置简单小型博客、静态文档原生 JS/模板引擎

2.2 静态资源托管(部署平台)

无需自建服务器,直接托管预构建的静态文件,提供全球 CDN 分发:

  • 主流平台:Vercel(Next.js 官方推荐,免费入门,一键部署)、Netlify(JAMStack 先驱,功能全面,支持表单/无服务器函数)、Cloudflare Pages(免费、CDN 速度快)、GitHub Pages(适合小型项目,免费无广告)。
  • 自建方案:将静态文件上传到阿里云 OSS + CDN、腾讯云 COS + CDN,适合需要私有化部署的场景。

2.3 API/BaaS 服务(后端能力补充)

JAMStack 无自建后端,需通过 API 获取动态能力(如数据库操作、用户认证):

  • 用户认证:Auth0、NextAuth.js(Next.js 专属)、Firebase Auth。
  • 数据库/存储:Supabase(开源 Firebase 替代方案,支持 PostgreSQL + 存储 + 认证)、Firebase Firestore、MongoDB Atlas。
  • 无服务器函数(Serverless Functions):Vercel Functions、Netlify Functions(无需部署独立 API 服务,在静态项目中直接编写 Node.js 函数,处理后端逻辑)。
  • 第三方 API:支付(Stripe)、邮件(SendGrid)、地图(高德/谷歌地图 API)等。

2.4 无头 CMS(内容管理)

适合非技术人员维护内容(如博客文章、产品信息),提供 API 供构建工具拉取数据:

  • 主流选择:Contentful、Sanity、Strapi(开源,可自建)、Ghost(专注博客)。
  • 核心作用:内容与代码分离,编辑者在 CMS 中修改内容后,触发构建工具重新预渲染静态页面(或通过 ISR 增量更新)。

3. JAMStack 项目实践:从 0 到 1 搭建博客网站

以“Next.js + Vercel + Supabase + Contentful”为例,搭建一个支持内容管理、用户评论的博客网站,步骤如下:

3.1 技术栈选型

  • 构建工具:Next.js(支持 SSG 预渲染,方便后续扩展动态功能)。
  • 托管平台:Vercel(一键部署,自动构建,全球 CDN)。
  • 内容管理:Contentful(免费版足够个人博客使用,API 友好)。
  • 动态功能:Supabase(提供 PostgreSQL 数据库,存储用户评论;Auth 功能实现评论登录)。
  • 样式方案:Tailwind CSS(快速开发,响应式设计)。

3.2 具体实施步骤

步骤 1:初始化 Next.js 项目(SSG 模式)

首先创建 Next.js 项目,开启 SSG 预渲染模式(Next.js 13+ 推荐 App Router):

bash
# 1. 创建项目
 npx create-next-app@latest jamstack-blog --typescript --tailwind --eslint
 cd jamstack-blog
 
@@ -186,4 +186,4 @@ import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.CqY1sKvl.j
 git add .
 git commit -m "initial jamstack blog"
 git remote add origin https://github.com/你的用户名/jamstack-blog.git
-git push -u origin main
  • 部署到 Vercel:

    • 访问 Vercel 官网,登录 GitHub 账号,导入上述仓库。
    • Vercel 会自动识别 Next.js 项目,无需额外配置,直接点击“Deploy”。
    • 部署完成后,Vercel 会生成一个免费域名(如 jamstack-blog-xxx.vercel.app),访问即可看到预渲染的博客网站。
  • 配置自动构建(内容更新后自动部署):

    • 在 Contentful 控制台中,添加“Webhook”:触发事件选择“Entry published”,URL 填写 Vercel 项目的“Deploy Hook”(在 Vercel 项目设置 → Git → Deploy Hooks 中生成)。
    • 此后,在 Contentful 中修改/新增文章并发布后,会自动触发 Vercel 重新构建项目,更新静态页面。
  • 3.3 项目扩展:从博客到电商(JAMStack 场景延伸)

    若需将博客扩展为电商网站,仅需补充以下步骤:

    1. 内容管理:在 Contentful 中添加 Product 内容模型(名称、价格、库存、图片等)。
    2. 购物车:使用 localStorage 存储购物车数据(静态场景),或 Supabase 存储用户购物车(登录后同步)。
    3. 支付集成:接入 Stripe API,通过 Vercel Functions 编写支付回调函数(避免前端暴露支付密钥)。
    4. 订单管理:在 Supabase 中创建 orders 表,存储订单信息,通过 API 实现订单查询。

    4. JAMStack 适用场景与不适用场景

    场景类型说明
    适用场景(优先选择 JAMStack)• 博客、文档、营销网站(内容更新不频繁,对性能要求高)。
    • 电商网站(商品页面预渲染,购物车/支付通过 API 实现)。
    • 管理后台(静态页面 + 接口调用,无需后端渲染)。
    • 个人/小型团队项目(降低开发、运维成本)。
    不适用场景(谨慎选择)• 实时性极高的应用(如聊天软件、股票交易平台):虽然可通过 SSE/WebSocket 弥补,但复杂度高于传统架构。
    • 内容频繁更新的网站(如新闻网站,每分钟更新数百篇文章):频繁触发重新构建,可能影响性能(可通过 ISR 增量渲染缓解)。
    • 重度依赖服务器端计算的应用(如复杂数据分析、视频处理):需额外集成 Serverless 函数或后端服务,架构复杂度上升。

    5. 总结

    JAMStack 的核心价值是“用静态资源的高性能 + API 的灵活性,替代传统动态网站的复杂架构”,其优势在于:开发效率高(无需关心后端运维)、性能极致(CDN 全球分发)、成本低(免费托管方案丰富)。

    对于开发者而言,实践 JAMStack 的关键步骤是:

    1. 选型:根据项目复杂度选择构建工具(Next.js 万能,11ty 轻量)。
    2. 开发:用 SSG 预渲染静态页面,动态功能通过 API/BaaS 实现。
    3. 部署:托管到 Vercel/Netlify 等平台,配置自动构建。
    4. 迭代:通过 Webhook 实现内容更新自动部署,通过 ISR 平衡静态性能与实时性。

    无论是个人博客、企业官网还是中小型电商,JAMStack 都是值得尝试的架构方案——它能让你专注于产品本身,而非基础设施的维护。

    `,57)])])}const y=i(t,[["render",p]]);export{g as __pageData,y as default}; +git push -u origin main
  • 部署到 Vercel:

    • 访问 Vercel 官网,登录 GitHub 账号,导入上述仓库。
    • Vercel 会自动识别 Next.js 项目,无需额外配置,直接点击“Deploy”。
    • 部署完成后,Vercel 会生成一个免费域名(如 jamstack-blog-xxx.vercel.app),访问即可看到预渲染的博客网站。
  • 配置自动构建(内容更新后自动部署):

    • 在 Contentful 控制台中,添加“Webhook”:触发事件选择“Entry published”,URL 填写 Vercel 项目的“Deploy Hook”(在 Vercel 项目设置 → Git → Deploy Hooks 中生成)。
    • 此后,在 Contentful 中修改/新增文章并发布后,会自动触发 Vercel 重新构建项目,更新静态页面。
  • 3.3 项目扩展:从博客到电商(JAMStack 场景延伸)

    若需将博客扩展为电商网站,仅需补充以下步骤:

    1. 内容管理:在 Contentful 中添加 Product 内容模型(名称、价格、库存、图片等)。
    2. 购物车:使用 localStorage 存储购物车数据(静态场景),或 Supabase 存储用户购物车(登录后同步)。
    3. 支付集成:接入 Stripe API,通过 Vercel Functions 编写支付回调函数(避免前端暴露支付密钥)。
    4. 订单管理:在 Supabase 中创建 orders 表,存储订单信息,通过 API 实现订单查询。

    4. JAMStack 适用场景与不适用场景

    场景类型说明
    适用场景(优先选择 JAMStack)• 博客、文档、营销网站(内容更新不频繁,对性能要求高)。
    • 电商网站(商品页面预渲染,购物车/支付通过 API 实现)。
    • 管理后台(静态页面 + 接口调用,无需后端渲染)。
    • 个人/小型团队项目(降低开发、运维成本)。
    不适用场景(谨慎选择)• 实时性极高的应用(如聊天软件、股票交易平台):虽然可通过 SSE/WebSocket 弥补,但复杂度高于传统架构。
    • 内容频繁更新的网站(如新闻网站,每分钟更新数百篇文章):频繁触发重新构建,可能影响性能(可通过 ISR 增量渲染缓解)。
    • 重度依赖服务器端计算的应用(如复杂数据分析、视频处理):需额外集成 Serverless 函数或后端服务,架构复杂度上升。

    5. 总结

    JAMStack 的核心价值是“用静态资源的高性能 + API 的灵活性,替代传统动态网站的复杂架构”,其优势在于:开发效率高(无需关心后端运维)、性能极致(CDN 全球分发)、成本低(免费托管方案丰富)。

    对于开发者而言,实践 JAMStack 的关键步骤是:

    1. 选型:根据项目复杂度选择构建工具(Next.js 万能,11ty 轻量)。
    2. 开发:用 SSG 预渲染静态页面,动态功能通过 API/BaaS 实现。
    3. 部署:托管到 Vercel/Netlify 等平台,配置自动构建。
    4. 迭代:通过 Webhook 实现内容更新自动部署,通过 ISR 平衡静态性能与实时性。

    无论是个人博客、企业官网还是中小型电商,JAMStack 都是值得尝试的架构方案——它能让你专注于产品本身,而非基础设施的维护。

    `,56)])])}const y=i(t,[["render",p]]);export{g as __pageData,y as default}; diff --git "a/assets/01.\345\205\250\346\240\210_40.\345\211\215\347\253\257\345\267\245\347\250\213_03.JAMStack \346\242\263\347\220\206\344\270\216\345\256\236\350\267\265\346\214\207\345\215\227.md.CdkgDOAk.lean.js" b/assets/fullstack_jamstack.md.BHwDJOwo.lean.js similarity index 66% rename from "assets/01.\345\205\250\346\240\210_40.\345\211\215\347\253\257\345\267\245\347\250\213_03.JAMStack \346\242\263\347\220\206\344\270\216\345\256\236\350\267\265\346\214\207\345\215\227.md.CdkgDOAk.lean.js" rename to assets/fullstack_jamstack.md.BHwDJOwo.lean.js index f37af692..b71a5f61 100644 --- "a/assets/01.\345\205\250\346\240\210_40.\345\211\215\347\253\257\345\267\245\347\250\213_03.JAMStack \346\242\263\347\220\206\344\270\216\345\256\236\350\267\265\346\214\207\345\215\227.md.CdkgDOAk.lean.js" +++ b/assets/fullstack_jamstack.md.BHwDJOwo.lean.js @@ -1 +1 @@ -import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const g=JSON.parse('{"title":"JAMStack 梳理与实践指南","description":"从核心概念、工具链选型(Next.js/Vercel/Supabase/Contentful)到从 0 搭建博客的完整实践,覆盖 JAMStack 适用与不适用场景,帮助判断何时选用该架构。","frontmatter":{"date":"2025-11-14T22:33:39.000Z","title":"JAMStack 梳理与实践指南","aliases":["静态站点生成器","SSG"],"tldr":"预渲染静态页面 + 动态 API,CDN 分发全球,替代传统动态网站的开发部署范式","description":"从核心概念、工具链选型(Next.js/Vercel/Supabase/Contentful)到从 0 搭建博客的完整实践,覆盖 JAMStack 适用与不适用场景,帮助判断何时选用该架构。","permalink":"/fullstack/jamstack","tags":["tutorial","jamstack","frontend-architecture","next.js","static-site-generator"],"categories":["全栈","前端工程"]},"headers":[],"relativePath":"01.全栈/40.前端工程/03.JAMStack 梳理与实践指南.md","filePath":"01.全栈/40.前端工程/03.JAMStack 梳理与实践指南.md"}'),t={name:"01.全栈/40.前端工程/03.JAMStack 梳理与实践指南.md"};function p(h,s,k,e,r,E){return n(),a("div",null,[...s[0]||(s[0]=[l("",57)])])}const y=i(t,[["render",p]]);export{g as __pageData,y as default}; +import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const g=JSON.parse('{"title":"JAMStack 梳理与实践指南","description":"从核心概念、工具链选型(Next.js/Vercel/Supabase/Contentful)到从 0 搭建博客的完整实践,覆盖 JAMStack 适用与不适用场景,帮助判断何时选用该架构。","frontmatter":{"date":"2025-11-14T22:33:39.000Z","title":"JAMStack 梳理与实践指南","aliases":["静态站点生成器","SSG"],"tldr":"预渲染静态页面 + 动态 API,CDN 分发全球,替代传统动态网站的开发部署范式","description":"从核心概念、工具链选型(Next.js/Vercel/Supabase/Contentful)到从 0 搭建博客的完整实践,覆盖 JAMStack 适用与不适用场景,帮助判断何时选用该架构。","permalink":"/fullstack/jamstack","tags":["tutorial","jamstack","frontend-architecture","next.js","static-site-generator"],"categories":["全栈","前端工程"]},"headers":[],"relativePath":"fullstack/jamstack.md","filePath":"01.全栈/40.前端工程/03.JAMStack 梳理与实践指南.md"}'),t={name:"fullstack/jamstack.md"};function p(h,s,k,e,r,E){return n(),a("div",null,[...s[0]||(s[0]=[l("",56)])])}const y=i(t,[["render",p]]);export{g as __pageData,y as default}; diff --git "a/assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_0.overview.md.CwRE_Svk.js" b/assets/fullstack_module-programming-practice-guide.md.C6GZ5LNW.js similarity index 98% rename from "assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_0.overview.md.CwRE_Svk.js" rename to assets/fullstack_module-programming-practice-guide.md.C6GZ5LNW.js index 3b6f9674..e7344077 100644 --- "a/assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_0.overview.md.CwRE_Svk.js" +++ b/assets/fullstack_module-programming-practice-guide.md.C6GZ5LNW.js @@ -1,4 +1,4 @@ -import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const E=JSON.parse('{"title":"模块化编程实践指南","description":"系统梳理 JavaScript 模块化演进(IIFE→CJS→ESM)、TypeScript 类型增强、分层架构与 DDD 实践。","frontmatter":{"date":"2024-05-18T22:49:57.000Z","title":"模块化编程实践指南","tldr":"从 ES Modules 到大型项目分层架构与工程化实践,构建全栈模块化知识体系。","description":"系统梳理 JavaScript 模块化演进(IIFE→CJS→ESM)、TypeScript 类型增强、分层架构与 DDD 实践。","permalink":"/fullstack/module-programming-practice-guide","tags":["tutorial","ESM","DDD","微前端"],"categories":["全栈","全栈基础素养","模块化编程实践指南"]},"headers":[],"relativePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/0.overview.md","filePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/0.overview.md"}'),p={name:"01.全栈/80.全栈基础素养/20.模块化编程实践指南/0.overview.md"};function h(k,s,t,e,r,F){return n(),a("div",null,[...s[0]||(s[0]=[l(`

    模块化编程实践指南

    作为模块化编程系列的总览文章,本文系统梳理了从基础概念到大型项目架构设计的全栈知识体系。首先介绍分层架构设计,包括前端 React 分层与后端 NestJS 分层,以及 DDD 四层架构。随后探讨微前端架构,解析 iframe、Web Components、single-spa、qiankun、模块联邦等方案的优劣势,并提供模块联邦的完整实战配置。系列文章涵盖 CommonJS、AMD、UMD、ES Modules 等规范演进,以及 TypeScript 模块增强、工程化实践与 Node.js 模块化。

    1. 引言

    模块化编程是现代 JavaScript/TypeScript 开发的核心原则,它通过将复杂系统拆分为独立可复用的模块,降低系统复杂性并提高可维护性与可复用性。因此,我们通过系列文章详细介绍了模块化的基础概念、演进历程、不同规范的深度解析、TypeScript模块化增强、ES Modules 核心语法与实践、模块化编程原则与最佳实践、前端工程化中的模块化、Node.js中的模块化实践、大型项目中的模块化设计、模块化与代码维护以及未来发展趋势。

    前面的系列文章主要有:

    本文将重点介绍大型项目中的模块化设计。

    2.分层架构设计

    分层架构是大型项目中常用的模块化设计模式,它将系统分为多个层次,每层负责特定的功能。

    2.1 前端分层架构

    以 React 技术栈为例,一个典型的前端分层架构通常包含以下核心层次:

    层级说明
    表现层负责 UI 渲染,包含组件与页面,遵循原子设计(Atomic Design)方法论
    业务逻辑层封装业务规则与流程,通过自定义 Hooks 和服务实现
    数据访问层处理与后端的通信,包括 API 请求、数据缓存与同步策略
    状态管理层管理全局与局部状态,确保数据流的可预测性
    路由层定义导航结构与路由守卫,处理权限控制与代码分割
    基础设施层提供横切关注点支持,包括工具函数、常量定义与配置管理

    以下是一个基于 React + TypeScript 的现代项目目录结构示例:

    shell
    src/
    +import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const g=JSON.parse('{"title":"模块化编程实践指南","description":"系统梳理 JavaScript 模块化演进(IIFE→CJS→ESM)、TypeScript 类型增强、分层架构与 DDD 实践。","frontmatter":{"date":"2024-05-18T22:49:57.000Z","title":"模块化编程实践指南","tldr":"从 ES Modules 到大型项目分层架构与工程化实践,构建全栈模块化知识体系。","description":"系统梳理 JavaScript 模块化演进(IIFE→CJS→ESM)、TypeScript 类型增强、分层架构与 DDD 实践。","permalink":"/fullstack/module-programming-practice-guide","tags":["tutorial","ESM","DDD","微前端"],"categories":["全栈","全栈基础素养","模块化编程实践指南"]},"headers":[],"relativePath":"fullstack/module-programming-practice-guide.md","filePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/0.overview.md"}'),p={name:"fullstack/module-programming-practice-guide.md"};function h(k,s,t,e,r,F){return n(),a("div",null,[...s[0]||(s[0]=[l(`

    模块化编程实践指南

    作为模块化编程系列的总览文章,本文系统梳理了从基础概念到大型项目架构设计的全栈知识体系。首先介绍分层架构设计,包括前端 React 分层与后端 NestJS 分层,以及 DDD 四层架构。随后探讨微前端架构,解析 iframe、Web Components、single-spa、qiankun、模块联邦等方案的优劣势,并提供模块联邦的完整实战配置。系列文章涵盖 CommonJS、AMD、UMD、ES Modules 等规范演进,以及 TypeScript 模块增强、工程化实践与 Node.js 模块化。

    1. 引言

    模块化编程是现代 JavaScript/TypeScript 开发的核心原则,它通过将复杂系统拆分为独立可复用的模块,降低系统复杂性并提高可维护性与可复用性。因此,我们通过系列文章详细介绍了模块化的基础概念、演进历程、不同规范的深度解析、TypeScript模块化增强、ES Modules 核心语法与实践、模块化编程原则与最佳实践、前端工程化中的模块化、Node.js中的模块化实践、大型项目中的模块化设计、模块化与代码维护以及未来发展趋势。

    前面的系列文章主要有:

    本文将重点介绍大型项目中的模块化设计。

    2.分层架构设计

    分层架构是大型项目中常用的模块化设计模式,它将系统分为多个层次,每层负责特定的功能。

    2.1 前端分层架构

    以 React 技术栈为例,一个典型的前端分层架构通常包含以下核心层次:

    层级说明
    表现层负责 UI 渲染,包含组件与页面,遵循原子设计(Atomic Design)方法论
    业务逻辑层封装业务规则与流程,通过自定义 Hooks 和服务实现
    数据访问层处理与后端的通信,包括 API 请求、数据缓存与同步策略
    状态管理层管理全局与局部状态,确保数据流的可预测性
    路由层定义导航结构与路由守卫,处理权限控制与代码分割
    基础设施层提供横切关注点支持,包括工具函数、常量定义与配置管理

    以下是一个基于 React + TypeScript 的现代项目目录结构示例:

    shell
    src/
     ├── app/                    # 应用层:应用配置和入口
        ├── App.tsx             # 应用根组件
        ├── Router.tsx          # 路由配置
    @@ -881,4 +881,4 @@ import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.CqY1sKvl.j
        └── docker-compose.yml
     
     ├── package.json                 # 根 package.json
    -└── README.md

    2.4.7 微前端最佳实践

    在实际项目中应用微前端架构,建议遵循以下最佳实践:

    策略要点具体措施
    合理划分子应用边界• 按业务领域划分:用户、商品、订单、支付等
    • 按团队职责划分:每个团队负责一个或多个子应用
    • 避免过度拆分:子应用数量不宜过多,建议 3-10 个
    统一技术规范• 制定统一的编码规范和目录结构
    • 统一 UI 组件库和设计系统
    • 统一 API 接口规范和数据格式
    共享依赖管理• 使用模块联邦的 shared 配置共享基础库
    • 避免版本冲突,统一管理依赖版本
    • 共享的依赖应该保持向后兼容
    样式隔离策略• 使用 CSS Modules 或 CSS-in-JS
    • 使用命名空间前缀(如 product-app__button
    • 使用 Shadow DOM 实现完全隔离
    性能优化• 使用懒加载和预加载策略
    • 合理配置共享依赖的加载时机
    • 监控子应用的加载性能
    错误处理• 子应用加载失败时的降级策略
    • 全局错误捕获和上报
    • 子应用之间的错误隔离

    2.4.8 微前端小结

    微前端架构是前端模块化发展的必然产物,它通过将大型前端应用拆分为多个独立的子应用,解决了以下核心问题:

    1. 复杂度控制:将复杂的单体应用拆分为多个简单的子应用,每个子应用专注于特定的业务领域,降低了系统的整体复杂度。

    2. 团队协作:不同团队可以独立开发和部署自己的子应用,互不影响,大大提高了开发效率和团队协作能力。

    3. 技术演进:子应用可以使用不同的技术栈,支持渐进式升级和技术迁移,避免了技术债务的积累。

    4. 可维护性:每个子应用都是独立的模块,可以独立测试、调试和维护,提高了代码的可维护性。

    5. 扩展性:新增业务功能时,只需添加新的子应用,无需修改现有代码,支持业务的快速扩展。

    然而,微前端架构也带来了一些挑战:

    • 架构复杂度:需要处理子应用的加载、通信、路由等问题
    • 调试困难:跨子应用的调试和问题定位更加复杂
    • 性能开销:多个子应用的加载可能影响首屏性能
    • 团队要求:需要团队具备较强的架构能力和协作能力

    因此,在决定采用微前端架构时,需要权衡项目的规模、团队的规模和技术能力。对于中小型项目,传统的单体应用可能更加合适;对于大型企业级应用,微前端架构则能够带来显著的收益。

    核心建议:微前端不是目的,而是手段。在采用微前端架构之前,务必评估项目的实际需求,避免为了微前端而微前端。只有在真正需要解决复杂度、团队协作和技术演进问题时,微前端架构才能发挥其最大的价值。

    结语

    通过梳理一系列模块化编程的核心概念和实践技巧,我们旨在理解不同模块化规范的特点与适用场景,熟练掌握 ES Modules 的核心语法和最佳实践,并能够在前端和 Node.js 项目中灵活应用模块化设计。

    模块化设计是构建大型、复杂应用的关键,它可以帮助开发者应对不断增长的应用复杂度,提高开发效率和代码质量。随着Web技术的不断发展,模块化设计将继续演进,与新兴技术深度融合,成为构建现代应用的核心原则。

    希望本系列文章能够帮助读者理解模块化编程的重要性,掌握一些模块化设计的原则和实践技巧,构建出更健壮、更可维护的大型应用。

    `,109)])])}const g=i(p,[["render",h]]);export{E as __pageData,g as default}; +└── README.md

    2.4.7 微前端最佳实践

    在实际项目中应用微前端架构,建议遵循以下最佳实践:

    策略要点具体措施
    合理划分子应用边界• 按业务领域划分:用户、商品、订单、支付等
    • 按团队职责划分:每个团队负责一个或多个子应用
    • 避免过度拆分:子应用数量不宜过多,建议 3-10 个
    统一技术规范• 制定统一的编码规范和目录结构
    • 统一 UI 组件库和设计系统
    • 统一 API 接口规范和数据格式
    共享依赖管理• 使用模块联邦的 shared 配置共享基础库
    • 避免版本冲突,统一管理依赖版本
    • 共享的依赖应该保持向后兼容
    样式隔离策略• 使用 CSS Modules 或 CSS-in-JS
    • 使用命名空间前缀(如 product-app__button
    • 使用 Shadow DOM 实现完全隔离
    性能优化• 使用懒加载和预加载策略
    • 合理配置共享依赖的加载时机
    • 监控子应用的加载性能
    错误处理• 子应用加载失败时的降级策略
    • 全局错误捕获和上报
    • 子应用之间的错误隔离

    2.4.8 微前端小结

    微前端架构是前端模块化发展的必然产物,它通过将大型前端应用拆分为多个独立的子应用,解决了以下核心问题:

    1. 复杂度控制:将复杂的单体应用拆分为多个简单的子应用,每个子应用专注于特定的业务领域,降低了系统的整体复杂度。

    2. 团队协作:不同团队可以独立开发和部署自己的子应用,互不影响,大大提高了开发效率和团队协作能力。

    3. 技术演进:子应用可以使用不同的技术栈,支持渐进式升级和技术迁移,避免了技术债务的积累。

    4. 可维护性:每个子应用都是独立的模块,可以独立测试、调试和维护,提高了代码的可维护性。

    5. 扩展性:新增业务功能时,只需添加新的子应用,无需修改现有代码,支持业务的快速扩展。

    然而,微前端架构也带来了一些挑战:

    • 架构复杂度:需要处理子应用的加载、通信、路由等问题
    • 调试困难:跨子应用的调试和问题定位更加复杂
    • 性能开销:多个子应用的加载可能影响首屏性能
    • 团队要求:需要团队具备较强的架构能力和协作能力

    因此,在决定采用微前端架构时,需要权衡项目的规模、团队的规模和技术能力。对于中小型项目,传统的单体应用可能更加合适;对于大型企业级应用,微前端架构则能够带来显著的收益。

    核心建议:微前端不是目的,而是手段。在采用微前端架构之前,务必评估项目的实际需求,避免为了微前端而微前端。只有在真正需要解决复杂度、团队协作和技术演进问题时,微前端架构才能发挥其最大的价值。

    结语

    通过梳理一系列模块化编程的核心概念和实践技巧,我们旨在理解不同模块化规范的特点与适用场景,熟练掌握 ES Modules 的核心语法和最佳实践,并能够在前端和 Node.js 项目中灵活应用模块化设计。

    模块化设计是构建大型、复杂应用的关键,它可以帮助开发者应对不断增长的应用复杂度,提高开发效率和代码质量。随着Web技术的不断发展,模块化设计将继续演进,与新兴技术深度融合,成为构建现代应用的核心原则。

    希望本系列文章能够帮助读者理解模块化编程的重要性,掌握一些模块化设计的原则和实践技巧,构建出更健壮、更可维护的大型应用。

    `,108)])])}const E=i(p,[["render",h]]);export{g as __pageData,E as default}; diff --git "a/assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_0.overview.md.CwRE_Svk.lean.js" b/assets/fullstack_module-programming-practice-guide.md.C6GZ5LNW.lean.js similarity index 57% rename from "assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_0.overview.md.CwRE_Svk.lean.js" rename to assets/fullstack_module-programming-practice-guide.md.C6GZ5LNW.lean.js index f1e8bf43..924226c5 100644 --- "a/assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_0.overview.md.CwRE_Svk.lean.js" +++ b/assets/fullstack_module-programming-practice-guide.md.C6GZ5LNW.lean.js @@ -1 +1 @@ -import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const E=JSON.parse('{"title":"模块化编程实践指南","description":"系统梳理 JavaScript 模块化演进(IIFE→CJS→ESM)、TypeScript 类型增强、分层架构与 DDD 实践。","frontmatter":{"date":"2024-05-18T22:49:57.000Z","title":"模块化编程实践指南","tldr":"从 ES Modules 到大型项目分层架构与工程化实践,构建全栈模块化知识体系。","description":"系统梳理 JavaScript 模块化演进(IIFE→CJS→ESM)、TypeScript 类型增强、分层架构与 DDD 实践。","permalink":"/fullstack/module-programming-practice-guide","tags":["tutorial","ESM","DDD","微前端"],"categories":["全栈","全栈基础素养","模块化编程实践指南"]},"headers":[],"relativePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/0.overview.md","filePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/0.overview.md"}'),p={name:"01.全栈/80.全栈基础素养/20.模块化编程实践指南/0.overview.md"};function h(k,s,t,e,r,F){return n(),a("div",null,[...s[0]||(s[0]=[l("",109)])])}const g=i(p,[["render",h]]);export{E as __pageData,g as default}; +import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const g=JSON.parse('{"title":"模块化编程实践指南","description":"系统梳理 JavaScript 模块化演进(IIFE→CJS→ESM)、TypeScript 类型增强、分层架构与 DDD 实践。","frontmatter":{"date":"2024-05-18T22:49:57.000Z","title":"模块化编程实践指南","tldr":"从 ES Modules 到大型项目分层架构与工程化实践,构建全栈模块化知识体系。","description":"系统梳理 JavaScript 模块化演进(IIFE→CJS→ESM)、TypeScript 类型增强、分层架构与 DDD 实践。","permalink":"/fullstack/module-programming-practice-guide","tags":["tutorial","ESM","DDD","微前端"],"categories":["全栈","全栈基础素养","模块化编程实践指南"]},"headers":[],"relativePath":"fullstack/module-programming-practice-guide.md","filePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/0.overview.md"}'),p={name:"fullstack/module-programming-practice-guide.md"};function h(k,s,t,e,r,F){return n(),a("div",null,[...s[0]||(s[0]=[l("",108)])])}const E=i(p,[["render",h]]);export{g as __pageData,E as default}; diff --git "a/assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_5.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\216\237\345\210\231\344\270\216\346\234\200\344\275\263\345\256\236\350\267\265.md.LTILHYsI.js" b/assets/fullstack_module-programming-principles-best-practices.md.B-Jmi3dC.js similarity index 92% rename from "assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_5.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\216\237\345\210\231\344\270\216\346\234\200\344\275\263\345\256\236\350\267\265.md.LTILHYsI.js" rename to assets/fullstack_module-programming-principles-best-practices.md.B-Jmi3dC.js index f8f19d48..2d5539eb 100644 --- "a/assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_5.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\216\237\345\210\231\344\270\216\346\234\200\344\275\263\345\256\236\350\267\265.md.LTILHYsI.js" +++ b/assets/fullstack_module-programming-principles-best-practices.md.B-Jmi3dC.js @@ -1,4 +1,4 @@ -import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const g=JSON.parse('{"title":"模块化编程原则梳理与总结","description":"系统梳理模块化编程的六大核心原则:单一职责、高内聚低耦合、粒度设计、命名规范及模块版本管理,附详细的工程实践建议与避坑指南。","frontmatter":{"date":"2024-05-17T22:30:50.000Z","title":"模块化编程原则梳理与总结","tldr":"掌握高内聚低耦合原则:模块化编程的设计准则与粒度控制。","description":"系统梳理模块化编程的六大核心原则:单一职责、高内聚低耦合、粒度设计、命名规范及模块版本管理,附详细的工程实践建议与避坑指南。","permalink":"/fullstack/module-programming-principles-best-practices","abstract":"如果说掌握模块化语法是术,那么理解其背后的设计原则就是道。单一职责原则强调模块只应有一个被改变的原因,避免 God Object 反模式。高内聚低耦合是衡量模块质量的终极标准——模块内部元素联系紧密,模块之间依赖关系尽可能简单。粒度设计要求单个模块保持在 100-500 行之间,功能能用一句话清晰描述,出现多分支复杂逻辑时通常是拆分信号。命名规范统一团队沟通语境(kebab-case 文件名、camelCase 方法名、PascalCase 类名)。模块版本管理遵循 SemVer 语义化版本,为公共模块的维护者与使用者建立契约。强调清晰的模块边界是 AI 辅助编程时代 AI 准确理解代码的前提。","tags":["concept","solid-principles","code-organization","best-practices","naming-conventions"],"categories":["全栈","全栈基础素养","模块化编程实践指南"]},"headers":[],"relativePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/5.模块化编程原则与最佳实践.md","filePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/5.模块化编程原则与最佳实践.md"}'),p={name:"01.全栈/80.全栈基础素养/20.模块化编程实践指南/5.模块化编程原则与最佳实践.md"};function h(e,s,t,k,r,d){return n(),a("div",null,[...s[0]||(s[0]=[l(`

    模块化编程原则梳理与总结

    如果说掌握模块化语法是“术”,那么理解其背后的设计原则就是“道”。在大型前端工程中,乱用模块化往往比不用更糟糕。为了构建出既健壮又易于扩展的系统,我们需要遵循一套行之有效的工程准则。

    1. 单一职责原则

    核心思想:一个模块应当有且只有一个被改变的原因。

    模块不应成为功能的“杂货铺”。当一个模块承担了太多不相关的业务逻辑时,它的复杂度会呈指数级上升,任何微小的改动都可能引发意想不到的连锁反应。

    代码演示:

    javascript
    // ✅ 推荐:职责拆分明确
    +import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const g=JSON.parse('{"title":"模块化编程原则梳理与总结","description":"系统梳理模块化编程的六大核心原则:单一职责、高内聚低耦合、粒度设计、命名规范及模块版本管理,附详细的工程实践建议与避坑指南。","frontmatter":{"date":"2024-05-17T22:30:50.000Z","title":"模块化编程原则梳理与总结","tldr":"掌握高内聚低耦合原则:模块化编程的设计准则与粒度控制。","description":"系统梳理模块化编程的六大核心原则:单一职责、高内聚低耦合、粒度设计、命名规范及模块版本管理,附详细的工程实践建议与避坑指南。","permalink":"/fullstack/module-programming-principles-best-practices","abstract":"如果说掌握模块化语法是术,那么理解其背后的设计原则就是道。单一职责原则强调模块只应有一个被改变的原因,避免 God Object 反模式。高内聚低耦合是衡量模块质量的终极标准——模块内部元素联系紧密,模块之间依赖关系尽可能简单。粒度设计要求单个模块保持在 100-500 行之间,功能能用一句话清晰描述,出现多分支复杂逻辑时通常是拆分信号。命名规范统一团队沟通语境(kebab-case 文件名、camelCase 方法名、PascalCase 类名)。模块版本管理遵循 SemVer 语义化版本,为公共模块的维护者与使用者建立契约。强调清晰的模块边界是 AI 辅助编程时代 AI 准确理解代码的前提。","tags":["concept","solid-principles","code-organization","best-practices","naming-conventions"],"categories":["全栈","全栈基础素养","模块化编程实践指南"]},"headers":[],"relativePath":"fullstack/module-programming-principles-best-practices.md","filePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/5.模块化编程原则与最佳实践.md"}'),p={name:"fullstack/module-programming-principles-best-practices.md"};function h(e,s,t,k,r,d){return n(),a("div",null,[...s[0]||(s[0]=[l(`

    模块化编程原则梳理与总结

    如果说掌握模块化语法是“术”,那么理解其背后的设计原则就是“道”。在大型前端工程中,乱用模块化往往比不用更糟糕。为了构建出既健壮又易于扩展的系统,我们需要遵循一套行之有效的工程准则。

    1. 单一职责原则

    核心思想:一个模块应当有且只有一个被改变的原因。

    模块不应成为功能的“杂货铺”。当一个模块承担了太多不相关的业务逻辑时,它的复杂度会呈指数级上升,任何微小的改动都可能引发意想不到的连锁反应。

    代码演示:

    javascript
    // ✅ 推荐:职责拆分明确
     // user-service.js - 仅处理用户数据的 CRUD
     export const getUser = async (id) => { /* ... */ };
     
    @@ -64,4 +64,4 @@ import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.CqY1sKvl.j
     
     ## 1.0.0 (2022-11-01)
     - 初始版本发布
    -- 支持 \`createUser\`\`getUser\` 方法

    6. 结语:构建可预测的秩序

    模块化编程的终点,不是将代码拆得零散,而是要在混沌的业务逻辑之上,构建出一套清晰、稳定、可预测的秩序。

    从单一职责的约束,到高内聚低耦合的权衡,再到对循环依赖的警惕,这些原则本质上都在做同一件事:降低心智负担。优秀的模块化设计应当让开发者在进入代码库时,能够迅速建立“地图感”——知道每一块拼图的位置,也清楚拿掉一块拼图后会产生的波纹。

    在 AI 辅助编程日益普及的今天,清晰的模块边界更是 AI 能够准确理解并生成高质量代码的前提。愿你不仅能写出跑得通的模块,更能设计出经得起时间推敲的工程结构。

    `,31)])])}const c=i(p,[["render",h]]);export{g as __pageData,c as default}; +- 支持 \`createUser\`\`getUser\` 方法

    6. 结语:构建可预测的秩序

    模块化编程的终点,不是将代码拆得零散,而是要在混沌的业务逻辑之上,构建出一套清晰、稳定、可预测的秩序。

    从单一职责的约束,到高内聚低耦合的权衡,再到对循环依赖的警惕,这些原则本质上都在做同一件事:降低心智负担。优秀的模块化设计应当让开发者在进入代码库时,能够迅速建立“地图感”——知道每一块拼图的位置,也清楚拿掉一块拼图后会产生的波纹。

    在 AI 辅助编程日益普及的今天,清晰的模块边界更是 AI 能够准确理解并生成高质量代码的前提。愿你不仅能写出跑得通的模块,更能设计出经得起时间推敲的工程结构。

    `,30)])])}const c=i(p,[["render",h]]);export{g as __pageData,c as default}; diff --git "a/assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_5.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\216\237\345\210\231\344\270\216\346\234\200\344\275\263\345\256\236\350\267\265.md.LTILHYsI.lean.js" b/assets/fullstack_module-programming-principles-best-practices.md.B-Jmi3dC.lean.js similarity index 75% rename from "assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_5.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\216\237\345\210\231\344\270\216\346\234\200\344\275\263\345\256\236\350\267\265.md.LTILHYsI.lean.js" rename to assets/fullstack_module-programming-principles-best-practices.md.B-Jmi3dC.lean.js index a647c0a5..6a721888 100644 --- "a/assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_5.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\216\237\345\210\231\344\270\216\346\234\200\344\275\263\345\256\236\350\267\265.md.LTILHYsI.lean.js" +++ b/assets/fullstack_module-programming-principles-best-practices.md.B-Jmi3dC.lean.js @@ -1 +1 @@ -import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const g=JSON.parse('{"title":"模块化编程原则梳理与总结","description":"系统梳理模块化编程的六大核心原则:单一职责、高内聚低耦合、粒度设计、命名规范及模块版本管理,附详细的工程实践建议与避坑指南。","frontmatter":{"date":"2024-05-17T22:30:50.000Z","title":"模块化编程原则梳理与总结","tldr":"掌握高内聚低耦合原则:模块化编程的设计准则与粒度控制。","description":"系统梳理模块化编程的六大核心原则:单一职责、高内聚低耦合、粒度设计、命名规范及模块版本管理,附详细的工程实践建议与避坑指南。","permalink":"/fullstack/module-programming-principles-best-practices","abstract":"如果说掌握模块化语法是术,那么理解其背后的设计原则就是道。单一职责原则强调模块只应有一个被改变的原因,避免 God Object 反模式。高内聚低耦合是衡量模块质量的终极标准——模块内部元素联系紧密,模块之间依赖关系尽可能简单。粒度设计要求单个模块保持在 100-500 行之间,功能能用一句话清晰描述,出现多分支复杂逻辑时通常是拆分信号。命名规范统一团队沟通语境(kebab-case 文件名、camelCase 方法名、PascalCase 类名)。模块版本管理遵循 SemVer 语义化版本,为公共模块的维护者与使用者建立契约。强调清晰的模块边界是 AI 辅助编程时代 AI 准确理解代码的前提。","tags":["concept","solid-principles","code-organization","best-practices","naming-conventions"],"categories":["全栈","全栈基础素养","模块化编程实践指南"]},"headers":[],"relativePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/5.模块化编程原则与最佳实践.md","filePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/5.模块化编程原则与最佳实践.md"}'),p={name:"01.全栈/80.全栈基础素养/20.模块化编程实践指南/5.模块化编程原则与最佳实践.md"};function h(e,s,t,k,r,d){return n(),a("div",null,[...s[0]||(s[0]=[l("",31)])])}const c=i(p,[["render",h]]);export{g as __pageData,c as default}; +import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const g=JSON.parse('{"title":"模块化编程原则梳理与总结","description":"系统梳理模块化编程的六大核心原则:单一职责、高内聚低耦合、粒度设计、命名规范及模块版本管理,附详细的工程实践建议与避坑指南。","frontmatter":{"date":"2024-05-17T22:30:50.000Z","title":"模块化编程原则梳理与总结","tldr":"掌握高内聚低耦合原则:模块化编程的设计准则与粒度控制。","description":"系统梳理模块化编程的六大核心原则:单一职责、高内聚低耦合、粒度设计、命名规范及模块版本管理,附详细的工程实践建议与避坑指南。","permalink":"/fullstack/module-programming-principles-best-practices","abstract":"如果说掌握模块化语法是术,那么理解其背后的设计原则就是道。单一职责原则强调模块只应有一个被改变的原因,避免 God Object 反模式。高内聚低耦合是衡量模块质量的终极标准——模块内部元素联系紧密,模块之间依赖关系尽可能简单。粒度设计要求单个模块保持在 100-500 行之间,功能能用一句话清晰描述,出现多分支复杂逻辑时通常是拆分信号。命名规范统一团队沟通语境(kebab-case 文件名、camelCase 方法名、PascalCase 类名)。模块版本管理遵循 SemVer 语义化版本,为公共模块的维护者与使用者建立契约。强调清晰的模块边界是 AI 辅助编程时代 AI 准确理解代码的前提。","tags":["concept","solid-principles","code-organization","best-practices","naming-conventions"],"categories":["全栈","全栈基础素养","模块化编程实践指南"]},"headers":[],"relativePath":"fullstack/module-programming-principles-best-practices.md","filePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/5.模块化编程原则与最佳实践.md"}'),p={name:"fullstack/module-programming-principles-best-practices.md"};function h(e,s,t,k,r,d){return n(),a("div",null,[...s[0]||(s[0]=[l("",30)])])}const c=i(p,[["render",h]]);export{g as __pageData,c as default}; diff --git "a/assets/01.\345\205\250\346\240\210_60.\347\275\221\347\273\234\344\270\216\351\200\232\344\277\241_03.\351\200\200\351\201\277\350\275\256\350\257\242\344\270\216\351\225\277\350\275\256\350\257\242\347\232\204\345\216\237\347\220\206\343\200\201\345\256\236\346\210\230\344\270\216\351\200\211\345\236\213\345\206\263\347\255\226.md.C2A_-RUG.js" b/assets/fullstack_networking-polling-optimization.md.COzdcUPj.js similarity index 89% rename from "assets/01.\345\205\250\346\240\210_60.\347\275\221\347\273\234\344\270\216\351\200\232\344\277\241_03.\351\200\200\351\201\277\350\275\256\350\257\242\344\270\216\351\225\277\350\275\256\350\257\242\347\232\204\345\216\237\347\220\206\343\200\201\345\256\236\346\210\230\344\270\216\351\200\211\345\236\213\345\206\263\347\255\226.md.C2A_-RUG.js" rename to assets/fullstack_networking-polling-optimization.md.COzdcUPj.js index 6ca85de3..75e25d20 100644 --- "a/assets/01.\345\205\250\346\240\210_60.\347\275\221\347\273\234\344\270\216\351\200\232\344\277\241_03.\351\200\200\351\201\277\350\275\256\350\257\242\344\270\216\351\225\277\350\275\256\350\257\242\347\232\204\345\216\237\347\220\206\343\200\201\345\256\236\346\210\230\344\270\216\351\200\211\345\236\213\345\206\263\347\255\226.md.C2A_-RUG.js" +++ b/assets/fullstack_networking-polling-optimization.md.COzdcUPj.js @@ -1,4 +1,4 @@ -import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const g=JSON.parse('{"title":"HTTP 轮询优化指南:退避轮询与长轮询的原理、实战与选型决策","description":"深入剖析退避轮询与长轮询的核心机制,提供 TypeScript/NestJS 实战代码,并构建技术选型决策树与适用场景速查。","frontmatter":{"date":"2026-02-25T22:10:48.000Z","title":"HTTP 轮询优化指南:退避轮询与长轮询的原理、实战与选型决策","tldr":"详解退避轮询与长轮询的实现原理,提供 HTTP 轮询优化策略与选型决策树。","description":"深入剖析退避轮询与长轮询的核心机制,提供 TypeScript/NestJS 实战代码,并构建技术选型决策树与适用场景速查。","tags":["HTTP 轮询","退避轮询","长轮询"],"categories":["全栈","网络与通信"],"permalink":"/fullstack/networking-polling-optimization"},"headers":[],"relativePath":"01.全栈/60.网络与通信/03.退避轮询与长轮询的原理、实战与选型决策.md","filePath":"01.全栈/60.网络与通信/03.退避轮询与长轮询的原理、实战与选型决策.md"}'),p={name:"01.全栈/60.网络与通信/03.退避轮询与长轮询的原理、实战与选型决策.md"};function h(k,s,t,e,r,E){return n(),a("div",null,[...s[0]||(s[0]=[l(`

    HTTP 轮询优化指南:退避轮询与长轮询的原理、实战与选型决策

    摘要总结: 针对传统固定频率轮询的服务器资源浪费问题,系统分析退避轮询与长轮询两种优化策略的核心原理与运行机制。通过 TypeScript 客户端与 NestJS 服务端的完整实现示例,对比两种方案在实时性、资源占用、复杂度等维度的差异。构建包含任务耗时、并发规模、基础设施约束的技术选型决策树,并提出退避+长轮询级联、按业务分级等混合策略建议。结论表明,低实时要求高并发场景选退避轮询,高实时要求中低并发场景选长轮询,复杂场景可两者结合。

    1. 引言

    在现代 Web 开发中,WebSocket 和 Server-Sent Events (SSE) 常常被视为实时通信的银弹。然而,HTTP 轮询(Polling)作为最朴素的实时通信方案,非但没有退出历史舞台,反而在特定的复杂业务场景中大放异彩。

    📖 如果你对 HTTP 轮询在整个 Web 通信协议体系中的定位尚不清晰,推荐先阅读 Web 通信协议全景:从 HTTP 到 WebSocket 的技术选型指南,了解轮询与短连接、长连接、WebSocket、SSE 等方案的演进关系与适用边界,再结合本文深入实践。

    在当前众多顶级的 AI AIGC 应用(如 Midjourney 类的第三方集成应用、Stable Diffusion 商业平台、长视频生成等)中,任务处理往往需要数十秒甚至数分钟。在面对海量并发和复杂的网关负载均衡时,HTTP 轮询因其无状态、易扩展、断连恢复成本极低的特性,成为了架构师经过深思熟虑后的首选方案。

    然而,传统的固定频率轮询(如每秒请求一次)对服务器极不友好。为了兼顾用户体验与服务器的稳定性,本文将深入探讨两种常用的 HTTP 轮询优化策略:退避轮询(Backoff Polling) 与 长轮询(Long Polling)。

    2. 退避轮询

    退避轮询是一种在计算机网络和分布式系统中常用的网络请求或重试策略。它的核心思想是:当服务端任务未完成时,客户端下一次查询的等待时间并非固定,而是随着查询次数的增加而递增。

    2.1 为什么需要退避轮询?

    在服务器过载、网络故障或由于短时间高频请求触发限流(如 HTTP 429 错误)时,如果客户端仍以固定高频重试,会引发严重的灾难:

    • 惊群效应:大量客户端同时高频重试,导致服务器压力倍增,进而彻底崩溃。
    • 资源浪费:服务端在执行耗时任务(如 AI 渲染)时,初期的频繁查询注定是无效的,这不仅浪费了服务器带宽,也消耗了客户端的设备电量与性能。

    2.2 核心机制与运行规则

    退避轮询通过不断拉大两次请求之间的延迟时间,巧妙地实现了请求分流。其典型规则如下:

    • 服务端:保持“极轻”的逻辑,收到请求后立刻查询状态并返回(完成、失败或处理中),不做任何阻塞。

    • 客户端:收到“处理中”状态时,按策略进入等待。例如:

      • 第一次等待:2 秒

      • 第二次等待:5 秒

      • 第三次等待:10 秒

      • 第 N 次等待:最大上限(如 15 秒,避免等待过久导致体验断层)

    设置最大值是为了避免等待时间变得不可接受(如几个小时),通常会设置一个最大等待时间(Max Delay)和最大重试次数。

    2.3 客户端实现示例

    在客户端中,我们可以通过简单的 while 循环和 setTimeout 挂起机制来实现:

    typescript
    
    +import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const g=JSON.parse('{"title":"HTTP 轮询优化指南:退避轮询与长轮询的原理、实战与选型决策","description":"深入剖析退避轮询与长轮询的核心机制,提供 TypeScript/NestJS 实战代码,并构建技术选型决策树与适用场景速查。","frontmatter":{"date":"2026-02-25T22:10:48.000Z","title":"HTTP 轮询优化指南:退避轮询与长轮询的原理、实战与选型决策","tldr":"详解退避轮询与长轮询的实现原理,提供 HTTP 轮询优化策略与选型决策树。","description":"深入剖析退避轮询与长轮询的核心机制,提供 TypeScript/NestJS 实战代码,并构建技术选型决策树与适用场景速查。","tags":["HTTP 轮询","退避轮询","长轮询"],"categories":["全栈","网络与通信"],"permalink":"/fullstack/networking-polling-optimization"},"headers":[],"relativePath":"fullstack/networking-polling-optimization.md","filePath":"01.全栈/60.网络与通信/03.退避轮询与长轮询的原理、实战与选型决策.md"}'),p={name:"fullstack/networking-polling-optimization.md"};function h(k,s,t,e,r,E){return n(),a("div",null,[...s[0]||(s[0]=[l(`

    HTTP 轮询优化指南:退避轮询与长轮询的原理、实战与选型决策

    摘要总结: 针对传统固定频率轮询的服务器资源浪费问题,系统分析退避轮询与长轮询两种优化策略的核心原理与运行机制。通过 TypeScript 客户端与 NestJS 服务端的完整实现示例,对比两种方案在实时性、资源占用、复杂度等维度的差异。构建包含任务耗时、并发规模、基础设施约束的技术选型决策树,并提出退避+长轮询级联、按业务分级等混合策略建议。结论表明,低实时要求高并发场景选退避轮询,高实时要求中低并发场景选长轮询,复杂场景可两者结合。

    1. 引言

    在现代 Web 开发中,WebSocket 和 Server-Sent Events (SSE) 常常被视为实时通信的银弹。然而,HTTP 轮询(Polling)作为最朴素的实时通信方案,非但没有退出历史舞台,反而在特定的复杂业务场景中大放异彩。

    📖 如果你对 HTTP 轮询在整个 Web 通信协议体系中的定位尚不清晰,推荐先阅读 Web 通信协议全景:从 HTTP 到 WebSocket 的技术选型指南,了解轮询与短连接、长连接、WebSocket、SSE 等方案的演进关系与适用边界,再结合本文深入实践。

    在当前众多顶级的 AI AIGC 应用(如 Midjourney 类的第三方集成应用、Stable Diffusion 商业平台、长视频生成等)中,任务处理往往需要数十秒甚至数分钟。在面对海量并发和复杂的网关负载均衡时,HTTP 轮询因其无状态、易扩展、断连恢复成本极低的特性,成为了架构师经过深思熟虑后的首选方案。

    然而,传统的固定频率轮询(如每秒请求一次)对服务器极不友好。为了兼顾用户体验与服务器的稳定性,本文将深入探讨两种常用的 HTTP 轮询优化策略:退避轮询(Backoff Polling) 与 长轮询(Long Polling)。

    2. 退避轮询

    退避轮询是一种在计算机网络和分布式系统中常用的网络请求或重试策略。它的核心思想是:当服务端任务未完成时,客户端下一次查询的等待时间并非固定,而是随着查询次数的增加而递增。

    2.1 为什么需要退避轮询?

    在服务器过载、网络故障或由于短时间高频请求触发限流(如 HTTP 429 错误)时,如果客户端仍以固定高频重试,会引发严重的灾难:

    • 惊群效应:大量客户端同时高频重试,导致服务器压力倍增,进而彻底崩溃。
    • 资源浪费:服务端在执行耗时任务(如 AI 渲染)时,初期的频繁查询注定是无效的,这不仅浪费了服务器带宽,也消耗了客户端的设备电量与性能。

    2.2 核心机制与运行规则

    退避轮询通过不断拉大两次请求之间的延迟时间,巧妙地实现了请求分流。其典型规则如下:

    • 服务端:保持“极轻”的逻辑,收到请求后立刻查询状态并返回(完成、失败或处理中),不做任何阻塞。

    • 客户端:收到“处理中”状态时,按策略进入等待。例如:

      • 第一次等待:2 秒

      • 第二次等待:5 秒

      • 第三次等待:10 秒

      • 第 N 次等待:最大上限(如 15 秒,避免等待过久导致体验断层)

    设置最大值是为了避免等待时间变得不可接受(如几个小时),通常会设置一个最大等待时间(Max Delay)和最大重试次数。

    2.3 客户端实现示例

    在客户端中,我们可以通过简单的 while 循环和 setTimeout 挂起机制来实现:

    typescript
    
     interface TaskResponse {
       status: 'processing' | 'completed' | 'failed';
       result?: string;
    @@ -143,4 +143,4 @@ import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.CqY1sKvl.j
     
     └─ 是否有事件驱动基础设施(Redis/消息队列)?
         ├─ 是 → 长轮询可发挥最佳性能
    -    └─ 否 → 退避轮询实现更简单,无需额外组件

    4.2 适用场景速查

    优先选择退避轮询

    • 任务耗时较长(数十秒到分钟级),对实时性要求不高
    • 海量并发场景,服务器资源敏感
    • 无需 WebSocket/SSE 环境(如某些 API 第三方集成)
    • 需要简洁的客户端实现,不希望引入长连接管理复杂度
    • 示例:AI 生图进度查询、视频渲染任务状态、批量数据导出进度

    优先选择长轮询

    • 需要在秒级获得任务完成反馈,用户体验要求较高
    • 服务器连接池资源相对充裕,可以承受一定数量的挂起连接
    • 任务完成时间方差较大(可能几秒也可能几十秒)
    • 已有事件驱动基础设施(Redis Pub/Sub、消息队列)可复用
    • 示例:即时通讯未读数刷新、协同文档状态同步、在线游戏状态同步

    4.3 混合策略建议

    在实际生产环境中,并不局限于二选一,我们可以考虑以下混合思路:

    1. 退避 + 长轮询级联:任务初期使用长轮询追求实时性,经历过若干轮后降级为退避轮询,避免长时间占用连接资源。
    2. 按业务分级:核心业务流程使用长轮询,次要或后台任务使用退避轮询。
    3. 按客户端分级:PC 端浏览器使用长轮询,移动端或低功耗设备使用退避轮询节省电量。
    `,52)])])}const y=i(p,[["render",h]]);export{g as __pageData,y as default}; + └─ 否 → 退避轮询实现更简单,无需额外组件

    4.2 适用场景速查

    优先选择退避轮询

    • 任务耗时较长(数十秒到分钟级),对实时性要求不高
    • 海量并发场景,服务器资源敏感
    • 无需 WebSocket/SSE 环境(如某些 API 第三方集成)
    • 需要简洁的客户端实现,不希望引入长连接管理复杂度
    • 示例:AI 生图进度查询、视频渲染任务状态、批量数据导出进度

    优先选择长轮询

    • 需要在秒级获得任务完成反馈,用户体验要求较高
    • 服务器连接池资源相对充裕,可以承受一定数量的挂起连接
    • 任务完成时间方差较大(可能几秒也可能几十秒)
    • 已有事件驱动基础设施(Redis Pub/Sub、消息队列)可复用
    • 示例:即时通讯未读数刷新、协同文档状态同步、在线游戏状态同步

    4.3 混合策略建议

    在实际生产环境中,并不局限于二选一,我们可以考虑以下混合思路:

    1. 退避 + 长轮询级联:任务初期使用长轮询追求实时性,经历过若干轮后降级为退避轮询,避免长时间占用连接资源。
    2. 按业务分级:核心业务流程使用长轮询,次要或后台任务使用退避轮询。
    3. 按客户端分级:PC 端浏览器使用长轮询,移动端或低功耗设备使用退避轮询节省电量。
    `,51)])])}const y=i(p,[["render",h]]);export{g as __pageData,y as default}; diff --git "a/assets/01.\345\205\250\346\240\210_60.\347\275\221\347\273\234\344\270\216\351\200\232\344\277\241_03.\351\200\200\351\201\277\350\275\256\350\257\242\344\270\216\351\225\277\350\275\256\350\257\242\347\232\204\345\216\237\347\220\206\343\200\201\345\256\236\346\210\230\344\270\216\351\200\211\345\236\213\345\206\263\347\255\226.md.C2A_-RUG.lean.js" b/assets/fullstack_networking-polling-optimization.md.COzdcUPj.lean.js similarity index 59% rename from "assets/01.\345\205\250\346\240\210_60.\347\275\221\347\273\234\344\270\216\351\200\232\344\277\241_03.\351\200\200\351\201\277\350\275\256\350\257\242\344\270\216\351\225\277\350\275\256\350\257\242\347\232\204\345\216\237\347\220\206\343\200\201\345\256\236\346\210\230\344\270\216\351\200\211\345\236\213\345\206\263\347\255\226.md.C2A_-RUG.lean.js" rename to assets/fullstack_networking-polling-optimization.md.COzdcUPj.lean.js index 022901e4..143935b5 100644 --- "a/assets/01.\345\205\250\346\240\210_60.\347\275\221\347\273\234\344\270\216\351\200\232\344\277\241_03.\351\200\200\351\201\277\350\275\256\350\257\242\344\270\216\351\225\277\350\275\256\350\257\242\347\232\204\345\216\237\347\220\206\343\200\201\345\256\236\346\210\230\344\270\216\351\200\211\345\236\213\345\206\263\347\255\226.md.C2A_-RUG.lean.js" +++ b/assets/fullstack_networking-polling-optimization.md.COzdcUPj.lean.js @@ -1 +1 @@ -import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const g=JSON.parse('{"title":"HTTP 轮询优化指南:退避轮询与长轮询的原理、实战与选型决策","description":"深入剖析退避轮询与长轮询的核心机制,提供 TypeScript/NestJS 实战代码,并构建技术选型决策树与适用场景速查。","frontmatter":{"date":"2026-02-25T22:10:48.000Z","title":"HTTP 轮询优化指南:退避轮询与长轮询的原理、实战与选型决策","tldr":"详解退避轮询与长轮询的实现原理,提供 HTTP 轮询优化策略与选型决策树。","description":"深入剖析退避轮询与长轮询的核心机制,提供 TypeScript/NestJS 实战代码,并构建技术选型决策树与适用场景速查。","tags":["HTTP 轮询","退避轮询","长轮询"],"categories":["全栈","网络与通信"],"permalink":"/fullstack/networking-polling-optimization"},"headers":[],"relativePath":"01.全栈/60.网络与通信/03.退避轮询与长轮询的原理、实战与选型决策.md","filePath":"01.全栈/60.网络与通信/03.退避轮询与长轮询的原理、实战与选型决策.md"}'),p={name:"01.全栈/60.网络与通信/03.退避轮询与长轮询的原理、实战与选型决策.md"};function h(k,s,t,e,r,E){return n(),a("div",null,[...s[0]||(s[0]=[l("",52)])])}const y=i(p,[["render",h]]);export{g as __pageData,y as default}; +import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const g=JSON.parse('{"title":"HTTP 轮询优化指南:退避轮询与长轮询的原理、实战与选型决策","description":"深入剖析退避轮询与长轮询的核心机制,提供 TypeScript/NestJS 实战代码,并构建技术选型决策树与适用场景速查。","frontmatter":{"date":"2026-02-25T22:10:48.000Z","title":"HTTP 轮询优化指南:退避轮询与长轮询的原理、实战与选型决策","tldr":"详解退避轮询与长轮询的实现原理,提供 HTTP 轮询优化策略与选型决策树。","description":"深入剖析退避轮询与长轮询的核心机制,提供 TypeScript/NestJS 实战代码,并构建技术选型决策树与适用场景速查。","tags":["HTTP 轮询","退避轮询","长轮询"],"categories":["全栈","网络与通信"],"permalink":"/fullstack/networking-polling-optimization"},"headers":[],"relativePath":"fullstack/networking-polling-optimization.md","filePath":"01.全栈/60.网络与通信/03.退避轮询与长轮询的原理、实战与选型决策.md"}'),p={name:"fullstack/networking-polling-optimization.md"};function h(k,s,t,e,r,E){return n(),a("div",null,[...s[0]||(s[0]=[l("",51)])])}const y=i(p,[["render",h]]);export{g as __pageData,y as default}; diff --git a/assets/fullstack_networking-protocol-selection-guide.md.Hd5lMFSd.js b/assets/fullstack_networking-protocol-selection-guide.md.Hd5lMFSd.js new file mode 100644 index 00000000..01063e4f --- /dev/null +++ b/assets/fullstack_networking-protocol-selection-guide.md.Hd5lMFSd.js @@ -0,0 +1 @@ +import{_ as e,g as o,h as r,U as a}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const c=JSON.parse('{"title":"Web 通信协议全景:从 HTTP 到 WebSocket 的技术选型指南","description":"深入剖析传统 HTTP、流式 HTTP、SSE、WebSocket、Webhooks、HTTP 轮询的原理与特性,结合 AI 场景提供技术选型决策矩阵。","frontmatter":{"date":"2026-02-24T08:40:31.000Z","title":"Web 通信协议全景:从 HTTP 到 WebSocket 的技术选型指南","tldr":"深入分析五种 Web 通信协议,提供 AI 时代的技术选型指南与最佳实践。","description":"深入剖析传统 HTTP、流式 HTTP、SSE、WebSocket、Webhooks、HTTP 轮询的原理与特性,结合 AI 场景提供技术选型决策矩阵。","categories":["全栈","网络与通信"],"tags":["HTTP","HTTP 轮询","SSE","WebSocket","Webhooks"],"permalink":"/fullstack/networking-protocol-selection-guide"},"headers":[],"relativePath":"fullstack/networking-protocol-selection-guide.md","filePath":"01.全栈/60.网络与通信/01.从 HTTP 到 WebSocket 的技术选型指南.md"}'),d={name:"fullstack/networking-protocol-selection-guide.md"};function n(s,t,h,l,i,g){return r(),o("div",null,[...t[0]||(t[0]=[a('

    Web 通信协议全景:从 HTTP 到 WebSocket 的技术选型指南

    摘要总结:本文针对传统 HTTP 在实时通信场景的局限,系统分析流式 HTTP、SSE、WebSocket、Webhooks、HTTP 轮询五种技术的核心原理、网络机制与适用边界。通过对比各方案在单向/双向推送、实时性、资源开销等维度的差异,结合 AI 文本对话、生图生视频等典型场景,构建技术选型决策矩阵。结论表明,不存在最优技术,需根据任务耗时特征、并发规模、基础设施约束等因素选择最适配方案。

    1. 引言

    HTTP 是一种基于文本的通信协议,主要用于 Web 浏览器、移动应用、桌面应用等客户端和 Web 服务器之间的数据传输。传统 HTTP 采用同步的请求-响应模式:请求 -> 等待 -> 完整响应。这种方式虽能满足大多数场景,但在实时性要求较高的领域——如游戏、聊天、视频会议,以及 AI 时代的对话式应用——却显得力不从心。

    为解决这一问题,业界发展出了多种实时 Web 通信方案。本文将围绕 流式 HTTP、SSE、WebSocket、Webhooks、HTTP 轮询 这五种主流技术,从原理、特性、适用场景出发,探讨它们在现代分布式架构中的选型策略与工程实践。

    2. 传统 HTTP——Web 通信的基石

    自 1991 年诞生以来,HTTP(超文本传输协议)便成为了互联网运行的“通用语言”。作为一种无状态、基于“请求-响应”模式的应用层协议,它构筑了现代 Web 通信的稳固基石。

    在核心运作机制上,传统 HTTP 遵循着严谨的单向驱动逻辑:通信必须由客户端发起请求(Request),服务器在处理完成后返回完整的响应(Response)。一旦数据传输完成,连接在逻辑上即告结束。

    维度说明
    网络特征HTTP 构建于 TCP 协议之上。尽管从 HTTP/1.1 开始,协议默认开启了 Connection: keep-alive 机制以复用底层 TCP 连接,减少了频繁三次握手的开销,但在应用层层面,它依然维持着半双工通信的本质——在同一时刻,数据只能单向流动,且服务器永远处于"被动应答"状态
    典型应用这种模式完美契合了绝大多数非即时性的资源获取场景,如加载网页 HTML、调用标准 RESTful API(获取用户信息、提交表单)以及加载静态图片等。

    随着 Web 应用向“实时化”与“高互动”演进,传统 HTTP 的固有特性逐渐演变为开发的痛点:

    痛点说明
    无法主动推送服务器如同一个被动的仓库管理员,即便仓库内的数据发生了更新,只要客户端不主动询问,服务器也无法将新信息触达用户。
    头部开销沉重在 HTTP/1.x 中,每次请求都必须携带完整的 Header 信息(包括 Cookie、User-Agent 等)。对于实时性要求高、但单次数据包极小的场景(如传感器数值同步),这些重复的头部数据往往比有效载荷还要大,造成了带宽的极大浪费。
    实时性的"伪实现"在 WebSocket 等原生实时技术成熟前,为了模拟实时效果,开发者通常被迫采用轮询(Polling)技术。无论是频繁发起连接的短轮询,还是长时间挂起请求的长轮询(Long Polling),都会产生大量冗余请求,对服务器并发处理能力提出了严峻挑战。

    3. 流式 HTTP(Streamable HTTP)

    如果说传统 HTTP 是严谨的“一问一答”,那么流式 HTTP(Streamable HTTP)则更像是一次“未完待续”的深度交流。它通过对响应机制的巧妙“变异”,打破了“服务端必须积攒全部结果才能返回”的物理限制,实现了数据的边计算、边传输。

    3.1 核心原理:分块传输的艺术

    流式 HTTP 的精髓在于它不再追求一次性交付,而是通过特定的协议头,将数据化整为零:

    • 传输机制:在 HTTP 响应头中声明 Transfer-Encoding: chunked(分块传输编码)或 Content-Type: text/event-stream。这告诉客户端:服务器目前尚不清楚响应的总长度(Content-Length),但会将数据切分成一个个逻辑块(Chunks)依次下发。

    • 网络特征:客户端在接收到 200 OK 状态码后,底层 TCP 连接并不会立即关闭。借助现代浏览器的 Fetch API 及其 ReadableStream 特性,前端可以像接水管一样,实时读取并处理源源不断传来的数据块,直到服务器发送一个长度为 0 的终止信号。

    3.2 应用场景:从大文件到 AI 时代

    这种“边读边播”的特性,使其在以下场景中无可替代:

    • AI 大模型“打字机”效果:这是当前最火热的应用。ChatGPT、Claude 等模型生成的长文本,正是通过流式 HTTP 将响应数据实时推送到前端,显著降低了用户的首字感知延迟(TTFT)。

    • 大容量资源下发:如超大文件或视频流的段落化加载,避免了内存爆仓,提升了系统吞吐量。

    • SSE 的灵活替代方案:配合 fetch-event-source 等库,它能完美模拟 SSE 的长连接功能,同时规避了标准 SSE 在请求方式(仅限 GET)和自定义 Header 上的限制。

    3.3 隐藏的坑:代理与缓冲

    虽然流式传输在逻辑上很美好,但在工程落地时必须关注“链路通畅”问题:

    局限说明
    单向传输局限它本质上仍是 Server-to-Client 的单向流。如果业务需要客户端也实时回传数据,则需要考虑其他双向通信协议。
    代理服务这是最常见的坑。一些旧版 Nginx、防火墙或负载均衡器默认开启了强缓冲(Buffering)机制。它们会试图"积攒"足够多的流式数据再统一发给客户端。这对于实时 AI 对话是致命的,开发者必须确保代理层配置了 X-Accel-Buffering: no 等指令来禁用缓冲,确保数据的"直达性"。

    4. SSE (Server-Sent Events):规范化的单向推送协议

    如果说 流式 HTTP 是一种底层的“传输机制”,那么 SSE 则是基于此机制建立的一套标准化应用层协议。它专门为“服务器向客户端推送事件”而生,在逻辑上比纯粹的流式传输更具约束力,也更便于浏览器集成

    4.1 核心原理:严格的文本契约

    SSE 不允许像普通流那样随心所欲地传输字符,它要求响应头强制设定为 Content-Type: text/event-stream,且数据格式必须遵循一套严密的“报文规范”:

    • 结构化字段:每条消息由 id:(事件 ID)、event:(事件类型)、data:(业务数据)和 retry:(重连间隔)等字段组成。

    • 消息边界:必须以双换行符 \\n\\n 作为一条独立消息的终点。这种协议级的约定,使得客户端能够精准地拆分出每一条业务事件,而无需开发者手动处理流的切片逻辑。

    4.2 网络机制:原生浏览器的“自动驾驶”

    SSE 的一大优势在于其深度集成了浏览器原生的 EventSource API。这赋予了它许多开箱即用的高级特性:

    • 自动重连:当网络波动导致连接中断时,EventSource 会自动发起重连尝试。

    • 状态追踪:利用 Last-Event-ID 机制,客户端在重连时会自动携带最后一次收到的 ID,服务端据此可以实现数据的“断点续传”,确保消息不丢失。

    4.3 典型场景:轻量级的实时感知

    SSE 极其适合那些“高频下发、低频上报”的业务场景:

    场景说明
    金融/行情股票价格、加密货币的实时波动。
    状态监控系统资源占用大盘、CI/CD 构建进度条。
    社交提醒站内信通知、点赞互动的实时更新。

    4.4 工程避坑指南:不可忽视的约束

    尽管 SSE 足够轻巧,但在实际架构设计中,必须正视其局限性:

    局限说明
    文本编码限制SSE 仅支持 UTF-8 文本流。如果需要传输二进制文件(如实时生成的缩略图),必须先转码为 Base64,这会带来约 33% 的体积开销。
    浏览器"单行道"限制原生的 EventSource 仅支持 GET 请求。在需要传递复杂查询参数(如超长的 JSON 过滤器)时,这一限制显得非常局促。这也是为什么许多现代项目(如 AI 聊天应用)宁愿使用 Fetch 模拟 SSE 的原因
    连接数水位线在 HTTP/1.1 环境下,浏览器对同一域名的并发长连接限制通常只有 6 个。这意味着如果你在浏览器中多开了几个监控标签页,很可能会耗尽连接池,导致页面其他请求完全阻塞。(注:在 HTTP/2 及以上版本中,由于多路复用特性的存在,这一限制已基本消除)。

    5. WebSocket:全双工通信

    WebSocket 不同于 流式 HTTP 和 SSE 这种在传统 HTTP 框架下的“精雕细琢”,而是一次彻底的“范式革命”。它不仅仅是一个简单的 API,而是一个独立的、与 HTTP 平级的应用层协议。

    它是一种基于 TCP 协议的全双工通信协议,真正的全双工持久连接方案,通过一次 HTTP 握手完成协议升级后,客户端与服务器可双向、实时、低延迟地传输数据,连接全程保持开放。旨在打破“请求-响应”的束缚,建立起真正意义上的“零延迟”双向通道。

    5.1 核心原理

    WebSocket 的建立遵循一个标准化的协议升级流程:

    • 协议升级握手:连接初始化阶段采用标准 HTTP 请求。客户端在请求头中声明 Upgrade: websocketConnection: Upgrade,表明协议升级意图。

    • 连接状态转换:服务器确认支持 WebSocket 协议后,返回 101 Switching Protocols 状态码。至此,底层 TCP 连接完成协议切换,后续通信采用 WebSocket 帧格式进行数据传输,不再承载 HTTP 协议开销。

    5.2 网络机制

    在 WebSocket 连接建立后,通信双方会进入全双工对等传输状态:

    • 全双工数据传输:客户端与服务器可随时、独立地向对端发送数据,无需等待对方请求或确认。这种双向并发通信机制彻底摆脱了 HTTP 协议"请求-响应"的串行约束,实现低延迟的实时数据交换。

    • 轻量级帧结构:相较于 HTTP 协议数百字节的首部开销,WebSocket 数据帧首部极为紧凑,固定部分仅 2 字节,带掩码时最大 14 字节。对于高频、小数据包传输场景(如实时游戏状态同步、传感器数据采集),显著降低网络带宽占用与传输延迟。

    • 原生二进制支持:WebSocket 协议原生支持文本(UTF-8)与二进制数据帧,无需像 SSE 那样进行 Base64 编码转换。该特性使其在实时音视频流传输、二进制协议封装等多媒体场景中具有显著的性能优势。

    5.3 应用场景:高互动的终极方案

    凡是需要“毫秒级同步”的场景,WebSocket 都是不二之选:

    场景典型应用
    即时通讯微信网页版、飞书聊天
    协同办公Google Docs、Figma 的多人在同步编辑
    竞技游戏实时同步玩家坐标与指令的 MMO 或 MOBA 游戏
    金融博弈极速波动的量化交易终端

    5.4 工程落地的“重装”代价

    作为一种"有状态"的协议,WebSocket 在带来极致性能的同时,也给后端架构带来了沉重的复杂性:

    • 状态维护与内存开销
      不同于 HTTP 的"阅后即焚"模式,服务器必须为每一个 WebSocket 连接维持一个持久的 Session 状态。当并发量攀升至十万甚至百万级时,内存占用与长连接管理压力将呈几何级数增长,对服务器的资源调度能力提出严峻考验。

    • 分布式系统的挑战
      在水平扩容场景下,WebSocket 堪称负载均衡器的"噩梦"。由于连接具有状态属性,若用户 A 连接至机器 1,用户 B 连接至机器 2,二者间的通信便无法直接完成。此时后端必须引入 Redis Pub/Sub、消息队列(Message Queue)或专用网关等中间件,以实现跨节点的"消息对齐"与状态同步。

    • 原始协议的局限
      WebSocket 协议本身设计得极为精简,并未内置自动重连、心跳保活或消息确认等机制。为保障连接在生产环境中的鲁棒性,开发者必须在应用层自行实现 Ping/Pong 心跳检测、断线感知以及带退避策略的重连逻辑,这无疑增加了工程实现的复杂度。

    6. Webhooks:事件驱动的反向回调

    如果说 SSE 是服务器"主动推送给浏览器",那么 Webhooks 则是服务器"主动推送给服务端"——它是一种基于 HTTP 的事件触发机制,专为服务端向服务端单向推送而设计。

    6.1 核心原理:回调的自动化

    Webhooks 的工作模式非常清晰:

    • 事件注册:客户端(通常是第三方应用)预先在服务端注册一个回调 URL,并指定关注的事件类型(如"订单完成"、"用户注册"、"文件上传"等)。

    • 事件触发:当服务端发生指定事件时,它会主动向客户端注册的 URL 发送一个 HTTP POST 请求,将事件详情封装在请求体中。

    • 即时响应:客户端收到回调后,执行相应业务逻辑(如更新本地数据、发送通知等),并返回一个确认响应。

    整个过程完全基于标准 HTTP,无需维护持久连接,也无需客户端持续轮询。

    6.2 典型场景:跨系统的松耦合集成

    场景说明
    支付回调当用户在第三方支付平台(如 Stripe、支付宝)完成付款后,支付平台会向商户服务器发送 Webhook 回调,通知交易结果。
    版本控制系统GitHub、GitLab 等平台通过 Webhooks 在代码提交、PR 创建时通知外部 CI/CD 系统。
    电商订单同步订单状态变更、用户注册等事件触发后,同步至 ERP、CRM 等内部系统。
    消息推送集成将消息平台的事件(如用户发送消息)推送至自有的聊天机器人或客服系统。

    6.3 工程考量:可靠投递与安全防护

    虽然 Webhooks 概念简单,但在生产环境中需要关注几个关键问题:

    考量点说明
    可靠投递保障HTTP 请求可能因网络问题投递失败,因此主流平台通常支持失败重试机制,并要求回调端点返回 2xx 状态码才视为成功。
    幂等性设计由于重试机制的存在,同一个事件可能被多次投递。客户端应当具备幂等处理能力,避免重复业务操作。
    安全验证为了防止恶意伪造回调,服务端通常会在请求中加入签名(如 HMAC 签名),客户端通过验证签名来确认请求的真实性。

    6.4 与 SSE 的本质区别

    维度WebhooksSSE
    推送对象服务端 → 服务端服务端 → 浏览器
    连接方向由接收方预先暴露 URL由发送方建立并维持连接
    适用场景跨系统事件同步浏览器端实时更新
    协议基础标准 HTTP POST长连接 + EventSource API

    7. 关于 HTTP 轮询的讨论

    HTTP 轮询是一种最朴素的实时通信方案,是实现实时性的基础方案,核心逻辑是客户端定时向服务器发起请求,主动拉取最新数据。

    不少人在学习了 流式 HTTP、SSE 和 WebSocket 后,会产生一种“技术洁癖”,觉得 HTTP 轮询是上古时代的落后技术,应当被彻底淘汰。但现实是,在当前很多顶级的 AI 生图(如 Midjourney 类的第三方集成应用、部分 Stable Diffusion 商业平台)甚至部分长视频生成应用中,HTTP 轮询不仅没有消失,反而是架构师经过深思熟虑后的首选方案。

    7.1 任务特性的本质差异:流式输出 vs 异步大任务

    AI 应用的交互模式决定了通信协议的选型:

    应用类型场景特征解释说明
    文本大模型(如 ChatGPT)流式持续输出模型在极短时间内(首个 Token 约 200ms 即可生成)就开始返回数据,随后持续"吐字"。若采用传统同步 HTTP,用户将面对长达数秒的白屏等待,体验极差。SSE/流式 HTTP 正是为此类场景量身打造。
    AI 生图/生视频重计算异步任务一张高质量图片的生成可能需要 GPU 满载运算 10~30 秒,甚至在高峰期需要排队数分钟。任务执行期间,除了偶尔的进度更新(10%、50%),并没有持续的数据流可供传输。让客户端和网关之间维持一条长达数十秒的"闲置长连接",仅用于等待最终一个图片 URL 的返回,在系统设计上是一笔不小的开销。

    7.2 基础设施的残酷现实:连接池枯竭与网关超时

    如果 AI 生图使用 WebSocket 或保持长达 30 秒的 HTTP 连接,会遇到严峻的基础设施挑战:

    挑战说明
    网关/负载均衡的超时限制大多数云厂商的负载均衡器(如 AWS ALB、Nginx 默认配置)和 CDN 对 HTTP 连接都有严格超时限制(通常为 30s 至 60s)。当 AI 任务耗时过长时,网关会主动切断连接并返回 504 Gateway Timeout。
    并发连接数瓶颈服务器的并发连接池是有限的。假设 1 万名用户同时排队等图片:使用 WebSocket 需要维持 1 万个长连接;而使用轮询,每位用户每 3 秒发起一个极轻量的 GET 请求,查询完毕立即释放连接。无状态的短连接模式能让服务器吞吐量提升数个量级。

    7.3 后端架构的天然要求:解耦与消息队列

    现代高并发 AI 生图平台的后端架构通常是彻底解耦的:

    1. 提交任务 (Client):客户端 POST 请求 /api/generate

    2. 下发队列 (API Server):API 服务器将任务投入 Kafka/RabbitMQ 队列中,生成唯一 task_id 并立即返回给客户端(耗时约 50ms)。

    3. 异步消费 (GPU Worker):后端 GPU 节点从队列中取出任务,执行计算。生成完毕后,将图片上传至 OSS/S3 并将结果写入数据库。

    4. 获取结果 (Client):客户端持有 task_id,每隔数秒轮询一次 /api/task/{task_id} 查询任务状态。

    在这个经典的生产者-消费者模型中,处理 HTTP 请求的 Web 服务器与真正执行计算的 GPU 服务器在物理上彼此隔离。若强行使用 WebSocket 或 SSE 将二者串联,不仅违背了解耦原则,还会使 Web 服务器与 GPU 节点间的状态同步变得极为复杂。

    7.4 移动端弱网环境下的"绝对鲁棒性"

    试想这样一个场景:用户在地铁中使用手机生图,刚提交任务便遭遇了 5 秒的网络中断。

    • 使用 WebSocket:连接断开后,重连时如何恢复先前的"会话状态"?服务器如何识别并继续向重连后的客户端推送结果?这需要一套复杂的重传与会话恢复机制。

    • 使用轮询 (Polling):则极为简洁。客户端持有 task_id。网络恢复后,继续发送 GET /api/task/{task_id} 即可获取结果。无状态特性带来了卓越的抗干扰能力。

    7.5 小结

    综上所述,轮询凭借其无状态、低连接开销、高吞吐量的特性,成为 AI 生图场景下更具性价比的通信方案

    当然,如果决定使用轮询,为了兼顾体验和服务器压力,业界通常会采用退避轮询策略——即随着任务等待时间延长,逐步降低查询频率。例如前 30 秒每 2 秒查询一次,30 秒后改为每 5 秒查询一次,到后期甚至可以降至每 10 秒一次。这种策略能在保证及时获取结果的同时,有效减少不必要的请求开销。

    8. 实践选型指南:不买最贵的,只选最对的

    在实际应用中,脱离业务场景谈协议与通信方案的优劣是毫无意义的。WebSocket 虽强,但并非银弹;标准 HTTP 虽“老”,但在大规模分布式系统中依然是最稳健的选择。

    8.1 决策矩阵:AI 与实时业务场景选型

    业务场景任务耗时特征推荐通信协议决策依据与变通方案
    AI 文本对话 (LLM)快速响应,持续文本流 (几秒~几十秒)流式 HTTP (Fetch / SSE)需提供“打字机”反馈以维持用户注意力。相比 WS,HTTP 更易穿透防火墙与网关。
    AI 实时语音/视觉助手极低延迟,双向高频互动 (<500ms)WebSocket / WebRTC必须消除 HTTP 握手与头部延迟,实现真正的全双工流式交互。
    AI 快速生图 (SDXL Turbo)耗时极短(<3s),无排队压力标准 HTTP (Request-Response)简单的挂起等待即可。无需引入长连接复杂度,保持架构简洁。
    高精生图/视频/长文生成耗时长且需排队(10s ~ 数分钟)异步提交 + HTTP 轮询保护网关的核心手段。解耦 GPU 计算节点与 Web 节点,客户端持 TaskID 定时查询状态。
    跨系统事件同步事件驱动,无固定耗时Webhooks适用于服务端间的异步事件通知(如支付回调、订单同步、Git 钩子触发 CI/CD)。接收方需预先暴露回调 URL,并确保幂等处理与签名验证。

    8.2 深度决策逻辑:工程选型的五条金律

    1、高频双向:WebSocket 的主场

    核心逻辑:HTTP 及其衍生品在双向交互下,重复的头部开销会吞噬大量带宽,且无法实现真正的全双工并发。

    若业务需要客户端与服务端互发高频消息(如多人竞技游戏、协作编辑、实时双向聊天),WebSocket 是唯一选择

    2、单向推送:SSE 的轻量优势

    若业务场景仅需服务端向客户端单向高频推送(如股票行情大盘、服务器实时日志、监控预警):

    首选方案是 SSE。它完全复用现有的 HTTP 基础设施(负载均衡、WAF、鉴权逻辑),无需额外配置 WebSocket 网关。同时,其原生的断线重连机制极大降低了前端的开发心智负担。

    3、流式响应:Streamable HTTP 的主场,AI 时代的主流选择

    这是目前 LLM 文本对话中最主流的"事实标准"

    痛点:原生 SSE 受限于浏览器实现,通常只能发起 GET 请求。但在 AI 场景下,我们需要发送庞大的 system_prompt 或上下文历史(Context),GET 的 URL 长度限制成为了瓶颈。

    变通方案使用 Fetch API 结合 POST 请求,通过 ReadableStream 接收流式响应。既能突破 GET 的长度限制,又避免了 WebSocket 在维持长连接、处理心跳保活方面的额外资源损耗。这正是 fetch-event-source 这类库在 AI 社区盛行的底层逻辑。

    4、异步任务:轮询的主场

    对于 AI 生图、生视频等耗时较长(10s ~ 数分钟)的重计算任务,其特点是计算期间无持续数据流,仅在完成后返回结果。

    此时若强行使用 WebSocket 或 SSE 维持长连接,不仅会遭遇网关超时限制(通常 30s~60s),还会造成并发连接数瓶颈。异步提交 + 轮询查询是更合理的架构:客户端提交任务后获得 TaskID,定期轮询查询状态。这种方式解耦了 Web 节点与 GPU 节点,无状态的短连接模式让服务器能够承载更高的吞吐量。

    5、跨系统回调:Webhooks 的主场

    若业务涉及跨服务的事件通知(如支付平台回调、订单状态变更通知、Git 仓库事件触发 CI/CD),且接收方是服务端而非浏览器:

    首选方案是 Webhooks。它完全基于标准 HTTP POST 请求,无需维护持久连接,由接收方预先暴露回调 URL 即可实现事件驱动推送。这种模式天然适合服务间的松耦合集成,但需注意幂等性处理与签名验证以确保安全。

    9. 结语

    回望这场从 HTTP 到 WebSocket 的技术演进,我们或许能提炼出一个更普适的架构哲学:没有"最好"的技术,只有"最合适"的技术

    技术的演进从来不是"长江后浪推前浪"的简单替代,而是一种"分工细化"的自然结果。传统 HTTP 依然是 Web 的基石,流式 HTTP 让它焕发新生;SSE 在单向推送场景轻量而优雅;WebSocket 为真正的实时双向交互打开了大门;轮询在 AI 时代的大模型洪流中,依然默默支撑着无数生图、生视频应用的正常运行;而 Webhooks 则在跨系统的服务端间编织出一张事件驱动的网络。

    真正成熟的架构师,不会执着于"最新"或"最复杂"的方案,而是深入理解每种技术的边界与代价,在业务场景的约束下做出最优雅的取舍。毕竟,最好的架构不是用技术堆砌出来的,而是让技术各归其位的顺势而为

    ',108)])])}const T=e(d,[["render",n]]);export{c as __pageData,T as default}; diff --git "a/assets/01.\345\205\250\346\240\210_60.\347\275\221\347\273\234\344\270\216\351\200\232\344\277\241_01.\344\273\216 HTTP \345\210\260 WebSocket \347\232\204\346\212\200\346\234\257\351\200\211\345\236\213\346\214\207\345\215\227.md.int3cA6G.lean.js" b/assets/fullstack_networking-protocol-selection-guide.md.Hd5lMFSd.lean.js similarity index 61% rename from "assets/01.\345\205\250\346\240\210_60.\347\275\221\347\273\234\344\270\216\351\200\232\344\277\241_01.\344\273\216 HTTP \345\210\260 WebSocket \347\232\204\346\212\200\346\234\257\351\200\211\345\236\213\346\214\207\345\215\227.md.int3cA6G.lean.js" rename to assets/fullstack_networking-protocol-selection-guide.md.Hd5lMFSd.lean.js index d7fbc3bc..fdbf6f20 100644 --- "a/assets/01.\345\205\250\346\240\210_60.\347\275\221\347\273\234\344\270\216\351\200\232\344\277\241_01.\344\273\216 HTTP \345\210\260 WebSocket \347\232\204\346\212\200\346\234\257\351\200\211\345\236\213\346\214\207\345\215\227.md.int3cA6G.lean.js" +++ b/assets/fullstack_networking-protocol-selection-guide.md.Hd5lMFSd.lean.js @@ -1 +1 @@ -import{_ as e,g as o,h as r,U as a}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const c=JSON.parse('{"title":"Web 通信协议全景:从 HTTP 到 WebSocket 的技术选型指南","description":"深入剖析传统 HTTP、流式 HTTP、SSE、WebSocket、Webhooks、HTTP 轮询的原理与特性,结合 AI 场景提供技术选型决策矩阵。","frontmatter":{"date":"2026-02-24T08:40:31.000Z","title":"Web 通信协议全景:从 HTTP 到 WebSocket 的技术选型指南","tldr":"深入分析五种 Web 通信协议,提供 AI 时代的技术选型指南与最佳实践。","description":"深入剖析传统 HTTP、流式 HTTP、SSE、WebSocket、Webhooks、HTTP 轮询的原理与特性,结合 AI 场景提供技术选型决策矩阵。","categories":["全栈","网络与通信"],"tags":["HTTP","HTTP 轮询","SSE","WebSocket","Webhooks"],"permalink":"/fullstack/networking-protocol-selection-guide"},"headers":[],"relativePath":"01.全栈/60.网络与通信/01.从 HTTP 到 WebSocket 的技术选型指南.md","filePath":"01.全栈/60.网络与通信/01.从 HTTP 到 WebSocket 的技术选型指南.md"}'),d={name:"01.全栈/60.网络与通信/01.从 HTTP 到 WebSocket 的技术选型指南.md"};function n(s,t,h,l,i,g){return r(),o("div",null,[...t[0]||(t[0]=[a("",109)])])}const T=e(d,[["render",n]]);export{c as __pageData,T as default}; +import{_ as e,g as o,h as r,U as a}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const c=JSON.parse('{"title":"Web 通信协议全景:从 HTTP 到 WebSocket 的技术选型指南","description":"深入剖析传统 HTTP、流式 HTTP、SSE、WebSocket、Webhooks、HTTP 轮询的原理与特性,结合 AI 场景提供技术选型决策矩阵。","frontmatter":{"date":"2026-02-24T08:40:31.000Z","title":"Web 通信协议全景:从 HTTP 到 WebSocket 的技术选型指南","tldr":"深入分析五种 Web 通信协议,提供 AI 时代的技术选型指南与最佳实践。","description":"深入剖析传统 HTTP、流式 HTTP、SSE、WebSocket、Webhooks、HTTP 轮询的原理与特性,结合 AI 场景提供技术选型决策矩阵。","categories":["全栈","网络与通信"],"tags":["HTTP","HTTP 轮询","SSE","WebSocket","Webhooks"],"permalink":"/fullstack/networking-protocol-selection-guide"},"headers":[],"relativePath":"fullstack/networking-protocol-selection-guide.md","filePath":"01.全栈/60.网络与通信/01.从 HTTP 到 WebSocket 的技术选型指南.md"}'),d={name:"fullstack/networking-protocol-selection-guide.md"};function n(s,t,h,l,i,g){return r(),o("div",null,[...t[0]||(t[0]=[a("",108)])])}const T=e(d,[["render",n]]);export{c as __pageData,T as default}; diff --git "a/assets/01.\345\205\250\346\240\210_60.\347\275\221\347\273\234\344\270\216\351\200\232\344\277\241_02.\346\265\201\345\274\217 HTTP \344\270\216 SSE \345\215\217\350\256\256\357\274\232\344\273\216\346\246\202\345\277\265\350\276\250\346\236\220\345\210\260\347\224\237\344\272\247\345\256\236\350\267\265.md.Cp-uzdUB.js" b/assets/fullstack_networking-sse-practice.md.CCWohLJK.js similarity index 95% rename from "assets/01.\345\205\250\346\240\210_60.\347\275\221\347\273\234\344\270\216\351\200\232\344\277\241_02.\346\265\201\345\274\217 HTTP \344\270\216 SSE \345\215\217\350\256\256\357\274\232\344\273\216\346\246\202\345\277\265\350\276\250\346\236\220\345\210\260\347\224\237\344\272\247\345\256\236\350\267\265.md.Cp-uzdUB.js" rename to assets/fullstack_networking-sse-practice.md.CCWohLJK.js index e0bd156d..bde76aa8 100644 --- "a/assets/01.\345\205\250\346\240\210_60.\347\275\221\347\273\234\344\270\216\351\200\232\344\277\241_02.\346\265\201\345\274\217 HTTP \344\270\216 SSE \345\215\217\350\256\256\357\274\232\344\273\216\346\246\202\345\277\265\350\276\250\346\236\220\345\210\260\347\224\237\344\272\247\345\256\236\350\267\265.md.Cp-uzdUB.js" +++ b/assets/fullstack_networking-sse-practice.md.CCWohLJK.js @@ -1,4 +1,4 @@ -import{H as a}from"./chunks/HighLightText.BFsbuOsY.js";import{g as h,h as k,U as n,i as l,S as i,z as p,s as e}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const c=JSON.parse('{"title":"流式 HTTP 与 SSE 协议:从概念辨析到生产实践","description":"辨析流式 HTTP 与 SSE 协议的概念与层次关系,详解客户端与服务端实现方案,提供生产实践完整指南。","frontmatter":{"date":"2026-03-05T16:54:35.000Z","title":"流式 HTTP 与 SSE 协议:从概念辨析到生产实践","aliases":["Server-Sent Events","HTTP Streaming"],"tldr":"深入解析流式 HTTP 与 SSE 协议,提供从概念到生产实践的完整解决方案。","description":"辨析流式 HTTP 与 SSE 协议的概念与层次关系,详解客户端与服务端实现方案,提供生产实践完整指南。","tags":["tutorial","SSE","HTTP Streaming","全栈"],"categories":["全栈","网络与通信"],"permalink":"/fullstack/networking/sse-practice"},"headers":[],"relativePath":"01.全栈/60.网络与通信/02.流式 HTTP 与 SSE 协议:从概念辨析到生产实践.md","filePath":"01.全栈/60.网络与通信/02.流式 HTTP 与 SSE 协议:从概念辨析到生产实践.md"}'),t={name:"01.全栈/60.网络与通信/02.流式 HTTP 与 SSE 协议:从概念辨析到生产实践.md"},y=Object.assign(t,{setup(r){return(E,s)=>(k(),h("div",null,[s[10]||(s[10]=n('

    流式 HTTP 与 SSE 协议:从概念辨析到生产实践

    摘要总结: 针对开发者容易混淆流式 HTTP 与 SSE 协议的问题,从概念层次出发厘清二者本质区别与协作关系,指出流式 HTTP 是底层传输机制而 SSE 是应用层数据格式约定。文章依次介绍原生 EventSource API、fetch + ReadableStream 进阶方案、@microsoft/fetch-event-source 工业级实现等三种客户端方案,并以 NestJS 为例展示服务端 SSE 响应的标准实现与 POST 请求扩展,最后涵盖指数退避重试、事件分类处理、连接状态追踪、资源清理等生产实践要点,为 AI 时代的流式响应场景提供完整技术方案。

    1. 引言

    Web 通信协议全景:从 HTTP 到 WebSocket 的技术选型指南中,我们对比分析了多种通信技术。在本文我们将重点探讨 SSE(Server-Sent Events)流式 HTTP(HTTP Streaming) 的实践。

    1.1 概念澄清:两种技术,两个层次

    很多开发者容易将 SSE 与流式 HTTP 混为一谈,实际上它们处于不同的技术层次:

    维度流式 HTTPSSE
    定位底层传输机制应用层协议
    核心原理HTTP Chunked Transfer Encoding,数据分块连续传输基于 HTTP 的事件流协议,定义了标准化的数据格式
    浏览器原生支持无,需自行解析数据流有,EventSource API
    协议规范无标准格式约定W3C 标准(text/event-stream
    ',8)),l("p",null,[s[2]||(s[2]=i("简而言之,",-1)),p(a,{bold:""},{default:e(()=>[...s[0]||(s[0]=[i("流式 HTTP 是一种“传输手段”,而 SSE 是一种“数据格式约定”",-1)])]),_:1}),s[3]||(s[3]=i("。",-1)),p(a,{type:"info"},{default:e(()=>[...s[1]||(s[1]=[i("流式 HTTP 关注的是如何把数据“边发边传”,而 SSE 关注的是如何让数据“按照固定格式组织”,便于客户端解析处理",-1)])]),_:1}),s[4]||(s[4]=i("。",-1))]),s[11]||(s[11]=n('

    1.2 关联与协作

    尽管处于不同层次,但二者完全可以协同工作:

    • SSE 必须基于流式 HTTP:SSE 的标准格式需要通过 HTTP 流式传输来实现,因此 SSE 协议的数据流底层必然依赖流式 HTTP
    • 流式 HTTP 不必局限于 SSE:纯流式 HTTP 可以自定义数据格式(如 JSON Lines、NDJSON),不一定要遵循 SSE 的 event:id:data: 等字段约定

    正是由于这种关系,我们可以利用 fetch + ReadableStream 突破 SSE 的一些局限

    1. 请求方式受限:原生 SSE 仅支持 GET 请求,当需要携带较大 body 数据(如文件上传上下文、复杂查询参数)时会受到限制,而 fetch API 不受此约束。
    2. 身份验证不便:原生 SSE 无法灵活地在请求头中添加 Authorization: Bearer <token> 等认证信息,fetch API 则可以像调用普通接口一样自定义 Header。

    因此,基于流式 HTTP,采用 fetch + ReadableStream 的方案,不仅保留了 fetch 的全部能力(POST 方法、自定义 Headers、超时控制等),同时具备了流式传输的实时性,并且在数据格式层面依然遵循 SSE 协议,保持良好的可解析性和通用性。相比原生 SSE,使用 Fetch API + ReadableStream 能突破 GET 请求限制,可携带任意大小的 body 数据,同时支持灵活的身份验证方式;相比 WebSocket,则避免了维护长连接和心跳保活的额外资源损耗。

    ',6)),l("p",null,[s[6]||(s[6]=i("这种“取两家之长”的方案,正是 ",-1)),s[7]||(s[7]=l("a",{href:"https://github.com/Azure/fetch-event-source",target:"_blank",rel:"noreferrer"},"@microsoft/fetch-event-source",-1)),s[8]||(s[8]=i(" 这类库在 AI 社区盛行的底层逻辑:",-1)),p(a,{bold:""},{default:e(()=>[...s[5]||(s[5]=[i("既能像调用普通接口一样编写业务逻辑,又能享受流式传输的实时性,数据格式依然遵循 SSE 协议,客户端解析毫无额外成本",-1)])]),_:1}),s[9]||(s[9]=i("。",-1))]),s[12]||(s[12]=n(`
    特性标准 EventSource (SSE)Fetch + Stream
    HTTP 方法仅限 GET支持 POST、PUT 等所有方法
    自定义 Header不支持(无法传 Token 等)完全支持
    **请求体 **(Body)不支持支持发送 JSON Payload
    重连机制浏览器内置,难以精细控制插件实现,支持高度自定义重连策略
    跨域 (CORS)比较死板,需特定配置遵循标准的 Fetch CORS 规则
    底层 API浏览器原生 EventSource 对象基于 fetch 和 ReadableStream

    1.3 SSE 协议数据格式

    SSE 协议对数据流格式有明确规定,服务器返回的响应头和数据体需遵循以下规范:

    markdown
    Content-Type: text/event-stream
    +import{H as a}from"./chunks/HighLightText.BD5ARcjF.js";import{g as h,h as k,U as n,i as l,S as i,z as p,s as e}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const c=JSON.parse('{"title":"流式 HTTP 与 SSE 协议:从概念辨析到生产实践","description":"辨析流式 HTTP 与 SSE 协议的概念与层次关系,详解客户端与服务端实现方案,提供生产实践完整指南。","frontmatter":{"date":"2026-03-05T16:54:35.000Z","title":"流式 HTTP 与 SSE 协议:从概念辨析到生产实践","aliases":["Server-Sent Events","HTTP Streaming"],"tldr":"深入解析流式 HTTP 与 SSE 协议,提供从概念到生产实践的完整解决方案。","description":"辨析流式 HTTP 与 SSE 协议的概念与层次关系,详解客户端与服务端实现方案,提供生产实践完整指南。","tags":["tutorial","SSE","HTTP Streaming","全栈"],"categories":["全栈","网络与通信"],"permalink":"/fullstack/networking-sse-practice"},"headers":[],"relativePath":"fullstack/networking-sse-practice.md","filePath":"01.全栈/60.网络与通信/02.流式 HTTP 与 SSE 协议:从概念辨析到生产实践.md"}'),t={name:"fullstack/networking-sse-practice.md"},y=Object.assign(t,{setup(r){return(E,s)=>(k(),h("div",null,[s[10]||(s[10]=n('

    流式 HTTP 与 SSE 协议:从概念辨析到生产实践

    摘要总结: 针对开发者容易混淆流式 HTTP 与 SSE 协议的问题,从概念层次出发厘清二者本质区别与协作关系,指出流式 HTTP 是底层传输机制而 SSE 是应用层数据格式约定。文章依次介绍原生 EventSource API、fetch + ReadableStream 进阶方案、@microsoft/fetch-event-source 工业级实现等三种客户端方案,并以 NestJS 为例展示服务端 SSE 响应的标准实现与 POST 请求扩展,最后涵盖指数退避重试、事件分类处理、连接状态追踪、资源清理等生产实践要点,为 AI 时代的流式响应场景提供完整技术方案。

    1. 引言

    Web 通信协议全景:从 HTTP 到 WebSocket 的技术选型指南中,我们对比分析了多种通信技术。在本文我们将重点探讨 SSE(Server-Sent Events)流式 HTTP(HTTP Streaming) 的实践。

    1.1 概念澄清:两种技术,两个层次

    很多开发者容易将 SSE 与流式 HTTP 混为一谈,实际上它们处于不同的技术层次:

    维度流式 HTTPSSE
    定位底层传输机制应用层协议
    核心原理HTTP Chunked Transfer Encoding,数据分块连续传输基于 HTTP 的事件流协议,定义了标准化的数据格式
    浏览器原生支持无,需自行解析数据流有,EventSource API
    协议规范无标准格式约定W3C 标准(text/event-stream
    ',7)),l("p",null,[s[2]||(s[2]=i("简而言之,",-1)),p(a,{bold:""},{default:e(()=>[...s[0]||(s[0]=[i("流式 HTTP 是一种“传输手段”,而 SSE 是一种“数据格式约定”",-1)])]),_:1}),s[3]||(s[3]=i("。",-1)),p(a,{type:"info"},{default:e(()=>[...s[1]||(s[1]=[i("流式 HTTP 关注的是如何把数据“边发边传”,而 SSE 关注的是如何让数据“按照固定格式组织”,便于客户端解析处理",-1)])]),_:1}),s[4]||(s[4]=i("。",-1))]),s[11]||(s[11]=n('

    1.2 关联与协作

    尽管处于不同层次,但二者完全可以协同工作:

    • SSE 必须基于流式 HTTP:SSE 的标准格式需要通过 HTTP 流式传输来实现,因此 SSE 协议的数据流底层必然依赖流式 HTTP
    • 流式 HTTP 不必局限于 SSE:纯流式 HTTP 可以自定义数据格式(如 JSON Lines、NDJSON),不一定要遵循 SSE 的 event:id:data: 等字段约定

    正是由于这种关系,我们可以利用 fetch + ReadableStream 突破 SSE 的一些局限

    1. 请求方式受限:原生 SSE 仅支持 GET 请求,当需要携带较大 body 数据(如文件上传上下文、复杂查询参数)时会受到限制,而 fetch API 不受此约束。
    2. 身份验证不便:原生 SSE 无法灵活地在请求头中添加 Authorization: Bearer <token> 等认证信息,fetch API 则可以像调用普通接口一样自定义 Header。

    因此,基于流式 HTTP,采用 fetch + ReadableStream 的方案,不仅保留了 fetch 的全部能力(POST 方法、自定义 Headers、超时控制等),同时具备了流式传输的实时性,并且在数据格式层面依然遵循 SSE 协议,保持良好的可解析性和通用性。相比原生 SSE,使用 Fetch API + ReadableStream 能突破 GET 请求限制,可携带任意大小的 body 数据,同时支持灵活的身份验证方式;相比 WebSocket,则避免了维护长连接和心跳保活的额外资源损耗。

    ',6)),l("p",null,[s[6]||(s[6]=i("这种“取两家之长”的方案,正是 ",-1)),s[7]||(s[7]=l("a",{href:"https://github.com/Azure/fetch-event-source",target:"_blank",rel:"noreferrer"},"@microsoft/fetch-event-source",-1)),s[8]||(s[8]=i(" 这类库在 AI 社区盛行的底层逻辑:",-1)),p(a,{bold:""},{default:e(()=>[...s[5]||(s[5]=[i("既能像调用普通接口一样编写业务逻辑,又能享受流式传输的实时性,数据格式依然遵循 SSE 协议,客户端解析毫无额外成本",-1)])]),_:1}),s[9]||(s[9]=i("。",-1))]),s[12]||(s[12]=n(`
    特性标准 EventSource (SSE)Fetch + Stream
    HTTP 方法仅限 GET支持 POST、PUT 等所有方法
    自定义 Header不支持(无法传 Token 等)完全支持
    **请求体 **(Body)不支持支持发送 JSON Payload
    重连机制浏览器内置,难以精细控制插件实现,支持高度自定义重连策略
    跨域 (CORS)比较死板,需特定配置遵循标准的 Fetch CORS 规则
    底层 API浏览器原生 EventSource 对象基于 fetch 和 ReadableStream

    1.3 SSE 协议数据格式

    SSE 协议对数据流格式有明确规定,服务器返回的响应头和数据体需遵循以下规范:

    markdown
    Content-Type: text/event-stream
     Cache-Control: no-cache
     Connection: keep-alive
     
    diff --git a/assets/fullstack_networking-sse-practice.md.CCWohLJK.lean.js b/assets/fullstack_networking-sse-practice.md.CCWohLJK.lean.js
    new file mode 100644
    index 00000000..15613d71
    --- /dev/null
    +++ b/assets/fullstack_networking-sse-practice.md.CCWohLJK.lean.js
    @@ -0,0 +1 @@
    +import{H as a}from"./chunks/HighLightText.BD5ARcjF.js";import{g as h,h as k,U as n,i as l,S as i,z as p,s as e}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const c=JSON.parse('{"title":"流式 HTTP 与 SSE 协议:从概念辨析到生产实践","description":"辨析流式 HTTP 与 SSE 协议的概念与层次关系,详解客户端与服务端实现方案,提供生产实践完整指南。","frontmatter":{"date":"2026-03-05T16:54:35.000Z","title":"流式 HTTP 与 SSE 协议:从概念辨析到生产实践","aliases":["Server-Sent Events","HTTP Streaming"],"tldr":"深入解析流式 HTTP 与 SSE 协议,提供从概念到生产实践的完整解决方案。","description":"辨析流式 HTTP 与 SSE 协议的概念与层次关系,详解客户端与服务端实现方案,提供生产实践完整指南。","tags":["tutorial","SSE","HTTP Streaming","全栈"],"categories":["全栈","网络与通信"],"permalink":"/fullstack/networking-sse-practice"},"headers":[],"relativePath":"fullstack/networking-sse-practice.md","filePath":"01.全栈/60.网络与通信/02.流式 HTTP 与 SSE 协议:从概念辨析到生产实践.md"}'),t={name:"fullstack/networking-sse-practice.md"},y=Object.assign(t,{setup(r){return(E,s)=>(k(),h("div",null,[s[10]||(s[10]=n("",7)),l("p",null,[s[2]||(s[2]=i("简而言之,",-1)),p(a,{bold:""},{default:e(()=>[...s[0]||(s[0]=[i("流式 HTTP 是一种“传输手段”,而 SSE 是一种“数据格式约定”",-1)])]),_:1}),s[3]||(s[3]=i("。",-1)),p(a,{type:"info"},{default:e(()=>[...s[1]||(s[1]=[i("流式 HTTP 关注的是如何把数据“边发边传”,而 SSE 关注的是如何让数据“按照固定格式组织”,便于客户端解析处理",-1)])]),_:1}),s[4]||(s[4]=i("。",-1))]),s[11]||(s[11]=n("",6)),l("p",null,[s[6]||(s[6]=i("这种“取两家之长”的方案,正是 ",-1)),s[7]||(s[7]=l("a",{href:"https://github.com/Azure/fetch-event-source",target:"_blank",rel:"noreferrer"},"@microsoft/fetch-event-source",-1)),s[8]||(s[8]=i(" 这类库在 AI 社区盛行的底层逻辑:",-1)),p(a,{bold:""},{default:e(()=>[...s[5]||(s[5]=[i("既能像调用普通接口一样编写业务逻辑,又能享受流式传输的实时性,数据格式依然遵循 SSE 协议,客户端解析毫无额外成本",-1)])]),_:1}),s[9]||(s[9]=i("。",-1))]),s[12]||(s[12]=n("",91))]))}});export{c as __pageData,y as default};
    diff --git "a/assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_6.\350\247\243\346\236\220 NodeJS \344\270\255\347\232\204\346\250\241\345\235\227\345\214\226.md.CGHtK9Bj.js" b/assets/fullstack_nodejs-module-programming-summary.md.CrdU3lTR.js
    similarity index 81%
    rename from "assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_6.\350\247\243\346\236\220 NodeJS \344\270\255\347\232\204\346\250\241\345\235\227\345\214\226.md.CGHtK9Bj.js"
    rename to assets/fullstack_nodejs-module-programming-summary.md.CrdU3lTR.js
    index d5fc4852..18d2165f 100644
    --- "a/assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_6.\350\247\243\346\236\220 NodeJS \344\270\255\347\232\204\346\250\241\345\235\227\345\214\226.md.CGHtK9Bj.js"	
    +++ b/assets/fullstack_nodejs-module-programming-summary.md.CrdU3lTR.js
    @@ -1,4 +1,4 @@
    -import{_ as i,g as a,h as e,U as n}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const c=JSON.parse('{"title":"Node.js 模块化编程梳理与总结","description":"解析 Node.js 中 CommonJS 与 ES Modules 的双模共存策略,涵盖模块加载优先级、缓存机制、package.json exports 条件导出及 Monorepo 架构实践。","frontmatter":{"date":"2024-05-17T23:33:09.000Z","title":"Node.js 模块化编程梳理与总结","tldr":"Node.js CJS 与 ESM 双模共存:模块加载机制与分层架构实践。","description":"解析 Node.js 中 CommonJS 与 ES Modules 的双模共存策略,涵盖模块加载优先级、缓存机制、package.json exports 条件导出及 Monorepo 架构实践。","permalink":"/fullstack/nodejs-module-programming-summary","abstract":"Node.js 模块化经历了从 CommonJS 独霸天下到 ES Modules 全面接入的范式转移。共存策略通过 .mjs/.cjs 后缀和 package.json type 字段控制两种规范的边界;ESM 可直接 import CJS(自动包装为默认导出),但 CJS 无法 require ESM 必须使用动态 import。模块加载遵循核心模块优先、文件模块、目录模块(index.js/package.json)、node_modules 逐级查找的优先级;require.cache 实现模块缓存,清除缓存(delete require.cache[path])是热更新工具的核心操作。package.json exports 字段支持条件导出(import/require 返回不同入口)。pnpm workspaces 凭借硬链接机制成为现代 Monorepo 首选。后端分层架构(API/Service/Repository)实现关注点分离,换数据库只需改 Repository 层。","tags":["concept","node.js","commonjs","esm","monorepo","layered-architecture"],"categories":["全栈","全栈基础素养","模块化编程实践指南"]},"headers":[],"relativePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/6.解析 NodeJS 中的模块化.md","filePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/6.解析 NodeJS 中的模块化.md"}'),l={name:"01.全栈/80.全栈基础素养/20.模块化编程实践指南/6.解析 NodeJS 中的模块化.md"};function p(t,s,r,o,h,d){return e(),a("div",null,[...s[0]||(s[0]=[n(`

    Node.js 模块化编程梳理与总结

    如果说浏览器端的模块化是为了"按需加载",那么 Node.js 的模块化则是为了"代码组织"。作为将 JavaScript 带入服务器端的先驱,Node.js 经历了从 CommonJS (CJS) 独霸天下到 ES Modules (ESM) 全面接入的范式转移。

    在服务器端,模块化不仅仅是为了拆分代码,更是为了构建清晰的项目结构、管理依赖关系,以及实现代码的复用与维护。

    1. CommonJS 与 ES Modules 双模共存

    在现代 Node.js 开发中,我们经常面临两种规范交织的情况。这不仅是文件后缀的改变,更是同步与异步加载逻辑的博弈。

    共存策略:

    1. 后缀决定论.mjs 始终被视为 ESM,.cjs 始终被视为 CJS。
    2. 包定义导向:在 package.json 中设置 "type": "module",则目录下所有 .js 均视为 ESM,反之默认为 CJS。
    3. 互操作性(Interop)
      • ESM 引用 CJS:直接 import 即可,Node 会将 module.exports 包装为默认导出。
      • CJS 引用 ESM:由于 ESM 是异步加载的,CJS 无法使用 require,必须使用 动态 import:const module = await import('./es-module.mjs')

    代码示例

    javascript
    // package.json
    +import{_ as i,g as a,h as e,U as n}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const c=JSON.parse('{"title":"Node.js 模块化编程梳理与总结","description":"解析 Node.js 中 CommonJS 与 ES Modules 的双模共存策略,涵盖模块加载优先级、缓存机制、package.json exports 条件导出及 Monorepo 架构实践。","frontmatter":{"date":"2024-05-17T23:33:09.000Z","title":"Node.js 模块化编程梳理与总结","tldr":"Node.js CJS 与 ESM 双模共存:模块加载机制与分层架构实践。","description":"解析 Node.js 中 CommonJS 与 ES Modules 的双模共存策略,涵盖模块加载优先级、缓存机制、package.json exports 条件导出及 Monorepo 架构实践。","permalink":"/fullstack/nodejs-module-programming-summary","abstract":"Node.js 模块化经历了从 CommonJS 独霸天下到 ES Modules 全面接入的范式转移。共存策略通过 .mjs/.cjs 后缀和 package.json type 字段控制两种规范的边界;ESM 可直接 import CJS(自动包装为默认导出),但 CJS 无法 require ESM 必须使用动态 import。模块加载遵循核心模块优先、文件模块、目录模块(index.js/package.json)、node_modules 逐级查找的优先级;require.cache 实现模块缓存,清除缓存(delete require.cache[path])是热更新工具的核心操作。package.json exports 字段支持条件导出(import/require 返回不同入口)。pnpm workspaces 凭借硬链接机制成为现代 Monorepo 首选。后端分层架构(API/Service/Repository)实现关注点分离,换数据库只需改 Repository 层。","tags":["concept","node.js","commonjs","esm","monorepo","layered-architecture"],"categories":["全栈","全栈基础素养","模块化编程实践指南"]},"headers":[],"relativePath":"fullstack/nodejs-module-programming-summary.md","filePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/6.解析 NodeJS 中的模块化.md"}'),l={name:"fullstack/nodejs-module-programming-summary.md"};function p(t,s,r,o,h,k){return e(),a("div",null,[...s[0]||(s[0]=[n(`

    Node.js 模块化编程梳理与总结

    如果说浏览器端的模块化是为了"按需加载",那么 Node.js 的模块化则是为了"代码组织"。作为将 JavaScript 带入服务器端的先驱,Node.js 经历了从 CommonJS (CJS) 独霸天下到 ES Modules (ESM) 全面接入的范式转移。

    在服务器端,模块化不仅仅是为了拆分代码,更是为了构建清晰的项目结构、管理依赖关系,以及实现代码的复用与维护。

    1. CommonJS 与 ES Modules 双模共存

    在现代 Node.js 开发中,我们经常面临两种规范交织的情况。这不仅是文件后缀的改变,更是同步与异步加载逻辑的博弈。

    共存策略:

    1. 后缀决定论.mjs 始终被视为 ESM,.cjs 始终被视为 CJS。
    2. 包定义导向:在 package.json 中设置 "type": "module",则目录下所有 .js 均视为 ESM,反之默认为 CJS。
    3. 互操作性(Interop)
      • ESM 引用 CJS:直接 import 即可,Node 会将 module.exports 包装为默认导出。
      • CJS 引用 ESM:由于 ESM 是异步加载的,CJS 无法使用 require,必须使用 动态 import:const module = await import('./es-module.mjs')

    代码示例

    javascript
    // package.json
     {
       "type": "module"
     }
    @@ -21,4 +21,4 @@ import{_ as i,g as a,h as e,U as n}from"./chunks/vitepress-theme-teek.CqY1sKvl.j
     }

    Monorepo 选型: 虽然 Lerna 曾是标配,但在现代工作流中,pnpm workspaces 凭借其极速的硬链接机制和简洁的配置,已成为 AI 时代开发者(AI-Augmented Builders)的首选。

    yaml
    # pnpm-workspace.yaml
     packages:
       - 'packages/*'
    -  - 'apps/*'

    通过 Monorepo,你可以轻松地在 apps/web 中引用 packages/shared-utils,而无需频繁发布 npm 包。

    4. 模块化架构:分层设计与关注点分离

    随着后端逻辑变厚,单纯的模块拆分已不够,我们需要引入分层架构(Layered Architecture)。

    • API / Controller 层:负责解析请求、参数校验,不触及核心业务。
    • Service 层:系统的灵魂。存放纯粹的业务逻辑,可被多个接口复用。
    • Repository / DAO 层:负责与数据库或外部 API 通信,将数据操作抽象化。
    • Constants, / Types 层:定义全域共用的常量与 TypeScript 契约。

    这种设计的精髓在于:哪怕你从 MySQL 换到了 MongoDB,理论上你只需要修改 Repository 层,而 Service 层的业务代码纹丝不动。

    5. 结语

    Node.js 的模块化实践,是一场从“能跑就行”到“优雅治理”的进化。我们从 CJS 与 ESM 的混战中学会了兼容的艺术,从加载机制中理解了性能的边界,又从 Monorepo 和分层架构中习得了掌控复杂系统的能力。

    模块化不应是开发的负担,而应是你的“工程外骨骼”。一个设计良好的 Node.js 架构,应当像是一组排列整齐、接口严密的精密齿轮——每一个模块都深藏功与名,只通过最精简的接口与外界对话。

    在编写下一行 import 之前,不妨停顿一秒:这个模块的边界清晰吗?它是否承担了不该属于它的因果?当你开始思考这些问题时,你已经从一个“写 Node.js 的人”,进化成为了一个真正的“后端架构守望者”。

    `,31)])])}const g=i(l,[["render",p]]);export{c as __pageData,g as default}; + - 'apps/*'

    通过 Monorepo,你可以轻松地在 apps/web 中引用 packages/shared-utils,而无需频繁发布 npm 包。

    4. 模块化架构:分层设计与关注点分离

    随着后端逻辑变厚,单纯的模块拆分已不够,我们需要引入分层架构(Layered Architecture)。

    • API / Controller 层:负责解析请求、参数校验,不触及核心业务。
    • Service 层:系统的灵魂。存放纯粹的业务逻辑,可被多个接口复用。
    • Repository / DAO 层:负责与数据库或外部 API 通信,将数据操作抽象化。
    • Constants, / Types 层:定义全域共用的常量与 TypeScript 契约。

    这种设计的精髓在于:哪怕你从 MySQL 换到了 MongoDB,理论上你只需要修改 Repository 层,而 Service 层的业务代码纹丝不动。

    5. 结语

    Node.js 的模块化实践,是一场从“能跑就行”到“优雅治理”的进化。我们从 CJS 与 ESM 的混战中学会了兼容的艺术,从加载机制中理解了性能的边界,又从 Monorepo 和分层架构中习得了掌控复杂系统的能力。

    模块化不应是开发的负担,而应是你的“工程外骨骼”。一个设计良好的 Node.js 架构,应当像是一组排列整齐、接口严密的精密齿轮——每一个模块都深藏功与名,只通过最精简的接口与外界对话。

    在编写下一行 import 之前,不妨停顿一秒:这个模块的边界清晰吗?它是否承担了不该属于它的因果?当你开始思考这些问题时,你已经从一个“写 Node.js 的人”,进化成为了一个真正的“后端架构守望者”。

    `,30)])])}const g=i(l,[["render",p]]);export{c as __pageData,g as default}; diff --git "a/assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_6.\350\247\243\346\236\220 NodeJS \344\270\255\347\232\204\346\250\241\345\235\227\345\214\226.md.CGHtK9Bj.lean.js" b/assets/fullstack_nodejs-module-programming-summary.md.CrdU3lTR.lean.js similarity index 76% rename from "assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_6.\350\247\243\346\236\220 NodeJS \344\270\255\347\232\204\346\250\241\345\235\227\345\214\226.md.CGHtK9Bj.lean.js" rename to assets/fullstack_nodejs-module-programming-summary.md.CrdU3lTR.lean.js index b064730b..9e85e0fd 100644 --- "a/assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_6.\350\247\243\346\236\220 NodeJS \344\270\255\347\232\204\346\250\241\345\235\227\345\214\226.md.CGHtK9Bj.lean.js" +++ b/assets/fullstack_nodejs-module-programming-summary.md.CrdU3lTR.lean.js @@ -1 +1 @@ -import{_ as i,g as a,h as e,U as n}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const c=JSON.parse('{"title":"Node.js 模块化编程梳理与总结","description":"解析 Node.js 中 CommonJS 与 ES Modules 的双模共存策略,涵盖模块加载优先级、缓存机制、package.json exports 条件导出及 Monorepo 架构实践。","frontmatter":{"date":"2024-05-17T23:33:09.000Z","title":"Node.js 模块化编程梳理与总结","tldr":"Node.js CJS 与 ESM 双模共存:模块加载机制与分层架构实践。","description":"解析 Node.js 中 CommonJS 与 ES Modules 的双模共存策略,涵盖模块加载优先级、缓存机制、package.json exports 条件导出及 Monorepo 架构实践。","permalink":"/fullstack/nodejs-module-programming-summary","abstract":"Node.js 模块化经历了从 CommonJS 独霸天下到 ES Modules 全面接入的范式转移。共存策略通过 .mjs/.cjs 后缀和 package.json type 字段控制两种规范的边界;ESM 可直接 import CJS(自动包装为默认导出),但 CJS 无法 require ESM 必须使用动态 import。模块加载遵循核心模块优先、文件模块、目录模块(index.js/package.json)、node_modules 逐级查找的优先级;require.cache 实现模块缓存,清除缓存(delete require.cache[path])是热更新工具的核心操作。package.json exports 字段支持条件导出(import/require 返回不同入口)。pnpm workspaces 凭借硬链接机制成为现代 Monorepo 首选。后端分层架构(API/Service/Repository)实现关注点分离,换数据库只需改 Repository 层。","tags":["concept","node.js","commonjs","esm","monorepo","layered-architecture"],"categories":["全栈","全栈基础素养","模块化编程实践指南"]},"headers":[],"relativePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/6.解析 NodeJS 中的模块化.md","filePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/6.解析 NodeJS 中的模块化.md"}'),l={name:"01.全栈/80.全栈基础素养/20.模块化编程实践指南/6.解析 NodeJS 中的模块化.md"};function p(t,s,r,o,h,d){return e(),a("div",null,[...s[0]||(s[0]=[n("",31)])])}const g=i(l,[["render",p]]);export{c as __pageData,g as default}; +import{_ as i,g as a,h as e,U as n}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const c=JSON.parse('{"title":"Node.js 模块化编程梳理与总结","description":"解析 Node.js 中 CommonJS 与 ES Modules 的双模共存策略,涵盖模块加载优先级、缓存机制、package.json exports 条件导出及 Monorepo 架构实践。","frontmatter":{"date":"2024-05-17T23:33:09.000Z","title":"Node.js 模块化编程梳理与总结","tldr":"Node.js CJS 与 ESM 双模共存:模块加载机制与分层架构实践。","description":"解析 Node.js 中 CommonJS 与 ES Modules 的双模共存策略,涵盖模块加载优先级、缓存机制、package.json exports 条件导出及 Monorepo 架构实践。","permalink":"/fullstack/nodejs-module-programming-summary","abstract":"Node.js 模块化经历了从 CommonJS 独霸天下到 ES Modules 全面接入的范式转移。共存策略通过 .mjs/.cjs 后缀和 package.json type 字段控制两种规范的边界;ESM 可直接 import CJS(自动包装为默认导出),但 CJS 无法 require ESM 必须使用动态 import。模块加载遵循核心模块优先、文件模块、目录模块(index.js/package.json)、node_modules 逐级查找的优先级;require.cache 实现模块缓存,清除缓存(delete require.cache[path])是热更新工具的核心操作。package.json exports 字段支持条件导出(import/require 返回不同入口)。pnpm workspaces 凭借硬链接机制成为现代 Monorepo 首选。后端分层架构(API/Service/Repository)实现关注点分离,换数据库只需改 Repository 层。","tags":["concept","node.js","commonjs","esm","monorepo","layered-architecture"],"categories":["全栈","全栈基础素养","模块化编程实践指南"]},"headers":[],"relativePath":"fullstack/nodejs-module-programming-summary.md","filePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/6.解析 NodeJS 中的模块化.md"}'),l={name:"fullstack/nodejs-module-programming-summary.md"};function p(t,s,r,o,h,k){return e(),a("div",null,[...s[0]||(s[0]=[n("",30)])])}const g=i(l,[["render",p]]);export{c as __pageData,g as default}; diff --git "a/assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_00.\345\245\245\345\215\241\345\247\206\345\211\203\345\210\200\345\216\237\345\210\231\357\274\232\344\273\216\347\220\206\350\256\272\345\210\260\347\274\226\347\250\213\350\256\276\350\256\241\347\232\204\345\256\236\350\267\265\346\214\207\345\215\227.md.B1vmVkqI.js" b/assets/fullstack_occams-razor-software-design.md.hjL2O9E6.js similarity index 98% rename from "assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_00.\345\245\245\345\215\241\345\247\206\345\211\203\345\210\200\345\216\237\345\210\231\357\274\232\344\273\216\347\220\206\350\256\272\345\210\260\347\274\226\347\250\213\350\256\276\350\256\241\347\232\204\345\256\236\350\267\265\346\214\207\345\215\227.md.B1vmVkqI.js" rename to assets/fullstack_occams-razor-software-design.md.hjL2O9E6.js index d5fce9da..a7a04c20 100644 --- "a/assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_00.\345\245\245\345\215\241\345\247\206\345\211\203\345\210\200\345\216\237\345\210\231\357\274\232\344\273\216\347\220\206\350\256\272\345\210\260\347\274\226\347\250\213\350\256\276\350\256\241\347\232\204\345\256\236\350\267\265\346\214\207\345\215\227.md.B1vmVkqI.js" +++ b/assets/fullstack_occams-razor-software-design.md.hjL2O9E6.js @@ -1,4 +1,4 @@ -import{H as n}from"./chunks/HighLightText.BFsbuOsY.js";import{g as t,h as l,U as a,i as s,z as e,s as h,S as p}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const k={tabindex:"0"},E=JSON.parse('{"title":"奥卡姆剃刀原则:从理论到编程设计的实践指南","description":"深入解析奥卡姆剃刀原则在编程与设计中的六大场景:拒绝过度预判、移除冗余逻辑、匹配架构规模、克制依赖引入、封装最小接口、先排查简单原因,并给出三个关键边界。","frontmatter":{"date":"2024-03-20T22:41:41.000Z","title":"奥卡姆剃刀原则:从理论到编程设计的实践指南","tldr":"在需求边界内追求最小复杂度——不是拒绝复杂,而是不主动制造复杂。","description":"深入解析奥卡姆剃刀原则在编程与设计中的六大场景:拒绝过度预判、移除冗余逻辑、匹配架构规模、克制依赖引入、封装最小接口、先排查简单原因,并给出三个关键边界。","permalink":"/fullstack/occams-razor-software-design","tags":["concept","engineering-fundamentals","code-design","software-engineering"],"categories":["全栈","全栈基础素养"]},"headers":[],"relativePath":"01.全栈/80.全栈基础素养/00.奥卡姆剃刀原则:从理论到编程设计的实践指南.md","filePath":"01.全栈/80.全栈基础素养/00.奥卡姆剃刀原则:从理论到编程设计的实践指南.md"}'),r={name:"01.全栈/80.全栈基础素养/00.奥卡姆剃刀原则:从理论到编程设计的实践指南.md"},c=Object.assign(r,{setup(d){return(o,i)=>(l(),t("div",null,[i[5]||(i[5]=a('

    奥卡姆剃刀原则:从理论到编程设计的实践指南

    摘要总结:奥卡姆剃刀原则由 14 世纪逻辑学家威廉·奥卡姆提出,其核心为"如无必要,勿增实体"——在多个同等有效的方案中,选择假设最少、最简洁的那个。该原则并非否定复杂性,而是避免无意义的过度设计。文章从编程与设计实践出发,依次探讨了需求实现、代码实现、架构设计、依赖管理、接口设计、调试优化六大场景的反例与正例,并明确指出三个关键边界:不可牺牲可维护性、可扩展性、安全性换取简洁。

    1. 奥卡姆剃刀原则的核心内涵

    "奥卡姆剃刀" 是哲学与科学研究中经典的思维工具,其核心思想可概括为"如无必要,勿增实体"。这一原则由 14 世纪逻辑学家、圣方济各会修士威廉·奥卡姆(William of Ockham)提出,本质是在多个能同等解释现象的理论中,选择假设最少、最简洁的那个——并非否定复杂的可能性,而是优先用简单方案解决问题,避免无意义的"过度设计"。

    要正确应用奥卡姆剃刀,需先理解其三个关键前提:

    ',6)),s("table",k,[i[4]||(i[4]=s("thead",null,[s("tr",null,[s("th",null,"关键前提"),s("th",null,"说明")])],-1)),s("tbody",null,[i[2]||(i[2]=s("tr",null,[s("td",null,[s("strong",null,'"同等有效"是前提')]),s("td",null,'仅当多个方案能实现相同的功能、满足相同的需求时,才用"简洁性"作为筛选标准;若简单方案无法覆盖需求(如安全性、可扩展性),则必须引入复杂设计,不可为了"简"而"简"。')],-1)),i[3]||(i[3]=s("tr",null,[s("td",null,[s("strong",null,'"实体"指"不必要的假设/组件"')]),s("td",null,'例如解释"手机没电","电池耗尽"比"电池故障+系统休眠+充电器接触不良"更简洁,后者多了两个无证据的"实体",应优先排除。')],-1)),s("tr",null,[s("td",null,[e(n,{type:"note",bold:""},{default:h(()=>[...i[0]||(i[0]=[p('"简洁"≠"简陋"',-1)])]),_:1})]),i[1]||(i[1]=s("td",null,'简洁是"去除冗余",而非"省略必要环节"。比如设计登录功能,"账号+密码"是简洁,"仅靠手机号(无验证)"是简陋,后者牺牲了安全性,不符合原则。',-1))])])]),i[6]||(i[6]=a(`

    2. 编程与设计中应用奥卡姆剃刀的核心场景

    在编程(代码实现)和设计(架构、接口、模块)中,"奥卡姆剃刀"的本质是减少"无价值的复杂性"——包括冗余代码、过度抽象、多余依赖、未使用的功能等。以下从六个核心场景展开,结合"反例"与"正例"说明实践方法:

    2.1 场景1:需求实现,拒绝"提前设计未来功能"

    开发中最常见的误区是"过度预判需求":为了"可能用得上"的功能,提前加入复杂逻辑,导致代码臃肿、维护成本升高。奥卡姆剃刀的要求是:只实现"当前明确需要"的功能,未来需求留待未来迭代

    反例(过度设计)

    开发一个"用户个人资料页"时,需求仅要求"展示姓名、手机号、邮箱",但开发者预判"未来可能要加地址、生日、社交账号",于是:

    java
    // 提前定义了大量未使用的字段和方法
    +import{H as n}from"./chunks/HighLightText.BD5ARcjF.js";import{g as t,h as l,U as a,i as s,z as e,s as h,S as p}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const k={tabindex:"0"},E=JSON.parse('{"title":"奥卡姆剃刀原则:从理论到编程设计的实践指南","description":"深入解析奥卡姆剃刀原则在编程与设计中的六大场景:拒绝过度预判、移除冗余逻辑、匹配架构规模、克制依赖引入、封装最小接口、先排查简单原因,并给出三个关键边界。","frontmatter":{"date":"2024-03-20T22:41:41.000Z","title":"奥卡姆剃刀原则:从理论到编程设计的实践指南","tldr":"在需求边界内追求最小复杂度——不是拒绝复杂,而是不主动制造复杂。","description":"深入解析奥卡姆剃刀原则在编程与设计中的六大场景:拒绝过度预判、移除冗余逻辑、匹配架构规模、克制依赖引入、封装最小接口、先排查简单原因,并给出三个关键边界。","permalink":"/fullstack/occams-razor-software-design","tags":["concept","engineering-fundamentals","code-design","software-engineering"],"categories":["全栈","全栈基础素养"]},"headers":[],"relativePath":"fullstack/occams-razor-software-design.md","filePath":"01.全栈/80.全栈基础素养/00.奥卡姆剃刀原则:从理论到编程设计的实践指南.md"}'),r={name:"fullstack/occams-razor-software-design.md"},c=Object.assign(r,{setup(d){return(o,i)=>(l(),t("div",null,[i[5]||(i[5]=a('

    奥卡姆剃刀原则:从理论到编程设计的实践指南

    摘要总结:奥卡姆剃刀原则由 14 世纪逻辑学家威廉·奥卡姆提出,其核心为"如无必要,勿增实体"——在多个同等有效的方案中,选择假设最少、最简洁的那个。该原则并非否定复杂性,而是避免无意义的过度设计。文章从编程与设计实践出发,依次探讨了需求实现、代码实现、架构设计、依赖管理、接口设计、调试优化六大场景的反例与正例,并明确指出三个关键边界:不可牺牲可维护性、可扩展性、安全性换取简洁。

    1. 奥卡姆剃刀原则的核心内涵

    "奥卡姆剃刀" 是哲学与科学研究中经典的思维工具,其核心思想可概括为"如无必要,勿增实体"。这一原则由 14 世纪逻辑学家、圣方济各会修士威廉·奥卡姆(William of Ockham)提出,本质是在多个能同等解释现象的理论中,选择假设最少、最简洁的那个——并非否定复杂的可能性,而是优先用简单方案解决问题,避免无意义的"过度设计"。

    要正确应用奥卡姆剃刀,需先理解其三个关键前提:

    ',5)),s("table",k,[i[4]||(i[4]=s("thead",null,[s("tr",null,[s("th",null,"关键前提"),s("th",null,"说明")])],-1)),s("tbody",null,[i[2]||(i[2]=s("tr",null,[s("td",null,[s("strong",null,'"同等有效"是前提')]),s("td",null,'仅当多个方案能实现相同的功能、满足相同的需求时,才用"简洁性"作为筛选标准;若简单方案无法覆盖需求(如安全性、可扩展性),则必须引入复杂设计,不可为了"简"而"简"。')],-1)),i[3]||(i[3]=s("tr",null,[s("td",null,[s("strong",null,'"实体"指"不必要的假设/组件"')]),s("td",null,'例如解释"手机没电","电池耗尽"比"电池故障+系统休眠+充电器接触不良"更简洁,后者多了两个无证据的"实体",应优先排除。')],-1)),s("tr",null,[s("td",null,[e(n,{type:"note",bold:""},{default:h(()=>[...i[0]||(i[0]=[p('"简洁"≠"简陋"',-1)])]),_:1})]),i[1]||(i[1]=s("td",null,'简洁是"去除冗余",而非"省略必要环节"。比如设计登录功能,"账号+密码"是简洁,"仅靠手机号(无验证)"是简陋,后者牺牲了安全性,不符合原则。',-1))])])]),i[6]||(i[6]=a(`

    2. 编程与设计中应用奥卡姆剃刀的核心场景

    在编程(代码实现)和设计(架构、接口、模块)中,"奥卡姆剃刀"的本质是减少"无价值的复杂性"——包括冗余代码、过度抽象、多余依赖、未使用的功能等。以下从六个核心场景展开,结合"反例"与"正例"说明实践方法:

    2.1 场景1:需求实现,拒绝"提前设计未来功能"

    开发中最常见的误区是"过度预判需求":为了"可能用得上"的功能,提前加入复杂逻辑,导致代码臃肿、维护成本升高。奥卡姆剃刀的要求是:只实现"当前明确需要"的功能,未来需求留待未来迭代

    反例(过度设计)

    开发一个"用户个人资料页"时,需求仅要求"展示姓名、手机号、邮箱",但开发者预判"未来可能要加地址、生日、社交账号",于是:

    java
    // 提前定义了大量未使用的字段和方法
     public class UserProfile {
         private String name;       // 必用
         private String phone;      // 必用
    diff --git a/assets/fullstack_occams-razor-software-design.md.hjL2O9E6.lean.js b/assets/fullstack_occams-razor-software-design.md.hjL2O9E6.lean.js
    new file mode 100644
    index 00000000..0813ed80
    --- /dev/null
    +++ b/assets/fullstack_occams-razor-software-design.md.hjL2O9E6.lean.js
    @@ -0,0 +1 @@
    +import{H as n}from"./chunks/HighLightText.BD5ARcjF.js";import{g as t,h as l,U as a,i as s,z as e,s as h,S as p}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const k={tabindex:"0"},E=JSON.parse('{"title":"奥卡姆剃刀原则:从理论到编程设计的实践指南","description":"深入解析奥卡姆剃刀原则在编程与设计中的六大场景:拒绝过度预判、移除冗余逻辑、匹配架构规模、克制依赖引入、封装最小接口、先排查简单原因,并给出三个关键边界。","frontmatter":{"date":"2024-03-20T22:41:41.000Z","title":"奥卡姆剃刀原则:从理论到编程设计的实践指南","tldr":"在需求边界内追求最小复杂度——不是拒绝复杂,而是不主动制造复杂。","description":"深入解析奥卡姆剃刀原则在编程与设计中的六大场景:拒绝过度预判、移除冗余逻辑、匹配架构规模、克制依赖引入、封装最小接口、先排查简单原因,并给出三个关键边界。","permalink":"/fullstack/occams-razor-software-design","tags":["concept","engineering-fundamentals","code-design","software-engineering"],"categories":["全栈","全栈基础素养"]},"headers":[],"relativePath":"fullstack/occams-razor-software-design.md","filePath":"01.全栈/80.全栈基础素养/00.奥卡姆剃刀原则:从理论到编程设计的实践指南.md"}'),r={name:"fullstack/occams-razor-software-design.md"},c=Object.assign(r,{setup(d){return(o,i)=>(l(),t("div",null,[i[5]||(i[5]=a("",5)),s("table",k,[i[4]||(i[4]=s("thead",null,[s("tr",null,[s("th",null,"关键前提"),s("th",null,"说明")])],-1)),s("tbody",null,[i[2]||(i[2]=s("tr",null,[s("td",null,[s("strong",null,'"同等有效"是前提')]),s("td",null,'仅当多个方案能实现相同的功能、满足相同的需求时,才用"简洁性"作为筛选标准;若简单方案无法覆盖需求(如安全性、可扩展性),则必须引入复杂设计,不可为了"简"而"简"。')],-1)),i[3]||(i[3]=s("tr",null,[s("td",null,[s("strong",null,'"实体"指"不必要的假设/组件"')]),s("td",null,'例如解释"手机没电","电池耗尽"比"电池故障+系统休眠+充电器接触不良"更简洁,后者多了两个无证据的"实体",应优先排除。')],-1)),s("tr",null,[s("td",null,[e(n,{type:"note",bold:""},{default:h(()=>[...i[0]||(i[0]=[p('"简洁"≠"简陋"',-1)])]),_:1})]),i[1]||(i[1]=s("td",null,'简洁是"去除冗余",而非"省略必要环节"。比如设计登录功能,"账号+密码"是简洁,"仅靠手机号(无验证)"是简陋,后者牺牲了安全性,不符合原则。',-1))])])]),i[6]||(i[6]=a("",60))]))}});export{E as __pageData,c as default};
    diff --git a/assets/fullstack_overview.md.Cxlo3Aed.js b/assets/fullstack_overview.md.Cxlo3Aed.js
    new file mode 100644
    index 00000000..ba3d1e47
    --- /dev/null
    +++ b/assets/fullstack_overview.md.Cxlo3Aed.js
    @@ -0,0 +1 @@
    +import{A as i}from"./chunks/ArticleCardList.DLUMmOfr.js";import{g as c,h as l,i as t,z as a,S as r,l as s}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const o=[{id:"ai-native",title:"AI Native 工程思维",icon:"🤖",color:"#a855f7",articles:[{title:"不止于代码:构建 AI 时代全栈工程师的“认知三层塔”",url:"/fullstack/ai-native",description:"在 AI 重塑软件工程的今天,全栈不再是技术的线性叠加,正在从“技术栈堆砌”转向“认知栈重构”。本文提出 “(工程 + 产品) × AI” 的新公式,助力开发者构建“洞察-架构-杠杆”认知三层塔,利用 AI 杠杆让自己进化为价值创造者。"},{title:"重构开发者:AI 时代下的工程师能力图谱与演进指南",url:"/fullstack/ai-engineer-capability",description:""},{title:"读 Anthropic 研究报告,探寻 AI 时代的工程范式重塑",url:"/fullstack/ai-change-work-workflow",description:"本文深度解读了 Anthropic 发布的里程碑报告《AI 如何改变 Anthropic 的工作方式》。我们正处于软件工程史上的又一次“抽象层大迁徙”——当编码成本趋于零,真正的挑战不再是“快”,而是如何对抗“平庸化”与“随机性”。"}]},{id:"ai-coding-guides",title:"AI 编程实践指南",icon:"✨",color:"#c084fc",articles:[{title:"AI 编程工具推荐",url:"/fullstack/ai-coding/resources",description:"本文系统梳理 AI 驱动编程的三大演进范式:Vibe Coding(自然语言零门槛构建)、AI IDE(编辑器深度辅助提效)及 Agentic Engineering(自主工程师执行任务)。并推了对应的主流 AI 编程工具与资源。"}]},{id:"frontend-engineering",title:"前端工程",icon:"🎨",color:"#f59e0b",articles:[{title:"React 设计哲学:AI 协作时代的组件化开发实践指南",url:"/fullstack/react-design-philosophy-ai-augmented",description:"当 AI 承接了 30% 的编码执行时,开发者需通过“规格驱动(SDD)”重夺 70% 的设计主权:从自治组件划分到单向数据流拓扑的深度推演。"},{title:"不止于 Fetch:React 服务端状态管理的范式转移与选型深度博弈",url:"/fullstack/server-state-management",description:"本文深度对比 React 生态中 SWR 与 TanStack Query 两大方案。从 stale-while-revalidate 机制到异步状态机架构,涵盖依赖查询、数据转换及架构级乐观更新实战。旨在帮助开发者在复杂业务中构建确定性的服务端状态基座。"},{title:"从原子化到变体驱动:现代 CSS 工程化的架构演进与混合实践指南",url:"/fullstack/css-engineering",description:"本文系统剖析主流 CSS 工程化方案的底层逻辑,提出“样式资产 ROI”评估模型,并针对 Vue/React 生态给出了面向 AI 时代的企业级混合架构选型建议。"},{title:"JAMStack 梳理与实践指南",url:"/fullstack/jamstack",description:"预渲染静态页面 + 动态 API,CDN 分发全球,替代传统动态网站的开发部署范式。 从核心概念、工具链选型(Next.js/Vercel/Supabase/Contentful)到从 0 搭建博客的完整实践,覆盖 JAMStack 适用与不适用场景,帮助判断何时选用该架构。"}]},{id:"fullstack-networking",title:"网络与通信",icon:"🌐",color:"#0ea5e9",articles:[{title:"Web 通信协议全景:从 HTTP 到 WebSocket 的技术选型指南",url:"/fullstack/networking-protocol-selection-guide",description:"文本深入剖析传统 HTTP、流式 HTTP、SSE、WebSocket、Webhooks、HTTP 轮询的原理与特性,结合 AI 场景提供技术选型决策矩阵"},{title:"流式 HTTP 与 SSE 协议:从概念辨析到生产实践",url:"/fullstack/networking-sse-practice",description:"本文辨析流式 HTTP 与 SSE 协议的概念与层次关系,详解客户端与服务端实现方案,提供生产实践完整指南。"},{title:"HTTP 轮询优化指南:退避轮询与长轮询的原理、实战与选型决策",url:"/fullstack/networking-polling-optimization",description:"针对传统固定频率轮询的服务器资源浪费问题,系统分析退避轮询与长轮询两种优化策略的核心原理与运行机制,提供 TypeScript/NestJS 实战代码,并构建技术选型决策树与适用场景速查。"}]},{id:"fullstack-basic",title:"全栈基础素养",icon:"📚",color:"#64748b",articles:[{title:"奥卡姆剃刀原则:从理论到编程设计的实践指南",url:"/fullstack/occams-razor-software-design",description:"在需求边界内追求最小复杂度——不是拒绝复杂,而是不主动制造复杂。本文深入解析奥卡姆剃刀原则在编程与设计中的六大场景:拒绝过度预判、移除冗余逻辑、匹配架构规模、克制依赖引入、封装最小接口、先排查简单原因,并给出三个关键边界。"},{title:"模块化编程实践指南",url:"/fullstack/module-programming-practice-guide",description:"系统梳理 JavaScript 模块化演进(IIFE→CJS→ESM)、TypeScript 类型增强、分层架构与 DDD 实践。从 ES Modules 到大型项目分层架构与工程化实践,构建全栈模块化知识体系。"},{title:"TypeScript 编译与调试完全指南",url:"/fullstack/typescript-compilation-debugging-guide",description:"TypeScript 完善的编译体系与调试工具链,是构建高质量应用的基石。本文深入解析 TypeScript 编译工具链与调试体系,涵盖 tsconfig.json 核心配置、Monorepo 项目配置(extends/references)、source map 调试、ESLint 与 Jest 单元测试等完整实践。"},{title:"聊一聊 TypeScript 中的泛型",url:"/fullstack/typescript-generic-types",description:"泛型将类型作为参数,使代码在多种类型上安全运行,是 TypeScript 类型抽象的核心特性。"}]},{id:"fullstack-resources",title:"工具与资源推荐",icon:"🔧",color:"#0ea5e9",articles:[{title:"全栈技术资源推荐",url:"/fullstack/full-stack-resources",description:"本文系统梳理了现代全栈开发的完整技术图谱与演进范式,为开发者提供了一站式的技术选型指南。文章从基石出发,覆盖 Web 核心语言(JS/TS) 与 主流 UI 框架(React/Vue/Svelte),并推荐以 Tailwind CSS 和 shadcn/ui 为代表的现代样式与组件原语。在核心业务逻辑层,深度对比了轻量化状态管理方案(首推 Zustand/Jotai),并重点解析了数据交互的三大现代架构范式:从基础 Axios 到 React Query 状态调度,再到 tRPC 和 GraphQL 带来的全栈类型安全与多端聚合。在工程化与服务端模块,文章全面拥抱 Vite、Rsbuild 等极速构建工具,并剖析了 Next.js/Nuxt 同构元框架与 NestJS 企业级 Node 服务的最佳适用场景。最后,辅以 Vercel 等现代边缘部署平台及丰富的开源社区学习资源。"}]}],g=JSON.parse('{"title":"全景一览","description":"本系列围绕现代全栈开发的能力体系展开,从 AI 时代的工程思维出发,覆盖前端工程(React/Vue/CSS)、全栈基础素养(TypeScript/JavaScript)、工具与资源推荐等核心领域,帮助构建从\\"认知层 → 技术领域 → 工程能力 → 基础设施\\"的完整全栈知识图谱。","frontmatter":{"date":"2026-03-19T23:05:50.000Z","title":"全景一览","description":"本系列围绕现代全栈开发的能力体系展开,从 AI 时代的工程思维出发,覆盖前端工程(React/Vue/CSS)、全栈基础素养(TypeScript/JavaScript)、工具与资源推荐等核心领域,帮助构建从\\"认知层 → 技术领域 → 工程能力 → 基础设施\\"的完整全栈知识图谱。","categories":["全栈"],"coverImg":"https://insight-stack-1252300811.cos.ap-shanghai.myqcloud.com/img/full-stack/insight_stack.png","permalink":"/fullstack/overview"},"headers":[],"relativePath":"fullstack/overview.md","filePath":"01.全栈/00.overview.md"}'),n={name:"fullstack/overview.md"},k=Object.assign(n,{setup(p){return(u,e)=>(l(),c("div",null,[e[0]||(e[0]=t("h1",{id:"全景一览",tabindex:"-1"},[r("全景一览 "),t("a",{class:"header-anchor",href:"#全景一览","aria-label":"Permalink to “全景一览”"},"​")],-1)),a(i,{categories:s(o)},null,8,["categories"])]))}});export{g as __pageData,k as default};
    diff --git a/assets/fullstack_overview.md.Cxlo3Aed.lean.js b/assets/fullstack_overview.md.Cxlo3Aed.lean.js
    new file mode 100644
    index 00000000..ba3d1e47
    --- /dev/null
    +++ b/assets/fullstack_overview.md.Cxlo3Aed.lean.js
    @@ -0,0 +1 @@
    +import{A as i}from"./chunks/ArticleCardList.DLUMmOfr.js";import{g as c,h as l,i as t,z as a,S as r,l as s}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const o=[{id:"ai-native",title:"AI Native 工程思维",icon:"🤖",color:"#a855f7",articles:[{title:"不止于代码:构建 AI 时代全栈工程师的“认知三层塔”",url:"/fullstack/ai-native",description:"在 AI 重塑软件工程的今天,全栈不再是技术的线性叠加,正在从“技术栈堆砌”转向“认知栈重构”。本文提出 “(工程 + 产品) × AI” 的新公式,助力开发者构建“洞察-架构-杠杆”认知三层塔,利用 AI 杠杆让自己进化为价值创造者。"},{title:"重构开发者:AI 时代下的工程师能力图谱与演进指南",url:"/fullstack/ai-engineer-capability",description:""},{title:"读 Anthropic 研究报告,探寻 AI 时代的工程范式重塑",url:"/fullstack/ai-change-work-workflow",description:"本文深度解读了 Anthropic 发布的里程碑报告《AI 如何改变 Anthropic 的工作方式》。我们正处于软件工程史上的又一次“抽象层大迁徙”——当编码成本趋于零,真正的挑战不再是“快”,而是如何对抗“平庸化”与“随机性”。"}]},{id:"ai-coding-guides",title:"AI 编程实践指南",icon:"✨",color:"#c084fc",articles:[{title:"AI 编程工具推荐",url:"/fullstack/ai-coding/resources",description:"本文系统梳理 AI 驱动编程的三大演进范式:Vibe Coding(自然语言零门槛构建)、AI IDE(编辑器深度辅助提效)及 Agentic Engineering(自主工程师执行任务)。并推了对应的主流 AI 编程工具与资源。"}]},{id:"frontend-engineering",title:"前端工程",icon:"🎨",color:"#f59e0b",articles:[{title:"React 设计哲学:AI 协作时代的组件化开发实践指南",url:"/fullstack/react-design-philosophy-ai-augmented",description:"当 AI 承接了 30% 的编码执行时,开发者需通过“规格驱动(SDD)”重夺 70% 的设计主权:从自治组件划分到单向数据流拓扑的深度推演。"},{title:"不止于 Fetch:React 服务端状态管理的范式转移与选型深度博弈",url:"/fullstack/server-state-management",description:"本文深度对比 React 生态中 SWR 与 TanStack Query 两大方案。从 stale-while-revalidate 机制到异步状态机架构,涵盖依赖查询、数据转换及架构级乐观更新实战。旨在帮助开发者在复杂业务中构建确定性的服务端状态基座。"},{title:"从原子化到变体驱动:现代 CSS 工程化的架构演进与混合实践指南",url:"/fullstack/css-engineering",description:"本文系统剖析主流 CSS 工程化方案的底层逻辑,提出“样式资产 ROI”评估模型,并针对 Vue/React 生态给出了面向 AI 时代的企业级混合架构选型建议。"},{title:"JAMStack 梳理与实践指南",url:"/fullstack/jamstack",description:"预渲染静态页面 + 动态 API,CDN 分发全球,替代传统动态网站的开发部署范式。 从核心概念、工具链选型(Next.js/Vercel/Supabase/Contentful)到从 0 搭建博客的完整实践,覆盖 JAMStack 适用与不适用场景,帮助判断何时选用该架构。"}]},{id:"fullstack-networking",title:"网络与通信",icon:"🌐",color:"#0ea5e9",articles:[{title:"Web 通信协议全景:从 HTTP 到 WebSocket 的技术选型指南",url:"/fullstack/networking-protocol-selection-guide",description:"文本深入剖析传统 HTTP、流式 HTTP、SSE、WebSocket、Webhooks、HTTP 轮询的原理与特性,结合 AI 场景提供技术选型决策矩阵"},{title:"流式 HTTP 与 SSE 协议:从概念辨析到生产实践",url:"/fullstack/networking-sse-practice",description:"本文辨析流式 HTTP 与 SSE 协议的概念与层次关系,详解客户端与服务端实现方案,提供生产实践完整指南。"},{title:"HTTP 轮询优化指南:退避轮询与长轮询的原理、实战与选型决策",url:"/fullstack/networking-polling-optimization",description:"针对传统固定频率轮询的服务器资源浪费问题,系统分析退避轮询与长轮询两种优化策略的核心原理与运行机制,提供 TypeScript/NestJS 实战代码,并构建技术选型决策树与适用场景速查。"}]},{id:"fullstack-basic",title:"全栈基础素养",icon:"📚",color:"#64748b",articles:[{title:"奥卡姆剃刀原则:从理论到编程设计的实践指南",url:"/fullstack/occams-razor-software-design",description:"在需求边界内追求最小复杂度——不是拒绝复杂,而是不主动制造复杂。本文深入解析奥卡姆剃刀原则在编程与设计中的六大场景:拒绝过度预判、移除冗余逻辑、匹配架构规模、克制依赖引入、封装最小接口、先排查简单原因,并给出三个关键边界。"},{title:"模块化编程实践指南",url:"/fullstack/module-programming-practice-guide",description:"系统梳理 JavaScript 模块化演进(IIFE→CJS→ESM)、TypeScript 类型增强、分层架构与 DDD 实践。从 ES Modules 到大型项目分层架构与工程化实践,构建全栈模块化知识体系。"},{title:"TypeScript 编译与调试完全指南",url:"/fullstack/typescript-compilation-debugging-guide",description:"TypeScript 完善的编译体系与调试工具链,是构建高质量应用的基石。本文深入解析 TypeScript 编译工具链与调试体系,涵盖 tsconfig.json 核心配置、Monorepo 项目配置(extends/references)、source map 调试、ESLint 与 Jest 单元测试等完整实践。"},{title:"聊一聊 TypeScript 中的泛型",url:"/fullstack/typescript-generic-types",description:"泛型将类型作为参数,使代码在多种类型上安全运行,是 TypeScript 类型抽象的核心特性。"}]},{id:"fullstack-resources",title:"工具与资源推荐",icon:"🔧",color:"#0ea5e9",articles:[{title:"全栈技术资源推荐",url:"/fullstack/full-stack-resources",description:"本文系统梳理了现代全栈开发的完整技术图谱与演进范式,为开发者提供了一站式的技术选型指南。文章从基石出发,覆盖 Web 核心语言(JS/TS) 与 主流 UI 框架(React/Vue/Svelte),并推荐以 Tailwind CSS 和 shadcn/ui 为代表的现代样式与组件原语。在核心业务逻辑层,深度对比了轻量化状态管理方案(首推 Zustand/Jotai),并重点解析了数据交互的三大现代架构范式:从基础 Axios 到 React Query 状态调度,再到 tRPC 和 GraphQL 带来的全栈类型安全与多端聚合。在工程化与服务端模块,文章全面拥抱 Vite、Rsbuild 等极速构建工具,并剖析了 Next.js/Nuxt 同构元框架与 NestJS 企业级 Node 服务的最佳适用场景。最后,辅以 Vercel 等现代边缘部署平台及丰富的开源社区学习资源。"}]}],g=JSON.parse('{"title":"全景一览","description":"本系列围绕现代全栈开发的能力体系展开,从 AI 时代的工程思维出发,覆盖前端工程(React/Vue/CSS)、全栈基础素养(TypeScript/JavaScript)、工具与资源推荐等核心领域,帮助构建从\\"认知层 → 技术领域 → 工程能力 → 基础设施\\"的完整全栈知识图谱。","frontmatter":{"date":"2026-03-19T23:05:50.000Z","title":"全景一览","description":"本系列围绕现代全栈开发的能力体系展开,从 AI 时代的工程思维出发,覆盖前端工程(React/Vue/CSS)、全栈基础素养(TypeScript/JavaScript)、工具与资源推荐等核心领域,帮助构建从\\"认知层 → 技术领域 → 工程能力 → 基础设施\\"的完整全栈知识图谱。","categories":["全栈"],"coverImg":"https://insight-stack-1252300811.cos.ap-shanghai.myqcloud.com/img/full-stack/insight_stack.png","permalink":"/fullstack/overview"},"headers":[],"relativePath":"fullstack/overview.md","filePath":"01.全栈/00.overview.md"}'),n={name:"fullstack/overview.md"},k=Object.assign(n,{setup(p){return(u,e)=>(l(),c("div",null,[e[0]||(e[0]=t("h1",{id:"全景一览",tabindex:"-1"},[r("全景一览 "),t("a",{class:"header-anchor",href:"#全景一览","aria-label":"Permalink to “全景一览”"},"​")],-1)),a(i,{categories:s(o)},null,8,["categories"])]))}});export{g as __pageData,k as default};
    diff --git a/assets/fullstack_react-design-philosophy-ai-augmented.md.CMWFdXhO.js b/assets/fullstack_react-design-philosophy-ai-augmented.md.CMWFdXhO.js
    new file mode 100644
    index 00000000..50365bde
    --- /dev/null
    +++ b/assets/fullstack_react-design-philosophy-ai-augmented.md.CMWFdXhO.js
    @@ -0,0 +1 @@
    +import{H as r}from"./chunks/HighLightText.BD5ARcjF.js";import{g as s,h as n,i as o,z as l,U as i,S as e,s as a}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const D=JSON.parse('{"title":"React 设计哲学:AI 协作时代的组件化开发实践指南","description":"本文探讨在 AI 增强开发背景下,如何重塑 React 组件设计原则。涵盖 SRP 职责划分、静态版本基线、最小状态(Derived Data)推导以及 SDD 人机协作模式的工程落地。","frontmatter":{"date":"2026-02-10T23:33:19.000Z","title":"React 设计哲学:AI 协作时代的组件化开发实践指南","tldr":"当 AI 承接了 30% 的编码执行时,开发者需通过“规格驱动(SDD)”重夺 70% 的设计主权:从自治组件划分到单向数据流拓扑的深度推演。","description":"本文探讨在 AI 增强开发背景下,如何重塑 React 组件设计原则。涵盖 SRP 职责划分、静态版本基线、最小状态(Derived Data)推导以及 SDD 人机协作模式的工程落地。","tags":["tutorial","react","component-design","state-management","ai-augmented","specification-driven"],"permalink":"/fullstack/react-design-philosophy-ai-augmented","categories":["全栈","前端工程"]},"headers":[],"relativePath":"fullstack/react-design-philosophy-ai-augmented.md","filePath":"01.全栈/40.前端工程/01.React 设计哲学:AI 协作时代的组件化开发实践指南.md"}'),g={name:"fullstack/react-design-philosophy-ai-augmented.md"},I=Object.assign(g,{setup(d){return(p,t)=>(n(),s("div",null,[t[10]||(t[10]=o("h1",{id:"react-设计哲学-ai-协作时代的组件化开发实践指南",tabindex:"-1"},[e("React 设计哲学:AI 协作时代的组件化开发实践指南 "),o("a",{class:"header-anchor",href:"#react-设计哲学-ai-协作时代的组件化开发实践指南","aria-label":"Permalink to “React 设计哲学:AI 协作时代的组件化开发实践指南”"},"​")],-1)),t[11]||(t[11]=o("h2",{id:"_1-引言",tabindex:"-1"},[e("1. 引言 "),o("a",{class:"header-anchor",href:"#_1-引言","aria-label":"Permalink to “1. 引言”"},"​")],-1)),o("p",null,[t[1]||(t[1]=e("在软件工程中,约 70% 的时间应投入于架构设计、需求拆解与接口语义推敲,仅 30% 用于实际编码。进入 AI 协作时代后,这一比例依然坚如磐石——开发者必须先完成深度思考,将“清晰的问题规格(Specification)”交给 AI,AI 才能输出高质量代码。",-1)),l(r,{type:"note",bold:""},{default:a(()=>[...t[0]||(t[0]=[e("AI 提升的是 30% 编码阶段的执行力,而非取代 70% 的架构裁决",-1)])]),_:1}),t[2]||(t[2]=e("。 高质量 React 应用的诞生,依然始于人类心智对数据流、副作用边界与可组合性的透彻推演。",-1))]),t[12]||(t[12]=o("p",null,'然而,真正驾驭 React 并非易事。许多团队在项目初期享受着组件化带来的快感,却在业务膨胀后陷入"组件地狱"——深嵌套的 prop drilling、失控的状态蔓延、难以追踪的副作用,让代码库逐渐腐化。问题的根源往往不在于 React 本身,而在于我们是否真正理解其背后的设计哲学。',-1)),l(r,{bold:""},{default:a(()=>[...t[3]||(t[3]=[e("React 的精髓在于以组件化为核心,将复杂的 UI 拆解为独立、可复用的自治单元,让数据沿着从输入(props)到输出(UI 元素)的轨迹形成清晰、可控的闭环",-1)])]),_:1}),t[13]||(t[13]=i('。为确保项目的可维护性与抗腐化能力,React 开发者应将以下标准内化为肌肉记忆:
    检查项核心标准架构目标
    1. 单一职责每个组件是否只做一件事(纯布局或纯逻辑)?控制认知复杂度,防止组件“上帝化”
    2. 组合优先是否优先使用了 children 或 Props 传递子组件?消除 Prop Drilling,提升灵活性
    3. DOM 扁平是否利用 <>...</> 移除了所有非必要的包装 <div>减小渲染开销,保持 DOM 树纯粹
    4. 拥抱 Hooks是否已用 Custom Hooks 替代了 HOC 嵌套?展平组件树,实现逻辑与视图的物理隔离

    2. 划分具备分层结构的“自治”组件

    组件是 React 对“关注点分离”这一软件工程经典原则的具象化落地。它将 UI 拆分为若干自治单元,每个单元对外仅暴露 props 契约,对内通过 state 管理自身行为。

    划分组件必须恪守单一职责(SRP)高内聚低耦合两条铁律:

    • 一事一议:理想状态下,一个组件只负责渲染一块特定的视觉或封装一类特定的交互。随着功能膨胀,必须果断将其裂变为更细粒度的子组件。
    • 显式通信:组件间仅通过 props 与回调通信,杜绝任何形式的隐式状态共享。

    在实践中,我们可以通过以下策略压平组件层级,维持架构的清爽:

    策略说明
    角色界定容器组件(Container):充当"调度中心",负责数据获取、状态管理与业务逻辑,随后将干净的数据流入子组件。避免在容器中混杂复杂的 DOM 结构,利用 Custom Hooks 抽离逻辑,能让 UI 层级瞬间变薄。
    展示组件(Presentational):充当"纯函数",专注于接收 props 并渲染视图,保持 DOM 结构的极度扁平。
    组合优于嵌套这是解决组件树过深的最强武器。永远不要在组件内部硬编码子组件,而是通过 children 或 render props,将子组件作为参数注入。这在语义上形成了一种"声明式 DSL",让代码本身成为直观的 UI 蓝图。
    极简接口组件的 props 契约应绝对最小化,仅暴露必要的输入。

    AI 协作小洞察:

    我们要先划分层级结构,不应该让 AI 盲目写代码,可以先让它充当“架构助理”进行结构划分与设计:

    • 投喂需求与视觉规格,提供需求描述或 UI 视觉稿截图,要求 AI(如 ChatGPT、Claude 等)辅助分析并输出组件层级树,同时解释其职责划分与层级结构设计的思路。
    • 定义职责约束,在 Prompt 中明确要求 AI 区分"容器组件"与"展示组件",并遵循单一职责原则为其命名——这既能启发思路,也能提前规避命名不当的问题。
    • 人工裁决,评估 AI 输出的结构,微调边界,确保这套“骨架”足够健壮,再进入下一步的实质性编码。

    3. 构建纯渲染的静态版本:确立工程基线

    在状态与交互介入之前,我们可以先用“数据占位符”把 UI 的纯渲染路径跑通,构建一个剥离了所有动态行为的“静态版本”。此过程不需要过多的逻辑烧脑,而是纯粹的结构编码。

    静态版本应保证组件无副作用,能为后续快照测试、服务端渲染(SSR)与 hydration 奠定可靠基础。这一步的工程价值不可估量:

    • 契约验证:强制检验当前的 props 设计是否足以表达所有的视觉状态差异。
    • 前置对齐:让设计师和产品提前验收“像素级”静态产物,规避后期可能出现的视觉返工。
    • 可信基线:为后续增量引入状态(State)与副作用(Effects)提供了一个随时可回滚的基线

    在编写代码时,我们通常采用“自顶向下”的构建顺序,即从顶层容器开始,逐层向叶子节点实现。这种策略能确保组件职责清晰,不会过早陷入局部细节,同时保证每个模块都是独立、可测试的。

    当然,在 AI 协作时代,借助 AI 生成静态版本无疑是更为高效的方式。但我们不建议直接采用全自动化构建作为最终方案——毕竟静态版本是整个项目的工程基线,一旦存在隐蔽缺陷,将为后续迭代埋下隐患。

    更稳健的做法是将全自动化与半自动化并行推进:先让 AI 基于第一阶段评审通过的组件划分树与职责描述,在独立分支中全自动化生成代码;与此同时,开发者在正式分支中以半自动化方式逐步搭建。由于全自动化产出速度极快,我们可以横向对比多份生成结果,择优验证后再整合到正式项目中。这种"边做边验"的模式,既能提升基线质量,也能加深开发者对架构的理解。

    进入静态版本构建阶段,我们需要关注以下三个关键环节:

    1、前置步骤:脚手架生成
    首先利用 AI 编程工具(如 Claude Code / Codex)快速初始化项目结构与配置文件。这一步是后续全自动化与半自动化并行模式的基础——AI 在标准化脚手架搭建上效率极高,能够迅速为我们铺好工程地基。

    2、注入规格,启动双轨模式
    将第一阶段确认好的"组件层级树与职责描述"作为明确的 Specification 喂给 AI,令其批量生成符合 React 规范的静态组件骨架。此时全自动化与半自动化两条线并行推进:AI 在独立分支快速产出多份候选代码,开发者则在主干分支逐步搭建,形成可对比、可验证的协作闭环。

    3、人机结对审查
    横向对比 AI 的自动化产出后,择优与人工代码融合,重点 Review 是否真正做到"无副作用"与"幂等渲染"。过程中也可让 AI 与人工协作,一旦发现问题或异常情况,立即通过对话纠正,确保这份静态基线的绝对纯粹——它将是后续引入状态与副作用时唯一可信的回滚锚点。

    4. 寻找状态的最简表示,敲定拓扑位置

    4.1 什么是 State?什么是 Derived Data(派生数据)?

    State 本质上是对应用随时间变化产生的差异的建模,为正确地构建应用,让应用可控,我们需要在这一阶段找出驱动 UI 运转的 State(状态)的最小完整集合

    在定义 State 之前,先做灵魂三问。先问自己三个关键问题。如果满足以下任何一条,它就绝对不是 State

    1. 随时间推移保持不变? (如静态配置) -> 不是 State。
    2. 通过 props 从父级传入? (如外部注入的数据) -> 不是 State。
    3. 能通过已有 State 或 props 计算得出? (如根据商品列表计算出的库存总量) -> 坚决不能作为 State。

    这些可通过计算得出的数据被称为 Derived Data(派生数据)。正确的做法是在渲染期间动态计算它们,或使用 useMemo 进行性能优化,而不是将其塞入 useState 中徒增同步烦恼。

    一份合格的状态必须:最小(剔除可推导字段)且完整(下游 UI 能基于此状态集合进行确定性渲染)。

    4.2 敲定 State 的安放位置

    小提示:防范状态爆炸与泄漏

    • 单一真实数据源:同一业务实体在组件树中只能存在一份状态副本。如果祖先节点已有,就通过 props 传递,严禁在不同组件内重复 useState
    • 无泄漏下沉:把状态隔离在局部子树时,必须显式定义读写边界——仅对真正需要的子孙暴露接口。禁止在模块顶层声明可变状态,防止状态隐式穿透组件边界。

    确定了“是什么”之后,更关键的是“放在哪”。State 的安置需要在状态提升(Lifting State Up)状态下沉(Colocating State)之间寻找动态平衡:

    • 状态提升(Lifting State Up):若多个兄弟组件需要共享同一状态,毫不犹豫地将其提升至它们最近的公共父节点。
    • 状态下沉(Colocating State):若状态仅在特定子树内部流转,应通过局部 Context 或轻量级状态库(Zustand / Jotai)将其隔离,避免污染全局。

    架构目标是绘制出一张清晰的数据流拓扑图:状态变更只沿单向轨道流动,出现 Bug 时,可以像排查电路图一样用万用表逐点测量。

    4. 建立反向数据流:让回调成为刚性契约

    React 的数据流天然是自顶向下的(Top-Down)。这种单向流动牺牲了双向绑定的“便捷性”,换来的是数据流转的绝对清晰与可预测性

    当底层展示组件需要向上级反馈用户行为时,我们需要设计反向数据流,其本质是将“UI 事件”转化为严谨的“回调契约”

    1. 父组件通过 props 向子组件下发契约:onXxx: (data: T) => void
    2. 子组件在适当时机触发契约,但不关心父组件如何处理,借此维持自身的纯粹与解耦。
    3. 父组件在回调中执行 setState,触发自顶向下的重新渲染,完成闭环。

    这种 事件 -> 回调 -> 状态突变 -> 重渲染 的循环,构成了 React 响应式架构的最小内核。面对跨层级通信时,可以引入 Context 或状态管理工具来收敛"回调地狱",但单向数据流的铁律绝不能被破坏

    5. 规范驱动开发(SDD):从执行者转变为立法者

    随着前四个阶段的稳步推进,基础架构已然确立,应用项目也进入了更深层次的开发迭代阶段。此时,如何高效地解决"怎么写"的问题?这正是 AI 协作编程大显身手的时刻。

    规范驱动开发(Specification-Driven Development,SDD)是一种比 Vibe Coding 更为可靠的人机协作实践模式:人类负责制定规范,AI 负责实现代码。这种分工让开发者从繁琐的编码劳动中解放出来,专注于真正创造价值的方案选择与设计决策。

    5.1 SDD 模式的核心流程与实践要点

    SDD 模式遵循一个五步闭环:规划阶段 → 生成规范 → 人工 Review → 自动化开发 → 工程验证

    阶段描述
    规划阶段让 AI 分析业务场景,输出设计文档。这一阶段的核心是明确"做什么"——包括模块边界、数据结构、接口签名、约束条件等。
    生成规范基于规划结果,让 AI 生成可指导编程的实现规范(Specification)。规范是一份可执行的契约,包含类型定义、函数签名、测试用例、边界条件等。规范的质量直接决定了代码的质量
    人工 Review开发者审核规范的合理性。这是人类决策的关键环节——确保设计符合架构原则、无冗余无泄漏、命名语义清晰、数据流方向明确。Review 通过后,规范成为 AI 实现的唯一依据。
    自动化开发确认规范后,让 AI 基于规范实现完整的功能模块。要求 AI 遵循 TDD 模式——先编写测试用例,再实现逻辑,确保行为的可预测性。每次开发应聚焦于一个完整、恰当粒度的功能或独立模块,避免碎片化。
    工程验证配置项目的 lint、类型检查与测试套件,由 AI 自动运行验证,形成质量闭环。若发现问题,应优先引导 AI 自行修正,而非手动干预。

    SDD 模式的实践要点可归纳为:

    • 规范先行,代码后置:永远不要让 AI 在没有规范的情况下直接写代码。模糊的需求描述只会让 AI 制造技术债务。一份清晰的规范,能让 AI 产出可维护的代码。

    • 恰当粒度,完整交付:每次让 AI 开发一个完整的功能模块,而非零散的代码片段。完整的模块有清晰的边界、完整的测试、可独立验证的行为。这种粒度既能保证开发效率,又能确保代码质量。

    • TDD 内嵌,测试驱动:在规范中明确要求 AI 先写测试、再写实现。测试用例是规范的具象化表达,也是验证代码正确性的唯一标准。

    • 引导修正,避免手动修补:当代码未通过验证时,优先引导 AI 自行修正,而非直接手动修改。手动修补会干扰 AI 对项目上下文的理解,导致后续生成的代码一致性下降。

    • 工程闭环,持续迭代:lint、类型检查、测试套件是质量的三道防线。每次开发完成后必须运行完整验证,确保代码符合项目规范。验证通过后再进入下一个模块的开发。

    5.2 SDD 模式的适用场景

    SDD 模式适用于多数应用的功能迭代开发阶段。在前端领域,它与 React 的声明式范式尤为契合,特别适合以下场景:

    • 状态管理模块:状态是应用的核心骨架,需要严格的类型约束与变更追踪。SDD 能确保状态设计遵循 SSOT 原则,杜绝冗余与泄漏。

    • 交互逻辑开发:反向数据流涉及组件间的通信契约,是典型的"接口语义推敲"场景。SDD 能确保回调命名语义清晰、数据流方向明确。

    • 独立组件开发:针对功能内聚、可复用的独立组件(如表单控件、数据卡片、模态框等),需先明确其 Props 契约、内部状态边界及副作用生命周期,再交由 AI 实现具体渲染逻辑与交互细节。

    • 基础设施代码:Custom Hooks、工具函数、类型定义等基础设施代码,适合用 SDD 模式批量生成,确保接口一致性。

    5.3 为什么 React 与 SDD 天生一对?

    React 的声明式(Declarative)特性意味着我们只需描述 State → UI 的映射关系——给定特定的状态输入,界面应当呈现何种输出,完全由开发者声明式地定义,而非通过命令式地操作 DOM 来达成。

    如果说 SDD(规格驱动开发)是人机协作的一套"宪法",那么 React 就是完美的"执行机构"。两者的天作之合并非偶然,而是源于底层架构范式的深度契合。React 所倡导的"描述即实现"的声明式编程范式,本质上就是一种显式契约(Props Contract),能够有效压缩 AI 的"幻觉空间"。

    当我们在 Spec 中定义好 interface Props 时,实际上是为 AI 划定了一个认知边界。AI 无需费力猜测上下文,只需在 Props 的约束范围内寻找局部最优解。这种高度的封装性从物理层面隔绝了 AI 产生"幻觉"的可能,确保生成的组件是高内聚、低耦合的自治单元。

    这与 SDD 的思维高度一致:开发者只需定义"映射规格"(即状态到 UI 的转换规则、组件的 Props 契约、数据的流动路径),而具体的实现细节——如何高效地 diff 虚拟 DOM、如何批量处理状态更新、如何优化重渲染性能——完全交由 AI 填充。在 SDD 模式下,人类聚焦于"做什么"(What)和"为什么"(Why),AI 负责"怎么做"(How)。这正是声明式编程与规范驱动开发在哲学层面的深度契合。

    6.结语:工程师的不可替代性

    当我们回望 React 设计哲学的四个核心步骤——组件划分、静态基线、状态定位、数据流闭环,会发现它们共同指向一个本质命题:如何在复杂性中建立秩序

    ',55)),o("p",null,[l(r,{type:"info"},{default:a(()=>[...t[4]||(t[4]=[e("组件化是对 UI 复杂性的分解,静态版本是对渲染行为的锚定,最小状态是对数据冗余的剔除,单向数据流是对变更轨迹的约束。这些设计原则并非 React 独有,而是软件工程几十年沉淀下来的智慧结晶——单一职责、关注点分离、显式优于隐式、数据流的可追溯性",-1)])]),_:1}),t[5]||(t[5]=e("。",-1))]),l(r,{type:"warning",bold:""},{default:a(()=>[...t[6]||(t[6]=[e("AI 时代的到来,并未改变这些原则的内核,反而让它们的价值更加凸显",-1)])]),_:1}),t[14]||(t[14]=e("。当 AI 能够以惊人的速度生成代码时,",-1)),t[15]||(t[15]=o("strong",null,'"写什么"的决策权比"怎么写"的执行力更为稀缺',-1)),t[16]||(t[16]=e("。一个清晰的设计规范,能让 AI 产出可维护的代码;而一个模糊的需求描述,只会让 AI 制造更多技术债务。",-1)),t[17]||(t[17]=o("p",null,[e("规范驱动开发(SDD)的本质是"),o("strong",null,"将架构思维外化为可执行的契约"),e('。开发者不再是代码的"搬运工",而是规范的"立法者"。我们定义组件边界、敲定状态拓扑、设计回调契约——AI 则在我们设定的框架内高效填充实现细节。这种分工,让开发者从繁琐的编码劳动中解放出来,将精力集中于真正创造价值的架构决策。')],-1)),o("p",null,[t[8]||(t[8]=e("最后,请记住:",-1)),l(r,{type:"note",bold:""},{default:a(()=>[...t[7]||(t[7]=[e("工具会迭代,技术会过时,但对复杂性的驾驭能力永远是工程师的核心竞争力",-1)])]),_:1}),t[9]||(t[9]=e('。React 的 API 可能会在未来被新的框架取代,但"如何在复杂性中建立秩序"这一命题,将伴随软件工程的始终。愿你在这场技术演进中,始终站在架构设计的高地,用清晰的思维驾驭强大的工具,构建出经得起时间考验的软件系统。',-1))])]))}});export{D as __pageData,I as default}; diff --git a/assets/fullstack_react-design-philosophy-ai-augmented.md.CMWFdXhO.lean.js b/assets/fullstack_react-design-philosophy-ai-augmented.md.CMWFdXhO.lean.js new file mode 100644 index 00000000..8c02d3bd --- /dev/null +++ b/assets/fullstack_react-design-philosophy-ai-augmented.md.CMWFdXhO.lean.js @@ -0,0 +1 @@ +import{H as r}from"./chunks/HighLightText.BD5ARcjF.js";import{g as s,h as n,i as o,z as l,U as i,S as e,s as a}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const D=JSON.parse('{"title":"React 设计哲学:AI 协作时代的组件化开发实践指南","description":"本文探讨在 AI 增强开发背景下,如何重塑 React 组件设计原则。涵盖 SRP 职责划分、静态版本基线、最小状态(Derived Data)推导以及 SDD 人机协作模式的工程落地。","frontmatter":{"date":"2026-02-10T23:33:19.000Z","title":"React 设计哲学:AI 协作时代的组件化开发实践指南","tldr":"当 AI 承接了 30% 的编码执行时,开发者需通过“规格驱动(SDD)”重夺 70% 的设计主权:从自治组件划分到单向数据流拓扑的深度推演。","description":"本文探讨在 AI 增强开发背景下,如何重塑 React 组件设计原则。涵盖 SRP 职责划分、静态版本基线、最小状态(Derived Data)推导以及 SDD 人机协作模式的工程落地。","tags":["tutorial","react","component-design","state-management","ai-augmented","specification-driven"],"permalink":"/fullstack/react-design-philosophy-ai-augmented","categories":["全栈","前端工程"]},"headers":[],"relativePath":"fullstack/react-design-philosophy-ai-augmented.md","filePath":"01.全栈/40.前端工程/01.React 设计哲学:AI 协作时代的组件化开发实践指南.md"}'),g={name:"fullstack/react-design-philosophy-ai-augmented.md"},I=Object.assign(g,{setup(d){return(p,t)=>(n(),s("div",null,[t[10]||(t[10]=o("h1",{id:"react-设计哲学-ai-协作时代的组件化开发实践指南",tabindex:"-1"},[e("React 设计哲学:AI 协作时代的组件化开发实践指南 "),o("a",{class:"header-anchor",href:"#react-设计哲学-ai-协作时代的组件化开发实践指南","aria-label":"Permalink to “React 设计哲学:AI 协作时代的组件化开发实践指南”"},"​")],-1)),t[11]||(t[11]=o("h2",{id:"_1-引言",tabindex:"-1"},[e("1. 引言 "),o("a",{class:"header-anchor",href:"#_1-引言","aria-label":"Permalink to “1. 引言”"},"​")],-1)),o("p",null,[t[1]||(t[1]=e("在软件工程中,约 70% 的时间应投入于架构设计、需求拆解与接口语义推敲,仅 30% 用于实际编码。进入 AI 协作时代后,这一比例依然坚如磐石——开发者必须先完成深度思考,将“清晰的问题规格(Specification)”交给 AI,AI 才能输出高质量代码。",-1)),l(r,{type:"note",bold:""},{default:a(()=>[...t[0]||(t[0]=[e("AI 提升的是 30% 编码阶段的执行力,而非取代 70% 的架构裁决",-1)])]),_:1}),t[2]||(t[2]=e("。 高质量 React 应用的诞生,依然始于人类心智对数据流、副作用边界与可组合性的透彻推演。",-1))]),t[12]||(t[12]=o("p",null,'然而,真正驾驭 React 并非易事。许多团队在项目初期享受着组件化带来的快感,却在业务膨胀后陷入"组件地狱"——深嵌套的 prop drilling、失控的状态蔓延、难以追踪的副作用,让代码库逐渐腐化。问题的根源往往不在于 React 本身,而在于我们是否真正理解其背后的设计哲学。',-1)),l(r,{bold:""},{default:a(()=>[...t[3]||(t[3]=[e("React 的精髓在于以组件化为核心,将复杂的 UI 拆解为独立、可复用的自治单元,让数据沿着从输入(props)到输出(UI 元素)的轨迹形成清晰、可控的闭环",-1)])]),_:1}),t[13]||(t[13]=i("",55)),o("p",null,[l(r,{type:"info"},{default:a(()=>[...t[4]||(t[4]=[e("组件化是对 UI 复杂性的分解,静态版本是对渲染行为的锚定,最小状态是对数据冗余的剔除,单向数据流是对变更轨迹的约束。这些设计原则并非 React 独有,而是软件工程几十年沉淀下来的智慧结晶——单一职责、关注点分离、显式优于隐式、数据流的可追溯性",-1)])]),_:1}),t[5]||(t[5]=e("。",-1))]),l(r,{type:"warning",bold:""},{default:a(()=>[...t[6]||(t[6]=[e("AI 时代的到来,并未改变这些原则的内核,反而让它们的价值更加凸显",-1)])]),_:1}),t[14]||(t[14]=e("。当 AI 能够以惊人的速度生成代码时,",-1)),t[15]||(t[15]=o("strong",null,'"写什么"的决策权比"怎么写"的执行力更为稀缺',-1)),t[16]||(t[16]=e("。一个清晰的设计规范,能让 AI 产出可维护的代码;而一个模糊的需求描述,只会让 AI 制造更多技术债务。",-1)),t[17]||(t[17]=o("p",null,[e("规范驱动开发(SDD)的本质是"),o("strong",null,"将架构思维外化为可执行的契约"),e('。开发者不再是代码的"搬运工",而是规范的"立法者"。我们定义组件边界、敲定状态拓扑、设计回调契约——AI 则在我们设定的框架内高效填充实现细节。这种分工,让开发者从繁琐的编码劳动中解放出来,将精力集中于真正创造价值的架构决策。')],-1)),o("p",null,[t[8]||(t[8]=e("最后,请记住:",-1)),l(r,{type:"note",bold:""},{default:a(()=>[...t[7]||(t[7]=[e("工具会迭代,技术会过时,但对复杂性的驾驭能力永远是工程师的核心竞争力",-1)])]),_:1}),t[9]||(t[9]=e('。React 的 API 可能会在未来被新的框架取代,但"如何在复杂性中建立秩序"这一命题,将伴随软件工程的始终。愿你在这场技术演进中,始终站在架构设计的高地,用清晰的思维驾驭强大的工具,构建出经得起时间考验的软件系统。',-1))])]))}});export{D as __pageData,I as default}; diff --git "a/assets/01.\345\205\250\346\240\210_40.\345\211\215\347\253\257\345\267\245\347\250\213_11.React \346\234\215\345\212\241\347\253\257\347\212\266\346\200\201\347\256\241\347\220\206\347\232\204\350\214\203\345\274\217\350\275\254\347\247\273\344\270\216\351\200\211\345\236\213\346\267\261\345\272\246\345\215\232\345\274\210.md.BpMi6J2x.js" b/assets/fullstack_server-state-management.md.ETGJXNWa.js similarity index 94% rename from "assets/01.\345\205\250\346\240\210_40.\345\211\215\347\253\257\345\267\245\347\250\213_11.React \346\234\215\345\212\241\347\253\257\347\212\266\346\200\201\347\256\241\347\220\206\347\232\204\350\214\203\345\274\217\350\275\254\347\247\273\344\270\216\351\200\211\345\236\213\346\267\261\345\272\246\345\215\232\345\274\210.md.BpMi6J2x.js" rename to assets/fullstack_server-state-management.md.ETGJXNWa.js index 724bfc7c..26c13b51 100644 --- "a/assets/01.\345\205\250\346\240\210_40.\345\211\215\347\253\257\345\267\245\347\250\213_11.React \346\234\215\345\212\241\347\253\257\347\212\266\346\200\201\347\256\241\347\220\206\347\232\204\350\214\203\345\274\217\350\275\254\347\247\273\344\270\216\351\200\211\345\236\213\346\267\261\345\272\246\345\215\232\345\274\210.md.BpMi6J2x.js" +++ b/assets/fullstack_server-state-management.md.ETGJXNWa.js @@ -1,4 +1,4 @@ -import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const g=JSON.parse('{"title":"不止于 Fetch:React 服务端状态管理的范式转移与选型深度博弈","description":"深度对比 React 生态中 SWR 与 TanStack Query 两大方案。从 stale-while-revalidate 机制到异步状态机架构,涵盖依赖查询、数据转换及架构级乐观更新实战。旨在帮助开发者在复杂业务中构建确定性的服务端状态基座。","frontmatter":{"date":"2025-11-15T09:20:23.000Z","title":"不止于 Fetch:React 服务端状态管理的范式转移与选型深度博弈","aliases":["SWR","TanStack Query","React","服务端状态","乐观更新","工程化"],"tldr":"深入解析 SWR 的极简协议与 TanStack Query 的精密状态机。通过对比缓存失效、乐观更新等核心场景,为高复杂度 B 端应用与轻量级项目提供清晰的架构选型模型。","description":"深度对比 React 生态中 SWR 与 TanStack Query 两大方案。从 stale-while-revalidate 机制到异步状态机架构,涵盖依赖查询、数据转换及架构级乐观更新实战。旨在帮助开发者在复杂业务中构建确定性的服务端状态基座。","permalink":"/fullstack/server-state-management","tags":["SWR","TanStack Query","前端工程"],"categories":["全栈","前端工程"]},"headers":[],"relativePath":"01.全栈/40.前端工程/11.React 服务端状态管理的范式转移与选型深度博弈.md","filePath":"01.全栈/40.前端工程/11.React 服务端状态管理的范式转移与选型深度博弈.md"}'),p={name:"01.全栈/40.前端工程/11.React 服务端状态管理的范式转移与选型深度博弈.md"};function e(t,s,h,k,r,E){return n(),a("div",null,[...s[0]||(s[0]=[l(`

    不止于 Fetch:React 服务端状态管理的范式转移与选型深度博弈

    摘要总结: 本文聚焦 UI 状态与服务端状态的管理边界,对比 SWR(基于 stale-while-revalidate 协议的轻量方案)与 TanStack Query(精密异步状态机)两者的核心机制差异,通过缓存策略、乐观更新、依赖查询等实战代码场景展开论述,最终给出以项目复杂度为维度的选型结论与决策框架。

    1. 引言

    在现代前端工程中,状态可严格区分为 UI 状态(UI State)服务端状态(Server State) 两类。对于 UI 状态的管理,开发者已较为熟悉,通常可借助 useStateuseEffect 等 Hooks,或 zustandjotai 等状态管理库来实现。然而,服务端状态的管理往往缺乏统一且高效的解决方案,开发者通常需要自行实现。

    在传统的数据获取流程中,我们一般使用 fetchaxios 向后端或 REST API 发送 HTTP 请求,随后手动将数据获取逻辑与前端业务逻辑及 UI 状态管理进行整合,以完成数据处理并驱动界面更新。

    TanStack QuerySWR 等库的出现,为数据获取提供了更加简洁和高效的解决方案。

    1. SWR

    1.1 简介与核心流程说明

    SWR is a minimal API with built-in caching, revalidation, and request deduplication. It keeps your UI fast, consistent, and always up to date — with a single React hook.

    SWR 是一个基于 React Hooks 的轻量级库,它的 API 简单易用,同时提供了强大的功能。它的设计目标是简化数据获取和缓存的过程。它的核心思想是“ stale-while-revalidate ”,即先返回缓存数据(stale),同时发送请求去更新缓存(revalidate),核心运作流也非常简洁:

    • Stale:首先从本地缓存中返回数据,实现快速响应,无白屏。
    • Fetch:在后台发送 Fetch 请求获取最新数据。
    • Revalidate:拿到最新数据后,对比缓存,若有变化则触发 React 重新渲染并更新缓存。

    这种机制彻底改变了传统 useEffect + setState 带来的“加载中 -> 渲染”的阻塞式体验,让应用在感官上具有“实时性”。

    简单示例如下:

    JSX
    import useSWR from 'swr';
    +import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const g=JSON.parse('{"title":"不止于 Fetch:React 服务端状态管理的范式转移与选型深度博弈","description":"深度对比 React 生态中 SWR 与 TanStack Query 两大方案。从 stale-while-revalidate 机制到异步状态机架构,涵盖依赖查询、数据转换及架构级乐观更新实战。旨在帮助开发者在复杂业务中构建确定性的服务端状态基座。","frontmatter":{"date":"2025-11-15T09:20:23.000Z","title":"不止于 Fetch:React 服务端状态管理的范式转移与选型深度博弈","aliases":["SWR","TanStack Query","React","服务端状态","乐观更新","工程化"],"tldr":"深入解析 SWR 的极简协议与 TanStack Query 的精密状态机。通过对比缓存失效、乐观更新等核心场景,为高复杂度 B 端应用与轻量级项目提供清晰的架构选型模型。","description":"深度对比 React 生态中 SWR 与 TanStack Query 两大方案。从 stale-while-revalidate 机制到异步状态机架构,涵盖依赖查询、数据转换及架构级乐观更新实战。旨在帮助开发者在复杂业务中构建确定性的服务端状态基座。","permalink":"/fullstack/server-state-management","tags":["SWR","TanStack Query","前端工程"],"categories":["全栈","前端工程"]},"headers":[],"relativePath":"fullstack/server-state-management.md","filePath":"01.全栈/40.前端工程/11.React 服务端状态管理的范式转移与选型深度博弈.md"}'),p={name:"fullstack/server-state-management.md"};function e(h,s,t,k,r,E){return n(),a("div",null,[...s[0]||(s[0]=[l(`

    不止于 Fetch:React 服务端状态管理的范式转移与选型深度博弈

    摘要总结: 本文聚焦 UI 状态与服务端状态的管理边界,对比 SWR(基于 stale-while-revalidate 协议的轻量方案)与 TanStack Query(精密异步状态机)两者的核心机制差异,通过缓存策略、乐观更新、依赖查询等实战代码场景展开论述,最终给出以项目复杂度为维度的选型结论与决策框架。

    1. 引言

    在现代前端工程中,状态可严格区分为 UI 状态(UI State)服务端状态(Server State) 两类。对于 UI 状态的管理,开发者已较为熟悉,通常可借助 useStateuseEffect 等 Hooks,或 zustandjotai 等状态管理库来实现。然而,服务端状态的管理往往缺乏统一且高效的解决方案,开发者通常需要自行实现。

    在传统的数据获取流程中,我们一般使用 fetchaxios 向后端或 REST API 发送 HTTP 请求,随后手动将数据获取逻辑与前端业务逻辑及 UI 状态管理进行整合,以完成数据处理并驱动界面更新。

    TanStack QuerySWR 等库的出现,为数据获取提供了更加简洁和高效的解决方案。

    1. SWR

    1.1 简介与核心流程说明

    SWR is a minimal API with built-in caching, revalidation, and request deduplication. It keeps your UI fast, consistent, and always up to date — with a single React hook.

    SWR 是一个基于 React Hooks 的轻量级库,它的 API 简单易用,同时提供了强大的功能。它的设计目标是简化数据获取和缓存的过程。它的核心思想是“ stale-while-revalidate ”,即先返回缓存数据(stale),同时发送请求去更新缓存(revalidate),核心运作流也非常简洁:

    • Stale:首先从本地缓存中返回数据,实现快速响应,无白屏。
    • Fetch:在后台发送 Fetch 请求获取最新数据。
    • Revalidate:拿到最新数据后,对比缓存,若有变化则触发 React 重新渲染并更新缓存。

    这种机制彻底改变了传统 useEffect + setState 带来的“加载中 -> 渲染”的阻塞式体验,让应用在感官上具有“实时性”。

    简单示例如下:

    JSX
    import useSWR from 'swr';
     import React from 'react';
     
     // 自定义 fetcher 函数,用于发送 HTTP 请求并获取数据
    @@ -208,4 +208,4 @@ import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.CqY1sKvl.j
           queryClient.invalidateQueries({ queryKey: ['todos'] });
         },
       });
    -}

    3. 选型评估:SWR vs React Query

    在 React 生态中,SWR 与 TanStack Query (React Query) 是最主流的两个服务端状态管理方案。两者各有侧重,适用于不同的项目场景。

    以下从多个维度进行对比分析,帮助我们根据项目需求做出合适的技术选型。

    3.1 核心设计与功能对比分析

    评估维度Vercel SWRTanStack Query (RQ)
    核心哲学极简主义、渐进式增强。核心是围绕 stale-while-revalidate 协议,以最小的 API 表面积提供极致的“快照渲染”体验。大而全的异步状态机。接管一切服务端状态,提供极度精细的生命周期控制和强大的底层 API。
    Bundle Size~4.3 kB (Minified + Gzipped)对现代轻量级构建极为友好。~13 kB (Minified + Gzipped)体积较大,但带来了开箱即用的完整生态。
    缓存标识 (Key)String (URL) 主导。天生契合 RESTful 路径。Array (数组) 主导。天生支持复杂组合查询与确定性哈希。
    API 契约天然契合 SDD (Contract-First Generation)。以 API 端点作为天然的 Key,前后端接口约束极其清晰。高度抽象。需要团队自行建立严格的 QueryKey 命名与管理规范。
    学习曲线极低,半天即可全团队推行。中等偏高。需深刻理解 staleTime、gcTime 等底层状态机逻辑。
    DevTools第三方支持,相对简陋。官方内置,极其强大。可视化时间旅行、缓存审查器,复杂场景下的 Debug 神器。

    两者在核心功能方面的对比分析:

    1. 数据变更与乐观更新 (Mutations & Optimistic UI) SWR 的局限:SWR 的 mutate 相对简单粗暴。开发者需要手动编写拦截逻辑、捕获异常,并手动维护回滚(Rollback)前的数据快照。在处理链式调用或复杂的并行变更时,代码容易变得面条化。

    TanStack Query 的压倒性优势:提供了专门的 useMutation Hook,它内置了极其优雅的 onMutate、onSuccess、onError、onSettled 生命周期回调。配合它的 Context 透传机制,实现带错误回滚的乐观更新是一种标准的、工程化的体验。

    1. 缓存失效与精细化刷新 (Query Invalidation) SWR 的方案: 全局 mutate(key),如果更新了一个项目详情,想刷新列表,就需要准确知道列表的 Key 才能触发它。

    RQ 的方案queryClient.invalidateQueries({ queryKey: ['projects'] })。RQ 的数组 Key 具有层级模糊匹配能力。当开发者变更了某个项目,一句代码可以使所有以 ['projects'] 开头的查询(如列表、统计面板、概览)全部自动在后台失效并重新获取,这在复杂中后台应用中是杀手级功能

    1. 依赖查询与请求瀑布流 (Dependent Queries):两者都支持基于前一个请求的结果发起下一个请求。但 TanStack Query 提供了 select 数据转换器,允许在组件订阅前对底层数据进行高性能的派生和过滤,多个组件共享一份基础缓存但各自 select 不同的视图,渲染性能更佳。

    3.2 场景驱动选型:到底需要哪一个?

    结合实际的研发场景,特别是那些涉及复杂中间态和高频交互的领域,可以得出两条选择结论:

    1、如果项目是一个重操作、重状态流转、强关联数据的复杂工程(例如包含大量配置面板、生成流水线、拖拽保存的工具型产品),我们就应当承担那额外的 8kB 体积和初期学习成本,直接选用 TanStack Query,它的工程化上限更高,长远来看能省去大量由于手动维护复杂缓存而产生的隐性技术债。

    2、相反,如果项目是一个重展示、高频读取、重前端轻交互的现代 Web 应用,并且你推崇极简的架构代码,SWR 就是更好的选择。

    场景 A:应该毫不犹豫选择 SWR 的情况

    • 轻量级/展示型为主的 C 端产品:核心诉求是首屏快、无白屏、切 Tab 时数据瞬间出现。SWR 的极简调度能用最低的性能开销换取最好的感官体验。

    • API 结构高度契合 RESTful 且数据流向单一:如果你的接口设计已经非常规范(Contract-First),直接把 URL 当作 Cache Key,代码将极其干净。

    • 追求极致的现代前端审美:配合 Vite/SWC 等现代工具链,你希望保持依赖树的纯净和 Bundle 的极限压缩,不希望引入过重的状态机。

    场景 B:应该毫不犹豫选择 TanStack Query 的情况

    • 超大型 B 端/企业级工作台: 页面上同时存在十几个需要联动的数据板块。你需要 TanStack Query 强大的 invalidateQueries 来保证数据的一致性,同时也极其依赖官方 DevTools 来排查状态污染。

    • AI-Native 的 Agentic 工作流交互: 在构建 AI 智能体应用时,用户的每一个 Prompt 可能会触发后端一系列的流式响应、工具调用(Tool Use)和状态变更。TanStack Query 严密的状态机能更好地管理这些复杂的“进行中”、“部分成功”、“需用户介入”等组合异步状态。

    • 复杂图形解析工具:应用往往涉及大量的中间态保存、节点解析重试、以及频繁的与服务端的同步(Save Draft, Commit Changes),开发者需要 useMutation 强大的生命周期来控制这些复杂的异步交互流,并在生成失败时优雅地回滚 UI。

    `,75)])])}const y=i(p,[["render",e]]);export{g as __pageData,y as default}; +}

    3. 选型评估:SWR vs React Query

    在 React 生态中,SWR 与 TanStack Query (React Query) 是最主流的两个服务端状态管理方案。两者各有侧重,适用于不同的项目场景。

    以下从多个维度进行对比分析,帮助我们根据项目需求做出合适的技术选型。

    3.1 核心设计与功能对比分析

    评估维度Vercel SWRTanStack Query (RQ)
    核心哲学极简主义、渐进式增强。核心是围绕 stale-while-revalidate 协议,以最小的 API 表面积提供极致的“快照渲染”体验。大而全的异步状态机。接管一切服务端状态,提供极度精细的生命周期控制和强大的底层 API。
    Bundle Size~4.3 kB (Minified + Gzipped)对现代轻量级构建极为友好。~13 kB (Minified + Gzipped)体积较大,但带来了开箱即用的完整生态。
    缓存标识 (Key)String (URL) 主导。天生契合 RESTful 路径。Array (数组) 主导。天生支持复杂组合查询与确定性哈希。
    API 契约天然契合 SDD (Contract-First Generation)。以 API 端点作为天然的 Key,前后端接口约束极其清晰。高度抽象。需要团队自行建立严格的 QueryKey 命名与管理规范。
    学习曲线极低,半天即可全团队推行。中等偏高。需深刻理解 staleTime、gcTime 等底层状态机逻辑。
    DevTools第三方支持,相对简陋。官方内置,极其强大。可视化时间旅行、缓存审查器,复杂场景下的 Debug 神器。

    两者在核心功能方面的对比分析:

    1. 数据变更与乐观更新 (Mutations & Optimistic UI) SWR 的局限:SWR 的 mutate 相对简单粗暴。开发者需要手动编写拦截逻辑、捕获异常,并手动维护回滚(Rollback)前的数据快照。在处理链式调用或复杂的并行变更时,代码容易变得面条化。

    TanStack Query 的压倒性优势:提供了专门的 useMutation Hook,它内置了极其优雅的 onMutate、onSuccess、onError、onSettled 生命周期回调。配合它的 Context 透传机制,实现带错误回滚的乐观更新是一种标准的、工程化的体验。

    1. 缓存失效与精细化刷新 (Query Invalidation) SWR 的方案: 全局 mutate(key),如果更新了一个项目详情,想刷新列表,就需要准确知道列表的 Key 才能触发它。

    RQ 的方案queryClient.invalidateQueries({ queryKey: ['projects'] })。RQ 的数组 Key 具有层级模糊匹配能力。当开发者变更了某个项目,一句代码可以使所有以 ['projects'] 开头的查询(如列表、统计面板、概览)全部自动在后台失效并重新获取,这在复杂中后台应用中是杀手级功能

    1. 依赖查询与请求瀑布流 (Dependent Queries):两者都支持基于前一个请求的结果发起下一个请求。但 TanStack Query 提供了 select 数据转换器,允许在组件订阅前对底层数据进行高性能的派生和过滤,多个组件共享一份基础缓存但各自 select 不同的视图,渲染性能更佳。

    3.2 场景驱动选型:到底需要哪一个?

    结合实际的研发场景,特别是那些涉及复杂中间态和高频交互的领域,可以得出两条选择结论:

    1、如果项目是一个重操作、重状态流转、强关联数据的复杂工程(例如包含大量配置面板、生成流水线、拖拽保存的工具型产品),我们就应当承担那额外的 8kB 体积和初期学习成本,直接选用 TanStack Query,它的工程化上限更高,长远来看能省去大量由于手动维护复杂缓存而产生的隐性技术债。

    2、相反,如果项目是一个重展示、高频读取、重前端轻交互的现代 Web 应用,并且你推崇极简的架构代码,SWR 就是更好的选择。

    场景 A:应该毫不犹豫选择 SWR 的情况

    • 轻量级/展示型为主的 C 端产品:核心诉求是首屏快、无白屏、切 Tab 时数据瞬间出现。SWR 的极简调度能用最低的性能开销换取最好的感官体验。

    • API 结构高度契合 RESTful 且数据流向单一:如果你的接口设计已经非常规范(Contract-First),直接把 URL 当作 Cache Key,代码将极其干净。

    • 追求极致的现代前端审美:配合 Vite/SWC 等现代工具链,你希望保持依赖树的纯净和 Bundle 的极限压缩,不希望引入过重的状态机。

    场景 B:应该毫不犹豫选择 TanStack Query 的情况

    • 超大型 B 端/企业级工作台: 页面上同时存在十几个需要联动的数据板块。你需要 TanStack Query 强大的 invalidateQueries 来保证数据的一致性,同时也极其依赖官方 DevTools 来排查状态污染。

    • AI-Native 的 Agentic 工作流交互: 在构建 AI 智能体应用时,用户的每一个 Prompt 可能会触发后端一系列的流式响应、工具调用(Tool Use)和状态变更。TanStack Query 严密的状态机能更好地管理这些复杂的“进行中”、“部分成功”、“需用户介入”等组合异步状态。

    • 复杂图形解析工具:应用往往涉及大量的中间态保存、节点解析重试、以及频繁的与服务端的同步(Save Draft, Commit Changes),开发者需要 useMutation 强大的生命周期来控制这些复杂的异步交互流,并在生成失败时优雅地回滚 UI。

    `,74)])])}const y=i(p,[["render",e]]);export{g as __pageData,y as default}; diff --git "a/assets/01.\345\205\250\346\240\210_40.\345\211\215\347\253\257\345\267\245\347\250\213_11.React \346\234\215\345\212\241\347\253\257\347\212\266\346\200\201\347\256\241\347\220\206\347\232\204\350\214\203\345\274\217\350\275\254\347\247\273\344\270\216\351\200\211\345\236\213\346\267\261\345\272\246\345\215\232\345\274\210.md.BpMi6J2x.lean.js" b/assets/fullstack_server-state-management.md.ETGJXNWa.lean.js similarity index 69% rename from "assets/01.\345\205\250\346\240\210_40.\345\211\215\347\253\257\345\267\245\347\250\213_11.React \346\234\215\345\212\241\347\253\257\347\212\266\346\200\201\347\256\241\347\220\206\347\232\204\350\214\203\345\274\217\350\275\254\347\247\273\344\270\216\351\200\211\345\236\213\346\267\261\345\272\246\345\215\232\345\274\210.md.BpMi6J2x.lean.js" rename to assets/fullstack_server-state-management.md.ETGJXNWa.lean.js index 6e793815..f923d709 100644 --- "a/assets/01.\345\205\250\346\240\210_40.\345\211\215\347\253\257\345\267\245\347\250\213_11.React \346\234\215\345\212\241\347\253\257\347\212\266\346\200\201\347\256\241\347\220\206\347\232\204\350\214\203\345\274\217\350\275\254\347\247\273\344\270\216\351\200\211\345\236\213\346\267\261\345\272\246\345\215\232\345\274\210.md.BpMi6J2x.lean.js" +++ b/assets/fullstack_server-state-management.md.ETGJXNWa.lean.js @@ -1 +1 @@ -import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const g=JSON.parse('{"title":"不止于 Fetch:React 服务端状态管理的范式转移与选型深度博弈","description":"深度对比 React 生态中 SWR 与 TanStack Query 两大方案。从 stale-while-revalidate 机制到异步状态机架构,涵盖依赖查询、数据转换及架构级乐观更新实战。旨在帮助开发者在复杂业务中构建确定性的服务端状态基座。","frontmatter":{"date":"2025-11-15T09:20:23.000Z","title":"不止于 Fetch:React 服务端状态管理的范式转移与选型深度博弈","aliases":["SWR","TanStack Query","React","服务端状态","乐观更新","工程化"],"tldr":"深入解析 SWR 的极简协议与 TanStack Query 的精密状态机。通过对比缓存失效、乐观更新等核心场景,为高复杂度 B 端应用与轻量级项目提供清晰的架构选型模型。","description":"深度对比 React 生态中 SWR 与 TanStack Query 两大方案。从 stale-while-revalidate 机制到异步状态机架构,涵盖依赖查询、数据转换及架构级乐观更新实战。旨在帮助开发者在复杂业务中构建确定性的服务端状态基座。","permalink":"/fullstack/server-state-management","tags":["SWR","TanStack Query","前端工程"],"categories":["全栈","前端工程"]},"headers":[],"relativePath":"01.全栈/40.前端工程/11.React 服务端状态管理的范式转移与选型深度博弈.md","filePath":"01.全栈/40.前端工程/11.React 服务端状态管理的范式转移与选型深度博弈.md"}'),p={name:"01.全栈/40.前端工程/11.React 服务端状态管理的范式转移与选型深度博弈.md"};function e(t,s,h,k,r,E){return n(),a("div",null,[...s[0]||(s[0]=[l("",75)])])}const y=i(p,[["render",e]]);export{g as __pageData,y as default}; +import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const g=JSON.parse('{"title":"不止于 Fetch:React 服务端状态管理的范式转移与选型深度博弈","description":"深度对比 React 生态中 SWR 与 TanStack Query 两大方案。从 stale-while-revalidate 机制到异步状态机架构,涵盖依赖查询、数据转换及架构级乐观更新实战。旨在帮助开发者在复杂业务中构建确定性的服务端状态基座。","frontmatter":{"date":"2025-11-15T09:20:23.000Z","title":"不止于 Fetch:React 服务端状态管理的范式转移与选型深度博弈","aliases":["SWR","TanStack Query","React","服务端状态","乐观更新","工程化"],"tldr":"深入解析 SWR 的极简协议与 TanStack Query 的精密状态机。通过对比缓存失效、乐观更新等核心场景,为高复杂度 B 端应用与轻量级项目提供清晰的架构选型模型。","description":"深度对比 React 生态中 SWR 与 TanStack Query 两大方案。从 stale-while-revalidate 机制到异步状态机架构,涵盖依赖查询、数据转换及架构级乐观更新实战。旨在帮助开发者在复杂业务中构建确定性的服务端状态基座。","permalink":"/fullstack/server-state-management","tags":["SWR","TanStack Query","前端工程"],"categories":["全栈","前端工程"]},"headers":[],"relativePath":"fullstack/server-state-management.md","filePath":"01.全栈/40.前端工程/11.React 服务端状态管理的范式转移与选型深度博弈.md"}'),p={name:"fullstack/server-state-management.md"};function e(h,s,t,k,r,E){return n(),a("div",null,[...s[0]||(s[0]=[l("",74)])])}const y=i(p,[["render",e]]);export{g as __pageData,y as default}; diff --git "a/assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_01.\347\274\226\350\257\221\344\270\216\350\260\203\350\257\225 TypeScript \351\241\271\347\233\256\346\214\207\345\215\227.md.BHyEzAuH.js" b/assets/fullstack_typescript-compilation-debugging-guide.md.C39DJVwc.js similarity index 97% rename from "assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_01.\347\274\226\350\257\221\344\270\216\350\260\203\350\257\225 TypeScript \351\241\271\347\233\256\346\214\207\345\215\227.md.BHyEzAuH.js" rename to assets/fullstack_typescript-compilation-debugging-guide.md.C39DJVwc.js index 5644502c..4a8f7af8 100644 --- "a/assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_01.\347\274\226\350\257\221\344\270\216\350\260\203\350\257\225 TypeScript \351\241\271\347\233\256\346\214\207\345\215\227.md.BHyEzAuH.js" +++ b/assets/fullstack_typescript-compilation-debugging-guide.md.C39DJVwc.js @@ -1,4 +1,4 @@ -import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const c=JSON.parse('{"title":"TypeScript 编译与调试完全指南","description":"深入解析 TypeScript 编译工具链与调试体系,涵盖 tsconfig.json 核心配置、Monorepo 项目配置(extends/references)、source map 调试、ESLint 与 Jest 单元测试等完整实践。","frontmatter":{"date":"2025-08-12T22:47:47.000Z","title":"TypeScript 编译与调试完全指南","tldr":"TypeScript 完善的编译体系与调试工具链,是构建高质量应用的基石。","description":"深入解析 TypeScript 编译工具链与调试体系,涵盖 tsconfig.json 核心配置、Monorepo 项目配置(extends/references)、source map 调试、ESLint 与 Jest 单元测试等完整实践。","permalink":"/fullstack/typescript-compilation-debugging-guide","tags":["tutorial","typescript","compilation","tooling","eslint","jest"],"categories":["全栈","全栈基础素养"]},"headers":[],"relativePath":"01.全栈/80.全栈基础素养/01.编译与调试 TypeScript 项目指南.md","filePath":"01.全栈/80.全栈基础素养/01.编译与调试 TypeScript 项目指南.md"}'),p={name:"01.全栈/80.全栈基础素养/01.编译与调试 TypeScript 项目指南.md"};function t(e,s,h,k,r,E){return n(),a("div",null,[...s[0]||(s[0]=[l(`

    TypeScript 编译与调试完全指南

    摘要总结: TypeScript 作为 JavaScript 的静态类型超集,不仅提供了类型安全,还构建了完善的编译工具链和调试能力。本文系统梳理 TypeScript 项目的编译与调试全流程,涵盖 TSC 编译器使用、tsconfig.json 各场景配置(单体项目、Monorepo 多包项目)、source map 浏览器调试、ESLint 静态检查与 Jest 单元测试等工程实践。通过对编译选项(strict、module、moduleResolution、incremental 等)的详细解读,以及 React+Vite、Node.js、npm 库等典型项目配置示例,帮助读者建立对 TypeScript 编译体系的完整认知。掌握这些核心技能,能够帮助开发者更高效地构建和维护高质量的 TypeScript 应用。

    编写代码只是开发工作的起点,真正决定项目质量的是后续的编译与调试环节。TypeScript 作为 JavaScript 的静态类型超集,不仅带来了类型安全,更提供了强大的编译工具和调试能力,让我们能够更高效地构建和维护可靠的应用程序。

    本文将对 TypeScript 项目的编译与调试进行梳理,包括编译工具 TSC 的使用、编译选项的配置、调试工具的使用等。

    1. TypeScript 编译配置与 tsconfig.json

    TSC(TypeScript Compiler)是 TypeScript 官方提供的编译工具,负责将 TypeScript 代码(.ts.tsx)转换为 JavaScript 代码(.js.jsx)。

    虽然你可以直接在终端运行 tsc 命令来编译单个文件,但在实际项目中,我们通常需要处理大量文件。为了提高编译命令的复用性和可维护性,TypeScript 提供了配置文件的方式来管理编译设置:

    • 配置文件:使用 tsconfig.json 文件集中管理待编译文件路径、编译选项和输出路径等。你可以通过 tsc --init 命令快速生成一个默认配置文件,然后根据项目需求进行调整。
    • 配置位置:通常将 tsconfig.json 放在项目根目录下。对于 Monorepo 项目结构,每个子项目可以拥有独立的配置文件,实现更精细的编译控制。

    1.1 tsconfig.json 核心配置梳理

    以下是一个生产环境常用的 tsconfig.json 配置示例,包含了 TypeScript 核心编译选项的详细注释说明:

    json
    {
    +import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const c=JSON.parse('{"title":"TypeScript 编译与调试完全指南","description":"深入解析 TypeScript 编译工具链与调试体系,涵盖 tsconfig.json 核心配置、Monorepo 项目配置(extends/references)、source map 调试、ESLint 与 Jest 单元测试等完整实践。","frontmatter":{"date":"2025-08-12T22:47:47.000Z","title":"TypeScript 编译与调试完全指南","tldr":"TypeScript 完善的编译体系与调试工具链,是构建高质量应用的基石。","description":"深入解析 TypeScript 编译工具链与调试体系,涵盖 tsconfig.json 核心配置、Monorepo 项目配置(extends/references)、source map 调试、ESLint 与 Jest 单元测试等完整实践。","permalink":"/fullstack/typescript-compilation-debugging-guide","tags":["tutorial","typescript","compilation","tooling","eslint","jest"],"categories":["全栈","全栈基础素养"]},"headers":[],"relativePath":"fullstack/typescript-compilation-debugging-guide.md","filePath":"01.全栈/80.全栈基础素养/01.编译与调试 TypeScript 项目指南.md"}'),p={name:"fullstack/typescript-compilation-debugging-guide.md"};function t(e,s,h,k,r,E){return n(),a("div",null,[...s[0]||(s[0]=[l(`

    TypeScript 编译与调试完全指南

    摘要总结: TypeScript 作为 JavaScript 的静态类型超集,不仅提供了类型安全,还构建了完善的编译工具链和调试能力。本文系统梳理 TypeScript 项目的编译与调试全流程,涵盖 TSC 编译器使用、tsconfig.json 各场景配置(单体项目、Monorepo 多包项目)、source map 浏览器调试、ESLint 静态检查与 Jest 单元测试等工程实践。通过对编译选项(strict、module、moduleResolution、incremental 等)的详细解读,以及 React+Vite、Node.js、npm 库等典型项目配置示例,帮助读者建立对 TypeScript 编译体系的完整认知。掌握这些核心技能,能够帮助开发者更高效地构建和维护高质量的 TypeScript 应用。

    编写代码只是开发工作的起点,真正决定项目质量的是后续的编译与调试环节。TypeScript 作为 JavaScript 的静态类型超集,不仅带来了类型安全,更提供了强大的编译工具和调试能力,让我们能够更高效地构建和维护可靠的应用程序。

    本文将对 TypeScript 项目的编译与调试进行梳理,包括编译工具 TSC 的使用、编译选项的配置、调试工具的使用等。

    1. TypeScript 编译配置与 tsconfig.json

    TSC(TypeScript Compiler)是 TypeScript 官方提供的编译工具,负责将 TypeScript 代码(.ts.tsx)转换为 JavaScript 代码(.js.jsx)。

    虽然你可以直接在终端运行 tsc 命令来编译单个文件,但在实际项目中,我们通常需要处理大量文件。为了提高编译命令的复用性和可维护性,TypeScript 提供了配置文件的方式来管理编译设置:

    • 配置文件:使用 tsconfig.json 文件集中管理待编译文件路径、编译选项和输出路径等。你可以通过 tsc --init 命令快速生成一个默认配置文件,然后根据项目需求进行调整。
    • 配置位置:通常将 tsconfig.json 放在项目根目录下。对于 Monorepo 项目结构,每个子项目可以拥有独立的配置文件,实现更精细的编译控制。

    1.1 tsconfig.json 核心配置梳理

    以下是一个生产环境常用的 tsconfig.json 配置示例,包含了 TypeScript 核心编译选项的详细注释说明:

    json
    {
       /*
        * ============================================
        * 编译信息配置
    @@ -546,4 +546,4 @@ import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.CqY1sKvl.j
         "test:watch": "jest --watch",
         "test:coverage": "jest --coverage"
       }
    -}

    运行测试:

    bash
    npm test

    4.2.5 高级特性

    Jest 还提供了一些高级特性,如异步测试、模拟函数、快照测试等,可以满足各种复杂的测试需求。更多详细信息请可参考 Jest 官方文档

    • 异步测试:支持 Promise 和 async/await
    • 模拟函数:使用 jest.fn() 创建模拟函数
    • 快照测试:生成组件或数据结构的快照
    • 测试覆盖率:自动生成覆盖率报告

    5. 结语

    TypeScript 的价值不仅在于静态类型检查带来的代码提示和编译时错误发现,更在于其完善的编译体系、调试能力和配套的质量保障工具。

    在实际项目中,我们需要关注以下几个层面:

    关注层面说明
    配置管理合理规划 tsconfig.json 的分层结构,无论是单体项目还是 Monorepo 架构,都能通过 extendsreferences 实现配置的复用与独立定制。
    代码质量ESLint 和 Prettier 与 TypeScript 相辅相成,前者保障代码规范,后者统一代码风格,共同减少团队协作中的摩擦。
    调试体验善用 source map 等调试技术,在保持源码可读性的同时,不牺牲生产环境的性能。
    测试覆盖完善的测试用例是类型检查之外的最后一道防线,Jest 等工具让我们能够更自信地进行代码重构。

    掌握这些编译与调试的核心技能,能够帮助我们更高效地构建和维护高质量的 TypeScript 应用。希望本文能为你的项目实践提供一些参考和帮助。

    `,100)])])}const g=i(p,[["render",t]]);export{c as __pageData,g as default}; +}

    运行测试:

    bash
    npm test

    4.2.5 高级特性

    Jest 还提供了一些高级特性,如异步测试、模拟函数、快照测试等,可以满足各种复杂的测试需求。更多详细信息请可参考 Jest 官方文档

    • 异步测试:支持 Promise 和 async/await
    • 模拟函数:使用 jest.fn() 创建模拟函数
    • 快照测试:生成组件或数据结构的快照
    • 测试覆盖率:自动生成覆盖率报告

    5. 结语

    TypeScript 的价值不仅在于静态类型检查带来的代码提示和编译时错误发现,更在于其完善的编译体系、调试能力和配套的质量保障工具。

    在实际项目中,我们需要关注以下几个层面:

    关注层面说明
    配置管理合理规划 tsconfig.json 的分层结构,无论是单体项目还是 Monorepo 架构,都能通过 extendsreferences 实现配置的复用与独立定制。
    代码质量ESLint 和 Prettier 与 TypeScript 相辅相成,前者保障代码规范,后者统一代码风格,共同减少团队协作中的摩擦。
    调试体验善用 source map 等调试技术,在保持源码可读性的同时,不牺牲生产环境的性能。
    测试覆盖完善的测试用例是类型检查之外的最后一道防线,Jest 等工具让我们能够更自信地进行代码重构。

    掌握这些编译与调试的核心技能,能够帮助我们更高效地构建和维护高质量的 TypeScript 应用。希望本文能为你的项目实践提供一些参考和帮助。

    `,99)])])}const g=i(p,[["render",t]]);export{c as __pageData,g as default}; diff --git "a/assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_01.\347\274\226\350\257\221\344\270\216\350\260\203\350\257\225 TypeScript \351\241\271\347\233\256\346\214\207\345\215\227.md.BHyEzAuH.lean.js" b/assets/fullstack_typescript-compilation-debugging-guide.md.C39DJVwc.lean.js similarity index 63% rename from "assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_01.\347\274\226\350\257\221\344\270\216\350\260\203\350\257\225 TypeScript \351\241\271\347\233\256\346\214\207\345\215\227.md.BHyEzAuH.lean.js" rename to assets/fullstack_typescript-compilation-debugging-guide.md.C39DJVwc.lean.js index d6388874..e8c2e43e 100644 --- "a/assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_01.\347\274\226\350\257\221\344\270\216\350\260\203\350\257\225 TypeScript \351\241\271\347\233\256\346\214\207\345\215\227.md.BHyEzAuH.lean.js" +++ b/assets/fullstack_typescript-compilation-debugging-guide.md.C39DJVwc.lean.js @@ -1 +1 @@ -import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const c=JSON.parse('{"title":"TypeScript 编译与调试完全指南","description":"深入解析 TypeScript 编译工具链与调试体系,涵盖 tsconfig.json 核心配置、Monorepo 项目配置(extends/references)、source map 调试、ESLint 与 Jest 单元测试等完整实践。","frontmatter":{"date":"2025-08-12T22:47:47.000Z","title":"TypeScript 编译与调试完全指南","tldr":"TypeScript 完善的编译体系与调试工具链,是构建高质量应用的基石。","description":"深入解析 TypeScript 编译工具链与调试体系,涵盖 tsconfig.json 核心配置、Monorepo 项目配置(extends/references)、source map 调试、ESLint 与 Jest 单元测试等完整实践。","permalink":"/fullstack/typescript-compilation-debugging-guide","tags":["tutorial","typescript","compilation","tooling","eslint","jest"],"categories":["全栈","全栈基础素养"]},"headers":[],"relativePath":"01.全栈/80.全栈基础素养/01.编译与调试 TypeScript 项目指南.md","filePath":"01.全栈/80.全栈基础素养/01.编译与调试 TypeScript 项目指南.md"}'),p={name:"01.全栈/80.全栈基础素养/01.编译与调试 TypeScript 项目指南.md"};function t(e,s,h,k,r,E){return n(),a("div",null,[...s[0]||(s[0]=[l("",100)])])}const g=i(p,[["render",t]]);export{c as __pageData,g as default}; +import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const c=JSON.parse('{"title":"TypeScript 编译与调试完全指南","description":"深入解析 TypeScript 编译工具链与调试体系,涵盖 tsconfig.json 核心配置、Monorepo 项目配置(extends/references)、source map 调试、ESLint 与 Jest 单元测试等完整实践。","frontmatter":{"date":"2025-08-12T22:47:47.000Z","title":"TypeScript 编译与调试完全指南","tldr":"TypeScript 完善的编译体系与调试工具链,是构建高质量应用的基石。","description":"深入解析 TypeScript 编译工具链与调试体系,涵盖 tsconfig.json 核心配置、Monorepo 项目配置(extends/references)、source map 调试、ESLint 与 Jest 单元测试等完整实践。","permalink":"/fullstack/typescript-compilation-debugging-guide","tags":["tutorial","typescript","compilation","tooling","eslint","jest"],"categories":["全栈","全栈基础素养"]},"headers":[],"relativePath":"fullstack/typescript-compilation-debugging-guide.md","filePath":"01.全栈/80.全栈基础素养/01.编译与调试 TypeScript 项目指南.md"}'),p={name:"fullstack/typescript-compilation-debugging-guide.md"};function t(e,s,h,k,r,E){return n(),a("div",null,[...s[0]||(s[0]=[l("",99)])])}const g=i(p,[["render",t]]);export{c as __pageData,g as default}; diff --git "a/assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_10.\350\201\212\344\270\200\350\201\212 Typescript \346\263\233\345\236\213.md.BpsDJhtc.js" b/assets/fullstack_typescript-generic-types.md.Cbx1pLcE.js similarity index 92% rename from "assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_10.\350\201\212\344\270\200\350\201\212 Typescript \346\263\233\345\236\213.md.BpsDJhtc.js" rename to assets/fullstack_typescript-generic-types.md.Cbx1pLcE.js index 05295f40..58821e45 100644 --- "a/assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_10.\350\201\212\344\270\200\350\201\212 Typescript \346\263\233\345\236\213.md.BpsDJhtc.js" +++ b/assets/fullstack_typescript-generic-types.md.Cbx1pLcE.js @@ -1,4 +1,4 @@ -import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const g=JSON.parse('{"title":"聊一聊 TypeScript 中的泛型","description":"本文系统解析 TypeScript 泛型的核心概念与工作机制,对比泛型与 any 类型的差异,涵盖泛型函数、接口、类、类型别名的实践用法,以及基本类型约束、接口约束、多重约束、keyof 约束等高阶技巧与最佳实践。","frontmatter":{"date":"2025-08-20T22:51:27.000Z","title":"聊一聊 TypeScript 中的泛型","tldr":"泛型将类型作为参数,使代码在多种类型上安全运行,是 TypeScript 类型抽象的核心特性。","description":"本文系统解析 TypeScript 泛型的核心概念与工作机制,对比泛型与 any 类型的差异,涵盖泛型函数、接口、类、类型别名的实践用法,以及基本类型约束、接口约束、多重约束、keyof 约束等高阶技巧与最佳实践。","permalink":"/fullstack/typescript-generic-types","tags":["tutorial","typescript","generics","type-system"],"categories":["全栈","全栈基础素养"]},"headers":[],"relativePath":"01.全栈/80.全栈基础素养/10.聊一聊 Typescript 泛型.md","filePath":"01.全栈/80.全栈基础素养/10.聊一聊 Typescript 泛型.md"}'),p={name:"01.全栈/80.全栈基础素养/10.聊一聊 Typescript 泛型.md"};function h(k,s,t,e,r,d){return n(),a("div",null,[...s[0]||(s[0]=[l(`

    聊一聊 TypeScript 中的泛型

    摘要总结: 泛型(Generics)是 TypeScript 中一种强大的类型系统特性,允许定义类型参数化的组件,使代码能够在多种类型上安全运行,同时保持类型检查。本文从泛型的基本概念出发,对比泛型与 any 类型的本质差异(类型安全、代码复用、类型推断、可读性),深入剖析类型参数化、类型检查、类型推断与类型擦除四方面工作原理。通过大量实战代码演示泛型函数、泛型接口、泛型类及泛型类型别名的高级应用,并系统讲解基本类型约束、接口约束、多重约束与 keyof 约束等高阶用法。泛型的学习路径本质上是从具体到抽象的思维训练,掌握泛型意味着掌握了 TypeScript 类型系统高阶能力的钥匙。

    1. 泛型的基本概念和作用

    1.1 核心定义

    泛型(Generics) 是 TypeScript 中一种强大的类型系统特性,允许定义类型参数化的组件,使代码能够在多种类型上安全运行,同时保持类型检查。泛型的核心思想是将类型作为参数传递给函数、接口或类,实现"编写一次,复用多次"的效果。

    1.2 泛型与 any 类型的对比

    特性泛型any 类型
    类型安全✅ 编译时进行类型检查❌ 完全失去类型检查
    代码复用✅ 支持多种类型复用✅ 支持多种类型,但失去类型信息
    类型推断✅ 编译器可推断具体类型❌ 无法推断具体类型
    可读性✅ 明确类型意图❌ 隐藏类型信息

    1.3 泛型的工作原理

    理解泛型的工作原理,需要从四个方面来把握:

    1、类型参数化

    当我们定义一个泛型函数 function foo<T>(arg: T): T 时,T 就像是一个"位置的占位符"。在编写代码时,我们还不知道 T 具体是什么类型,但它已经具备了类型的语义——在参数位置、返回值位置,甚至是后续的变量声明中,T 都会被当作一个有效的类型来使用。

    2、类型检查

    TypeScript 编译器会对泛型代码进行严格的类型检查。例如,在函数体内对 T 类型的参数调用只有特定类型才有的方法时,编译器会报错。这种检查发生在编译阶段,而不是运行时,从而避免了许多潜在的 bug。

    3、类型推断

    当我们调用泛型函数时,TypeScript 会根据传入的参数自动推断 T 的具体类型。比如调用 identity(42),编译器自动推断 Tnumber。这一步是可选的,如果无法推断,我们也可以显式指定类型参数 identity<number>(42)

    4、类型擦除

    这是泛型的一个重要特性——泛型类型信息只存在于编译阶段。编译为 JavaScript 时,所有 <T> 相关的类型标注都会被擦除,只保留普通的类型注释或完全没有任何类型信息。例如 function identity<T>(arg: T): T 编译后会变成 function identity(arg) { return arg; },最终产物中不存在任何泛型的痕迹。

    1.4 泛型的核心优势

    泛型之所以重要,是因为它解决了 JavaScript 类型系统中的几个核心问题:

    核心优势说明
    代码复用性的质变在没有泛型的时代,如果我们想让一个函数同时支持 string 和 number 类型,通常需要编写两个独立函数,或者使用 any 类型牺牲类型安全。而泛型让我们编写一套代码,就能安全地处理多种类型。例如,一个 identity 函数既可以处理 number,也可以处理 string,甚至是自定义的对象类型。
    类型安全是最大的保障使用 any 类型意味着彻底放弃类型检查,任何类型错误都要到运行时才能发现。而泛型在编译阶段就能捕获类型不匹配的问题,将 bug 消灭在摇篮里。这对于大型项目尤为重要,因为运行时类型错误往往难以定位和修复。
    代码意图更加清晰any 类型像是一个"黑箱",开发者无法从类型声明中得知这个值应该是什么类型。而泛型 Array<T>Promise<T> 等声明方式,让代码自描述性更强,后续维护者能够快速理解数据的结构和流向。
    面向未来的扩展性基于泛型设计的接口和类,不需要修改原有代码就能支持新的数据类型。比如我们定义了一个 Response<T> 接口,当业务需要新增一种数据类型时,只需要传入新的类型参数即可,而无需改动接口定义本身。
    推动更好的设计泛型鼓励开发者从一开始就从通用的角度思考问题,设计出更具抽象性和复用性的组件。这种思考方式与面向对象设计模式中的"依赖倒置"、"开闭原则"等思想不谋而合。

    1.5 泛型的应用场景

    泛型在实际开发中的应用非常广泛,以下是几个最常见的场景:

    应用场景说明
    通用数据结构的实现数据结构往往是通用的——一个栈不应该只能存储 number,它应该能存储任意类型。泛型让我们能够定义如 Stack<T>Queue<T>LinkedList<T> 这样真正通用的数据结构,同时保持对内部元素类型的严格检查。
    工具函数和类库开发日常开发中的工具函数,如深拷贝、JSON 序列化、数组处理等,都非常适合使用泛型。这类函数需要处理各种不同的数据类型,泛型能够在保持类型安全的同时,实现真正的复用。
    API 响应数据的类型化与后端接口交互时,响应数据的结构往往是固定的,但具体的数据类型可能不同。通过泛型 ApiResponse<T>,我们可以为每个接口定义精确的返回类型,同时保持 API 请求逻辑的统一。
    前端组件库开发在 React、Vue 等框架中,组件通常需要处理各种类型的 props 和 state。泛型组件如 Table<T>List<T> 等,能够在提供类型安全的同时,适应不同的业务数据模型。
    通用接口和类的设计面向对象编程中,我们经常需要定义一些有通用约束的接口。比如定义一个 Repository<T> 接口,所有实体仓储都实现这个接口,但每个仓储操作的实体类型各不相同。泛型让这种设计成为可能。

    2. 泛型代码示例

    2.1 基础泛型函数

    typescript
    // 泛型标识函数:返回与输入相同类型的值
    +import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const g=JSON.parse('{"title":"聊一聊 TypeScript 中的泛型","description":"本文系统解析 TypeScript 泛型的核心概念与工作机制,对比泛型与 any 类型的差异,涵盖泛型函数、接口、类、类型别名的实践用法,以及基本类型约束、接口约束、多重约束、keyof 约束等高阶技巧与最佳实践。","frontmatter":{"date":"2025-08-20T22:51:27.000Z","title":"聊一聊 TypeScript 中的泛型","tldr":"泛型将类型作为参数,使代码在多种类型上安全运行,是 TypeScript 类型抽象的核心特性。","description":"本文系统解析 TypeScript 泛型的核心概念与工作机制,对比泛型与 any 类型的差异,涵盖泛型函数、接口、类、类型别名的实践用法,以及基本类型约束、接口约束、多重约束、keyof 约束等高阶技巧与最佳实践。","permalink":"/fullstack/typescript-generic-types","tags":["tutorial","typescript","generics","type-system"],"categories":["全栈","全栈基础素养"]},"headers":[],"relativePath":"fullstack/typescript-generic-types.md","filePath":"01.全栈/80.全栈基础素养/10.聊一聊 Typescript 泛型.md"}'),p={name:"fullstack/typescript-generic-types.md"};function h(k,s,t,e,r,E){return n(),a("div",null,[...s[0]||(s[0]=[l(`

    聊一聊 TypeScript 中的泛型

    摘要总结: 泛型(Generics)是 TypeScript 中一种强大的类型系统特性,允许定义类型参数化的组件,使代码能够在多种类型上安全运行,同时保持类型检查。本文从泛型的基本概念出发,对比泛型与 any 类型的本质差异(类型安全、代码复用、类型推断、可读性),深入剖析类型参数化、类型检查、类型推断与类型擦除四方面工作原理。通过大量实战代码演示泛型函数、泛型接口、泛型类及泛型类型别名的高级应用,并系统讲解基本类型约束、接口约束、多重约束与 keyof 约束等高阶用法。泛型的学习路径本质上是从具体到抽象的思维训练,掌握泛型意味着掌握了 TypeScript 类型系统高阶能力的钥匙。

    1. 泛型的基本概念和作用

    1.1 核心定义

    泛型(Generics) 是 TypeScript 中一种强大的类型系统特性,允许定义类型参数化的组件,使代码能够在多种类型上安全运行,同时保持类型检查。泛型的核心思想是将类型作为参数传递给函数、接口或类,实现"编写一次,复用多次"的效果。

    1.2 泛型与 any 类型的对比

    特性泛型any 类型
    类型安全✅ 编译时进行类型检查❌ 完全失去类型检查
    代码复用✅ 支持多种类型复用✅ 支持多种类型,但失去类型信息
    类型推断✅ 编译器可推断具体类型❌ 无法推断具体类型
    可读性✅ 明确类型意图❌ 隐藏类型信息

    1.3 泛型的工作原理

    理解泛型的工作原理,需要从四个方面来把握:

    1、类型参数化

    当我们定义一个泛型函数 function foo<T>(arg: T): T 时,T 就像是一个"位置的占位符"。在编写代码时,我们还不知道 T 具体是什么类型,但它已经具备了类型的语义——在参数位置、返回值位置,甚至是后续的变量声明中,T 都会被当作一个有效的类型来使用。

    2、类型检查

    TypeScript 编译器会对泛型代码进行严格的类型检查。例如,在函数体内对 T 类型的参数调用只有特定类型才有的方法时,编译器会报错。这种检查发生在编译阶段,而不是运行时,从而避免了许多潜在的 bug。

    3、类型推断

    当我们调用泛型函数时,TypeScript 会根据传入的参数自动推断 T 的具体类型。比如调用 identity(42),编译器自动推断 Tnumber。这一步是可选的,如果无法推断,我们也可以显式指定类型参数 identity<number>(42)

    4、类型擦除

    这是泛型的一个重要特性——泛型类型信息只存在于编译阶段。编译为 JavaScript 时,所有 <T> 相关的类型标注都会被擦除,只保留普通的类型注释或完全没有任何类型信息。例如 function identity<T>(arg: T): T 编译后会变成 function identity(arg) { return arg; },最终产物中不存在任何泛型的痕迹。

    1.4 泛型的核心优势

    泛型之所以重要,是因为它解决了 JavaScript 类型系统中的几个核心问题:

    核心优势说明
    代码复用性的质变在没有泛型的时代,如果我们想让一个函数同时支持 string 和 number 类型,通常需要编写两个独立函数,或者使用 any 类型牺牲类型安全。而泛型让我们编写一套代码,就能安全地处理多种类型。例如,一个 identity 函数既可以处理 number,也可以处理 string,甚至是自定义的对象类型。
    类型安全是最大的保障使用 any 类型意味着彻底放弃类型检查,任何类型错误都要到运行时才能发现。而泛型在编译阶段就能捕获类型不匹配的问题,将 bug 消灭在摇篮里。这对于大型项目尤为重要,因为运行时类型错误往往难以定位和修复。
    代码意图更加清晰any 类型像是一个"黑箱",开发者无法从类型声明中得知这个值应该是什么类型。而泛型 Array<T>Promise<T> 等声明方式,让代码自描述性更强,后续维护者能够快速理解数据的结构和流向。
    面向未来的扩展性基于泛型设计的接口和类,不需要修改原有代码就能支持新的数据类型。比如我们定义了一个 Response<T> 接口,当业务需要新增一种数据类型时,只需要传入新的类型参数即可,而无需改动接口定义本身。
    推动更好的设计泛型鼓励开发者从一开始就从通用的角度思考问题,设计出更具抽象性和复用性的组件。这种思考方式与面向对象设计模式中的"依赖倒置"、"开闭原则"等思想不谋而合。

    1.5 泛型的应用场景

    泛型在实际开发中的应用非常广泛,以下是几个最常见的场景:

    应用场景说明
    通用数据结构的实现数据结构往往是通用的——一个栈不应该只能存储 number,它应该能存储任意类型。泛型让我们能够定义如 Stack<T>Queue<T>LinkedList<T> 这样真正通用的数据结构,同时保持对内部元素类型的严格检查。
    工具函数和类库开发日常开发中的工具函数,如深拷贝、JSON 序列化、数组处理等,都非常适合使用泛型。这类函数需要处理各种不同的数据类型,泛型能够在保持类型安全的同时,实现真正的复用。
    API 响应数据的类型化与后端接口交互时,响应数据的结构往往是固定的,但具体的数据类型可能不同。通过泛型 ApiResponse<T>,我们可以为每个接口定义精确的返回类型,同时保持 API 请求逻辑的统一。
    前端组件库开发在 React、Vue 等框架中,组件通常需要处理各种类型的 props 和 state。泛型组件如 Table<T>List<T> 等,能够在提供类型安全的同时,适应不同的业务数据模型。
    通用接口和类的设计面向对象编程中,我们经常需要定义一些有通用约束的接口。比如定义一个 Repository<T> 接口,所有实体仓储都实现这个接口,但每个仓储操作的实体类型各不相同。泛型让这种设计成为可能。

    2. 泛型代码示例

    2.1 基础泛型函数

    typescript
    // 泛型标识函数:返回与输入相同类型的值
     // <T>:类型参数,代表任意类型
     // arg: T:参数类型为 T
     // : T:返回值类型为 T
    @@ -333,4 +333,4 @@ import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.CqY1sKvl.j
     
     // 编译报错:普通对象不是 DatabaseModel 的子类
     // const plainObject = { id: 1, name: 'Test' };
    -// saveToDatabase(plainObject);

    4.6 小结

    泛型约束是 TypeScript 泛型系统中的核心机制,通过限制泛型参数的类型范围,实现了类型安全与代码复用的平衡。不同类型的泛型约束适用于不同的场景:

    约束类型适用场景说明
    基本类型约束需要处理特定基本类型的场景如数字、字符串等,确保可以安全使用 .length.toFixed() 等内置方法
    接口约束项目开发中最常用的约束形式通过定义接口规范数据结构,确保数据具有预期的属性和方法,如 extends HasName 约束对象必须有 name 属性
    多重约束需要泛型参数具备多种能力的场景通过 & 操作符组合多个约束条件,如 <T extends HasName & HasId> 要求同时满足多个接口
    Keyof 约束构建类型安全的属性访问工具函数结合 keyof 操作符实现,如 <T, K extends keyof T> 确保访问的属性确实存在于对象中
    类约束处理继承体系的场景确保泛型参数是某个基类的子类,继承其属性和方法,常用于数据库模型、UI 组件等场景

    泛型约束的核心价值在于平衡类型安全代码通用性

    价值维度体现
    质量编译期捕获类型错误,减少运行时异常
    复用通用的函数和组件,一次编写,多处复用
    可读明确的类型约束,让代码意图一目了然
    扩展灵活应对复杂的数据结构和继承关系

    泛型约束与接口、keyof、类等特性结合,构成了 TypeScript 类型系统的高阶能力,是构建大型可靠应用的重要基础。

    5. 结语

    泛型不仅仅是一种语法特性,更是一种抽象思维的体现。

    从本文可以看到,泛型的学习曲线实际上是从具体到抽象的过程:起初我们学习 <T> 的写法、基本函数的使用;进而理解约束、keyof、多重泛型等高阶用法;最终,我们学会用泛型的思维方式去设计通用的数据结构、工具函数和组件接口。

    这条学习路径,本质上与软件设计中"从特殊到一般"的抽象能力培养路径一致。一个真正掌握了泛型的开发者,看待问题的角度会发生转变——不再满足于"针对这个具体问题写这段具体代码",而是会思考"这个问题能否抽象成一个通用方案,让未来类似的问题也能复用"

    这种思维方式的价值远超泛型本身,它会渗透到代码设计的方方面面。TypeScript 的类型系统是一座宝库,泛型只是其中的一个子集。希望本文不仅帮助你掌握了泛型,更帮助你窥见了 TypeScript 类型系统的魅力所在。

    `,82)])])}const y=i(p,[["render",h]]);export{g as __pageData,y as default}; +// saveToDatabase(plainObject);

    4.6 小结

    泛型约束是 TypeScript 泛型系统中的核心机制,通过限制泛型参数的类型范围,实现了类型安全与代码复用的平衡。不同类型的泛型约束适用于不同的场景:

    约束类型适用场景说明
    基本类型约束需要处理特定基本类型的场景如数字、字符串等,确保可以安全使用 .length.toFixed() 等内置方法
    接口约束项目开发中最常用的约束形式通过定义接口规范数据结构,确保数据具有预期的属性和方法,如 extends HasName 约束对象必须有 name 属性
    多重约束需要泛型参数具备多种能力的场景通过 & 操作符组合多个约束条件,如 <T extends HasName & HasId> 要求同时满足多个接口
    Keyof 约束构建类型安全的属性访问工具函数结合 keyof 操作符实现,如 <T, K extends keyof T> 确保访问的属性确实存在于对象中
    类约束处理继承体系的场景确保泛型参数是某个基类的子类,继承其属性和方法,常用于数据库模型、UI 组件等场景

    泛型约束的核心价值在于平衡类型安全代码通用性

    价值维度体现
    质量编译期捕获类型错误,减少运行时异常
    复用通用的函数和组件,一次编写,多处复用
    可读明确的类型约束,让代码意图一目了然
    扩展灵活应对复杂的数据结构和继承关系

    泛型约束与接口、keyof、类等特性结合,构成了 TypeScript 类型系统的高阶能力,是构建大型可靠应用的重要基础。

    5. 结语

    泛型不仅仅是一种语法特性,更是一种抽象思维的体现。

    从本文可以看到,泛型的学习曲线实际上是从具体到抽象的过程:起初我们学习 <T> 的写法、基本函数的使用;进而理解约束、keyof、多重泛型等高阶用法;最终,我们学会用泛型的思维方式去设计通用的数据结构、工具函数和组件接口。

    这条学习路径,本质上与软件设计中"从特殊到一般"的抽象能力培养路径一致。一个真正掌握了泛型的开发者,看待问题的角度会发生转变——不再满足于"针对这个具体问题写这段具体代码",而是会思考"这个问题能否抽象成一个通用方案,让未来类似的问题也能复用"

    这种思维方式的价值远超泛型本身,它会渗透到代码设计的方方面面。TypeScript 的类型系统是一座宝库,泛型只是其中的一个子集。希望本文不仅帮助你掌握了泛型,更帮助你窥见了 TypeScript 类型系统的魅力所在。

    `,81)])])}const y=i(p,[["render",h]]);export{g as __pageData,y as default}; diff --git "a/assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_10.\350\201\212\344\270\200\350\201\212 Typescript \346\263\233\345\236\213.md.BpsDJhtc.lean.js" b/assets/fullstack_typescript-generic-types.md.Cbx1pLcE.lean.js similarity index 68% rename from "assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_10.\350\201\212\344\270\200\350\201\212 Typescript \346\263\233\345\236\213.md.BpsDJhtc.lean.js" rename to assets/fullstack_typescript-generic-types.md.Cbx1pLcE.lean.js index 99b4aca2..0d963d1a 100644 --- "a/assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_10.\350\201\212\344\270\200\350\201\212 Typescript \346\263\233\345\236\213.md.BpsDJhtc.lean.js" +++ b/assets/fullstack_typescript-generic-types.md.Cbx1pLcE.lean.js @@ -1 +1 @@ -import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const g=JSON.parse('{"title":"聊一聊 TypeScript 中的泛型","description":"本文系统解析 TypeScript 泛型的核心概念与工作机制,对比泛型与 any 类型的差异,涵盖泛型函数、接口、类、类型别名的实践用法,以及基本类型约束、接口约束、多重约束、keyof 约束等高阶技巧与最佳实践。","frontmatter":{"date":"2025-08-20T22:51:27.000Z","title":"聊一聊 TypeScript 中的泛型","tldr":"泛型将类型作为参数,使代码在多种类型上安全运行,是 TypeScript 类型抽象的核心特性。","description":"本文系统解析 TypeScript 泛型的核心概念与工作机制,对比泛型与 any 类型的差异,涵盖泛型函数、接口、类、类型别名的实践用法,以及基本类型约束、接口约束、多重约束、keyof 约束等高阶技巧与最佳实践。","permalink":"/fullstack/typescript-generic-types","tags":["tutorial","typescript","generics","type-system"],"categories":["全栈","全栈基础素养"]},"headers":[],"relativePath":"01.全栈/80.全栈基础素养/10.聊一聊 Typescript 泛型.md","filePath":"01.全栈/80.全栈基础素养/10.聊一聊 Typescript 泛型.md"}'),p={name:"01.全栈/80.全栈基础素养/10.聊一聊 Typescript 泛型.md"};function h(k,s,t,e,r,d){return n(),a("div",null,[...s[0]||(s[0]=[l("",82)])])}const y=i(p,[["render",h]]);export{g as __pageData,y as default}; +import{_ as i,g as a,h as n,U as l}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const g=JSON.parse('{"title":"聊一聊 TypeScript 中的泛型","description":"本文系统解析 TypeScript 泛型的核心概念与工作机制,对比泛型与 any 类型的差异,涵盖泛型函数、接口、类、类型别名的实践用法,以及基本类型约束、接口约束、多重约束、keyof 约束等高阶技巧与最佳实践。","frontmatter":{"date":"2025-08-20T22:51:27.000Z","title":"聊一聊 TypeScript 中的泛型","tldr":"泛型将类型作为参数,使代码在多种类型上安全运行,是 TypeScript 类型抽象的核心特性。","description":"本文系统解析 TypeScript 泛型的核心概念与工作机制,对比泛型与 any 类型的差异,涵盖泛型函数、接口、类、类型别名的实践用法,以及基本类型约束、接口约束、多重约束、keyof 约束等高阶技巧与最佳实践。","permalink":"/fullstack/typescript-generic-types","tags":["tutorial","typescript","generics","type-system"],"categories":["全栈","全栈基础素养"]},"headers":[],"relativePath":"fullstack/typescript-generic-types.md","filePath":"01.全栈/80.全栈基础素养/10.聊一聊 Typescript 泛型.md"}'),p={name:"fullstack/typescript-generic-types.md"};function h(k,s,t,e,r,E){return n(),a("div",null,[...s[0]||(s[0]=[l("",81)])])}const y=i(p,[["render",h]]);export{g as __pageData,y as default}; diff --git "a/assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_4.Typescript \345\257\271\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\347\232\204\345\242\236\345\274\272.md.hJ1lv1QY.js" b/assets/fullstack_typescript-module-programming-enhancement.md.CDxy6Uow.js similarity index 92% rename from "assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_4.Typescript \345\257\271\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\347\232\204\345\242\236\345\274\272.md.hJ1lv1QY.js" rename to assets/fullstack_typescript-module-programming-enhancement.md.CDxy6Uow.js index bcc9487a..ea388023 100644 --- "a/assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_4.Typescript \345\257\271\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\347\232\204\345\242\236\345\274\272.md.hJ1lv1QY.js" +++ b/assets/fullstack_typescript-module-programming-enhancement.md.CDxy6Uow.js @@ -1,4 +1,4 @@ -import{_ as i,g as a,h as n,U as p}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const g=JSON.parse('{"title":"从逻辑隔离到类型契约:TypeScript 对模块化编程的增强","description":"系统讲解 TypeScript 对 ES Modules 的类型增强,涵盖 import type 运行时优化、接口契约、声明文件 .d.ts 及 tsconfig 模块化配置。","frontmatter":{"date":"2024-05-16T21:27:36.000Z","title":"从逻辑隔离到类型契约:TypeScript 对模块化编程的增强","tldr":"TypeScript 将模块依赖提升为编译时类型契约,从 import type 到声明文件。","description":"系统讲解 TypeScript 对 ES Modules 的类型增强,涵盖 import type 运行时优化、接口契约、声明文件 .d.ts 及 tsconfig 模块化配置。","permalink":"/fullstack/typescript-module-programming-enhancement","tags":["concept","全栈","typescript","tsconfig"],"categories":["全栈","全栈基础素养","模块化编程实践指南"]},"headers":[],"relativePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/4.Typescript 对模块化编程的增强.md","filePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/4.Typescript 对模块化编程的增强.md"}'),l={name:"01.全栈/80.全栈基础素养/20.模块化编程实践指南/4.Typescript 对模块化编程的增强.md"};function t(h,s,e,k,r,d){return n(),a("div",null,[...s[0]||(s[0]=[p(`

    从逻辑隔离到类型契约:TypeScript 对模块化编程的增强

    摘要总结: TypeScript 将模块间的依赖关系从简单的代码引用提升为编译时类型契约。本文系统讲解 TypeScript 对 ES Modules 的类型增强,涵盖 import type 运行时优化、接口契约、声明文件 .d.ts 及 tsconfig 模块化配置。

    1. 引言

    在原生 JavaScript 模块化解决了代码组织问题后,TypeScript(TS)进一步将其推向了工业级高度。TS 不仅仅是为模块添加了类型标注,它通过类型导出导入、编译时优化、以及声明文件系统,将模块间的依赖关系从简单的“代码引用”提升到了“契约交互”。

    本文我们将聚焦于 TypeScript 如何通过类型系统增强模块化编程,并探讨在现代工程(尤其是 TS 5.0+ 时代)下的最佳配置实践。

    2. 类型导出与导入:极致的运行时优化

    TypeScript 对 ES Modules 语法最显著的扩展是支持“仅类型”(Type-only)的导出与导入。这不仅是语义上的清晰,更是性能优化的关键——类型导入在编译为 JS 后会被完全抹除,确保不会引入冗余的运行时负载。

    示例代码

    typescript
    // types.ts - 类型导出
    +import{_ as i,g as a,h as n,U as p}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const g=JSON.parse('{"title":"从逻辑隔离到类型契约:TypeScript 对模块化编程的增强","description":"系统讲解 TypeScript 对 ES Modules 的类型增强,涵盖 import type 运行时优化、接口契约、声明文件 .d.ts 及 tsconfig 模块化配置。","frontmatter":{"date":"2024-05-16T21:27:36.000Z","title":"从逻辑隔离到类型契约:TypeScript 对模块化编程的增强","tldr":"TypeScript 将模块依赖提升为编译时类型契约,从 import type 到声明文件。","description":"系统讲解 TypeScript 对 ES Modules 的类型增强,涵盖 import type 运行时优化、接口契约、声明文件 .d.ts 及 tsconfig 模块化配置。","permalink":"/fullstack/typescript-module-programming-enhancement","tags":["concept","全栈","typescript","tsconfig"],"categories":["全栈","全栈基础素养","模块化编程实践指南"]},"headers":[],"relativePath":"fullstack/typescript-module-programming-enhancement.md","filePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/4.Typescript 对模块化编程的增强.md"}'),l={name:"fullstack/typescript-module-programming-enhancement.md"};function t(h,s,e,k,r,d){return n(),a("div",null,[...s[0]||(s[0]=[p(`

    从逻辑隔离到类型契约:TypeScript 对模块化编程的增强

    摘要总结: TypeScript 将模块间的依赖关系从简单的代码引用提升为编译时类型契约。本文系统讲解 TypeScript 对 ES Modules 的类型增强,涵盖 import type 运行时优化、接口契约、声明文件 .d.ts 及 tsconfig 模块化配置。

    1. 引言

    在原生 JavaScript 模块化解决了代码组织问题后,TypeScript(TS)进一步将其推向了工业级高度。TS 不仅仅是为模块添加了类型标注,它通过类型导出导入、编译时优化、以及声明文件系统,将模块间的依赖关系从简单的“代码引用”提升到了“契约交互”。

    本文我们将聚焦于 TypeScript 如何通过类型系统增强模块化编程,并探讨在现代工程(尤其是 TS 5.0+ 时代)下的最佳配置实践。

    2. 类型导出与导入:极致的运行时优化

    TypeScript 对 ES Modules 语法最显著的扩展是支持“仅类型”(Type-only)的导出与导入。这不仅是语义上的清晰,更是性能优化的关键——类型导入在编译为 JS 后会被完全抹除,确保不会引入冗余的运行时负载。

    示例代码

    typescript
    // types.ts - 类型导出
     export interface User {
       id: string;
       name: string;
    @@ -81,4 +81,4 @@ import{_ as i,g as a,h as n,U as p}from"./chunks/vitepress-theme-teek.CqY1sKvl.j
     
     // app.ts
     import { power } from './math.js';
    -console.log(power(2, 3)); // 输出:8

    8. 结语:构建稳固的类型防线

    TypeScript 对模块化的增强,本质上是将工程质量的保障从“运行时测试”提前到了“编译时检查”。通过合理使用类型导入、规范的声明文件以及现代的编译配置,我们可以构建起一套坚不可摧的代码契约。

    在全栈开发的语境下,这种增强不仅限于前端。当我们在 Node.js 服务端和 React 前端之间共享一套类型声明模块时,就会发现“全栈一致性”才真正从理想变成了现实。

    `,41)])])}const y=i(l,[["render",t]]);export{g as __pageData,y as default}; +console.log(power(2, 3)); // 输出:8

    8. 结语:构建稳固的类型防线

    TypeScript 对模块化的增强,本质上是将工程质量的保障从“运行时测试”提前到了“编译时检查”。通过合理使用类型导入、规范的声明文件以及现代的编译配置,我们可以构建起一套坚不可摧的代码契约。

    在全栈开发的语境下,这种增强不仅限于前端。当我们在 Node.js 服务端和 React 前端之间共享一套类型声明模块时,就会发现“全栈一致性”才真正从理想变成了现实。

    `,40)])])}const y=i(l,[["render",t]]);export{g as __pageData,y as default}; diff --git "a/assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_4.Typescript \345\257\271\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\347\232\204\345\242\236\345\274\272.md.hJ1lv1QY.lean.js" b/assets/fullstack_typescript-module-programming-enhancement.md.CDxy6Uow.lean.js similarity index 60% rename from "assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_4.Typescript \345\257\271\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\347\232\204\345\242\236\345\274\272.md.hJ1lv1QY.lean.js" rename to assets/fullstack_typescript-module-programming-enhancement.md.CDxy6Uow.lean.js index 84b19e75..b63feb98 100644 --- "a/assets/01.\345\205\250\346\240\210_80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273_20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227_4.Typescript \345\257\271\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\347\232\204\345\242\236\345\274\272.md.hJ1lv1QY.lean.js" +++ b/assets/fullstack_typescript-module-programming-enhancement.md.CDxy6Uow.lean.js @@ -1 +1 @@ -import{_ as i,g as a,h as n,U as p}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const g=JSON.parse('{"title":"从逻辑隔离到类型契约:TypeScript 对模块化编程的增强","description":"系统讲解 TypeScript 对 ES Modules 的类型增强,涵盖 import type 运行时优化、接口契约、声明文件 .d.ts 及 tsconfig 模块化配置。","frontmatter":{"date":"2024-05-16T21:27:36.000Z","title":"从逻辑隔离到类型契约:TypeScript 对模块化编程的增强","tldr":"TypeScript 将模块依赖提升为编译时类型契约,从 import type 到声明文件。","description":"系统讲解 TypeScript 对 ES Modules 的类型增强,涵盖 import type 运行时优化、接口契约、声明文件 .d.ts 及 tsconfig 模块化配置。","permalink":"/fullstack/typescript-module-programming-enhancement","tags":["concept","全栈","typescript","tsconfig"],"categories":["全栈","全栈基础素养","模块化编程实践指南"]},"headers":[],"relativePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/4.Typescript 对模块化编程的增强.md","filePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/4.Typescript 对模块化编程的增强.md"}'),l={name:"01.全栈/80.全栈基础素养/20.模块化编程实践指南/4.Typescript 对模块化编程的增强.md"};function t(h,s,e,k,r,d){return n(),a("div",null,[...s[0]||(s[0]=[p("",41)])])}const y=i(l,[["render",t]]);export{g as __pageData,y as default}; +import{_ as i,g as a,h as n,U as p}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const g=JSON.parse('{"title":"从逻辑隔离到类型契约:TypeScript 对模块化编程的增强","description":"系统讲解 TypeScript 对 ES Modules 的类型增强,涵盖 import type 运行时优化、接口契约、声明文件 .d.ts 及 tsconfig 模块化配置。","frontmatter":{"date":"2024-05-16T21:27:36.000Z","title":"从逻辑隔离到类型契约:TypeScript 对模块化编程的增强","tldr":"TypeScript 将模块依赖提升为编译时类型契约,从 import type 到声明文件。","description":"系统讲解 TypeScript 对 ES Modules 的类型增强,涵盖 import type 运行时优化、接口契约、声明文件 .d.ts 及 tsconfig 模块化配置。","permalink":"/fullstack/typescript-module-programming-enhancement","tags":["concept","全栈","typescript","tsconfig"],"categories":["全栈","全栈基础素养","模块化编程实践指南"]},"headers":[],"relativePath":"fullstack/typescript-module-programming-enhancement.md","filePath":"01.全栈/80.全栈基础素养/20.模块化编程实践指南/4.Typescript 对模块化编程的增强.md"}'),l={name:"fullstack/typescript-module-programming-enhancement.md"};function t(h,s,e,k,r,d){return n(),a("div",null,[...s[0]||(s[0]=[p("",40)])])}const y=i(l,[["render",t]]);export{g as __pageData,y as default}; diff --git "a/assets/30.\346\202\246\350\257\273\346\227\266\345\205\211_01.\345\245\275\344\271\246\346\216\250\350\215\220.md.lGftAF4x.js" b/assets/growth_books.md.B9CjQKY5.js similarity index 82% rename from "assets/30.\346\202\246\350\257\273\346\227\266\345\205\211_01.\345\245\275\344\271\246\346\216\250\350\215\220.md.lGftAF4x.js" rename to assets/growth_books.md.B9CjQKY5.js index 23539f17..54d81121 100644 --- "a/assets/30.\346\202\246\350\257\273\346\227\266\345\205\211_01.\345\245\275\344\271\246\346\216\250\350\215\220.md.lGftAF4x.js" +++ b/assets/growth_books.md.B9CjQKY5.js @@ -1 +1 @@ -import{d as A,p as B,h as a,z as h,Y as I,s as W,g as l,y as _,v as P,i as e,W as v,x as c,F as p,t as f,S as n,T as Y,_ as C,r as j,c as T,k as M,U as x,l as g}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const $="/img/cover/health_bg.png",N={class:"book-panel__drawer"},V={class:"book-panel__header-meta"},G={class:"book-panel__title"},D={class:"book-panel__author"},F={class:"book-panel__body"},R={class:"book-panel__top-bar"},Z={class:"book-panel__top-left"},H={class:"book-panel__tags"},J={key:0,class:"book-panel__rating"},O={class:"stars"},E={key:0,viewBox:"0 0 24 24",fill:"currentColor"},K={key:1,viewBox:"0 0 24 24",class:"half-star"},Q=["id"],X=["clip-path"],U={key:2,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"1.5"},ee={class:"rating-text"},te={class:"book-panel__links"},oe=["href"],ae={width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",style:{"flex-shrink":"0"}},le=["href"],re={width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",style:{"flex-shrink":"0"}},ne={class:"book-panel__section"},se={class:"book-panel__desc"},ie={key:0,class:"book-panel__section"},de={class:"book-panel__highlights"},ce=A({__name:"BookDetailPanel",props:{book:{},open:{type:Boolean},heroColor:{},tagColors:{}},emits:["close"],setup(r,{emit:b}){const t=b;return(w,o)=>(a(),B(Y,{to:"body"},[h(I,{name:"panel-slide"},{default:W(()=>[r.open&&r.book?(a(),l("div",{key:0,class:"book-panel",onClick:o[2]||(o[2]=P(i=>t("close"),["self"]))},[e("div",{class:"book-panel__overlay",onClick:o[0]||(o[0]=i=>t("close"))}),e("div",N,[e("div",{class:"book-panel__header",style:v({background:r.heroColor})},[e("button",{class:"book-panel__close",title:"关闭",onClick:o[1]||(o[1]=i=>t("close"))},[...o[3]||(o[3]=[e("svg",{width:"14",height:"14",viewBox:"0 0 16 16",fill:"none"},[e("path",{d:"M12 4L4 12M4 4l8 8",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round"})],-1)])]),e("div",V,[e("h2",G,c(r.book.title),1),e("p",D,c(r.book.author),1)])],4),e("div",F,[e("div",R,[e("div",Z,[e("div",H,[(a(!0),l(p,null,f(r.book.tags,(i,m)=>(a(),l("span",{key:i,class:"book-panel__tag",style:v({background:r.tagColors[m%r.tagColors.length].bg,color:r.tagColors[m%r.tagColors.length].text})},c(i),5))),128))]),r.book.rating!=null?(a(),l("div",J,[o[8]||(o[8]=e("span",{class:"rating-label"},"推荐指数:",-1)),e("div",O,[(a(),l(p,null,f(5,i=>e("span",{key:i,class:"star"},[i<=Math.floor(r.book.rating)?(a(),l("svg",E,[...o[4]||(o[4]=[e("path",{d:"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"},null,-1)])])):i===Math.ceil(r.book.rating)&&r.book.rating%1!==0?(a(),l("svg",K,[e("defs",null,[e("clipPath",{id:"clip-"+r.book.id},[...o[5]||(o[5]=[e("rect",{x:"0",y:"0",width:"12",height:"24"},null,-1)])],8,Q)]),o[6]||(o[6]=e("path",{class:"star-empty",d:"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z",fill:"none",stroke:"currentColor","stroke-width":"1.5"},null,-1)),e("path",{class:"star-filled",d:"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z",fill:"currentColor","clip-path":"url(#clip-"+r.book.id+")"},null,8,X)])):(a(),l("svg",U,[...o[7]||(o[7]=[e("path",{d:"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"},null,-1)])]))])),64))]),e("span",ee,c(r.book.rating.toFixed(1)),1)])):_("",!0)]),e("div",te,[e("a",{href:r.book.link,target:"_blank",rel:"noopener",class:"book-panel__link-btn"},[(a(),l("svg",ae,[...o[9]||(o[9]=[e("path",{d:"M18 13v6a2 2 0 01-2 2H5a2 2 0 01-2-2V8a2 2 0 012-2h6M15 3h6v6M10 14L21 3",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},null,-1)])])),o[10]||(o[10]=n(" 豆瓣 ",-1))],8,oe),r.book.wereadLink?(a(),l("a",{key:0,href:r.book.wereadLink,target:"_blank",rel:"noopener",class:"book-panel__link-btn"},[(a(),l("svg",re,[...o[11]||(o[11]=[e("path",{d:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z",fill:"currentColor"},null,-1)])])),o[12]||(o[12]=n(" 微信读书 ",-1))],8,le)):_("",!0)])]),o[15]||(o[15]=e("div",{class:"book-panel__divider"},null,-1)),e("section",ne,[o[13]||(o[13]=e("h3",{class:"book-panel__section-title"},[e("span",{class:"book-panel__section-icon"},"📖"),n(" 内容简介 ")],-1)),e("p",se,c(r.book.desc),1)]),r.book.highlights&&r.book.highlights.length>0?(a(),l("section",ie,[o[14]||(o[14]=e("h3",{class:"book-panel__section-title"},[e("span",{class:"book-panel__section-icon"},"✨"),n(" 书籍亮点 ")],-1)),e("ul",de,[(a(!0),l(p,null,f(r.book.highlights,(i,m)=>(a(),l("li",{key:m,class:"book-panel__highlight-item"},c(i),1))),128))])])):_("",!0)])])])):_("",!0)]),_:1})]))}}),he=C(ce,[["__scopeId","data-v-1ddfc013"]]),be={class:"book-list"},ue=["onClick"],ge=["src","alt"],ke={class:"book-cover__overlay"},pe={key:0,class:"book-cover__hint"},we=["href"],me={class:"book-info"},_e={class:"book-info__title"},fe={class:"book-info__author"},qe={key:0,class:"book-info__rating"},ve={class:"stars"},je={key:0,viewBox:"0 0 24 24",fill:"currentColor"},Le={key:1,viewBox:"0 0 24 24",class:"half-star"},ye=["id"],Se=["clip-path"],xe={key:2,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"1.5"},Ae={class:"rating-text"},Pe={class:"book-info__tags"},Ce={class:"book-info__desc"},ze=A({__name:"BookRecommend",props:{books:{}},setup(r){const b=["linear-gradient(135deg, #e8f0fe 0%, #c7d9fd 100%)","linear-gradient(135deg, #e6f4ea 0%, #b7dfc4 100%)","linear-gradient(135deg, #fff3e0 0%, #ffd9a0 100%)","linear-gradient(135deg, #fce4ec 0%, #f8b4c8 100%)","linear-gradient(135deg, #ede7f6 0%, #cdb8ee 100%)","linear-gradient(135deg, #e0f7fa 0%, #9ee8f0 100%)"],t=[{bg:"#e8f0fe",text:"#3b5bdb"},{bg:"#e6f4ea",text:"#2e7d32"},{bg:"#fff3e0",text:"#e65100"},{bg:"#fce4ec",text:"#c2185b"},{bg:"#ede7f6",text:"#6a1b9a"},{bg:"#e0f7fa",text:"#00838f"}],w=j(null),o=j(0),i=j(!1),m=T(()=>b[o.value%b.length]);function z(q,d){q.withPanel!==!1&&(w.value?.id===q.id&&i.value?L():(w.value=q,o.value=d,i.value=!0))}function L(){i.value=!1,setTimeout(()=>{w.value=null},300)}return(q,d)=>(a(),l(p,null,[e("div",be,[(a(!0),l(p,null,f(r.books,(s,y)=>(a(),l("div",{key:s.id,class:M(["book-card",{"book-card--active":w.value?.id===s.id&&i.value}]),onClick:u=>z(s,y)},[e("div",{class:"book-cover",style:v({background:b[y%b.length]})},[s.cover?(a(),l("img",{key:0,src:s.cover,alt:s.title,class:"book-cover__img"},null,8,ge)):_("",!0),e("div",ke,[s.withPanel!==!1?(a(),l("span",pe,"点击查看详情")):(a(),l("a",{key:1,href:s.link,target:"_blank",rel:"noopener",class:"book-cover__hint",onClick:d[0]||(d[0]=P(()=>{},["stop"]))},"查看豆瓣",8,we))])],4),e("div",me,[e("div",_e,"《"+c(s.title)+"》",1),e("div",fe,c(s.author),1),s.rating!=null?(a(),l("div",qe,[e("div",ve,[(a(),l(p,null,f(5,u=>e("span",{key:u,class:"star"},[u<=Math.floor(s.rating)?(a(),l("svg",je,[...d[1]||(d[1]=[e("path",{d:"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"},null,-1)])])):u===Math.ceil(s.rating)&&s.rating%1!==0?(a(),l("svg",Le,[e("defs",null,[e("clipPath",{id:"card-clip-"+s.id},[...d[2]||(d[2]=[e("rect",{x:"0",y:"0",width:"12",height:"24"},null,-1)])],8,ye)]),d[3]||(d[3]=e("path",{class:"star-empty",d:"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z",fill:"none",stroke:"currentColor","stroke-width":"1.5"},null,-1)),e("path",{class:"star-filled",d:"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z",fill:"currentColor","clip-path":"url(#card-clip-"+s.id+")"},null,8,Se)])):(a(),l("svg",xe,[...d[4]||(d[4]=[e("path",{d:"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"},null,-1)])]))])),64))]),e("span",Ae,c(s.rating.toFixed(1)),1)])):_("",!0),e("div",Pe,[(a(!0),l(p,null,f(s.tags,(u,S)=>(a(),l("span",{key:u,class:"tag",style:v({background:t[S%t.length].bg,color:t[S%t.length].text})},c(u),5))),128))]),e("p",Ce,c(s.desc),1)])],10,ue))),128))]),h(he,{book:w.value,open:i.value,"hero-color":m.value,"tag-colors":t,onClose:L},null,8,["book","open","hero-color"])],64))}}),k=C(ze,[["__scopeId","data-v-fd79cd55"]]),Be=[{id:"book-001",title:"心中有数:生活中的数学思维",author:"刘雪峰",cover:"https://cdn.weread.qq.com/weread/cover/39/3300018939/t6_3300018939.jpg",wereadLink:"https://weread.qq.com/web/reader/df6323a0813ab6de5g019a31#outline?noScroll=1",link:"https://book.douban.com/subject/35749693/",tags:["数学思维","科普","决策"],desc:"本书通过大量贴近日常的例子,展示数学思维如何优化我们的生活决策。作者用概率、统计、最优化等数学工具,为生活、职场、人际交往中的权衡问题提供分析框架,帮助读者在面对不确定性时像计算机一样找到“最优解”。",rating:4.9,highlights:["将大数定律、最小二乘法等硬核数学概念与日常生活巧妙结合","提供应对不确定性和多目标抉择的科学决策框架","强调数学不仅是公式计算,更是看世界、优化人生的高效思维工具"]},{id:"book-0020",title:"智慧的疆界:从图灵机到人工智能",author:"周志明",cover:"https://cdn.weread.qq.com/weread/cover/92/YueWen_23637052/t6_YueWen_23637052.jpg",wereadLink:"https://weread.qq.com/web/reader/b9732f007168ac3cb976eca#outline?noScroll=1",link:"https://book.douban.com/subject/30379536/",tags:["人工智能","科技史","通识读物"],desc:"本书是一部面向大众的人工智能通识读物。作者周明以时间为主线,将人工智能的发展历程、关键人物与里程碑事件串联起来,从五个维度展开:学术理论、历史沿革、技术应用、研究成果以及面临的困难与未来挑战。全书旨在用通俗的语言和巧妙的结构,把人工智能从“阳春白雪”的学术殿堂带到公众视野,帮助读者理解 AI 能做什么、做不到什么,以及背后的技术与思想根源。",rating:5,highlights:["以时间为主线,清晰梳理人工智能的发展脉络与里程碑","深入浅出,用通俗语言将复杂的学术理论带入公众视野","客观剖析,帮助读者准确界定AI“能做什么”与“做不到什么”"]},{id:"book-004",title:"为什么伟大不能被计划",author:"肯尼斯·斯坦利 / 乔尔·雷曼",cover:"https://cdn.weread.qq.com/weread/cover/22/cpplatform_wfdzhk1dx7ig9aep4gagof/t6_cpplatform_wfdzhk1dx7ig9aep4gagof1686304376.jpg",wereadLink:"https://weread.qq.com/web/reader/0bf32020813ab7e6bg016510#outline?noScroll=1",link:"https://book.douban.com/subject/36357804/",tags:["人工智能","创新思维","认知科学"],desc:"本书由两位前沿AI科学家合著,提出了颠覆传统“目标-计划”思维的全新视角。结合AI研究实践,书中论证了伟大成就往往并非出自精心设计的蓝图,而是源于对未知的好奇、随机探索与不断试错。通过“寻宝者思维”和“踏脚石模型”等方法,为读者在高度不确定的环境中激发突破性创新提供了具体的行动框架。",rating:4.5,highlights:["颠覆传统的“目标论”,论证伟大成就源自对未知的好奇与无边界的探索","提供“寻宝者思维”“踏脚石模型”“新奇性探索”三大可操作的认知与实践工具","扎根OpenAI等前沿机构的实证背景,其启发意义跨学科适用于科研、商业及人生规划"]},{id:"book-003",title:"这就是ChatGPT",author:"斯蒂芬·沃尔弗拉姆",cover:"https://cdn.weread.qq.com/weread/cover/24/cpplatform_4cn8w4tmgzntjobg9ffeny/t6_cpplatform_4cn8w4tmgzntjobg9ffeny1703648785.jpg",wereadLink:"https://weread.qq.com/web/reader/74332a90813ab86c4g019d98#outline?noScroll=1",link:"https://book.douban.com/subject/36449803/",tags:["人工智能","大模型","ChatGPT"],desc:"本书由著名科学家斯蒂芬·沃尔弗拉姆撰写,全景式拆解了ChatGPT的内部工作机制。作者用通俗语言解释了神经网络和自回归架构等核心技术,探讨了简单的计算规则如何涌现出令人惊叹的智能,帮助读者深刻理解大语言模型为何能生成高质量的人类水平文本。",rating:4.3,highlights:["全景拆解核心技术:深入浅出地讲清ChatGPT背后的神经网络与自回归架构","独特的大师视角:将大模型视为“简单的计算规则”涌现复杂智能的绝佳范例","兼顾技术与商业影响:结合算力规模与行业冲击,全面探讨AI时代的机遇与挑战"]},{id:"book-0030",title:"人工智能:现代方法(第4版)(上下册)",author:"[美]斯图尔特·罗素(Stuart Russell) / [美]彼得·诺维格(Peter Norvig)",cover:"https://cdn.weread.qq.com/weread/cover/33/cpplatform_8rthznqfhsjuz5fswwn6kx/t6_cpplatform_8rthznqfhsjuz5fswwn6kx1675928213.jpg",wereadLink:"https://weread.qq.com/web/reader/fc332020813ab7942g0102ad#outline?noScroll=1",link:"https://book.douban.com/subject/36152133",tags:["人工智能","教材","理论实践结合","经典著作","计算机科学"],desc:"本书是人工智能领域的经典权威教材,系统、深入地探讨AI领域的理论与实践,以统一风格融合当今流行的AI思想与术语到前沿应用中,真正实现理论与实践相结合。全书分7个部分共28章,理论部分涵盖逻辑、概率、连续数学、感知、推理、学习、行动及公平、信任、社会公益和安全等社会议题;实践部分选取微电子设备、机器人行星探测器、在线服务、AlphaZero、人形机器人、自动驾驶、AI辅助医疗等热门场景。由加州大学伯克利分校教授斯图尔特·罗素与前谷歌研究总监彼得·诺维格联合撰写,被全球1500多所高校采用,适合作为AI相关专业本科生和研究生教材,也可作为专业人员的参考书。",rating:5,highlights:["体系完整覆盖面广,7个部分28章构成自洽的AI理论主线,涵盖核心理论与前沿议题","理论与实践并重,既阐述核心算法与模型,又展示在热门场景中的落地实例,便于知识迁移","紧跟前沿关注社会议题,专门讨论AI伦理与安全,引导思考技术与社会的交互责任","一站式权威参考,兼具教材属性与专业参考价值,适配高校教学与产业实践双重需求","现代理念贯穿始终,通过最新案例体现AI进展与行业趋势,呈现“活”的AI生态"]},{id:"book-0031",title:"模型思维:简化世界的人工智能模型",author:"龚才春",cover:"https://cdn.weread.qq.com/weread/cover/26/YueWen_38601826/t6_YueWen_38601826.jpg",wereadLink:"https://weread.qq.com/web/reader/5a8326e0724d04625a8e740#outline?noScroll=1",link:"https://book.douban.com/subject/35488925/",tags:["模型思维","人工智能","算法模型","机器学习","入门实践"],desc:"本书聚焦“如何用模型简化世界”的核心主题,将人工智能在现实业务中面临的难题归纳为权重、状态、序列、表示、相似、分类六大问题,并围绕该框架讲解对应模型思路与算法。书中弱化复杂数学公式,以大量生活化、业务化案例阐释模型理论与落地场景,帮助读者建立“模型—场景”映射关系,降低AI模型学习门槛,既是人工智能初学者的入门读物,也可为企业工程师、科研人员提供实践参考,适合各类读者学习并将模型思维应用到生活与工作中。",rating:4.8,highlights:["以“六大问题”框架串联AI模型,可按场景快速检索适配的模型思路","侧重落地实践,搭配大量生活化与业务案例,助力建立“模型—场景”映射","降低学习门槛,少数学公式、多直观案例,兼顾初学者与工程落地需求","受众群体广泛,适配工程师、科研人员及普通读者,可迁移模型思维至实际场景"]},{id:"book-005",title:"你看起来好像……我爱你:AI的工作原理以及它为这个世界带来的稀奇古怪",author:"贾内尔·沙内",cover:"https://wfqqreader-1252317822.image.myqcloud.com/cover/970/39481970/t6_39481970.jpg",wereadLink:"https://weread.qq.com/book-detail?type=1&senderVid=40710128&v=f9a32c10725a7272f9a14f9&wtheme=white&wfrom=app&wvid=40710128&scene=bottomSheetShare",link:"https://book.douban.com/subject/35407136/",tags:["人工智能","趣味科普","漫画算法"],desc:"这是一部写给普通读者的人工智能趣味科普读物。作者贾内尔·沙内结合生活化的比喻和超级可爱的漫画,深入浅出地讲解了AI的基本工作原理、实际应用及其局限性。书中通过大量幽默的AI实验与“翻车”案例,带领读者在轻松捧腹的氛围中,准确理解算法能做什么、不能做什么。",rating:4.2,highlights:["幽默可爱的漫画导览:用插图和通俗语言将“深度学习”“神经网络”等抽象概念可视化","丰富的趣味实验案例:通过精选的AI“翻车”故事,直观揭示算法背后的逻辑与潜在偏差","客观建立AI认知:在展示AI强大能力的同时,明确指出其在语境理解和处理模糊信息时的短板"]},{id:"book-006",title:"AI经济:机器人时代的工作、财富和社会福利",author:"罗杰·布特尔",cover:"https://cdn.weread.qq.com/weread/cover/30/YueWen_38229387/t6_YueWen_38229387.jpg",wereadLink:"https://weread.qq.com/web/reader/653320207247558b65332f5#outline?noScroll=1",link:"https://book.douban.com/subject/35433060/",tags:["人工智能","经济学","社会学","未来趋势"],desc:"本书由知名经济学家罗杰·布特尔撰写,聚焦AI与机器人技术对经济和社会的深远影响。作者拨开艰涩的科技术语,从经济增长、通货膨胀及财富分配等宏观视角,理性剖析AI革命将如何重塑我们的工作、教育与休闲方式,以乐观的姿态为迎接未来的社会变革指明路径。",rating:4.1,highlights:["宏观经济视角解析:深入探讨AI对经济增长、通货膨胀、财富与权力分配的真实影响","全景式社会洞察:全面检视机器人时代下,人类教育体系、工作模式与休闲形态的深刻变革","理性乐观的未来指南:拒绝技术恐慌,为个人与社会在变迁的世界中提供清晰可行的应对计划"]}],Ie=[{id:"book-007",title:"做对产品",author:"阿尔贝托·索维亚",cover:"https://cdn.weread.qq.com/weread/cover/53/YueWen_40877841/t6_YueWen_40877841.jpg",wereadLink:"https://weread.qq.com/web/reader/254322a0726fbf1125472c9#outline?noScroll=1",link:"https://book.douban.com/subject/35607961/",tags:["产品思维","创业","商业方法论"],slogan:"为什么有些产品注定失败,有些产品却能大获成功?来自谷歌与斯坦福的产品工具和产品战术。",desc:"谷歌首任产品总监阿尔贝托·索维亚结合在谷歌、斯坦福的实战经验与自身代价高昂的创业失败经历,总结出的一套防败手册。书中揭示了新产品高达90%的“市场失败律”,并创新性地提出了“预型”(Pre型)理念,指导团队在正式开发前,以极低的成本和真实数据快速验证关键假设,确保把创意打磨成“正确的它”。",rating:4.8,highlights:["揭示残酷的市场失败律:正视90%新产品必然失败的商业常态,并以此倒推破局的实战方法论","首创“预型”(Pre型)概念:提供8大测试工具,主张用极低成本和小规模试错快速逼近正确的产品形态","强调真实数据驱动决策:辅以特斯拉、谷歌等完整案例回溯,教导团队将决策建立在客观证据而非主观直觉之上"]},{id:"book-009",title:"俞军产品方法论",author:"俞军",cover:"https://cdn.weread.qq.com/weread/cover/47/YueWen_28165041/t6_YueWen_28165041.jpg",wereadLink:"https://weread.qq.com/web/reader/1cc3252071adc3b11cc0162#outline?noScroll=1",link:"https://book.douban.com/subject/34907971/",tags:["产品思维","产品经理","互联网","方法论"],desc:"“百度贴吧之父”俞军二十余年产品实践与思考的系统总结。本书将产品经理定义为“以科学方法研究人性并转化为商业方案”的交叉学科,深入解析了用户模型、交易模型和决策模型三大核心框架,为产品人提供了一套在不确定环境中权衡多方利益的实战指南。",rating:4.4,highlights:["沉淀二十年行业经验:从广为流传的“PM12条”到系统化的产品哲学,展现顶尖产品经理的认知迭代史","三大核心模型拆解:深度剖析用户模型与交易模型,指导如何通过让交易发生来创造“有利可图”的真实用户价值","兼顾科学与人文视角:强调批判性思维的运用,并清晰梳理了从新人到顶尖大牛的能力进阶路径"]},{id:"book-016",title:"策略产品经理:模型与方法论",author:"青十五",cover:"https://cdn.weread.qq.com/weread/cover/31/cpplatform_gheeqe7hjb2czyzthzf5nm/t6_cpplatform_gheeqe7hjb2czyzthzf5nm1735654872.jpg",wereadLink:"https://weread.qq.com/web/reader/4de32800813ab98d5g01286b#outline?noScroll=1",link:"https://book.douban.com/subject/35218721/",tags:["产品经理","策略产品","算法思维"],desc:"本书围绕“策略产品经理”这一复合角色,系统性地构建了从理念到实践的完整知识框架。作者从机器学习理论与经济学视角出发,结合推荐、搜索、广告、风控等核心业务场景,深入浅出地讲解了函数建模与策略应用,并对策略产品经理的核心能力与团队建设给出了详尽指导。",rating:3.9,highlights:["系统化的角色认知建构:清晰界定策略产品经理的时代背景、职责边界与工作内容,为从业者夯实概念基础","跨学科的模型与业务结合:利用机器学习的函数方法论与经济学理论,深度剖析推荐、搜索、广告、风控及定价等真实业务场景的解法","硬核算法的通俗化解析:深入浅出地拆解机器学习本质、常见算法及深度学习前沿技术,帮助产品经理真正理解策略背后的技术支撑","可落地的团队建设指南:全面拆解数据分析、沟通与项目管理等核心能力项,并针对不同产品生命周期提供策略团队的组建思路"]},{id:"book-008",title:"创造:用非传统方式做有价值的事",author:"托尼·法德尔",cover:"https://cdn.weread.qq.com/weread/cover/53/cpPlatform_tzdqT27m3vyaHnX5o8Vbwk/t6_cpPlatform_tzdqT27m3vyaHnX5o8Vbwk.jpg",wereadLink:"https://weread.qq.com/web/reader/13832ac0813ab725fg018645#outline?noScroll=1",link:"https://book.douban.com/subject/36071759/",tags:["产品思维","管理学","创业"],desc:"本书是iPod、iPhone、Nest等爆款产品幕后推手托尼·法德尔30余年职业经历的智慧结晶。作者毫无保留地分享了他在产品设计、团队管理、职业选择和公司经营等方面的“非传统”方法论,帮助读者在各自的领域内刻意练习创造力,做真正有价值的事。",rating:4.9,highlights:["源自顶级创新者的实战经验:连续打造iPod、iPhone等划时代产品的亲历复盘与真实反面教训","覆盖从个人到公司的完整路径:系统解答职业选择、产品设计、团队管理与企业经营等核心问题","提供可复制的“非传统”方法论:强调“亮点思维”与持续复盘,教导读者以反常规的视角刻意练习创造力"]},{id:"book-010",title:"产品思维",author:"刘飞",cover:"https://cdn.weread.qq.com/weread/cover/56/YueWen_25568738/t6_YueWen_25568738.jpg",wereadLink:"https://weread.qq.com/web/reader/38332ce0718625e23831fe7#outline?noScroll=1",link:"https://book.douban.com/subject/33456375/",tags:["产品思维","产品经理","个人成长","互联网"],desc:"实战派产品经理刘飞结合在一线大厂的丰富经验,围绕产品人如何实现能力跃迁展开的底层能力指南。全书掰开揉碎地讲解了认知盲点与实践痛点,通过“认知用户”“创造价值”和“产品落地”三大核心板块,系统拆解了从建立用户模型、高质量决策到快速迭代验证的完整产品方法论。",rating:4.2,highlights:["三大核心板块系统拆解:完整覆盖“认知用户”“创造价值”与“产品落地”的产品闭环","直击痛点的一线实战经验:毫无保留地分享实战中新手迫切需要却难以获取的隐性知识","聚焦底层能力与思维升维:不仅教授落地方法,更注重决策质量与思维模式的跃迁"]},{id:"book-011",title:"产品思维:创新设计的六条法则(全彩)",author:"张印帅",cover:"https://wfqqreader-1252317822.image.myqcloud.com/cover/253/26687253/t6_26687253.jpg",wereadLink:"https://weread.qq.com/web/reader/a823297071973715a8202b0#outline?noScroll=1",link:"https://book.douban.com/subject/34859540/",tags:["产品设计","创新思维","方法论","设计灵感"],desc:"本书围绕作者张印帅多年产品设计实践总结出的6条创意公式展开,旨在帮助读者系统化地获取设计灵感并解决创新难题。全书通过大量经典案例,详细解析了从发散思考到重组创新的全过程,并在最后提供了从需求到草图再到最终方案的完整项目落地演示。",rating:4,highlights:["提炼6条实用的创新设计公式:将发散思考与重组创新系统化,打造可复用的设计灵感库","丰富的经典设计案例解析:详细展示“问题+方法”、“1+1>2”等法则在真实产品设计中的应用","呈现从需求到方案的落地全流程:通过综合案例演示概念打磨与草图设计的实战过程"]}],We=[{id:"book-012",title:"小而美:持续盈利的经营法则",author:"萨希尔·拉文吉亚",cover:"https://cdn.weread.qq.com/weread/cover/91/cpplatform_vl4abrrrqgxnry833gcrtt/t6_cpplatform_vl4abrrrqgxnry833gcrtt1677578056.jpg",wereadLink:"https://weread.qq.com/web/reader/02932980813ab7a43g012e77#outline?noScroll=1",link:"https://book.douban.com/subject/36280425/",tags:["创业","商业模式","极简主义"],desc:"本书打破了硅谷盲目追求“独角兽”的扩张迷思,聚焦于“规模不是唯一出路”的商业现实。作者结合创立Gumroad的亲身经历,提出了“极简创业经营”理念。全书指导创业者与管理者如何通过从社区切入、聚焦核心能力、精简团队等方式,用最少的资源打造出不仅能活下去,而且还能持续盈利的“慢公司”。",rating:5,highlights:["颠覆传统的扩张迷思:提出盈利至上而非规模至上,将持续赚钱和实际利润作为衡量企业成功的核心标准","可落地的极简法则:总结出“越少越好”“瞄准前100个客户”等7条创业清单,构建从定位、产品到销售的完整闭环","社区驱动的商业逻辑:提倡从虚拟社区入手,以“贡献-创作-教学”的方式低成本验证产品形态并获取早期信任","打造高韧性的“慢公司”:结合疫情与远程办公背景,展示如何通过精简组织和分布式协作,在不确定的时代保持稳定的现金流"]},{id:"book-013",title:"做难而正确的事:进步最快的方式",author:"尤里·莱文",cover:"https://cdn.weread.qq.com/weread/cover/53/cpplatform_bunxjyygj8m9stnwcgwqqk/t6_cpplatform_bunxjyygj8m9stnwcgwqqk1728876401.jpg",wereadLink:"https://weread.qq.com/web/reader/aa032fb0813ab9461g018406#outline?noScroll=1",link:"https://book.douban.com/subject/37054102/",tags:["创业","产品思维","商业管理"],desc:"Waze联合创始人尤里·莱文写给创业者和管理者的行动指南。作者结合连续打造两家估值超10亿美元公司的实战经验,提出“先做难事、再做正确事”的核心哲学。全书通过13个阶段的系统拆解,指导读者如何寻找真正的用户痛点、构建高价值产品,并在不确定的环境中通过不断复盘实现跨越式成长。",rating:4.9,highlights:["世界级创业者的实战复盘:连续打造两家独角兽公司的创始人亲授,提供极具可信度的第一手商业洞察与落地经验","践行“难而正确”的核心哲学:强调不追逐短期热点,而是去解决效率极低却被忽视的痛点,以此建立坚实的商业护城河","覆盖从0到1的全周期指南:系统拆解从寻找痛点、产品构建、融资运作到团队管理的13个关键阶段,提供可操作的行动清单","直面失败的心理韧性建设:不回避挫折,将“从错误中学习”提炼为核心方法,为身处高压环境的读者提供情感共鸣与心理支持","广泛的跨场景应用价值:书中给出的决策工具不仅适用于初创团队,同样能为大公司内部创新及个人职业认知升级提供指导"]},{id:"book-015",title:"创新公司:皮克斯的启示",author:"艾德·卡特姆",cover:"https://cdn.weread.qq.com/weread/cover/20/YueWen_814380/t6_YueWen_814380.jpg",wereadLink:"https://weread.qq.com/web/reader/2ef329605c6d2c2efeeb70d#outline?noScroll=1",link:"https://book.douban.com/subject/26314955/",tags:["创新思维","组织文化","企业管理"],desc:"皮克斯联合创始人艾德·卡特姆结合《玩具总动员》《机器人瓦力》等经典动画的幕后制作故事,深度揭示了皮克斯如何长期保持创意领先的秘密。本书不仅详述了皮克斯从初创到壮大的历程,更抽丝剥茧地解析了其在团队文化、跨部门协作、人才培养和允许失败等方面的独特创意管理机制,为各类组织提供了可复制的创新指南。",rating:4.5,highlights:["揭秘“皮克斯奇迹”背后的管理哲学:通过14部经典动画的真实幕后故事,展示创意从无到有、再到票房口碑双赢的全过程","深度解析创新土壤的搭建:阐述如何通过允许失败的文化、流程设计和激励机制,将“不断推动创新”彻底融入公司DNA","提供跨行业可复用的管理工具:总结项目立项、跨部门协作与风险控制的具体做法,为不同规模和行业的企业提供落地的实战模板"]},{id:"book-017",title:"重来:更为简单的商业思维",author:"贾森·弗里德 / 戴维·海涅迈尔·汉森",cover:"https://cdn.weread.qq.com/weread/cover/1/YueWen_635904/t6_YueWen_635904.jpg",wereadLink:"https://weread.qq.com/web/reader/0363228059b4000363b29e9#outline?noScroll=1",link:"https://book.douban.com/subject/5320866/",tags:["商业思维","创业","企业管理","极简主义"],desc:"37signals联合创始人基于十年创业实战经验,写给职场人与创业者的极简商业法则。本书摒弃了传统的MBA术语与复杂的商业教条,以“辛辣、直接、靠谱”的语言,颠覆了关于项目管理、人才招聘、产品设计与企业文化的常规认知,教导读者如何在真实的商业世界中“做更少,但创造更多价值”。",rating:4.3,highlights:["颠覆传统的极简商业哲学:反叛复杂的商业教条,主张“做更少,创造更多”,通过最小可行步骤降低试错成本并快速迭代","源自37signals的十年实战精髓:覆盖从项目管理、产品设计到市场营销的完整链条,提供不讲废话、拿来即用的行动指南","重塑职场与团队管理的认知:提出诸多务实且反常规的观点(如严苛的简历筛选标准),打造基于信任与结果导向的高效团队","适用面极广的实操手册:无论是寻求突破的精英企业家、小团队创业者,还是渴望提升工作效率的普通职场人,都能直接对照落地"]},{id:"book-018",title:"重来2:更为简单高效的远程工作方式",author:"贾森·弗里德 / 戴维·海涅迈尔·汉森",cover:"https://cdn.weread.qq.com/weread/cover/38/YueWen_635721/t6_YueWen_635721.jpg",wereadLink:"https://weread.qq.com/web/reader/46b3220059b34946b517012#outline?noScroll=1",link:"https://book.douban.com/subject/25861795/",tags:["企业管理","远程工作","工作方式","团队协作"],desc:"Basecamp(原37signals)创始人基于自身团队多年的全球分布式协作经验,为企业和个人提供的一套远程工作“思想升级包”。本书直面行业争议,破解了“创新只能面对面”及“文化会淡化”等常见误区,并系统提供了借助异步沟通、协作工具与流程设计来打造高效、人性化远程团队的实战指南。",rating:4.1,highlights:["提供思想层面的“升级包”:直击传统办公室痛点,用真实数据与反例打破关于远程办公的固有认知误区","第一手的分布式团队管理经验:Basecamp创始人亲授,展示如何突破地域限制招募顶尖人才,并保持健康、高效的工作节奏","系统可落地的工具与流程方法:详述如何利用协作工具降低管理成本,让远程工作从“特殊福利”真正转变为可持续的主流组织模式"]},{id:"book-019",title:"重来3:做得更少,但赚得更多",author:"贾森·弗里德 / 戴维·海涅迈尔·汉森",cover:"https://cdn.weread.qq.com/weread/cover/62/cpplatform_tqth8pnlq8h9ing5uciwhi/t6_cpplatform_tqth8pnlq8h9ing5uciwhi1748502715.jpg",wereadLink:"https://weread.qq.com/web/reader/b6a32ed0813ab9fb5g015181#outline?noScroll=1",link:"https://book.douban.com/subject/37367276/",tags:["工作方式","反内卷","企业文化"],desc:"Basecamp创始人带来的“反内卷”与“反过度忙碌”的管理指南。作者基于近20年带领54人团队服务全球10万家企业的成功经验,直击现代企业盲目扩张、无效加班等八大症结。全书主张以“冷静”颠覆“忙碌”文化,指导企业和个人通过40小时工作制、拒绝KPI和异步沟通等极简方式,在不牺牲生活质量的前提下实现健康发展与持续盈利。",rating:4.2,highlights:["以“冷静”颠覆“忙碌”文化:倡导高效比高产更重要,用稳定的节奏替代疯狂加班的内卷常态","直击现代企业八大症结:深度诊断快速扩张、无效加班、会议泛滥与目标绑架等痛点,提供对症下药的思路","提供四大可落地的管理工具:引入40小时工作制、拒绝硬性KPI、推行非实时沟通,坚持利润优先于规模","源自Basecamp的真实反向案例:展示“小而美”团队如何通过“少做但做好”的策略,跑赢新经济并保持高利润"]}],Ye=[{id:"book-024",title:"要事第一",author:"史蒂芬·柯维 / 罗杰·梅里尔 / 丽贝卡·梅里尔",cover:"https://cdn.weread.qq.com/weread/cover/57/yuewen_33091834/t6_yuewen_330918341686208943.jpg",wereadLink:"https://weread.qq.com/web/reader/f523268071f8f0faf52b806#outline?noScroll=1",link:"https://book.douban.com/subject/1028372/",tags:["时间管理","自我管理","经典思维"],desc:"作为《高效能人士的七个习惯》的延伸与加强版,本书提出了颠覆传统的“第四代时间管理”方法。作者强调,比提升做事速度(时钟)更重要的是找准人生的方向(罗盘)。全书指导读者通过自我意识的觉醒,以原则和价值观为中心,将精力聚焦于“重要而不紧急”的长期目标上,从而在繁忙的现代生活中真正做到“要事第一”。",rating:4.5,highlights:["从“时钟”到“罗盘”的思维跨越:打破一味追求“更快、更努力”的传统效率迷思,确立人生方向优先的哲学","经典的四象限时间管理矩阵:引导读者跳出紧急事务的“救火圈”,将核心精力倾注于第二象限(重要但不紧急)的高价值事务中","生动的“大石块”优先法则:通过“先放石头再倒水”的直观比喻,确保关键目标与核心使命在碎片化日程中得到绝对的优先落实","以原则为中心的自我驱动框架:不仅提供日程安排工具,更通过唤醒良知,帮助读者在工作、家庭等多元角色中实现真正的平衡与统合综效"]},{id:"book-025",title:"清单革命",author:"阿图·葛文德",cover:"https://cdn.weread.qq.com/weread/cover/12/cpPlatform_rudGZN3LDW5m9FBYr7rMBA/t6_cpPlatform_rudGZN3LDW5m9FBYr7rMBA.jpg",wereadLink:"https://weread.qq.com/web/reader/18332f80813ab7292g010065#outline?noScroll=1",link:"https://book.douban.com/subject/27168564/",tags:["管理学","认知科学","工作效率"],desc:"这是一部针对现代复杂世界所撰写的“认知防护手册”。作者阿图·葛文德通过医疗、建筑、投资等高风险领域的真实案例,揭示了人类在海量信息与高压环境下极易出现的判断疏忽。书中提出了“权力下放、简单至上、人为根本、持续改善”四大原则,指导读者将最佳实践外化为可操作的清单,从而在复杂系统中构建一道低成本、高回报的安全防线。",rating:4.6,highlights:["直面复杂时代的认知瓶颈:揭示在海量信息流中,清单如何作为“认知防护网”弥补人类记忆力与注意力分配的先天不足","提供兼具理念与落地的四大原则:通过“权力下放、简单至上、人为根本、持续改善”,构建一套可复用的清单设计哲学","扎实的医学实证背书:以手术感染率骤降等真实临床数据为支撑,证明清单思维在医疗、建筑、投资等高风险领域的跨行业普适性","简洁而具力量的流程创新:强调清单服务于人而非取代人,是帮助专业人士在高压环境下将复杂环节显性化、流程化的必备工具"]},{id:"book-020",title:"别让猴子跳回背上",author:"威廉·安肯三世",cover:"https://cdn.weread.qq.com/weread/cover/69/cpPlatform_7fFoBQ7dtqgABGSTskpJSN/t6_cpPlatform_7fFoBQ7dtqgABGSTskpJSN.jpg",wereadLink:"https://weread.qq.com/web/reader/9fc32010813ab7291g0196bd#outline?noScroll=1",link:"https://book.douban.com/subject/36103994/",tags:["时间管理","领导力","项目管理"],desc:"这是一部以“猴子”生动隐喻任务与责任的经典管理学著作。作者威廉·安肯三世深刻剖析了管理者常被琐事淹没的时间困境,并提出系统化的“猴子管理法”。通过明确任务归属、责任递减与有效授权,指导管理者如何把不属于自己的“猴子”交出去,从而释放精力专注于最高价值的战略思考,实现团队与个人的共同成长。",rating:4.3,highlights:["生动有趣的“猴子”隐喻:将枯燥的责任划分与任务流转具象化,直击职场中“忙碌却低效”的痛点","实用高效的“三步交接”法则:通过明确期望、授予资源与约定检查点,彻底避免下属的待办任务重新跳回自己背上","重塑时间管理与人才培养体系:指导高层放权、中层辅导、基层自发,将企业的成功真正建立在员工自主性的提升之上"]}],Te=[{id:"book-022",title:"学会提问(原书第12版)",author:"尼尔·布朗 / 斯图尔特·基利",cover:"https://cdn.weread.qq.com/weread/cover/68/YueWen_39980443/t6_YueWen_39980443.jpg",wereadLink:"https://weread.qq.com/web/reader/e6832d3072620d9be68aabf#outline?noScroll=1",link:"https://book.douban.com/subject/35513147/",tags:["批判性思维","逻辑学","认知科学","经典书"],desc:"这是一部培养批判性思维的经典实战指南。作者尼尔·布朗与斯图尔特·基利结合长期的教学与研究实践,提供了一套系统化、可操作的提问流程。全书通过大量真实情境案例,教导读者如何在信息泛滥的时代识别隐含假设、区分事实与观点,用高质量的“判断性问题”看透事物本质,从而做出更理性的决策。",rating:5,highlights:["聚焦批判性思考的核心能力:系统拆解“如何提出好问题”的思维过程,帮助读者在复杂信息中迅速抓住本质","提供可落地的提问与评估框架:从背景信息、关键概念到逻辑推理,构建一条完整的判断性问题链条","丰富的真实场景应用示范:结合课堂讨论、写作、日常沟通与职场决策等多元场景,让理论能“立即上手”","打造实用的思考检查单:不仅讲透“提问的价值”,更提供可直接转化为日常习惯的思维检查表,助你有效避开认知陷阱"]},{id:"book-026",title:"如何阅读一本书",author:"莫提默·J. 艾德勒 / 查尔斯·范多伦",cover:"https://wfqqreader-1252317822.image.myqcloud.com/cover/810/23723810/t6_23723810.jpg",wereadLink:"https://weread.qq.com/book-detail?type=1&senderVid=40710128&v=272326407169ff22272934f&wtheme=white&wfrom=app&wvid=40710128&scene=bottomSheetShare",link:"https://book.douban.com/subject/1013208/",tags:["阅读方法","思维训练","经典"],desc:"阅读领域的“元方法”指南。作者艾德勒与范多伦将阅读划分为基础阅读、检视阅读、分析阅读与主题阅读四个进阶层次,并强调阅读是一项主动的思考活动。本书不仅提供了从“快速略读”到“系统拆解论点”的实操技巧,更致力于通过提问、归纳与批判,将阅读转化为训练理解力、批判力与终身学习的终极工具。",rating:5,highlights:["构建系统的四级阅读框架:从检视阅读到分析阅读再到主题阅读,为读者提供了一套从入门到精通的进阶路径","强调“主动与批判”的阅读观:拒绝被动接收,教导读者如何通过提问、归纳与反思,真正将作者的洞见转化为自己的认知","高效的检视阅读技巧:提供如何在有限时间内通过看目录、挑重点等方式,快速筛选并判断书目价值的核心能力","跨时代的经典效能:自1940年问世以来长盛不衰,其对逻辑拆解与深度思考的指导,是提升所有知识吸收效率的“总开关”"]},{id:"book-023",title:"检索力:打破信息差的科学方法",author:"龚芙蓉",cover:"https://cdn.weread.qq.com/weread/cover/58/cpplatform_feaxemubry47bnkzylqzwv/t6_cpplatform_feaxemubry47bnkzylqzwv1716796541.jpg",wereadLink:"https://weread.qq.com/web/reader/9de32810813ab8e00g018130#outline?noScroll=1",link:"https://book.douban.com/subject/36899979/",tags:["信息素养","检索能力","思维认知"],desc:"本书聚焦“检索力”这一核心技能,旨在帮助读者在信息过载的时代主动掌握“逆风而行”的搜索能力。作者龚芙蓉结合二十余年实践经验,用生动的人文与诺贝尔奖级科学案例,将枯燥的检索工具化为有趣的故事。不仅教授非线性、迭代式的搜索技巧,更致力于重塑读者的探究精神,赋予其走出“信息茧房”的勇气。",rating:4.2,highlights:["丰富的跨学科趣味案例驱动:用“张冠李戴的马克思名言”等生动故事,将枯燥繁琐的检索步骤转化为轻松的探索之旅","重塑非线性与迭代的搜索思维:打破按部就班的线性流程误区,建立以耐心与热情驱动的多轮迭代搜索心态","直击科研与职场的实用痛点:提供可快速落地的实操指南,帮助读者切实缩短科研周期、大幅提升工作效率","兼顾技能训练与人文底色:在教授如何利用和创造信息的同时,注重培养读者的信息素养与打破信息差的认知勇气"]},{id:"book-027",title:"原则",author:"瑞·达利欧",cover:"https://cdn.weread.qq.com/weread/cover/23/YueWen_921568/t6_YueWen_921568.jpg",wereadLink:"https://weread.qq.com/web/reader/848324405e0fe08483ab6a4#outline?noScroll=1",link:"https://book.douban.com/subject/27608239/",tags:["投资","方法论","自我管理"],desc:"桥水基金创始人瑞·达利欧总结四十余年投资、管理与人生经验的集大成之作。作者提出将生活和工作像机器一样系统化,确立了“极度求真”与“极度透明”两大基石,并通过“创意择优”与“基于可信度的决策机制”来迭代思维。书中包含500多条可操作原则,旨在帮助读者在复杂世界中保持开放心态、看清现实,并做出最优决策。",rating:4.8,highlights:["“极度求真”与“极度透明”的基石:主张诚实面对现实,通过公开决策过程来获取外部反馈,达成高效协作","创意择优与可信度加权机制:摒弃个人权威,利用数据驱动的讨论与可信度权重,在团队中选出最优方案","500余条可落地的原则清单:涵盖自我认知、投资决策、团队治理等场景,构建出一套随时可查的行动指南","系统化的“机器”思维:将生活与组织管理拆解为可维护、可迭代的系统,有效规避情绪化干扰"]},{id:"book-031",title:"价值",author:"张磊",cover:"https://wfqqreader-1252317822.image.myqcloud.com/cover/958/33577958/t6_33577958.jpg",wereadLink:"https://weread.qq.com/web/reader/5be32a3072005be65bef195#outline?noScroll=1",link:"https://book.douban.com/subject/35188914/",tags:["价值投资","商业思维","创业"],desc:"高瓴资本创始人张磊首部个人及投资思想著作。全书通过回顾作者的个人求学与创业历程,系统阐释了“长期主义”与“重仓中国”的核心投资理念,并首次披露了高瓴投资的七大公式。作者将十余个典型投资案例与个人价值修养相结合,揭示了如何在不确定的商业环境中,通过坚持原则、敬畏规则与持续创新,创造长久、真实的价值。",rating:4.6,highlights:["系统构建长期主义哲学:首次系统化梳理“高瓴七大公式”,为读者提供从认知、决策到执行的价值投资实战模型","深度复盘经典实战案例:通过腾讯、货拉拉等真实商业案例,拆解如何在复杂市场中识别企业护城河与核心价值","投资之外的人文思考:延伸至教育、人才与科学观,展现作者作为顶尖投资者对社会责任与长期价值创造的深度思考","可视化的阅读体验:精选多幅手绘彩插与历史影像,将深刻的投资逻辑与企业成长叙事变得更加生动、直观"]},{id:"book-032",title:"纳瓦尔宝典",author:"埃里克·乔根森 / 纳瓦尔·拉维坎特",cover:"https://cdn.weread.qq.com/weread/cover/89/YueWen_44026191/t6_YueWen_44026191.jpg",wereadLink:"https://weread.qq.com/web/reader/e1e32b00729fc94fe1e824d#outline?noScroll=1",link:"https://book.douban.com/subject/35876121/",tags:["财富管理","个人成长","幸福哲学","思维认知"],desc:"这是一部汇集硅谷著名投资人纳瓦尔·拉维坎特过去十年关于财富与幸福思考的行动指南。全书摒弃了“致富靠运气”的传统观念,提出积累财富与幸福生活是可以通过学习掌握的技能。通过系统整理推特、播客与访谈中的智慧,本书为读者提供了如何在快速变化的科技与经济环境中,利用杠杆、发挥个人独特性,进而实现财务自由并获得持久内心满足的方法论。",rating:4.7,highlights:["将财富与幸福视为可习得的技能:打破运气论,强调通过建立杠杆、发挥个人独特性来获取非线性的回报","十年思想的系统化编纂:将碎片化的互联网智慧提炼为成体系的方法论,打造了数字时代个人的“行动指南”","兼顾财富积累与内心满足:不仅教导如何高效赚钱,更深入探讨如何通过阅读、冥想与长期主义,在职场成功中寻找内心的宁静","极具实操性的工具箱:提供如深度思考、刻意练习、构建个人品牌等具体路径,帮助读者在碎片化时代快速实现自我迭代"]},{id:"book-028",title:"优秀的绵羊",author:"威廉·德雷谢维奇",cover:"https://cdn.weread.qq.com/weread/cover/78/cpplatform_3ncoeekcuaectlzj9hf5nr/t6_cpplatform_3ncoeekcuaectlzj9hf5nr1744626569.jpg",wereadLink:"https://weread.qq.com/web/reader/1c0324c0813ab9d91g010aba#outline?noScroll=1",link:"https://book.douban.com/subject/26747208/",tags:["博雅教育","社会学","个人成长"],desc:"耶鲁大学前教授威廉·德雷谢维奇对美国常春藤精英教育体制的尖锐批判之作。作者通过二十余年的教学观察,指出顶尖学府培养出一群虽然聪明、优秀,但普遍焦虑、缺乏目标感且唯命是从的“优秀绵羊”。本书呼吁社会重新审视教育的本质,摆脱对名校与高薪的盲目崇拜,回归博雅教育,鼓励学生探索内在驱动力与自我价值。",rating:4.2,highlights:["犀利剖析精英教育弊端:直击常春藤体制培养出“聪明但没有灵魂”的学生的现实,反思唯名校与成绩论的单一评价体系","回归博雅教育的核心价值:批判应试化倾向,提倡给予学生更多探索、失败与重塑自我的空间,强调教育的本质在于帮助个体找到自我","提供挣脱外部期待的认知框架:既为迷茫的年轻人指明如何重建内在动力,也给家长和教育者敲响了关于“成功定义”的警钟","跨文化背景下的教育共鸣:尽管以美国精英教育为例,其对“教育内卷”与“缺乏目标感”的批判,引发了全球高压教育环境下的深层共鸣"]},{id:"book-029",title:"把自己变成稀缺资产",author:"何思平",cover:"https://cdn.weread.qq.com/weread/cover/98/cpplatform_ncqzerh3wdywn9mlc9cjna/t6_cpplatform_ncqzerh3wdywn9mlc9cjna1694085413.jpg",wereadLink:"https://weread.qq.com/web/reader/2fe326f0813ab821fg0146df#outline?noScroll=1",link:"https://book.douban.com/subject/36513648/",tags:["个人成长","思维认知","自我管理","投资理财"],desc:"这是一个将“人生”视作“公司”来经营的实战指南。作者何思平结合自身从严重口吃到演讲冠军、再到连续创业成功的跨越式经历,提出了“人生有限公司”的经营哲学。全书通过“生命立方体”模型,从认知、实践、精力管理三个维度拆解了如何通过持续输出与跨界学习,将自己打造为具有高壁垒、不可替代的“稀缺资产”。",rating:4.2,highlights:["提出“人生有限公司”经营哲学:倡导将自己视作最值得投资的上市公司,通过不断提升认知与能力壁垒,把“人生”经营成稀缺资产","系统化的“生命立方体”模型:从认知、实践、精力管理三个维度构建个人成长闭环,解决成长中的无序感与碎片化难题","聚焦个人核心竞争力:深度拆解认知力、学习力与共情力等稀缺能力的获取路径,教导读者在不同场景中通过实战验证自我价值","高度可操作的工具清单:摒弃鸡汤式说教,将自我成长拆解为具体的习惯改造与复盘清单,帮助读者在痛点与高光时刻都能通过反馈机制实现自我迭代"]},{id:"book-030",title:"成长第二曲线:跨越S型持续成长",author:"查尔斯·汉迪",cover:"https://cdn.weread.qq.com/weread/cover/65/YueWen_39427437/t6_YueWen_39427437.jpg",wereadLink:"https://weread.qq.com/web/reader/15d32ed072599d6d15daa86#outline?noScroll=1",link:"https://book.douban.com/subject/35531368/",tags:["管理学","个人成长","人生哲学","未来趋势"],desc:"管理大师查尔斯·汉迪的“人生长跑指南”。本书通过书信体形式,深度探讨了在数字时代背景下个人如何识别并跨越“第二曲线”。汉迪指出,无论组织还是个人,都受制于S型增长曲线,只有在第一曲线衰退前主动布局新的增长点,并保持内在价值的独立与进化,才能在不断变化的环境中获得持续且有意义的成长。",rating:4.5,highlights:["百岁管理大师的人生体悟:以书信体浓缩一生管理研究与个人经验,提供了从时间维度审视工作、学习与生活的全景视角","“第二曲线”理论的全面进阶:深刻揭示组织与个人的兴衰规律,教导读者如何在第一曲线的巅峰前就主动布局新的增长引擎","全场景下的持续进化方案:将第二曲线思维跨界应用于教育、职业规划、婚姻与家庭中,强调“变化才是常态”,鼓励持续自我重塑","面向Z世代的清醒处方:在科技高歌猛进的数字时代,提醒后人重视诚信、协作等软实力,保持独立判断,避免在算法与焦虑中迷失自我"]}],Me=[{id:"book-033",title:"枪炮、病菌与钢铁",author:"贾雷德·戴蒙德",cover:"https://cdn.weread.qq.com/weread/cover/99/YueWen_42766048/t6_YueWen_42766048.jpg",wereadLink:"https://weread.qq.com/web/reader/843329f0728c8ee08434fb1#outline?noScroll=1",link:"https://book.douban.com/subject/1813841/",tags:["人类历史","地理决定论","社会学","跨学科"],desc:"一部重新定义人类历史发展的宏大著作。作者贾雷德·戴蒙德通过生物学、地理学、人类学等多学科交叉视角,强有力地反驳了“种族决定论”和“西方文明优越论”。他提出,决定文明兴衰的关键并非种族,而是环境因素、地理格局以及动植物驯化的差异,这些自然条件的偶然性最终导致了技术、免疫力和权力结构的差异,从而重塑了现代世界的全球版图。",rating:4.8,highlights:["颠覆性的历史观:以环境与地理差异解释文明兴衰,有力冲击了长期流行的西方文明优越论,提供了理解人类历史的全新视角","跨学科的综合研究框架:巧妙融合生物学、地理学、历史学、社会学等多学科知识,重建人类文明演进的逻辑路径","系统揭示历史演变的机制:深入剖析农业、病菌传播与技术权力如何形成相互强化的循环,展示了文明发展背后复杂的资源互动","具备公共思想者的宏观视野:将严谨的科学研究转化为对人类命运与社会发展的深刻反思,为现代人理解自身在历史长河中的位置提供了绝佳参照"]},{id:"book-034",title:"中国社会各阶层分析",author:"梁晓声",cover:"https://cdn.weread.qq.com/weread/cover/0/yuewen_42682684/t6_yuewen_426826841728383400.jpg",wereadLink:"https://weread.qq.com/web/reader/085326e0728b493c085ade1#outline?noScroll=1",link:"https://book.douban.com/subject/35485315/",tags:["社会观察","阶层研究","现实主义"],desc:"茅盾文学奖得主梁晓声基于多年社会观察的现实题材力作。作者将快速变迁的中国社会划分为不同阶层,以平民视角细腻描摹各群体的生存状态、心理困境与阶层焦虑。全书不追求纯学术的枯燥分析,而是通过文学化的社会观察,勾勒出一幅当代中国社会的“浮世绘”,引导读者在时代坐标中找准定位,理解社会变迁背后的结构性逻辑。",rating:4.3,highlights:["平民视角下的社会“浮世绘”:通过细腻的笔触勾勒各阶层的生存逻辑与心理画像,帮助读者直观理解宏观社会结构","兼具现实痛点与精神深度:不仅呈现物质生活的差异,更深刻剖析阶层焦虑背后的价值困境,为理解当代社会提供人文参照","时代脉络中的命运书写:将个体命运置于历史事件的宏观背景中考察,展现了半个世纪以来社会变迁的深层脉络","文学笔触下的社会关怀:作为茅盾文学奖得主,作者通过富有故事性的叙事,既保留了批判性,又让文本充满了温暖的人文温度"]},{id:"book-021",title:"把自己作为方法",author:"项飙 / 吴琦",cover:"https://cdn.weread.qq.com/weread/cover/81/cpPlatform_3300003962/t6_cpPlatform_3300003962.jpg",wereadLink:"https://weread.qq.com/web/reader/d7532f80813ab680cg012708#outline?noScroll=1",link:"https://book.douban.com/subject/35092383/",tags:["社会学","访谈录","思想方法"],desc:"两代学人项飙与吴琦历时三年、跨越五地的深度对话实录。本书从项飙的个人经验切入,探讨了中国社会近半个世纪的变迁、全球化与民粹主义等宏大议题。在自我泛滥与思想受困的时代,作者提出“把自己作为方法”,指导读者如何在全球化年代重新定位自我、重建“附近”,并在个人体验与宏观叙事之间搭建起思考与行动的桥梁。",rating:4.6,highlights:["以“自我”切入回应宏大议题:示范如何在个人真实体验与全球化、社会变迁等宏观叙事之间搭建认知的桥梁","提供重建“附近”的行动指南:在自我泛滥的潮流中,指导读者如何审视现实,创造性地建设身边的小世界","兼具学术深度与极高可读性:将人类学、社会学的深刻理论洞察,巧妙融入生动的田野故事与双人生活化对谈中","跨越三年的思想碰撞:历时三年、跨越五地的持续对话结集,反思知识生产与公共讨论的真实处境"]}],$e=[{id:"book-035",title:"百岁人生:长寿时代的生活和工作",author:"琳达·格拉顿 / 安德鲁·斯科特",cover:"https://wfqqreader-1252317822.image.myqcloud.com/cover/860/22902860/t6_22902860.jpg",wereadLink:"https://weread.qq.com/web/reader/30c323e0715d784c30c1e1b#outline?noScroll=1",link:"https://book.douban.com/subject/30245089/",tags:["人生规划","长寿时代","社会学"],desc:"基于伦敦商学院的经典课程,作者琳达·格拉顿与安德鲁·斯科特提出,面对一半概率活到100岁的长寿时代,传统的“学习-工作-退休”三段式人生模式已彻底失效。本书指导读者如何重新设计人生,通过拥抱多阶段人生模型,在更长的生命周期中平衡工作、学习与休闲,并强调在财务资产之外,更要注重健康、友谊与知识等“无形资产”的持续投入与增值。",rating:4.3,highlights:["重构人生模式:打破传统的“三段式”生活范式,提出充满弹性的“多阶段人生”模型,让工作与学习不再是线性的重复","从关注财务到“无形资产”:除了养老金,强调健康、友谊、社交网络与心理韧性等“无形资产”才是维持长寿生活质量的核心动力","职场与转型的系统规划:提供针对长寿时代的职业设计思路,涵盖何时转型、如何投资自身、怎样应对不确定性等实战框架","社会与制度的深度洞察:探讨长寿如何冲击养老金体系、劳动力市场与企业模式,帮助个人在宏观变革中把握主动权"]},{id:"book-00043",title:"重启吧!我的健康人生",author:"兰根·查特吉",cover:"https://cdn.weread.qq.com/weread/cover/80/cpplatform_kbrswv3bm7cix2zlyo6wtx/t6_cpplatform_kbrswv3bm7cix2zlyo6wtx1716362285.jpg",wereadLink:"https://weread.qq.com/web/reader/e8a32e80813ab8de4g0191c2#outline?noScroll=1",link:"https://book.douban.com/subject/36899697/",tags:["生活方式","预防医学","身心健康","自我管理"],desc:"英国临床医生基于20多年行医经验写就。本书主张“生活方式即良药”,围绕休息、饮食、运动和睡眠四个领域设计了20个微小行动计划,帮助现代人通过低成本的习惯改变逆转慢性问题。",rating:4.6,highlights:["提出99%的健康取决于日常习惯而非医学治疗,强调整体干预","构建“4×5”微行动框架,涵盖休息、饮食、运动、睡眠四个维度的20个小改变","兼顾科学深度与极简实操,如“12小时进食窗口”、“10分钟高强度运动”","关注现代职场人痛点,提供“小投入、大回报”的可叠加身心健康投资策略"]},{id:"book-00040",title:"你是你吃出来的:吃对少生病,病了这样吃",author:"夏萌",cover:"https://cdn.weread.qq.com/weread/cover/86/YueWen_920661/t6_YueWen_920661.jpg",wereadLink:"https://weread.qq.com/web/reader/7bb32c305e0c557bbdeab81#outline?noScroll=1",link:"https://book.douban.com/subject/27590675/",tags:["饮食科普","营养学","健康管理"],desc:"前安贞医院营养科主任夏萌结合十余年临床经验写成。本书颠覆“低油低脂”误区,提出回归进化的“65%植物+35%动物”膳食配比,并针对14种常见慢病给出“四分法”饮食干预方案,帮助读者重建健康饮食观。",rating:5,highlights:["指出多数慢病源于“蛋白质缺乏式营养不良”,打破常规低油低脂迷思","提出清晰量化的“65%植物类+35%动物类”科学饮食结构","针对冠心病、高血压等14种常见慢病提供实操性极强的“四分法”菜单","源于十万+真实临床病例,强调“一日三餐才是真正的保健品”"]},{id:"book-00041",title:"你是你吃出来的2",author:"夏萌",cover:"https://wfqqreader-1252317822.image.myqcloud.com/cover/883/35905883/t6_35905883.jpg",wereadLink:"https://weread.qq.com/web/reader/40532d007223e15b4052fae#outline?noScroll=1",link:"https://book.douban.com/subject/35340053/",tags:["饮食指导","科普","疾病防治"],desc:"聚焦高血压、高脂血症、糖尿病等7大常见慢病,从临床营养医学角度逐一破除诸如“血压高不能吃肉”等饮食误区,提供系统的“上游-中游-下游”疾病防控思路与个体化营养处方。",rating:4.6,highlights:["专攻7大常见慢性病,为患者提供针对性的“生病了怎么吃”个体化指导","科学辟谣,破除“血压高不能吃肉”、“胆固醇高不能吃鸡蛋”等常见误区","梳理疾病发生因果链条,帮助读者从源头找到健康干预的着力点","提供从一日三餐、运动到心态调养的具体可操作生活方式清单"]}],Ge=JSON.parse('{"title":"好书推荐","description":"读书心得、推荐书籍和阅读技巧","frontmatter":{"title":"好书推荐","date":"2024-01-01T16:00:00.000Z","description":"读书心得、推荐书籍和阅读技巧","categories":["growth"],"coverImg":"https://insight-stack-1252300811.cos.ap-shanghai.myqcloud.com/img/cover/books_reading_bg.png","permalink":"/growth/books","tags":["悦读时光","资源推荐"]},"headers":[],"relativePath":"30.悦读时光/01.好书推荐.md","filePath":"30.悦读时光/01.好书推荐.md"}'),Ne={name:"30.悦读时光/01.好书推荐.md"},De=Object.assign(Ne,{setup(r){return(b,t)=>(a(),l("div",null,[t[0]||(t[0]=x('

    好书推荐

    1. AI 与数学思维

    在大模型发展日新月异的今天,理解 AI 本质上是在升级我们资深的“认知操作系统”, 理解 AI,本质上是理解数据、数学与逻辑如何重构这个世界

    这套书单从数学思维的底层逻辑出发,让我们理解 ChatGPT 等大模型背后的计算机制,将硬核的神经网络与概率统计转化为优化生活的决策工具。它不仅能界定机器智能的边界,更颠覆了传统的“目标论”,倡导在不确定性中通过“踏脚石”思维寻找突破性创新的可能。AI 的研究实践告诉我们,伟大的突破往往无法被预设,唯有拥抱“寻宝者思维”才能在未知中偶遇奇迹,我们需要颠覆传统的创新范式。

    ',4)),h(k,{books:g(Be)},null,8,["books"]),t[1]||(t[1]=x('

    2. 产品与商业

    about site background

    2.1 产品 Sense 与创造

    在产品成功率不足 10% 的残酷市场中,好的创造绝非源于盲目的灵感,而是建立在极致的风险验证与深刻的人性洞察之上。

    卓越的产品力不仅关乎功能设计,更是一场关于策略与创造力的刻意练习:我们需要通过“预型”思维以极低成本进行真实数据验证,确保我们在投入开发前是在“做对产品”;并利用用户模型、交易模型等底层框架,将零散的需求转化为可获利的商业方案。

    ',4)),h(k,{books:g(Ie)},null,8,["books"]),t[2]||(t[2]=e("h3",{id:"_2-2-商业化",tabindex:"-1"},[n("2.2 商业化 "),e("a",{class:"header-anchor",href:"#_2-2-商业化","aria-label":"Permalink to “2.2 商业化”"},"​")],-1)),t[3]||(t[3]=e("blockquote",null,[e("p",null,[n("在追逐“独角兽”和规模扩张的狂热迷思之后,真正的商业高手正在重新回归本质:"),e("strong",null,"盈利才是企业的核心护城河。"),n(" 这套书单为我们揭示了一种"),e("strong",null,"更具韧性的商业路径——“小而美”的极简经营"),n("。它教导我们如何拒绝低效的内卷与忙碌,通过“做更少但创造更多价值”的思维,打造在不确定时代下依然能保持稳定现金流的“慢公司”。")]),e("p",null,[e("strong",null,"商业的成功,往往源于敢于挑战“难而正确”的事"),n("。从皮克斯如何建立允许失败的创意土壤,到 Waze 如何通过解决被忽视的痛点实现跨越式成长,这些世界级案例证明了:卓越的组织不仅需要极简的流程与高效的分布式协作(远程办公),更需要一种“冷静”的文化,将利润置于规模之上。")])],-1)),h(k,{books:g(We)},null,8,["books"]),t[4]||(t[4]=e("h2",{id:"_3-效率与效能",tabindex:"-1"},[n("3. 效率与效能 "),e("a",{class:"header-anchor",href:"#_3-效率与效能","aria-label":"Permalink to “3. 效率与效能”"},"​")],-1)),t[5]||(t[5]=e("blockquote",null,[e("p",null,[n("在信息过载与高压竞争的现代环境中,平庸与卓越的分水岭不再是做事的速度,而是"),e("strong",null,"决策的精度与责任的边界"),n("。这套书单为我们提供了一套从个人认知到组织协作的“效能防线”:首先,它"),e("strong",null,"引导我们完成从“时钟”到“罗盘”的思维跨越,打破盲目追求速度的迷思,确保将核心精力倾注在真正产生长远复利的“重要非紧急”事务之上"),n("。 真正的效能源于对复杂性的科学驾驭:")]),e("ul",null,[e("li",null,"通过“清单革命”式的认知防护,我们将最佳实践外化为可靠的防错系统,弥补人类在极端环境下的认知局限;"),e("li",null,"“猴子管理法”则以生动的视角重塑了职场协作的责任逻辑,教我们通过有效授权拒绝无谓的干扰,释放战略思考的精力;")])],-1)),h(k,{books:g(Ye)},null,8,["books"]),t[6]||(t[6]=e("h2",{id:"_4-学习与成长",tabindex:"-1"},[n("4. 学习与成长 "),e("a",{class:"header-anchor",href:"#_4-学习与成长","aria-label":"Permalink to “4. 学习与成长”"},"​")],-1)),t[7]||(t[7]=e("blockquote",null,[e("p",null,[n("在信息爆炸与快速变革的时代,"),e("strong",null,"真正的成长不再是知识的被动堆砌,而是认知系统的彻底迭代"),n("。这套书单为我们构建了一个从底层思维到人生经营的闭环:")]),e("ul",null,[e("li",null,"首先,通过批判性思维与深度阅读夯实“元能力”,在泛滥的信息中识别本质,将他人的洞见转化为自己的血肉;"),e("li",null,"其次,利用“检索力”打破信息差,确保自己在任何领域都能快速获取高质量资源,掌握逆风而行的主动权。")]),e("p",null,[e("strong",null,"人生不是一场盲目的长跑,而是一场基于“原则”的精密经营"),n("。从达利欧的系统化决策,到纳瓦尔的财富与幸福逻辑,这些智者教导我们如何利用杠杆、坚持长期主义,将自己视作一家“人生有限公司”来经营。我们需要摆脱“优秀绵羊”式的被动驱动,通过识别成长的“第二曲线”,在巅峰时刻主动寻求突破,将自己打造成不可替代的稀缺资产。阅读这些经典,不仅是为了习得技能,更是为了在算法与焦虑的夹击中,重塑内心的宁静与独立判断的勇气。")])],-1)),h(k,{books:g(Te)},null,8,["books"]),t[8]||(t[8]=e("h2",{id:"_5-人文社科",tabindex:"-1"},[n("5. 人文社科 "),e("a",{class:"header-anchor",href:"#_5-人文社科","aria-label":"Permalink to “5. 人文社科”"},"​")],-1)),t[9]||(t[9]=e("blockquote",null,[e("p",null,"在宏观历史与微观现实间构建认知:在碎片化与不确定性并存的时代,穿透表象、直达本质的洞察力成为必需。这套单为我们开启了两扇窗:"),e("ul",null,[e("li",null,"一扇望向万年文明的宏大坐标,通过《枪炮、病菌与钢铁》的跨学科视野,拆解地理环境如何冷酷而偶然地重塑全球版图,彻底颠覆“文明优越论”的傲慢;"),e("li",null,"另一扇则照向当下社会的真实肌理,在梁晓声对各阶层生存困境的细腻描摹中,读懂大时代变革背后隐秘的结构性逻辑与阶层焦虑。")]),e("p",null,[e("strong",null,"人文思考的终极价值,在于如何将宏大叙事转化为个人的行动力量"),n("。正如项飙所倡导的“把自己作为方法”,这些著作不仅是知识的传递,更是思维的松绑。它们教导我们不再做时代的被动旁观者,而是学会在个人体验与宏观世界之间搭建桥梁,通过重建“附近”的小世界,在喧嚣中找准自我的定位。")])],-1)),h(k,{books:g(Me)},null,8,["books"]),t[10]||(t[10]=e("h2",{id:"_6-健康生活",tabindex:"-1"},[n("6. 健康生活 "),e("a",{class:"header-anchor",href:"#_6-健康生活","aria-label":"Permalink to “6. 健康生活”"},"​")],-1)),t[11]||(t[11]=e("img",{src:$,style:{width:"100%","border-radius":"8px","margin-bottom":"20px"},alt:"about site background"},null,-1)),t[12]||(t[12]=e("blockquote",null,[e("p",null,[n("在面临大概率活到100岁的“长寿时代”,传统的线性人生模式正在失效。我们需要对“健康”进行一次彻底的认知重构:"),e("strong",null,"健康不再仅仅是“没有疾病”,而是支撑我们跨越漫长生命周期、应对多阶段人生挑战的最核心“无形资产”"),n("。想要让这套生命系统长期平稳运行,真正的解法并不在医院的处方笺里,而是隐藏在我们每天的日常选择中。")]),e("p",null,[n("决定我们长期健康状态的,有 99 %取决于日常习惯。我们需要"),e("strong",null,"在休息、饮食、运动、睡眠这四个高频生活维度中,植入微小但杠杆率极高的改变"),n("(例如12小时进食窗口、10分钟高强度运动、睡前屏蔽数字通知等)。用最低的执行成本,置换身心状态的巨大回报。")])],-1)),h(k,{books:g($e)},null,8,["books"])]))}});export{Ge as __pageData,De as default}; +import{d as x,p as A,h as a,z as h,Y as B,s as I,g as r,y as _,v as P,i as e,W as v,x as c,F as p,t as f,S as l,T as W,_ as C,r as j,c as Y,k as $,U as M,l as g}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const T="/img/cover/health_bg.png",N={class:"book-panel__drawer"},V={class:"book-panel__header-meta"},G={class:"book-panel__title"},D={class:"book-panel__author"},F={class:"book-panel__body"},Z={class:"book-panel__top-bar"},H={class:"book-panel__top-left"},J={class:"book-panel__tags"},O={key:0,class:"book-panel__rating"},R={class:"stars"},E={key:0,viewBox:"0 0 24 24",fill:"currentColor"},K={key:1,viewBox:"0 0 24 24",class:"half-star"},Q=["id"],X=["clip-path"],U={key:2,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"1.5"},ee={class:"rating-text"},te={class:"book-panel__links"},oe=["href"],ae={width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",style:{"flex-shrink":"0"}},le=["href"],re={width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",style:{"flex-shrink":"0"}},ne={class:"book-panel__section"},se={class:"book-panel__desc"},ie={key:0,class:"book-panel__section"},de={class:"book-panel__highlights"},ce=x({__name:"BookDetailPanel",props:{book:{},open:{type:Boolean},heroColor:{},tagColors:{}},emits:["close"],setup(n,{emit:b}){const t=b;return(w,o)=>(a(),A(W,{to:"body"},[h(B,{name:"panel-slide"},{default:I(()=>[n.open&&n.book?(a(),r("div",{key:0,class:"book-panel",onClick:o[2]||(o[2]=P(i=>t("close"),["self"]))},[e("div",{class:"book-panel__overlay",onClick:o[0]||(o[0]=i=>t("close"))}),e("div",N,[e("div",{class:"book-panel__header",style:v({background:n.heroColor})},[e("button",{class:"book-panel__close",title:"关闭",onClick:o[1]||(o[1]=i=>t("close"))},[...o[3]||(o[3]=[e("svg",{width:"14",height:"14",viewBox:"0 0 16 16",fill:"none"},[e("path",{d:"M12 4L4 12M4 4l8 8",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round"})],-1)])]),e("div",V,[e("h2",G,c(n.book.title),1),e("p",D,c(n.book.author),1)])],4),e("div",F,[e("div",Z,[e("div",H,[e("div",J,[(a(!0),r(p,null,f(n.book.tags,(i,m)=>(a(),r("span",{key:i,class:"book-panel__tag",style:v({background:n.tagColors[m%n.tagColors.length].bg,color:n.tagColors[m%n.tagColors.length].text})},c(i),5))),128))]),n.book.rating!=null?(a(),r("div",O,[o[8]||(o[8]=e("span",{class:"rating-label"},"推荐指数:",-1)),e("div",R,[(a(),r(p,null,f(5,i=>e("span",{key:i,class:"star"},[i<=Math.floor(n.book.rating)?(a(),r("svg",E,[...o[4]||(o[4]=[e("path",{d:"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"},null,-1)])])):i===Math.ceil(n.book.rating)&&n.book.rating%1!==0?(a(),r("svg",K,[e("defs",null,[e("clipPath",{id:"clip-"+n.book.id},[...o[5]||(o[5]=[e("rect",{x:"0",y:"0",width:"12",height:"24"},null,-1)])],8,Q)]),o[6]||(o[6]=e("path",{class:"star-empty",d:"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z",fill:"none",stroke:"currentColor","stroke-width":"1.5"},null,-1)),e("path",{class:"star-filled",d:"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z",fill:"currentColor","clip-path":"url(#clip-"+n.book.id+")"},null,8,X)])):(a(),r("svg",U,[...o[7]||(o[7]=[e("path",{d:"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"},null,-1)])]))])),64))]),e("span",ee,c(n.book.rating.toFixed(1)),1)])):_("",!0)]),e("div",te,[e("a",{href:n.book.link,target:"_blank",rel:"noopener",class:"book-panel__link-btn"},[(a(),r("svg",ae,[...o[9]||(o[9]=[e("path",{d:"M18 13v6a2 2 0 01-2 2H5a2 2 0 01-2-2V8a2 2 0 012-2h6M15 3h6v6M10 14L21 3",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},null,-1)])])),o[10]||(o[10]=l(" 豆瓣 ",-1))],8,oe),n.book.wereadLink?(a(),r("a",{key:0,href:n.book.wereadLink,target:"_blank",rel:"noopener",class:"book-panel__link-btn"},[(a(),r("svg",re,[...o[11]||(o[11]=[e("path",{d:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z",fill:"currentColor"},null,-1)])])),o[12]||(o[12]=l(" 微信读书 ",-1))],8,le)):_("",!0)])]),o[15]||(o[15]=e("div",{class:"book-panel__divider"},null,-1)),e("section",ne,[o[13]||(o[13]=e("h3",{class:"book-panel__section-title"},[e("span",{class:"book-panel__section-icon"},"📖"),l(" 内容简介 ")],-1)),e("p",se,c(n.book.desc),1)]),n.book.highlights&&n.book.highlights.length>0?(a(),r("section",ie,[o[14]||(o[14]=e("h3",{class:"book-panel__section-title"},[e("span",{class:"book-panel__section-icon"},"✨"),l(" 书籍亮点 ")],-1)),e("ul",de,[(a(!0),r(p,null,f(n.book.highlights,(i,m)=>(a(),r("li",{key:m,class:"book-panel__highlight-item"},c(i),1))),128))])])):_("",!0)])])])):_("",!0)]),_:1})]))}}),he=C(ce,[["__scopeId","data-v-1ddfc013"]]),be={class:"book-list"},ue=["onClick"],ge=["src","alt"],ke={class:"book-cover__overlay"},pe={key:0,class:"book-cover__hint"},we=["href"],me={class:"book-info"},_e={class:"book-info__title"},fe={class:"book-info__author"},qe={key:0,class:"book-info__rating"},ve={class:"stars"},je={key:0,viewBox:"0 0 24 24",fill:"currentColor"},Le={key:1,viewBox:"0 0 24 24",class:"half-star"},ye=["id"],Se=["clip-path"],xe={key:2,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"1.5"},Pe={class:"rating-text"},Ce={class:"book-info__tags"},ze={class:"book-info__desc"},Ae=x({__name:"BookRecommend",props:{books:{}},setup(n){const b=["linear-gradient(135deg, #e8f0fe 0%, #c7d9fd 100%)","linear-gradient(135deg, #e6f4ea 0%, #b7dfc4 100%)","linear-gradient(135deg, #fff3e0 0%, #ffd9a0 100%)","linear-gradient(135deg, #fce4ec 0%, #f8b4c8 100%)","linear-gradient(135deg, #ede7f6 0%, #cdb8ee 100%)","linear-gradient(135deg, #e0f7fa 0%, #9ee8f0 100%)"],t=[{bg:"#e8f0fe",text:"#3b5bdb"},{bg:"#e6f4ea",text:"#2e7d32"},{bg:"#fff3e0",text:"#e65100"},{bg:"#fce4ec",text:"#c2185b"},{bg:"#ede7f6",text:"#6a1b9a"},{bg:"#e0f7fa",text:"#00838f"}],w=j(null),o=j(0),i=j(!1),m=Y(()=>b[o.value%b.length]);function z(q,d){q.withPanel!==!1&&(w.value?.id===q.id&&i.value?L():(w.value=q,o.value=d,i.value=!0))}function L(){i.value=!1,setTimeout(()=>{w.value=null},300)}return(q,d)=>(a(),r(p,null,[e("div",be,[(a(!0),r(p,null,f(n.books,(s,y)=>(a(),r("div",{key:s.id,class:$(["book-card",{"book-card--active":w.value?.id===s.id&&i.value}]),onClick:u=>z(s,y)},[e("div",{class:"book-cover",style:v({background:b[y%b.length]})},[s.cover?(a(),r("img",{key:0,src:s.cover,alt:s.title,class:"book-cover__img"},null,8,ge)):_("",!0),e("div",ke,[s.withPanel!==!1?(a(),r("span",pe,"点击查看详情")):(a(),r("a",{key:1,href:s.link,target:"_blank",rel:"noopener",class:"book-cover__hint",onClick:d[0]||(d[0]=P(()=>{},["stop"]))},"查看豆瓣",8,we))])],4),e("div",me,[e("div",_e,"《"+c(s.title)+"》",1),e("div",fe,c(s.author),1),s.rating!=null?(a(),r("div",qe,[e("div",ve,[(a(),r(p,null,f(5,u=>e("span",{key:u,class:"star"},[u<=Math.floor(s.rating)?(a(),r("svg",je,[...d[1]||(d[1]=[e("path",{d:"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"},null,-1)])])):u===Math.ceil(s.rating)&&s.rating%1!==0?(a(),r("svg",Le,[e("defs",null,[e("clipPath",{id:"card-clip-"+s.id},[...d[2]||(d[2]=[e("rect",{x:"0",y:"0",width:"12",height:"24"},null,-1)])],8,ye)]),d[3]||(d[3]=e("path",{class:"star-empty",d:"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z",fill:"none",stroke:"currentColor","stroke-width":"1.5"},null,-1)),e("path",{class:"star-filled",d:"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z",fill:"currentColor","clip-path":"url(#card-clip-"+s.id+")"},null,8,Se)])):(a(),r("svg",xe,[...d[4]||(d[4]=[e("path",{d:"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"},null,-1)])]))])),64))]),e("span",Pe,c(s.rating.toFixed(1)),1)])):_("",!0),e("div",Ce,[(a(!0),r(p,null,f(s.tags,(u,S)=>(a(),r("span",{key:u,class:"tag",style:v({background:t[S%t.length].bg,color:t[S%t.length].text})},c(u),5))),128))]),e("p",ze,c(s.desc),1)])],10,ue))),128))]),h(he,{book:w.value,open:i.value,"hero-color":m.value,"tag-colors":t,onClose:L},null,8,["book","open","hero-color"])],64))}}),k=C(Ae,[["__scopeId","data-v-fd79cd55"]]),Be=[{id:"book-001",title:"心中有数:生活中的数学思维",author:"刘雪峰",cover:"https://cdn.weread.qq.com/weread/cover/39/3300018939/t6_3300018939.jpg",wereadLink:"https://weread.qq.com/web/reader/df6323a0813ab6de5g019a31#outline?noScroll=1",link:"https://book.douban.com/subject/35749693/",tags:["数学思维","科普","决策"],desc:"本书通过大量贴近日常的例子,展示数学思维如何优化我们的生活决策。作者用概率、统计、最优化等数学工具,为生活、职场、人际交往中的权衡问题提供分析框架,帮助读者在面对不确定性时像计算机一样找到“最优解”。",rating:4.9,highlights:["将大数定律、最小二乘法等硬核数学概念与日常生活巧妙结合","提供应对不确定性和多目标抉择的科学决策框架","强调数学不仅是公式计算,更是看世界、优化人生的高效思维工具"]},{id:"book-0020",title:"智慧的疆界:从图灵机到人工智能",author:"周志明",cover:"https://cdn.weread.qq.com/weread/cover/92/YueWen_23637052/t6_YueWen_23637052.jpg",wereadLink:"https://weread.qq.com/web/reader/b9732f007168ac3cb976eca#outline?noScroll=1",link:"https://book.douban.com/subject/30379536/",tags:["人工智能","科技史","通识读物"],desc:"本书是一部面向大众的人工智能通识读物。作者周明以时间为主线,将人工智能的发展历程、关键人物与里程碑事件串联起来,从五个维度展开:学术理论、历史沿革、技术应用、研究成果以及面临的困难与未来挑战。全书旨在用通俗的语言和巧妙的结构,把人工智能从“阳春白雪”的学术殿堂带到公众视野,帮助读者理解 AI 能做什么、做不到什么,以及背后的技术与思想根源。",rating:5,highlights:["以时间为主线,清晰梳理人工智能的发展脉络与里程碑","深入浅出,用通俗语言将复杂的学术理论带入公众视野","客观剖析,帮助读者准确界定AI“能做什么”与“做不到什么”"]},{id:"book-004",title:"为什么伟大不能被计划",author:"肯尼斯·斯坦利 / 乔尔·雷曼",cover:"https://cdn.weread.qq.com/weread/cover/22/cpplatform_wfdzhk1dx7ig9aep4gagof/t6_cpplatform_wfdzhk1dx7ig9aep4gagof1686304376.jpg",wereadLink:"https://weread.qq.com/web/reader/0bf32020813ab7e6bg016510#outline?noScroll=1",link:"https://book.douban.com/subject/36357804/",tags:["人工智能","创新思维","认知科学"],desc:"本书由两位前沿AI科学家合著,提出了颠覆传统“目标-计划”思维的全新视角。结合AI研究实践,书中论证了伟大成就往往并非出自精心设计的蓝图,而是源于对未知的好奇、随机探索与不断试错。通过“寻宝者思维”和“踏脚石模型”等方法,为读者在高度不确定的环境中激发突破性创新提供了具体的行动框架。",rating:4.5,highlights:["颠覆传统的“目标论”,论证伟大成就源自对未知的好奇与无边界的探索","提供“寻宝者思维”“踏脚石模型”“新奇性探索”三大可操作的认知与实践工具","扎根OpenAI等前沿机构的实证背景,其启发意义跨学科适用于科研、商业及人生规划"]},{id:"book-003",title:"这就是ChatGPT",author:"斯蒂芬·沃尔弗拉姆",cover:"https://cdn.weread.qq.com/weread/cover/24/cpplatform_4cn8w4tmgzntjobg9ffeny/t6_cpplatform_4cn8w4tmgzntjobg9ffeny1703648785.jpg",wereadLink:"https://weread.qq.com/web/reader/74332a90813ab86c4g019d98#outline?noScroll=1",link:"https://book.douban.com/subject/36449803/",tags:["人工智能","大模型","ChatGPT"],desc:"本书由著名科学家斯蒂芬·沃尔弗拉姆撰写,全景式拆解了ChatGPT的内部工作机制。作者用通俗语言解释了神经网络和自回归架构等核心技术,探讨了简单的计算规则如何涌现出令人惊叹的智能,帮助读者深刻理解大语言模型为何能生成高质量的人类水平文本。",rating:4.3,highlights:["全景拆解核心技术:深入浅出地讲清ChatGPT背后的神经网络与自回归架构","独特的大师视角:将大模型视为“简单的计算规则”涌现复杂智能的绝佳范例","兼顾技术与商业影响:结合算力规模与行业冲击,全面探讨AI时代的机遇与挑战"]},{id:"book-0030",title:"人工智能:现代方法(第4版)(上下册)",author:"[美]斯图尔特·罗素(Stuart Russell) / [美]彼得·诺维格(Peter Norvig)",cover:"https://cdn.weread.qq.com/weread/cover/33/cpplatform_8rthznqfhsjuz5fswwn6kx/t6_cpplatform_8rthznqfhsjuz5fswwn6kx1675928213.jpg",wereadLink:"https://weread.qq.com/web/reader/fc332020813ab7942g0102ad#outline?noScroll=1",link:"https://book.douban.com/subject/36152133",tags:["人工智能","教材","理论实践结合","经典著作","计算机科学"],desc:"本书是人工智能领域的经典权威教材,系统、深入地探讨AI领域的理论与实践,以统一风格融合当今流行的AI思想与术语到前沿应用中,真正实现理论与实践相结合。全书分7个部分共28章,理论部分涵盖逻辑、概率、连续数学、感知、推理、学习、行动及公平、信任、社会公益和安全等社会议题;实践部分选取微电子设备、机器人行星探测器、在线服务、AlphaZero、人形机器人、自动驾驶、AI辅助医疗等热门场景。由加州大学伯克利分校教授斯图尔特·罗素与前谷歌研究总监彼得·诺维格联合撰写,被全球1500多所高校采用,适合作为AI相关专业本科生和研究生教材,也可作为专业人员的参考书。",rating:5,highlights:["体系完整覆盖面广,7个部分28章构成自洽的AI理论主线,涵盖核心理论与前沿议题","理论与实践并重,既阐述核心算法与模型,又展示在热门场景中的落地实例,便于知识迁移","紧跟前沿关注社会议题,专门讨论AI伦理与安全,引导思考技术与社会的交互责任","一站式权威参考,兼具教材属性与专业参考价值,适配高校教学与产业实践双重需求","现代理念贯穿始终,通过最新案例体现AI进展与行业趋势,呈现“活”的AI生态"]},{id:"book-0031",title:"模型思维:简化世界的人工智能模型",author:"龚才春",cover:"https://cdn.weread.qq.com/weread/cover/26/YueWen_38601826/t6_YueWen_38601826.jpg",wereadLink:"https://weread.qq.com/web/reader/5a8326e0724d04625a8e740#outline?noScroll=1",link:"https://book.douban.com/subject/35488925/",tags:["模型思维","人工智能","算法模型","机器学习","入门实践"],desc:"本书聚焦“如何用模型简化世界”的核心主题,将人工智能在现实业务中面临的难题归纳为权重、状态、序列、表示、相似、分类六大问题,并围绕该框架讲解对应模型思路与算法。书中弱化复杂数学公式,以大量生活化、业务化案例阐释模型理论与落地场景,帮助读者建立“模型—场景”映射关系,降低AI模型学习门槛,既是人工智能初学者的入门读物,也可为企业工程师、科研人员提供实践参考,适合各类读者学习并将模型思维应用到生活与工作中。",rating:4.8,highlights:["以“六大问题”框架串联AI模型,可按场景快速检索适配的模型思路","侧重落地实践,搭配大量生活化与业务案例,助力建立“模型—场景”映射","降低学习门槛,少数学公式、多直观案例,兼顾初学者与工程落地需求","受众群体广泛,适配工程师、科研人员及普通读者,可迁移模型思维至实际场景"]},{id:"book-005",title:"你看起来好像……我爱你:AI的工作原理以及它为这个世界带来的稀奇古怪",author:"贾内尔·沙内",cover:"https://wfqqreader-1252317822.image.myqcloud.com/cover/970/39481970/t6_39481970.jpg",wereadLink:"https://weread.qq.com/book-detail?type=1&senderVid=40710128&v=f9a32c10725a7272f9a14f9&wtheme=white&wfrom=app&wvid=40710128&scene=bottomSheetShare",link:"https://book.douban.com/subject/35407136/",tags:["人工智能","趣味科普","漫画算法"],desc:"这是一部写给普通读者的人工智能趣味科普读物。作者贾内尔·沙内结合生活化的比喻和超级可爱的漫画,深入浅出地讲解了AI的基本工作原理、实际应用及其局限性。书中通过大量幽默的AI实验与“翻车”案例,带领读者在轻松捧腹的氛围中,准确理解算法能做什么、不能做什么。",rating:4.2,highlights:["幽默可爱的漫画导览:用插图和通俗语言将“深度学习”“神经网络”等抽象概念可视化","丰富的趣味实验案例:通过精选的AI“翻车”故事,直观揭示算法背后的逻辑与潜在偏差","客观建立AI认知:在展示AI强大能力的同时,明确指出其在语境理解和处理模糊信息时的短板"]},{id:"book-006",title:"AI经济:机器人时代的工作、财富和社会福利",author:"罗杰·布特尔",cover:"https://cdn.weread.qq.com/weread/cover/30/YueWen_38229387/t6_YueWen_38229387.jpg",wereadLink:"https://weread.qq.com/web/reader/653320207247558b65332f5#outline?noScroll=1",link:"https://book.douban.com/subject/35433060/",tags:["人工智能","经济学","社会学","未来趋势"],desc:"本书由知名经济学家罗杰·布特尔撰写,聚焦AI与机器人技术对经济和社会的深远影响。作者拨开艰涩的科技术语,从经济增长、通货膨胀及财富分配等宏观视角,理性剖析AI革命将如何重塑我们的工作、教育与休闲方式,以乐观的姿态为迎接未来的社会变革指明路径。",rating:4.1,highlights:["宏观经济视角解析:深入探讨AI对经济增长、通货膨胀、财富与权力分配的真实影响","全景式社会洞察:全面检视机器人时代下,人类教育体系、工作模式与休闲形态的深刻变革","理性乐观的未来指南:拒绝技术恐慌,为个人与社会在变迁的世界中提供清晰可行的应对计划"]}],Ie=[{id:"book-007",title:"做对产品",author:"阿尔贝托·索维亚",cover:"https://cdn.weread.qq.com/weread/cover/53/YueWen_40877841/t6_YueWen_40877841.jpg",wereadLink:"https://weread.qq.com/web/reader/254322a0726fbf1125472c9#outline?noScroll=1",link:"https://book.douban.com/subject/35607961/",tags:["产品思维","创业","商业方法论"],slogan:"为什么有些产品注定失败,有些产品却能大获成功?来自谷歌与斯坦福的产品工具和产品战术。",desc:"谷歌首任产品总监阿尔贝托·索维亚结合在谷歌、斯坦福的实战经验与自身代价高昂的创业失败经历,总结出的一套防败手册。书中揭示了新产品高达90%的“市场失败律”,并创新性地提出了“预型”(Pre型)理念,指导团队在正式开发前,以极低的成本和真实数据快速验证关键假设,确保把创意打磨成“正确的它”。",rating:4.8,highlights:["揭示残酷的市场失败律:正视90%新产品必然失败的商业常态,并以此倒推破局的实战方法论","首创“预型”(Pre型)概念:提供8大测试工具,主张用极低成本和小规模试错快速逼近正确的产品形态","强调真实数据驱动决策:辅以特斯拉、谷歌等完整案例回溯,教导团队将决策建立在客观证据而非主观直觉之上"]},{id:"book-009",title:"俞军产品方法论",author:"俞军",cover:"https://cdn.weread.qq.com/weread/cover/47/YueWen_28165041/t6_YueWen_28165041.jpg",wereadLink:"https://weread.qq.com/web/reader/1cc3252071adc3b11cc0162#outline?noScroll=1",link:"https://book.douban.com/subject/34907971/",tags:["产品思维","产品经理","互联网","方法论"],desc:"“百度贴吧之父”俞军二十余年产品实践与思考的系统总结。本书将产品经理定义为“以科学方法研究人性并转化为商业方案”的交叉学科,深入解析了用户模型、交易模型和决策模型三大核心框架,为产品人提供了一套在不确定环境中权衡多方利益的实战指南。",rating:4.4,highlights:["沉淀二十年行业经验:从广为流传的“PM12条”到系统化的产品哲学,展现顶尖产品经理的认知迭代史","三大核心模型拆解:深度剖析用户模型与交易模型,指导如何通过让交易发生来创造“有利可图”的真实用户价值","兼顾科学与人文视角:强调批判性思维的运用,并清晰梳理了从新人到顶尖大牛的能力进阶路径"]},{id:"book-016",title:"策略产品经理:模型与方法论",author:"青十五",cover:"https://cdn.weread.qq.com/weread/cover/31/cpplatform_gheeqe7hjb2czyzthzf5nm/t6_cpplatform_gheeqe7hjb2czyzthzf5nm1735654872.jpg",wereadLink:"https://weread.qq.com/web/reader/4de32800813ab98d5g01286b#outline?noScroll=1",link:"https://book.douban.com/subject/35218721/",tags:["产品经理","策略产品","算法思维"],desc:"本书围绕“策略产品经理”这一复合角色,系统性地构建了从理念到实践的完整知识框架。作者从机器学习理论与经济学视角出发,结合推荐、搜索、广告、风控等核心业务场景,深入浅出地讲解了函数建模与策略应用,并对策略产品经理的核心能力与团队建设给出了详尽指导。",rating:3.9,highlights:["系统化的角色认知建构:清晰界定策略产品经理的时代背景、职责边界与工作内容,为从业者夯实概念基础","跨学科的模型与业务结合:利用机器学习的函数方法论与经济学理论,深度剖析推荐、搜索、广告、风控及定价等真实业务场景的解法","硬核算法的通俗化解析:深入浅出地拆解机器学习本质、常见算法及深度学习前沿技术,帮助产品经理真正理解策略背后的技术支撑","可落地的团队建设指南:全面拆解数据分析、沟通与项目管理等核心能力项,并针对不同产品生命周期提供策略团队的组建思路"]},{id:"book-008",title:"创造:用非传统方式做有价值的事",author:"托尼·法德尔",cover:"https://cdn.weread.qq.com/weread/cover/53/cpPlatform_tzdqT27m3vyaHnX5o8Vbwk/t6_cpPlatform_tzdqT27m3vyaHnX5o8Vbwk.jpg",wereadLink:"https://weread.qq.com/web/reader/13832ac0813ab725fg018645#outline?noScroll=1",link:"https://book.douban.com/subject/36071759/",tags:["产品思维","管理学","创业"],desc:"本书是iPod、iPhone、Nest等爆款产品幕后推手托尼·法德尔30余年职业经历的智慧结晶。作者毫无保留地分享了他在产品设计、团队管理、职业选择和公司经营等方面的“非传统”方法论,帮助读者在各自的领域内刻意练习创造力,做真正有价值的事。",rating:4.9,highlights:["源自顶级创新者的实战经验:连续打造iPod、iPhone等划时代产品的亲历复盘与真实反面教训","覆盖从个人到公司的完整路径:系统解答职业选择、产品设计、团队管理与企业经营等核心问题","提供可复制的“非传统”方法论:强调“亮点思维”与持续复盘,教导读者以反常规的视角刻意练习创造力"]},{id:"book-010",title:"产品思维",author:"刘飞",cover:"https://cdn.weread.qq.com/weread/cover/56/YueWen_25568738/t6_YueWen_25568738.jpg",wereadLink:"https://weread.qq.com/web/reader/38332ce0718625e23831fe7#outline?noScroll=1",link:"https://book.douban.com/subject/33456375/",tags:["产品思维","产品经理","个人成长","互联网"],desc:"实战派产品经理刘飞结合在一线大厂的丰富经验,围绕产品人如何实现能力跃迁展开的底层能力指南。全书掰开揉碎地讲解了认知盲点与实践痛点,通过“认知用户”“创造价值”和“产品落地”三大核心板块,系统拆解了从建立用户模型、高质量决策到快速迭代验证的完整产品方法论。",rating:4.2,highlights:["三大核心板块系统拆解:完整覆盖“认知用户”“创造价值”与“产品落地”的产品闭环","直击痛点的一线实战经验:毫无保留地分享实战中新手迫切需要却难以获取的隐性知识","聚焦底层能力与思维升维:不仅教授落地方法,更注重决策质量与思维模式的跃迁"]},{id:"book-011",title:"产品思维:创新设计的六条法则(全彩)",author:"张印帅",cover:"https://wfqqreader-1252317822.image.myqcloud.com/cover/253/26687253/t6_26687253.jpg",wereadLink:"https://weread.qq.com/web/reader/a823297071973715a8202b0#outline?noScroll=1",link:"https://book.douban.com/subject/34859540/",tags:["产品设计","创新思维","方法论","设计灵感"],desc:"本书围绕作者张印帅多年产品设计实践总结出的6条创意公式展开,旨在帮助读者系统化地获取设计灵感并解决创新难题。全书通过大量经典案例,详细解析了从发散思考到重组创新的全过程,并在最后提供了从需求到草图再到最终方案的完整项目落地演示。",rating:4,highlights:["提炼6条实用的创新设计公式:将发散思考与重组创新系统化,打造可复用的设计灵感库","丰富的经典设计案例解析:详细展示“问题+方法”、“1+1>2”等法则在真实产品设计中的应用","呈现从需求到方案的落地全流程:通过综合案例演示概念打磨与草图设计的实战过程"]}],We=[{id:"book-012",title:"小而美:持续盈利的经营法则",author:"萨希尔·拉文吉亚",cover:"https://cdn.weread.qq.com/weread/cover/91/cpplatform_vl4abrrrqgxnry833gcrtt/t6_cpplatform_vl4abrrrqgxnry833gcrtt1677578056.jpg",wereadLink:"https://weread.qq.com/web/reader/02932980813ab7a43g012e77#outline?noScroll=1",link:"https://book.douban.com/subject/36280425/",tags:["创业","商业模式","极简主义"],desc:"本书打破了硅谷盲目追求“独角兽”的扩张迷思,聚焦于“规模不是唯一出路”的商业现实。作者结合创立Gumroad的亲身经历,提出了“极简创业经营”理念。全书指导创业者与管理者如何通过从社区切入、聚焦核心能力、精简团队等方式,用最少的资源打造出不仅能活下去,而且还能持续盈利的“慢公司”。",rating:5,highlights:["颠覆传统的扩张迷思:提出盈利至上而非规模至上,将持续赚钱和实际利润作为衡量企业成功的核心标准","可落地的极简法则:总结出“越少越好”“瞄准前100个客户”等7条创业清单,构建从定位、产品到销售的完整闭环","社区驱动的商业逻辑:提倡从虚拟社区入手,以“贡献-创作-教学”的方式低成本验证产品形态并获取早期信任","打造高韧性的“慢公司”:结合疫情与远程办公背景,展示如何通过精简组织和分布式协作,在不确定的时代保持稳定的现金流"]},{id:"book-013",title:"做难而正确的事:进步最快的方式",author:"尤里·莱文",cover:"https://cdn.weread.qq.com/weread/cover/53/cpplatform_bunxjyygj8m9stnwcgwqqk/t6_cpplatform_bunxjyygj8m9stnwcgwqqk1728876401.jpg",wereadLink:"https://weread.qq.com/web/reader/aa032fb0813ab9461g018406#outline?noScroll=1",link:"https://book.douban.com/subject/37054102/",tags:["创业","产品思维","商业管理"],desc:"Waze联合创始人尤里·莱文写给创业者和管理者的行动指南。作者结合连续打造两家估值超10亿美元公司的实战经验,提出“先做难事、再做正确事”的核心哲学。全书通过13个阶段的系统拆解,指导读者如何寻找真正的用户痛点、构建高价值产品,并在不确定的环境中通过不断复盘实现跨越式成长。",rating:4.9,highlights:["世界级创业者的实战复盘:连续打造两家独角兽公司的创始人亲授,提供极具可信度的第一手商业洞察与落地经验","践行“难而正确”的核心哲学:强调不追逐短期热点,而是去解决效率极低却被忽视的痛点,以此建立坚实的商业护城河","覆盖从0到1的全周期指南:系统拆解从寻找痛点、产品构建、融资运作到团队管理的13个关键阶段,提供可操作的行动清单","直面失败的心理韧性建设:不回避挫折,将“从错误中学习”提炼为核心方法,为身处高压环境的读者提供情感共鸣与心理支持","广泛的跨场景应用价值:书中给出的决策工具不仅适用于初创团队,同样能为大公司内部创新及个人职业认知升级提供指导"]},{id:"book-015",title:"创新公司:皮克斯的启示",author:"艾德·卡特姆",cover:"https://cdn.weread.qq.com/weread/cover/20/YueWen_814380/t6_YueWen_814380.jpg",wereadLink:"https://weread.qq.com/web/reader/2ef329605c6d2c2efeeb70d#outline?noScroll=1",link:"https://book.douban.com/subject/26314955/",tags:["创新思维","组织文化","企业管理"],desc:"皮克斯联合创始人艾德·卡特姆结合《玩具总动员》《机器人瓦力》等经典动画的幕后制作故事,深度揭示了皮克斯如何长期保持创意领先的秘密。本书不仅详述了皮克斯从初创到壮大的历程,更抽丝剥茧地解析了其在团队文化、跨部门协作、人才培养和允许失败等方面的独特创意管理机制,为各类组织提供了可复制的创新指南。",rating:4.5,highlights:["揭秘“皮克斯奇迹”背后的管理哲学:通过14部经典动画的真实幕后故事,展示创意从无到有、再到票房口碑双赢的全过程","深度解析创新土壤的搭建:阐述如何通过允许失败的文化、流程设计和激励机制,将“不断推动创新”彻底融入公司DNA","提供跨行业可复用的管理工具:总结项目立项、跨部门协作与风险控制的具体做法,为不同规模和行业的企业提供落地的实战模板"]},{id:"book-017",title:"重来:更为简单的商业思维",author:"贾森·弗里德 / 戴维·海涅迈尔·汉森",cover:"https://cdn.weread.qq.com/weread/cover/1/YueWen_635904/t6_YueWen_635904.jpg",wereadLink:"https://weread.qq.com/web/reader/0363228059b4000363b29e9#outline?noScroll=1",link:"https://book.douban.com/subject/5320866/",tags:["商业思维","创业","企业管理","极简主义"],desc:"37signals联合创始人基于十年创业实战经验,写给职场人与创业者的极简商业法则。本书摒弃了传统的MBA术语与复杂的商业教条,以“辛辣、直接、靠谱”的语言,颠覆了关于项目管理、人才招聘、产品设计与企业文化的常规认知,教导读者如何在真实的商业世界中“做更少,但创造更多价值”。",rating:4.3,highlights:["颠覆传统的极简商业哲学:反叛复杂的商业教条,主张“做更少,创造更多”,通过最小可行步骤降低试错成本并快速迭代","源自37signals的十年实战精髓:覆盖从项目管理、产品设计到市场营销的完整链条,提供不讲废话、拿来即用的行动指南","重塑职场与团队管理的认知:提出诸多务实且反常规的观点(如严苛的简历筛选标准),打造基于信任与结果导向的高效团队","适用面极广的实操手册:无论是寻求突破的精英企业家、小团队创业者,还是渴望提升工作效率的普通职场人,都能直接对照落地"]},{id:"book-018",title:"重来2:更为简单高效的远程工作方式",author:"贾森·弗里德 / 戴维·海涅迈尔·汉森",cover:"https://cdn.weread.qq.com/weread/cover/38/YueWen_635721/t6_YueWen_635721.jpg",wereadLink:"https://weread.qq.com/web/reader/46b3220059b34946b517012#outline?noScroll=1",link:"https://book.douban.com/subject/25861795/",tags:["企业管理","远程工作","工作方式","团队协作"],desc:"Basecamp(原37signals)创始人基于自身团队多年的全球分布式协作经验,为企业和个人提供的一套远程工作“思想升级包”。本书直面行业争议,破解了“创新只能面对面”及“文化会淡化”等常见误区,并系统提供了借助异步沟通、协作工具与流程设计来打造高效、人性化远程团队的实战指南。",rating:4.1,highlights:["提供思想层面的“升级包”:直击传统办公室痛点,用真实数据与反例打破关于远程办公的固有认知误区","第一手的分布式团队管理经验:Basecamp创始人亲授,展示如何突破地域限制招募顶尖人才,并保持健康、高效的工作节奏","系统可落地的工具与流程方法:详述如何利用协作工具降低管理成本,让远程工作从“特殊福利”真正转变为可持续的主流组织模式"]},{id:"book-019",title:"重来3:做得更少,但赚得更多",author:"贾森·弗里德 / 戴维·海涅迈尔·汉森",cover:"https://cdn.weread.qq.com/weread/cover/62/cpplatform_tqth8pnlq8h9ing5uciwhi/t6_cpplatform_tqth8pnlq8h9ing5uciwhi1748502715.jpg",wereadLink:"https://weread.qq.com/web/reader/b6a32ed0813ab9fb5g015181#outline?noScroll=1",link:"https://book.douban.com/subject/37367276/",tags:["工作方式","反内卷","企业文化"],desc:"Basecamp创始人带来的“反内卷”与“反过度忙碌”的管理指南。作者基于近20年带领54人团队服务全球10万家企业的成功经验,直击现代企业盲目扩张、无效加班等八大症结。全书主张以“冷静”颠覆“忙碌”文化,指导企业和个人通过40小时工作制、拒绝KPI和异步沟通等极简方式,在不牺牲生活质量的前提下实现健康发展与持续盈利。",rating:4.2,highlights:["以“冷静”颠覆“忙碌”文化:倡导高效比高产更重要,用稳定的节奏替代疯狂加班的内卷常态","直击现代企业八大症结:深度诊断快速扩张、无效加班、会议泛滥与目标绑架等痛点,提供对症下药的思路","提供四大可落地的管理工具:引入40小时工作制、拒绝硬性KPI、推行非实时沟通,坚持利润优先于规模","源自Basecamp的真实反向案例:展示“小而美”团队如何通过“少做但做好”的策略,跑赢新经济并保持高利润"]}],Ye=[{id:"book-024",title:"要事第一",author:"史蒂芬·柯维 / 罗杰·梅里尔 / 丽贝卡·梅里尔",cover:"https://cdn.weread.qq.com/weread/cover/57/yuewen_33091834/t6_yuewen_330918341686208943.jpg",wereadLink:"https://weread.qq.com/web/reader/f523268071f8f0faf52b806#outline?noScroll=1",link:"https://book.douban.com/subject/1028372/",tags:["时间管理","自我管理","经典思维"],desc:"作为《高效能人士的七个习惯》的延伸与加强版,本书提出了颠覆传统的“第四代时间管理”方法。作者强调,比提升做事速度(时钟)更重要的是找准人生的方向(罗盘)。全书指导读者通过自我意识的觉醒,以原则和价值观为中心,将精力聚焦于“重要而不紧急”的长期目标上,从而在繁忙的现代生活中真正做到“要事第一”。",rating:4.5,highlights:["从“时钟”到“罗盘”的思维跨越:打破一味追求“更快、更努力”的传统效率迷思,确立人生方向优先的哲学","经典的四象限时间管理矩阵:引导读者跳出紧急事务的“救火圈”,将核心精力倾注于第二象限(重要但不紧急)的高价值事务中","生动的“大石块”优先法则:通过“先放石头再倒水”的直观比喻,确保关键目标与核心使命在碎片化日程中得到绝对的优先落实","以原则为中心的自我驱动框架:不仅提供日程安排工具,更通过唤醒良知,帮助读者在工作、家庭等多元角色中实现真正的平衡与统合综效"]},{id:"book-025",title:"清单革命",author:"阿图·葛文德",cover:"https://cdn.weread.qq.com/weread/cover/12/cpPlatform_rudGZN3LDW5m9FBYr7rMBA/t6_cpPlatform_rudGZN3LDW5m9FBYr7rMBA.jpg",wereadLink:"https://weread.qq.com/web/reader/18332f80813ab7292g010065#outline?noScroll=1",link:"https://book.douban.com/subject/27168564/",tags:["管理学","认知科学","工作效率"],desc:"这是一部针对现代复杂世界所撰写的“认知防护手册”。作者阿图·葛文德通过医疗、建筑、投资等高风险领域的真实案例,揭示了人类在海量信息与高压环境下极易出现的判断疏忽。书中提出了“权力下放、简单至上、人为根本、持续改善”四大原则,指导读者将最佳实践外化为可操作的清单,从而在复杂系统中构建一道低成本、高回报的安全防线。",rating:4.6,highlights:["直面复杂时代的认知瓶颈:揭示在海量信息流中,清单如何作为“认知防护网”弥补人类记忆力与注意力分配的先天不足","提供兼具理念与落地的四大原则:通过“权力下放、简单至上、人为根本、持续改善”,构建一套可复用的清单设计哲学","扎实的医学实证背书:以手术感染率骤降等真实临床数据为支撑,证明清单思维在医疗、建筑、投资等高风险领域的跨行业普适性","简洁而具力量的流程创新:强调清单服务于人而非取代人,是帮助专业人士在高压环境下将复杂环节显性化、流程化的必备工具"]},{id:"book-020",title:"别让猴子跳回背上",author:"威廉·安肯三世",cover:"https://cdn.weread.qq.com/weread/cover/69/cpPlatform_7fFoBQ7dtqgABGSTskpJSN/t6_cpPlatform_7fFoBQ7dtqgABGSTskpJSN.jpg",wereadLink:"https://weread.qq.com/web/reader/9fc32010813ab7291g0196bd#outline?noScroll=1",link:"https://book.douban.com/subject/36103994/",tags:["时间管理","领导力","项目管理"],desc:"这是一部以“猴子”生动隐喻任务与责任的经典管理学著作。作者威廉·安肯三世深刻剖析了管理者常被琐事淹没的时间困境,并提出系统化的“猴子管理法”。通过明确任务归属、责任递减与有效授权,指导管理者如何把不属于自己的“猴子”交出去,从而释放精力专注于最高价值的战略思考,实现团队与个人的共同成长。",rating:4.3,highlights:["生动有趣的“猴子”隐喻:将枯燥的责任划分与任务流转具象化,直击职场中“忙碌却低效”的痛点","实用高效的“三步交接”法则:通过明确期望、授予资源与约定检查点,彻底避免下属的待办任务重新跳回自己背上","重塑时间管理与人才培养体系:指导高层放权、中层辅导、基层自发,将企业的成功真正建立在员工自主性的提升之上"]}],$e=[{id:"book-022",title:"学会提问(原书第12版)",author:"尼尔·布朗 / 斯图尔特·基利",cover:"https://cdn.weread.qq.com/weread/cover/68/YueWen_39980443/t6_YueWen_39980443.jpg",wereadLink:"https://weread.qq.com/web/reader/e6832d3072620d9be68aabf#outline?noScroll=1",link:"https://book.douban.com/subject/35513147/",tags:["批判性思维","逻辑学","认知科学","经典书"],desc:"这是一部培养批判性思维的经典实战指南。作者尼尔·布朗与斯图尔特·基利结合长期的教学与研究实践,提供了一套系统化、可操作的提问流程。全书通过大量真实情境案例,教导读者如何在信息泛滥的时代识别隐含假设、区分事实与观点,用高质量的“判断性问题”看透事物本质,从而做出更理性的决策。",rating:5,highlights:["聚焦批判性思考的核心能力:系统拆解“如何提出好问题”的思维过程,帮助读者在复杂信息中迅速抓住本质","提供可落地的提问与评估框架:从背景信息、关键概念到逻辑推理,构建一条完整的判断性问题链条","丰富的真实场景应用示范:结合课堂讨论、写作、日常沟通与职场决策等多元场景,让理论能“立即上手”","打造实用的思考检查单:不仅讲透“提问的价值”,更提供可直接转化为日常习惯的思维检查表,助你有效避开认知陷阱"]},{id:"book-026",title:"如何阅读一本书",author:"莫提默·J. 艾德勒 / 查尔斯·范多伦",cover:"https://wfqqreader-1252317822.image.myqcloud.com/cover/810/23723810/t6_23723810.jpg",wereadLink:"https://weread.qq.com/book-detail?type=1&senderVid=40710128&v=272326407169ff22272934f&wtheme=white&wfrom=app&wvid=40710128&scene=bottomSheetShare",link:"https://book.douban.com/subject/1013208/",tags:["阅读方法","思维训练","经典"],desc:"阅读领域的“元方法”指南。作者艾德勒与范多伦将阅读划分为基础阅读、检视阅读、分析阅读与主题阅读四个进阶层次,并强调阅读是一项主动的思考活动。本书不仅提供了从“快速略读”到“系统拆解论点”的实操技巧,更致力于通过提问、归纳与批判,将阅读转化为训练理解力、批判力与终身学习的终极工具。",rating:5,highlights:["构建系统的四级阅读框架:从检视阅读到分析阅读再到主题阅读,为读者提供了一套从入门到精通的进阶路径","强调“主动与批判”的阅读观:拒绝被动接收,教导读者如何通过提问、归纳与反思,真正将作者的洞见转化为自己的认知","高效的检视阅读技巧:提供如何在有限时间内通过看目录、挑重点等方式,快速筛选并判断书目价值的核心能力","跨时代的经典效能:自1940年问世以来长盛不衰,其对逻辑拆解与深度思考的指导,是提升所有知识吸收效率的“总开关”"]},{id:"book-023",title:"检索力:打破信息差的科学方法",author:"龚芙蓉",cover:"https://cdn.weread.qq.com/weread/cover/58/cpplatform_feaxemubry47bnkzylqzwv/t6_cpplatform_feaxemubry47bnkzylqzwv1716796541.jpg",wereadLink:"https://weread.qq.com/web/reader/9de32810813ab8e00g018130#outline?noScroll=1",link:"https://book.douban.com/subject/36899979/",tags:["信息素养","检索能力","思维认知"],desc:"本书聚焦“检索力”这一核心技能,旨在帮助读者在信息过载的时代主动掌握“逆风而行”的搜索能力。作者龚芙蓉结合二十余年实践经验,用生动的人文与诺贝尔奖级科学案例,将枯燥的检索工具化为有趣的故事。不仅教授非线性、迭代式的搜索技巧,更致力于重塑读者的探究精神,赋予其走出“信息茧房”的勇气。",rating:4.2,highlights:["丰富的跨学科趣味案例驱动:用“张冠李戴的马克思名言”等生动故事,将枯燥繁琐的检索步骤转化为轻松的探索之旅","重塑非线性与迭代的搜索思维:打破按部就班的线性流程误区,建立以耐心与热情驱动的多轮迭代搜索心态","直击科研与职场的实用痛点:提供可快速落地的实操指南,帮助读者切实缩短科研周期、大幅提升工作效率","兼顾技能训练与人文底色:在教授如何利用和创造信息的同时,注重培养读者的信息素养与打破信息差的认知勇气"]},{id:"book-027",title:"原则",author:"瑞·达利欧",cover:"https://cdn.weread.qq.com/weread/cover/23/YueWen_921568/t6_YueWen_921568.jpg",wereadLink:"https://weread.qq.com/web/reader/848324405e0fe08483ab6a4#outline?noScroll=1",link:"https://book.douban.com/subject/27608239/",tags:["投资","方法论","自我管理"],desc:"桥水基金创始人瑞·达利欧总结四十余年投资、管理与人生经验的集大成之作。作者提出将生活和工作像机器一样系统化,确立了“极度求真”与“极度透明”两大基石,并通过“创意择优”与“基于可信度的决策机制”来迭代思维。书中包含500多条可操作原则,旨在帮助读者在复杂世界中保持开放心态、看清现实,并做出最优决策。",rating:4.8,highlights:["“极度求真”与“极度透明”的基石:主张诚实面对现实,通过公开决策过程来获取外部反馈,达成高效协作","创意择优与可信度加权机制:摒弃个人权威,利用数据驱动的讨论与可信度权重,在团队中选出最优方案","500余条可落地的原则清单:涵盖自我认知、投资决策、团队治理等场景,构建出一套随时可查的行动指南","系统化的“机器”思维:将生活与组织管理拆解为可维护、可迭代的系统,有效规避情绪化干扰"]},{id:"book-031",title:"价值",author:"张磊",cover:"https://wfqqreader-1252317822.image.myqcloud.com/cover/958/33577958/t6_33577958.jpg",wereadLink:"https://weread.qq.com/web/reader/5be32a3072005be65bef195#outline?noScroll=1",link:"https://book.douban.com/subject/35188914/",tags:["价值投资","商业思维","创业"],desc:"高瓴资本创始人张磊首部个人及投资思想著作。全书通过回顾作者的个人求学与创业历程,系统阐释了“长期主义”与“重仓中国”的核心投资理念,并首次披露了高瓴投资的七大公式。作者将十余个典型投资案例与个人价值修养相结合,揭示了如何在不确定的商业环境中,通过坚持原则、敬畏规则与持续创新,创造长久、真实的价值。",rating:4.6,highlights:["系统构建长期主义哲学:首次系统化梳理“高瓴七大公式”,为读者提供从认知、决策到执行的价值投资实战模型","深度复盘经典实战案例:通过腾讯、货拉拉等真实商业案例,拆解如何在复杂市场中识别企业护城河与核心价值","投资之外的人文思考:延伸至教育、人才与科学观,展现作者作为顶尖投资者对社会责任与长期价值创造的深度思考","可视化的阅读体验:精选多幅手绘彩插与历史影像,将深刻的投资逻辑与企业成长叙事变得更加生动、直观"]},{id:"book-032",title:"纳瓦尔宝典",author:"埃里克·乔根森 / 纳瓦尔·拉维坎特",cover:"https://cdn.weread.qq.com/weread/cover/89/YueWen_44026191/t6_YueWen_44026191.jpg",wereadLink:"https://weread.qq.com/web/reader/e1e32b00729fc94fe1e824d#outline?noScroll=1",link:"https://book.douban.com/subject/35876121/",tags:["财富管理","个人成长","幸福哲学","思维认知"],desc:"这是一部汇集硅谷著名投资人纳瓦尔·拉维坎特过去十年关于财富与幸福思考的行动指南。全书摒弃了“致富靠运气”的传统观念,提出积累财富与幸福生活是可以通过学习掌握的技能。通过系统整理推特、播客与访谈中的智慧,本书为读者提供了如何在快速变化的科技与经济环境中,利用杠杆、发挥个人独特性,进而实现财务自由并获得持久内心满足的方法论。",rating:4.7,highlights:["将财富与幸福视为可习得的技能:打破运气论,强调通过建立杠杆、发挥个人独特性来获取非线性的回报","十年思想的系统化编纂:将碎片化的互联网智慧提炼为成体系的方法论,打造了数字时代个人的“行动指南”","兼顾财富积累与内心满足:不仅教导如何高效赚钱,更深入探讨如何通过阅读、冥想与长期主义,在职场成功中寻找内心的宁静","极具实操性的工具箱:提供如深度思考、刻意练习、构建个人品牌等具体路径,帮助读者在碎片化时代快速实现自我迭代"]},{id:"book-028",title:"优秀的绵羊",author:"威廉·德雷谢维奇",cover:"https://cdn.weread.qq.com/weread/cover/78/cpplatform_3ncoeekcuaectlzj9hf5nr/t6_cpplatform_3ncoeekcuaectlzj9hf5nr1744626569.jpg",wereadLink:"https://weread.qq.com/web/reader/1c0324c0813ab9d91g010aba#outline?noScroll=1",link:"https://book.douban.com/subject/26747208/",tags:["博雅教育","社会学","个人成长"],desc:"耶鲁大学前教授威廉·德雷谢维奇对美国常春藤精英教育体制的尖锐批判之作。作者通过二十余年的教学观察,指出顶尖学府培养出一群虽然聪明、优秀,但普遍焦虑、缺乏目标感且唯命是从的“优秀绵羊”。本书呼吁社会重新审视教育的本质,摆脱对名校与高薪的盲目崇拜,回归博雅教育,鼓励学生探索内在驱动力与自我价值。",rating:4.2,highlights:["犀利剖析精英教育弊端:直击常春藤体制培养出“聪明但没有灵魂”的学生的现实,反思唯名校与成绩论的单一评价体系","回归博雅教育的核心价值:批判应试化倾向,提倡给予学生更多探索、失败与重塑自我的空间,强调教育的本质在于帮助个体找到自我","提供挣脱外部期待的认知框架:既为迷茫的年轻人指明如何重建内在动力,也给家长和教育者敲响了关于“成功定义”的警钟","跨文化背景下的教育共鸣:尽管以美国精英教育为例,其对“教育内卷”与“缺乏目标感”的批判,引发了全球高压教育环境下的深层共鸣"]},{id:"book-029",title:"把自己变成稀缺资产",author:"何思平",cover:"https://cdn.weread.qq.com/weread/cover/98/cpplatform_ncqzerh3wdywn9mlc9cjna/t6_cpplatform_ncqzerh3wdywn9mlc9cjna1694085413.jpg",wereadLink:"https://weread.qq.com/web/reader/2fe326f0813ab821fg0146df#outline?noScroll=1",link:"https://book.douban.com/subject/36513648/",tags:["个人成长","思维认知","自我管理","投资理财"],desc:"这是一个将“人生”视作“公司”来经营的实战指南。作者何思平结合自身从严重口吃到演讲冠军、再到连续创业成功的跨越式经历,提出了“人生有限公司”的经营哲学。全书通过“生命立方体”模型,从认知、实践、精力管理三个维度拆解了如何通过持续输出与跨界学习,将自己打造为具有高壁垒、不可替代的“稀缺资产”。",rating:4.2,highlights:["提出“人生有限公司”经营哲学:倡导将自己视作最值得投资的上市公司,通过不断提升认知与能力壁垒,把“人生”经营成稀缺资产","系统化的“生命立方体”模型:从认知、实践、精力管理三个维度构建个人成长闭环,解决成长中的无序感与碎片化难题","聚焦个人核心竞争力:深度拆解认知力、学习力与共情力等稀缺能力的获取路径,教导读者在不同场景中通过实战验证自我价值","高度可操作的工具清单:摒弃鸡汤式说教,将自我成长拆解为具体的习惯改造与复盘清单,帮助读者在痛点与高光时刻都能通过反馈机制实现自我迭代"]},{id:"book-030",title:"成长第二曲线:跨越S型持续成长",author:"查尔斯·汉迪",cover:"https://cdn.weread.qq.com/weread/cover/65/YueWen_39427437/t6_YueWen_39427437.jpg",wereadLink:"https://weread.qq.com/web/reader/15d32ed072599d6d15daa86#outline?noScroll=1",link:"https://book.douban.com/subject/35531368/",tags:["管理学","个人成长","人生哲学","未来趋势"],desc:"管理大师查尔斯·汉迪的“人生长跑指南”。本书通过书信体形式,深度探讨了在数字时代背景下个人如何识别并跨越“第二曲线”。汉迪指出,无论组织还是个人,都受制于S型增长曲线,只有在第一曲线衰退前主动布局新的增长点,并保持内在价值的独立与进化,才能在不断变化的环境中获得持续且有意义的成长。",rating:4.5,highlights:["百岁管理大师的人生体悟:以书信体浓缩一生管理研究与个人经验,提供了从时间维度审视工作、学习与生活的全景视角","“第二曲线”理论的全面进阶:深刻揭示组织与个人的兴衰规律,教导读者如何在第一曲线的巅峰前就主动布局新的增长引擎","全场景下的持续进化方案:将第二曲线思维跨界应用于教育、职业规划、婚姻与家庭中,强调“变化才是常态”,鼓励持续自我重塑","面向Z世代的清醒处方:在科技高歌猛进的数字时代,提醒后人重视诚信、协作等软实力,保持独立判断,避免在算法与焦虑中迷失自我"]}],Me=[{id:"book-033",title:"枪炮、病菌与钢铁",author:"贾雷德·戴蒙德",cover:"https://cdn.weread.qq.com/weread/cover/99/YueWen_42766048/t6_YueWen_42766048.jpg",wereadLink:"https://weread.qq.com/web/reader/843329f0728c8ee08434fb1#outline?noScroll=1",link:"https://book.douban.com/subject/1813841/",tags:["人类历史","地理决定论","社会学","跨学科"],desc:"一部重新定义人类历史发展的宏大著作。作者贾雷德·戴蒙德通过生物学、地理学、人类学等多学科交叉视角,强有力地反驳了“种族决定论”和“西方文明优越论”。他提出,决定文明兴衰的关键并非种族,而是环境因素、地理格局以及动植物驯化的差异,这些自然条件的偶然性最终导致了技术、免疫力和权力结构的差异,从而重塑了现代世界的全球版图。",rating:4.8,highlights:["颠覆性的历史观:以环境与地理差异解释文明兴衰,有力冲击了长期流行的西方文明优越论,提供了理解人类历史的全新视角","跨学科的综合研究框架:巧妙融合生物学、地理学、历史学、社会学等多学科知识,重建人类文明演进的逻辑路径","系统揭示历史演变的机制:深入剖析农业、病菌传播与技术权力如何形成相互强化的循环,展示了文明发展背后复杂的资源互动","具备公共思想者的宏观视野:将严谨的科学研究转化为对人类命运与社会发展的深刻反思,为现代人理解自身在历史长河中的位置提供了绝佳参照"]},{id:"book-034",title:"中国社会各阶层分析",author:"梁晓声",cover:"https://cdn.weread.qq.com/weread/cover/0/yuewen_42682684/t6_yuewen_426826841728383400.jpg",wereadLink:"https://weread.qq.com/web/reader/085326e0728b493c085ade1#outline?noScroll=1",link:"https://book.douban.com/subject/35485315/",tags:["社会观察","阶层研究","现实主义"],desc:"茅盾文学奖得主梁晓声基于多年社会观察的现实题材力作。作者将快速变迁的中国社会划分为不同阶层,以平民视角细腻描摹各群体的生存状态、心理困境与阶层焦虑。全书不追求纯学术的枯燥分析,而是通过文学化的社会观察,勾勒出一幅当代中国社会的“浮世绘”,引导读者在时代坐标中找准定位,理解社会变迁背后的结构性逻辑。",rating:4.3,highlights:["平民视角下的社会“浮世绘”:通过细腻的笔触勾勒各阶层的生存逻辑与心理画像,帮助读者直观理解宏观社会结构","兼具现实痛点与精神深度:不仅呈现物质生活的差异,更深刻剖析阶层焦虑背后的价值困境,为理解当代社会提供人文参照","时代脉络中的命运书写:将个体命运置于历史事件的宏观背景中考察,展现了半个世纪以来社会变迁的深层脉络","文学笔触下的社会关怀:作为茅盾文学奖得主,作者通过富有故事性的叙事,既保留了批判性,又让文本充满了温暖的人文温度"]},{id:"book-021",title:"把自己作为方法",author:"项飙 / 吴琦",cover:"https://cdn.weread.qq.com/weread/cover/81/cpPlatform_3300003962/t6_cpPlatform_3300003962.jpg",wereadLink:"https://weread.qq.com/web/reader/d7532f80813ab680cg012708#outline?noScroll=1",link:"https://book.douban.com/subject/35092383/",tags:["社会学","访谈录","思想方法"],desc:"两代学人项飙与吴琦历时三年、跨越五地的深度对话实录。本书从项飙的个人经验切入,探讨了中国社会近半个世纪的变迁、全球化与民粹主义等宏大议题。在自我泛滥与思想受困的时代,作者提出“把自己作为方法”,指导读者如何在全球化年代重新定位自我、重建“附近”,并在个人体验与宏观叙事之间搭建起思考与行动的桥梁。",rating:4.6,highlights:["以“自我”切入回应宏大议题:示范如何在个人真实体验与全球化、社会变迁等宏观叙事之间搭建认知的桥梁","提供重建“附近”的行动指南:在自我泛滥的潮流中,指导读者如何审视现实,创造性地建设身边的小世界","兼具学术深度与极高可读性:将人类学、社会学的深刻理论洞察,巧妙融入生动的田野故事与双人生活化对谈中","跨越三年的思想碰撞:历时三年、跨越五地的持续对话结集,反思知识生产与公共讨论的真实处境"]}],Te=[{id:"book-035",title:"百岁人生:长寿时代的生活和工作",author:"琳达·格拉顿 / 安德鲁·斯科特",cover:"https://wfqqreader-1252317822.image.myqcloud.com/cover/860/22902860/t6_22902860.jpg",wereadLink:"https://weread.qq.com/web/reader/30c323e0715d784c30c1e1b#outline?noScroll=1",link:"https://book.douban.com/subject/30245089/",tags:["人生规划","长寿时代","社会学"],desc:"基于伦敦商学院的经典课程,作者琳达·格拉顿与安德鲁·斯科特提出,面对一半概率活到100岁的长寿时代,传统的“学习-工作-退休”三段式人生模式已彻底失效。本书指导读者如何重新设计人生,通过拥抱多阶段人生模型,在更长的生命周期中平衡工作、学习与休闲,并强调在财务资产之外,更要注重健康、友谊与知识等“无形资产”的持续投入与增值。",rating:4.3,highlights:["重构人生模式:打破传统的“三段式”生活范式,提出充满弹性的“多阶段人生”模型,让工作与学习不再是线性的重复","从关注财务到“无形资产”:除了养老金,强调健康、友谊、社交网络与心理韧性等“无形资产”才是维持长寿生活质量的核心动力","职场与转型的系统规划:提供针对长寿时代的职业设计思路,涵盖何时转型、如何投资自身、怎样应对不确定性等实战框架","社会与制度的深度洞察:探讨长寿如何冲击养老金体系、劳动力市场与企业模式,帮助个人在宏观变革中把握主动权"]},{id:"book-00043",title:"重启吧!我的健康人生",author:"兰根·查特吉",cover:"https://cdn.weread.qq.com/weread/cover/80/cpplatform_kbrswv3bm7cix2zlyo6wtx/t6_cpplatform_kbrswv3bm7cix2zlyo6wtx1716362285.jpg",wereadLink:"https://weread.qq.com/web/reader/e8a32e80813ab8de4g0191c2#outline?noScroll=1",link:"https://book.douban.com/subject/36899697/",tags:["生活方式","预防医学","身心健康","自我管理"],desc:"英国临床医生基于20多年行医经验写就。本书主张“生活方式即良药”,围绕休息、饮食、运动和睡眠四个领域设计了20个微小行动计划,帮助现代人通过低成本的习惯改变逆转慢性问题。",rating:4.6,highlights:["提出99%的健康取决于日常习惯而非医学治疗,强调整体干预","构建“4×5”微行动框架,涵盖休息、饮食、运动、睡眠四个维度的20个小改变","兼顾科学深度与极简实操,如“12小时进食窗口”、“10分钟高强度运动”","关注现代职场人痛点,提供“小投入、大回报”的可叠加身心健康投资策略"]},{id:"book-00040",title:"你是你吃出来的:吃对少生病,病了这样吃",author:"夏萌",cover:"https://cdn.weread.qq.com/weread/cover/86/YueWen_920661/t6_YueWen_920661.jpg",wereadLink:"https://weread.qq.com/web/reader/7bb32c305e0c557bbdeab81#outline?noScroll=1",link:"https://book.douban.com/subject/27590675/",tags:["饮食科普","营养学","健康管理"],desc:"前安贞医院营养科主任夏萌结合十余年临床经验写成。本书颠覆“低油低脂”误区,提出回归进化的“65%植物+35%动物”膳食配比,并针对14种常见慢病给出“四分法”饮食干预方案,帮助读者重建健康饮食观。",rating:5,highlights:["指出多数慢病源于“蛋白质缺乏式营养不良”,打破常规低油低脂迷思","提出清晰量化的“65%植物类+35%动物类”科学饮食结构","针对冠心病、高血压等14种常见慢病提供实操性极强的“四分法”菜单","源于十万+真实临床病例,强调“一日三餐才是真正的保健品”"]},{id:"book-00041",title:"你是你吃出来的2",author:"夏萌",cover:"https://wfqqreader-1252317822.image.myqcloud.com/cover/883/35905883/t6_35905883.jpg",wereadLink:"https://weread.qq.com/web/reader/40532d007223e15b4052fae#outline?noScroll=1",link:"https://book.douban.com/subject/35340053/",tags:["饮食指导","科普","疾病防治"],desc:"聚焦高血压、高脂血症、糖尿病等7大常见慢病,从临床营养医学角度逐一破除诸如“血压高不能吃肉”等饮食误区,提供系统的“上游-中游-下游”疾病防控思路与个体化营养处方。",rating:4.6,highlights:["专攻7大常见慢性病,为患者提供针对性的“生病了怎么吃”个体化指导","科学辟谣,破除“血压高不能吃肉”、“胆固醇高不能吃鸡蛋”等常见误区","梳理疾病发生因果链条,帮助读者从源头找到健康干预的着力点","提供从一日三餐、运动到心态调养的具体可操作生活方式清单"]}],Ge=JSON.parse('{"title":"好书推荐","description":"读书心得、推荐书籍和阅读技巧","frontmatter":{"title":"好书推荐","date":"2024-01-01T16:00:00.000Z","description":"读书心得、推荐书籍和阅读技巧","categories":["growth"],"coverImg":"https://insight-stack-1252300811.cos.ap-shanghai.myqcloud.com/img/cover/books_reading_bg.png","permalink":"/growth/books","tags":["悦读时光","资源推荐"]},"headers":[],"relativePath":"growth/books.md","filePath":"30.悦读时光/01.好书推荐.md"}'),Ne={name:"growth/books.md"},De=Object.assign(Ne,{setup(n){return(b,t)=>(a(),r("div",null,[t[0]||(t[0]=e("h1",{id:"好书推荐",tabindex:"-1"},[l("好书推荐 "),e("a",{class:"header-anchor",href:"#好书推荐","aria-label":"Permalink to “好书推荐”"},"​")],-1)),t[1]||(t[1]=e("h2",{id:"_1-ai-与数学思维",tabindex:"-1"},[l("1. AI 与数学思维 "),e("a",{class:"header-anchor",href:"#_1-ai-与数学思维","aria-label":"Permalink to “1. AI 与数学思维”"},"​")],-1)),t[2]||(t[2]=e("blockquote",null,[e("p",null,[l("在大模型发展日新月异的今天,理解 AI 本质上是在升级我们资深的“认知操作系统”, "),e("strong",null,"理解 AI,本质上是理解数据、数学与逻辑如何重构这个世界"),l("。")]),e("p",null,"这套书单从数学思维的底层逻辑出发,让我们理解 ChatGPT 等大模型背后的计算机制,将硬核的神经网络与概率统计转化为优化生活的决策工具。它不仅能界定机器智能的边界,更颠覆了传统的“目标论”,倡导在不确定性中通过“踏脚石”思维寻找突破性创新的可能。AI 的研究实践告诉我们,伟大的突破往往无法被预设,唯有拥抱“寻宝者思维”才能在未知中偶遇奇迹,我们需要颠覆传统的创新范式。")],-1)),h(k,{books:g(Be)},null,8,["books"]),t[3]||(t[3]=M('

    2. 产品与商业

    about site background

    2.1 产品 Sense 与创造

    在产品成功率不足 10% 的残酷市场中,好的创造绝非源于盲目的灵感,而是建立在极致的风险验证与深刻的人性洞察之上。

    卓越的产品力不仅关乎功能设计,更是一场关于策略与创造力的刻意练习:我们需要通过“预型”思维以极低成本进行真实数据验证,确保我们在投入开发前是在“做对产品”;并利用用户模型、交易模型等底层框架,将零散的需求转化为可获利的商业方案。

    ',4)),h(k,{books:g(Ie)},null,8,["books"]),t[4]||(t[4]=e("h3",{id:"_2-2-商业化",tabindex:"-1"},[l("2.2 商业化 "),e("a",{class:"header-anchor",href:"#_2-2-商业化","aria-label":"Permalink to “2.2 商业化”"},"​")],-1)),t[5]||(t[5]=e("blockquote",null,[e("p",null,[l("在追逐“独角兽”和规模扩张的狂热迷思之后,真正的商业高手正在重新回归本质:"),e("strong",null,"盈利才是企业的核心护城河。"),l(" 这套书单为我们揭示了一种"),e("strong",null,"更具韧性的商业路径——“小而美”的极简经营"),l("。它教导我们如何拒绝低效的内卷与忙碌,通过“做更少但创造更多价值”的思维,打造在不确定时代下依然能保持稳定现金流的“慢公司”。")]),e("p",null,[e("strong",null,"商业的成功,往往源于敢于挑战“难而正确”的事"),l("。从皮克斯如何建立允许失败的创意土壤,到 Waze 如何通过解决被忽视的痛点实现跨越式成长,这些世界级案例证明了:卓越的组织不仅需要极简的流程与高效的分布式协作(远程办公),更需要一种“冷静”的文化,将利润置于规模之上。")])],-1)),h(k,{books:g(We)},null,8,["books"]),t[6]||(t[6]=e("h2",{id:"_3-效率与效能",tabindex:"-1"},[l("3. 效率与效能 "),e("a",{class:"header-anchor",href:"#_3-效率与效能","aria-label":"Permalink to “3. 效率与效能”"},"​")],-1)),t[7]||(t[7]=e("blockquote",null,[e("p",null,[l("在信息过载与高压竞争的现代环境中,平庸与卓越的分水岭不再是做事的速度,而是"),e("strong",null,"决策的精度与责任的边界"),l("。这套书单为我们提供了一套从个人认知到组织协作的“效能防线”:首先,它"),e("strong",null,"引导我们完成从“时钟”到“罗盘”的思维跨越,打破盲目追求速度的迷思,确保将核心精力倾注在真正产生长远复利的“重要非紧急”事务之上"),l("。 真正的效能源于对复杂性的科学驾驭:")]),e("ul",null,[e("li",null,"通过“清单革命”式的认知防护,我们将最佳实践外化为可靠的防错系统,弥补人类在极端环境下的认知局限;"),e("li",null,"“猴子管理法”则以生动的视角重塑了职场协作的责任逻辑,教我们通过有效授权拒绝无谓的干扰,释放战略思考的精力;")])],-1)),h(k,{books:g(Ye)},null,8,["books"]),t[8]||(t[8]=e("h2",{id:"_4-学习与成长",tabindex:"-1"},[l("4. 学习与成长 "),e("a",{class:"header-anchor",href:"#_4-学习与成长","aria-label":"Permalink to “4. 学习与成长”"},"​")],-1)),t[9]||(t[9]=e("blockquote",null,[e("p",null,[l("在信息爆炸与快速变革的时代,"),e("strong",null,"真正的成长不再是知识的被动堆砌,而是认知系统的彻底迭代"),l("。这套书单为我们构建了一个从底层思维到人生经营的闭环:")]),e("ul",null,[e("li",null,"首先,通过批判性思维与深度阅读夯实“元能力”,在泛滥的信息中识别本质,将他人的洞见转化为自己的血肉;"),e("li",null,"其次,利用“检索力”打破信息差,确保自己在任何领域都能快速获取高质量资源,掌握逆风而行的主动权。")]),e("p",null,[e("strong",null,"人生不是一场盲目的长跑,而是一场基于“原则”的精密经营"),l("。从达利欧的系统化决策,到纳瓦尔的财富与幸福逻辑,这些智者教导我们如何利用杠杆、坚持长期主义,将自己视作一家“人生有限公司”来经营。我们需要摆脱“优秀绵羊”式的被动驱动,通过识别成长的“第二曲线”,在巅峰时刻主动寻求突破,将自己打造成不可替代的稀缺资产。阅读这些经典,不仅是为了习得技能,更是为了在算法与焦虑的夹击中,重塑内心的宁静与独立判断的勇气。")])],-1)),h(k,{books:g($e)},null,8,["books"]),t[10]||(t[10]=e("h2",{id:"_5-人文社科",tabindex:"-1"},[l("5. 人文社科 "),e("a",{class:"header-anchor",href:"#_5-人文社科","aria-label":"Permalink to “5. 人文社科”"},"​")],-1)),t[11]||(t[11]=e("blockquote",null,[e("p",null,"在宏观历史与微观现实间构建认知:在碎片化与不确定性并存的时代,穿透表象、直达本质的洞察力成为必需。这套单为我们开启了两扇窗:"),e("ul",null,[e("li",null,"一扇望向万年文明的宏大坐标,通过《枪炮、病菌与钢铁》的跨学科视野,拆解地理环境如何冷酷而偶然地重塑全球版图,彻底颠覆“文明优越论”的傲慢;"),e("li",null,"另一扇则照向当下社会的真实肌理,在梁晓声对各阶层生存困境的细腻描摹中,读懂大时代变革背后隐秘的结构性逻辑与阶层焦虑。")]),e("p",null,[e("strong",null,"人文思考的终极价值,在于如何将宏大叙事转化为个人的行动力量"),l("。正如项飙所倡导的“把自己作为方法”,这些著作不仅是知识的传递,更是思维的松绑。它们教导我们不再做时代的被动旁观者,而是学会在个人体验与宏观世界之间搭建桥梁,通过重建“附近”的小世界,在喧嚣中找准自我的定位。")])],-1)),h(k,{books:g(Me)},null,8,["books"]),t[12]||(t[12]=e("h2",{id:"_6-健康生活",tabindex:"-1"},[l("6. 健康生活 "),e("a",{class:"header-anchor",href:"#_6-健康生活","aria-label":"Permalink to “6. 健康生活”"},"​")],-1)),t[13]||(t[13]=e("img",{src:T,style:{width:"100%","border-radius":"8px","margin-bottom":"20px"},alt:"about site background"},null,-1)),t[14]||(t[14]=e("blockquote",null,[e("p",null,[l("在面临大概率活到100岁的“长寿时代”,传统的线性人生模式正在失效。我们需要对“健康”进行一次彻底的认知重构:"),e("strong",null,"健康不再仅仅是“没有疾病”,而是支撑我们跨越漫长生命周期、应对多阶段人生挑战的最核心“无形资产”"),l("。想要让这套生命系统长期平稳运行,真正的解法并不在医院的处方笺里,而是隐藏在我们每天的日常选择中。")]),e("p",null,[l("决定我们长期健康状态的,有 99 %取决于日常习惯。我们需要"),e("strong",null,"在休息、饮食、运动、睡眠这四个高频生活维度中,植入微小但杠杆率极高的改变"),l("(例如12小时进食窗口、10分钟高强度运动、睡前屏蔽数字通知等)。用最低的执行成本,置换身心状态的巨大回报。")])],-1)),h(k,{books:g(Te)},null,8,["books"])]))}});export{Ge as __pageData,De as default}; diff --git "a/assets/30.\346\202\246\350\257\273\346\227\266\345\205\211_01.\345\245\275\344\271\246\346\216\250\350\215\220.md.lGftAF4x.lean.js" b/assets/growth_books.md.B9CjQKY5.lean.js similarity index 83% rename from "assets/30.\346\202\246\350\257\273\346\227\266\345\205\211_01.\345\245\275\344\271\246\346\216\250\350\215\220.md.lGftAF4x.lean.js" rename to assets/growth_books.md.B9CjQKY5.lean.js index 0b444bff..a711ad85 100644 --- "a/assets/30.\346\202\246\350\257\273\346\227\266\345\205\211_01.\345\245\275\344\271\246\346\216\250\350\215\220.md.lGftAF4x.lean.js" +++ b/assets/growth_books.md.B9CjQKY5.lean.js @@ -1 +1 @@ -import{d as A,p as B,h as a,z as h,Y as I,s as W,g as l,y as _,v as P,i as e,W as v,x as c,F as p,t as f,S as n,T as Y,_ as C,r as j,c as T,k as M,U as x,l as g}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const $="/img/cover/health_bg.png",N={class:"book-panel__drawer"},V={class:"book-panel__header-meta"},G={class:"book-panel__title"},D={class:"book-panel__author"},F={class:"book-panel__body"},R={class:"book-panel__top-bar"},Z={class:"book-panel__top-left"},H={class:"book-panel__tags"},J={key:0,class:"book-panel__rating"},O={class:"stars"},E={key:0,viewBox:"0 0 24 24",fill:"currentColor"},K={key:1,viewBox:"0 0 24 24",class:"half-star"},Q=["id"],X=["clip-path"],U={key:2,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"1.5"},ee={class:"rating-text"},te={class:"book-panel__links"},oe=["href"],ae={width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",style:{"flex-shrink":"0"}},le=["href"],re={width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",style:{"flex-shrink":"0"}},ne={class:"book-panel__section"},se={class:"book-panel__desc"},ie={key:0,class:"book-panel__section"},de={class:"book-panel__highlights"},ce=A({__name:"BookDetailPanel",props:{book:{},open:{type:Boolean},heroColor:{},tagColors:{}},emits:["close"],setup(r,{emit:b}){const t=b;return(w,o)=>(a(),B(Y,{to:"body"},[h(I,{name:"panel-slide"},{default:W(()=>[r.open&&r.book?(a(),l("div",{key:0,class:"book-panel",onClick:o[2]||(o[2]=P(i=>t("close"),["self"]))},[e("div",{class:"book-panel__overlay",onClick:o[0]||(o[0]=i=>t("close"))}),e("div",N,[e("div",{class:"book-panel__header",style:v({background:r.heroColor})},[e("button",{class:"book-panel__close",title:"关闭",onClick:o[1]||(o[1]=i=>t("close"))},[...o[3]||(o[3]=[e("svg",{width:"14",height:"14",viewBox:"0 0 16 16",fill:"none"},[e("path",{d:"M12 4L4 12M4 4l8 8",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round"})],-1)])]),e("div",V,[e("h2",G,c(r.book.title),1),e("p",D,c(r.book.author),1)])],4),e("div",F,[e("div",R,[e("div",Z,[e("div",H,[(a(!0),l(p,null,f(r.book.tags,(i,m)=>(a(),l("span",{key:i,class:"book-panel__tag",style:v({background:r.tagColors[m%r.tagColors.length].bg,color:r.tagColors[m%r.tagColors.length].text})},c(i),5))),128))]),r.book.rating!=null?(a(),l("div",J,[o[8]||(o[8]=e("span",{class:"rating-label"},"推荐指数:",-1)),e("div",O,[(a(),l(p,null,f(5,i=>e("span",{key:i,class:"star"},[i<=Math.floor(r.book.rating)?(a(),l("svg",E,[...o[4]||(o[4]=[e("path",{d:"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"},null,-1)])])):i===Math.ceil(r.book.rating)&&r.book.rating%1!==0?(a(),l("svg",K,[e("defs",null,[e("clipPath",{id:"clip-"+r.book.id},[...o[5]||(o[5]=[e("rect",{x:"0",y:"0",width:"12",height:"24"},null,-1)])],8,Q)]),o[6]||(o[6]=e("path",{class:"star-empty",d:"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z",fill:"none",stroke:"currentColor","stroke-width":"1.5"},null,-1)),e("path",{class:"star-filled",d:"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z",fill:"currentColor","clip-path":"url(#clip-"+r.book.id+")"},null,8,X)])):(a(),l("svg",U,[...o[7]||(o[7]=[e("path",{d:"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"},null,-1)])]))])),64))]),e("span",ee,c(r.book.rating.toFixed(1)),1)])):_("",!0)]),e("div",te,[e("a",{href:r.book.link,target:"_blank",rel:"noopener",class:"book-panel__link-btn"},[(a(),l("svg",ae,[...o[9]||(o[9]=[e("path",{d:"M18 13v6a2 2 0 01-2 2H5a2 2 0 01-2-2V8a2 2 0 012-2h6M15 3h6v6M10 14L21 3",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},null,-1)])])),o[10]||(o[10]=n(" 豆瓣 ",-1))],8,oe),r.book.wereadLink?(a(),l("a",{key:0,href:r.book.wereadLink,target:"_blank",rel:"noopener",class:"book-panel__link-btn"},[(a(),l("svg",re,[...o[11]||(o[11]=[e("path",{d:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z",fill:"currentColor"},null,-1)])])),o[12]||(o[12]=n(" 微信读书 ",-1))],8,le)):_("",!0)])]),o[15]||(o[15]=e("div",{class:"book-panel__divider"},null,-1)),e("section",ne,[o[13]||(o[13]=e("h3",{class:"book-panel__section-title"},[e("span",{class:"book-panel__section-icon"},"📖"),n(" 内容简介 ")],-1)),e("p",se,c(r.book.desc),1)]),r.book.highlights&&r.book.highlights.length>0?(a(),l("section",ie,[o[14]||(o[14]=e("h3",{class:"book-panel__section-title"},[e("span",{class:"book-panel__section-icon"},"✨"),n(" 书籍亮点 ")],-1)),e("ul",de,[(a(!0),l(p,null,f(r.book.highlights,(i,m)=>(a(),l("li",{key:m,class:"book-panel__highlight-item"},c(i),1))),128))])])):_("",!0)])])])):_("",!0)]),_:1})]))}}),he=C(ce,[["__scopeId","data-v-1ddfc013"]]),be={class:"book-list"},ue=["onClick"],ge=["src","alt"],ke={class:"book-cover__overlay"},pe={key:0,class:"book-cover__hint"},we=["href"],me={class:"book-info"},_e={class:"book-info__title"},fe={class:"book-info__author"},qe={key:0,class:"book-info__rating"},ve={class:"stars"},je={key:0,viewBox:"0 0 24 24",fill:"currentColor"},Le={key:1,viewBox:"0 0 24 24",class:"half-star"},ye=["id"],Se=["clip-path"],xe={key:2,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"1.5"},Ae={class:"rating-text"},Pe={class:"book-info__tags"},Ce={class:"book-info__desc"},ze=A({__name:"BookRecommend",props:{books:{}},setup(r){const b=["linear-gradient(135deg, #e8f0fe 0%, #c7d9fd 100%)","linear-gradient(135deg, #e6f4ea 0%, #b7dfc4 100%)","linear-gradient(135deg, #fff3e0 0%, #ffd9a0 100%)","linear-gradient(135deg, #fce4ec 0%, #f8b4c8 100%)","linear-gradient(135deg, #ede7f6 0%, #cdb8ee 100%)","linear-gradient(135deg, #e0f7fa 0%, #9ee8f0 100%)"],t=[{bg:"#e8f0fe",text:"#3b5bdb"},{bg:"#e6f4ea",text:"#2e7d32"},{bg:"#fff3e0",text:"#e65100"},{bg:"#fce4ec",text:"#c2185b"},{bg:"#ede7f6",text:"#6a1b9a"},{bg:"#e0f7fa",text:"#00838f"}],w=j(null),o=j(0),i=j(!1),m=T(()=>b[o.value%b.length]);function z(q,d){q.withPanel!==!1&&(w.value?.id===q.id&&i.value?L():(w.value=q,o.value=d,i.value=!0))}function L(){i.value=!1,setTimeout(()=>{w.value=null},300)}return(q,d)=>(a(),l(p,null,[e("div",be,[(a(!0),l(p,null,f(r.books,(s,y)=>(a(),l("div",{key:s.id,class:M(["book-card",{"book-card--active":w.value?.id===s.id&&i.value}]),onClick:u=>z(s,y)},[e("div",{class:"book-cover",style:v({background:b[y%b.length]})},[s.cover?(a(),l("img",{key:0,src:s.cover,alt:s.title,class:"book-cover__img"},null,8,ge)):_("",!0),e("div",ke,[s.withPanel!==!1?(a(),l("span",pe,"点击查看详情")):(a(),l("a",{key:1,href:s.link,target:"_blank",rel:"noopener",class:"book-cover__hint",onClick:d[0]||(d[0]=P(()=>{},["stop"]))},"查看豆瓣",8,we))])],4),e("div",me,[e("div",_e,"《"+c(s.title)+"》",1),e("div",fe,c(s.author),1),s.rating!=null?(a(),l("div",qe,[e("div",ve,[(a(),l(p,null,f(5,u=>e("span",{key:u,class:"star"},[u<=Math.floor(s.rating)?(a(),l("svg",je,[...d[1]||(d[1]=[e("path",{d:"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"},null,-1)])])):u===Math.ceil(s.rating)&&s.rating%1!==0?(a(),l("svg",Le,[e("defs",null,[e("clipPath",{id:"card-clip-"+s.id},[...d[2]||(d[2]=[e("rect",{x:"0",y:"0",width:"12",height:"24"},null,-1)])],8,ye)]),d[3]||(d[3]=e("path",{class:"star-empty",d:"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z",fill:"none",stroke:"currentColor","stroke-width":"1.5"},null,-1)),e("path",{class:"star-filled",d:"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z",fill:"currentColor","clip-path":"url(#card-clip-"+s.id+")"},null,8,Se)])):(a(),l("svg",xe,[...d[4]||(d[4]=[e("path",{d:"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"},null,-1)])]))])),64))]),e("span",Ae,c(s.rating.toFixed(1)),1)])):_("",!0),e("div",Pe,[(a(!0),l(p,null,f(s.tags,(u,S)=>(a(),l("span",{key:u,class:"tag",style:v({background:t[S%t.length].bg,color:t[S%t.length].text})},c(u),5))),128))]),e("p",Ce,c(s.desc),1)])],10,ue))),128))]),h(he,{book:w.value,open:i.value,"hero-color":m.value,"tag-colors":t,onClose:L},null,8,["book","open","hero-color"])],64))}}),k=C(ze,[["__scopeId","data-v-fd79cd55"]]),Be=[{id:"book-001",title:"心中有数:生活中的数学思维",author:"刘雪峰",cover:"https://cdn.weread.qq.com/weread/cover/39/3300018939/t6_3300018939.jpg",wereadLink:"https://weread.qq.com/web/reader/df6323a0813ab6de5g019a31#outline?noScroll=1",link:"https://book.douban.com/subject/35749693/",tags:["数学思维","科普","决策"],desc:"本书通过大量贴近日常的例子,展示数学思维如何优化我们的生活决策。作者用概率、统计、最优化等数学工具,为生活、职场、人际交往中的权衡问题提供分析框架,帮助读者在面对不确定性时像计算机一样找到“最优解”。",rating:4.9,highlights:["将大数定律、最小二乘法等硬核数学概念与日常生活巧妙结合","提供应对不确定性和多目标抉择的科学决策框架","强调数学不仅是公式计算,更是看世界、优化人生的高效思维工具"]},{id:"book-0020",title:"智慧的疆界:从图灵机到人工智能",author:"周志明",cover:"https://cdn.weread.qq.com/weread/cover/92/YueWen_23637052/t6_YueWen_23637052.jpg",wereadLink:"https://weread.qq.com/web/reader/b9732f007168ac3cb976eca#outline?noScroll=1",link:"https://book.douban.com/subject/30379536/",tags:["人工智能","科技史","通识读物"],desc:"本书是一部面向大众的人工智能通识读物。作者周明以时间为主线,将人工智能的发展历程、关键人物与里程碑事件串联起来,从五个维度展开:学术理论、历史沿革、技术应用、研究成果以及面临的困难与未来挑战。全书旨在用通俗的语言和巧妙的结构,把人工智能从“阳春白雪”的学术殿堂带到公众视野,帮助读者理解 AI 能做什么、做不到什么,以及背后的技术与思想根源。",rating:5,highlights:["以时间为主线,清晰梳理人工智能的发展脉络与里程碑","深入浅出,用通俗语言将复杂的学术理论带入公众视野","客观剖析,帮助读者准确界定AI“能做什么”与“做不到什么”"]},{id:"book-004",title:"为什么伟大不能被计划",author:"肯尼斯·斯坦利 / 乔尔·雷曼",cover:"https://cdn.weread.qq.com/weread/cover/22/cpplatform_wfdzhk1dx7ig9aep4gagof/t6_cpplatform_wfdzhk1dx7ig9aep4gagof1686304376.jpg",wereadLink:"https://weread.qq.com/web/reader/0bf32020813ab7e6bg016510#outline?noScroll=1",link:"https://book.douban.com/subject/36357804/",tags:["人工智能","创新思维","认知科学"],desc:"本书由两位前沿AI科学家合著,提出了颠覆传统“目标-计划”思维的全新视角。结合AI研究实践,书中论证了伟大成就往往并非出自精心设计的蓝图,而是源于对未知的好奇、随机探索与不断试错。通过“寻宝者思维”和“踏脚石模型”等方法,为读者在高度不确定的环境中激发突破性创新提供了具体的行动框架。",rating:4.5,highlights:["颠覆传统的“目标论”,论证伟大成就源自对未知的好奇与无边界的探索","提供“寻宝者思维”“踏脚石模型”“新奇性探索”三大可操作的认知与实践工具","扎根OpenAI等前沿机构的实证背景,其启发意义跨学科适用于科研、商业及人生规划"]},{id:"book-003",title:"这就是ChatGPT",author:"斯蒂芬·沃尔弗拉姆",cover:"https://cdn.weread.qq.com/weread/cover/24/cpplatform_4cn8w4tmgzntjobg9ffeny/t6_cpplatform_4cn8w4tmgzntjobg9ffeny1703648785.jpg",wereadLink:"https://weread.qq.com/web/reader/74332a90813ab86c4g019d98#outline?noScroll=1",link:"https://book.douban.com/subject/36449803/",tags:["人工智能","大模型","ChatGPT"],desc:"本书由著名科学家斯蒂芬·沃尔弗拉姆撰写,全景式拆解了ChatGPT的内部工作机制。作者用通俗语言解释了神经网络和自回归架构等核心技术,探讨了简单的计算规则如何涌现出令人惊叹的智能,帮助读者深刻理解大语言模型为何能生成高质量的人类水平文本。",rating:4.3,highlights:["全景拆解核心技术:深入浅出地讲清ChatGPT背后的神经网络与自回归架构","独特的大师视角:将大模型视为“简单的计算规则”涌现复杂智能的绝佳范例","兼顾技术与商业影响:结合算力规模与行业冲击,全面探讨AI时代的机遇与挑战"]},{id:"book-0030",title:"人工智能:现代方法(第4版)(上下册)",author:"[美]斯图尔特·罗素(Stuart Russell) / [美]彼得·诺维格(Peter Norvig)",cover:"https://cdn.weread.qq.com/weread/cover/33/cpplatform_8rthznqfhsjuz5fswwn6kx/t6_cpplatform_8rthznqfhsjuz5fswwn6kx1675928213.jpg",wereadLink:"https://weread.qq.com/web/reader/fc332020813ab7942g0102ad#outline?noScroll=1",link:"https://book.douban.com/subject/36152133",tags:["人工智能","教材","理论实践结合","经典著作","计算机科学"],desc:"本书是人工智能领域的经典权威教材,系统、深入地探讨AI领域的理论与实践,以统一风格融合当今流行的AI思想与术语到前沿应用中,真正实现理论与实践相结合。全书分7个部分共28章,理论部分涵盖逻辑、概率、连续数学、感知、推理、学习、行动及公平、信任、社会公益和安全等社会议题;实践部分选取微电子设备、机器人行星探测器、在线服务、AlphaZero、人形机器人、自动驾驶、AI辅助医疗等热门场景。由加州大学伯克利分校教授斯图尔特·罗素与前谷歌研究总监彼得·诺维格联合撰写,被全球1500多所高校采用,适合作为AI相关专业本科生和研究生教材,也可作为专业人员的参考书。",rating:5,highlights:["体系完整覆盖面广,7个部分28章构成自洽的AI理论主线,涵盖核心理论与前沿议题","理论与实践并重,既阐述核心算法与模型,又展示在热门场景中的落地实例,便于知识迁移","紧跟前沿关注社会议题,专门讨论AI伦理与安全,引导思考技术与社会的交互责任","一站式权威参考,兼具教材属性与专业参考价值,适配高校教学与产业实践双重需求","现代理念贯穿始终,通过最新案例体现AI进展与行业趋势,呈现“活”的AI生态"]},{id:"book-0031",title:"模型思维:简化世界的人工智能模型",author:"龚才春",cover:"https://cdn.weread.qq.com/weread/cover/26/YueWen_38601826/t6_YueWen_38601826.jpg",wereadLink:"https://weread.qq.com/web/reader/5a8326e0724d04625a8e740#outline?noScroll=1",link:"https://book.douban.com/subject/35488925/",tags:["模型思维","人工智能","算法模型","机器学习","入门实践"],desc:"本书聚焦“如何用模型简化世界”的核心主题,将人工智能在现实业务中面临的难题归纳为权重、状态、序列、表示、相似、分类六大问题,并围绕该框架讲解对应模型思路与算法。书中弱化复杂数学公式,以大量生活化、业务化案例阐释模型理论与落地场景,帮助读者建立“模型—场景”映射关系,降低AI模型学习门槛,既是人工智能初学者的入门读物,也可为企业工程师、科研人员提供实践参考,适合各类读者学习并将模型思维应用到生活与工作中。",rating:4.8,highlights:["以“六大问题”框架串联AI模型,可按场景快速检索适配的模型思路","侧重落地实践,搭配大量生活化与业务案例,助力建立“模型—场景”映射","降低学习门槛,少数学公式、多直观案例,兼顾初学者与工程落地需求","受众群体广泛,适配工程师、科研人员及普通读者,可迁移模型思维至实际场景"]},{id:"book-005",title:"你看起来好像……我爱你:AI的工作原理以及它为这个世界带来的稀奇古怪",author:"贾内尔·沙内",cover:"https://wfqqreader-1252317822.image.myqcloud.com/cover/970/39481970/t6_39481970.jpg",wereadLink:"https://weread.qq.com/book-detail?type=1&senderVid=40710128&v=f9a32c10725a7272f9a14f9&wtheme=white&wfrom=app&wvid=40710128&scene=bottomSheetShare",link:"https://book.douban.com/subject/35407136/",tags:["人工智能","趣味科普","漫画算法"],desc:"这是一部写给普通读者的人工智能趣味科普读物。作者贾内尔·沙内结合生活化的比喻和超级可爱的漫画,深入浅出地讲解了AI的基本工作原理、实际应用及其局限性。书中通过大量幽默的AI实验与“翻车”案例,带领读者在轻松捧腹的氛围中,准确理解算法能做什么、不能做什么。",rating:4.2,highlights:["幽默可爱的漫画导览:用插图和通俗语言将“深度学习”“神经网络”等抽象概念可视化","丰富的趣味实验案例:通过精选的AI“翻车”故事,直观揭示算法背后的逻辑与潜在偏差","客观建立AI认知:在展示AI强大能力的同时,明确指出其在语境理解和处理模糊信息时的短板"]},{id:"book-006",title:"AI经济:机器人时代的工作、财富和社会福利",author:"罗杰·布特尔",cover:"https://cdn.weread.qq.com/weread/cover/30/YueWen_38229387/t6_YueWen_38229387.jpg",wereadLink:"https://weread.qq.com/web/reader/653320207247558b65332f5#outline?noScroll=1",link:"https://book.douban.com/subject/35433060/",tags:["人工智能","经济学","社会学","未来趋势"],desc:"本书由知名经济学家罗杰·布特尔撰写,聚焦AI与机器人技术对经济和社会的深远影响。作者拨开艰涩的科技术语,从经济增长、通货膨胀及财富分配等宏观视角,理性剖析AI革命将如何重塑我们的工作、教育与休闲方式,以乐观的姿态为迎接未来的社会变革指明路径。",rating:4.1,highlights:["宏观经济视角解析:深入探讨AI对经济增长、通货膨胀、财富与权力分配的真实影响","全景式社会洞察:全面检视机器人时代下,人类教育体系、工作模式与休闲形态的深刻变革","理性乐观的未来指南:拒绝技术恐慌,为个人与社会在变迁的世界中提供清晰可行的应对计划"]}],Ie=[{id:"book-007",title:"做对产品",author:"阿尔贝托·索维亚",cover:"https://cdn.weread.qq.com/weread/cover/53/YueWen_40877841/t6_YueWen_40877841.jpg",wereadLink:"https://weread.qq.com/web/reader/254322a0726fbf1125472c9#outline?noScroll=1",link:"https://book.douban.com/subject/35607961/",tags:["产品思维","创业","商业方法论"],slogan:"为什么有些产品注定失败,有些产品却能大获成功?来自谷歌与斯坦福的产品工具和产品战术。",desc:"谷歌首任产品总监阿尔贝托·索维亚结合在谷歌、斯坦福的实战经验与自身代价高昂的创业失败经历,总结出的一套防败手册。书中揭示了新产品高达90%的“市场失败律”,并创新性地提出了“预型”(Pre型)理念,指导团队在正式开发前,以极低的成本和真实数据快速验证关键假设,确保把创意打磨成“正确的它”。",rating:4.8,highlights:["揭示残酷的市场失败律:正视90%新产品必然失败的商业常态,并以此倒推破局的实战方法论","首创“预型”(Pre型)概念:提供8大测试工具,主张用极低成本和小规模试错快速逼近正确的产品形态","强调真实数据驱动决策:辅以特斯拉、谷歌等完整案例回溯,教导团队将决策建立在客观证据而非主观直觉之上"]},{id:"book-009",title:"俞军产品方法论",author:"俞军",cover:"https://cdn.weread.qq.com/weread/cover/47/YueWen_28165041/t6_YueWen_28165041.jpg",wereadLink:"https://weread.qq.com/web/reader/1cc3252071adc3b11cc0162#outline?noScroll=1",link:"https://book.douban.com/subject/34907971/",tags:["产品思维","产品经理","互联网","方法论"],desc:"“百度贴吧之父”俞军二十余年产品实践与思考的系统总结。本书将产品经理定义为“以科学方法研究人性并转化为商业方案”的交叉学科,深入解析了用户模型、交易模型和决策模型三大核心框架,为产品人提供了一套在不确定环境中权衡多方利益的实战指南。",rating:4.4,highlights:["沉淀二十年行业经验:从广为流传的“PM12条”到系统化的产品哲学,展现顶尖产品经理的认知迭代史","三大核心模型拆解:深度剖析用户模型与交易模型,指导如何通过让交易发生来创造“有利可图”的真实用户价值","兼顾科学与人文视角:强调批判性思维的运用,并清晰梳理了从新人到顶尖大牛的能力进阶路径"]},{id:"book-016",title:"策略产品经理:模型与方法论",author:"青十五",cover:"https://cdn.weread.qq.com/weread/cover/31/cpplatform_gheeqe7hjb2czyzthzf5nm/t6_cpplatform_gheeqe7hjb2czyzthzf5nm1735654872.jpg",wereadLink:"https://weread.qq.com/web/reader/4de32800813ab98d5g01286b#outline?noScroll=1",link:"https://book.douban.com/subject/35218721/",tags:["产品经理","策略产品","算法思维"],desc:"本书围绕“策略产品经理”这一复合角色,系统性地构建了从理念到实践的完整知识框架。作者从机器学习理论与经济学视角出发,结合推荐、搜索、广告、风控等核心业务场景,深入浅出地讲解了函数建模与策略应用,并对策略产品经理的核心能力与团队建设给出了详尽指导。",rating:3.9,highlights:["系统化的角色认知建构:清晰界定策略产品经理的时代背景、职责边界与工作内容,为从业者夯实概念基础","跨学科的模型与业务结合:利用机器学习的函数方法论与经济学理论,深度剖析推荐、搜索、广告、风控及定价等真实业务场景的解法","硬核算法的通俗化解析:深入浅出地拆解机器学习本质、常见算法及深度学习前沿技术,帮助产品经理真正理解策略背后的技术支撑","可落地的团队建设指南:全面拆解数据分析、沟通与项目管理等核心能力项,并针对不同产品生命周期提供策略团队的组建思路"]},{id:"book-008",title:"创造:用非传统方式做有价值的事",author:"托尼·法德尔",cover:"https://cdn.weread.qq.com/weread/cover/53/cpPlatform_tzdqT27m3vyaHnX5o8Vbwk/t6_cpPlatform_tzdqT27m3vyaHnX5o8Vbwk.jpg",wereadLink:"https://weread.qq.com/web/reader/13832ac0813ab725fg018645#outline?noScroll=1",link:"https://book.douban.com/subject/36071759/",tags:["产品思维","管理学","创业"],desc:"本书是iPod、iPhone、Nest等爆款产品幕后推手托尼·法德尔30余年职业经历的智慧结晶。作者毫无保留地分享了他在产品设计、团队管理、职业选择和公司经营等方面的“非传统”方法论,帮助读者在各自的领域内刻意练习创造力,做真正有价值的事。",rating:4.9,highlights:["源自顶级创新者的实战经验:连续打造iPod、iPhone等划时代产品的亲历复盘与真实反面教训","覆盖从个人到公司的完整路径:系统解答职业选择、产品设计、团队管理与企业经营等核心问题","提供可复制的“非传统”方法论:强调“亮点思维”与持续复盘,教导读者以反常规的视角刻意练习创造力"]},{id:"book-010",title:"产品思维",author:"刘飞",cover:"https://cdn.weread.qq.com/weread/cover/56/YueWen_25568738/t6_YueWen_25568738.jpg",wereadLink:"https://weread.qq.com/web/reader/38332ce0718625e23831fe7#outline?noScroll=1",link:"https://book.douban.com/subject/33456375/",tags:["产品思维","产品经理","个人成长","互联网"],desc:"实战派产品经理刘飞结合在一线大厂的丰富经验,围绕产品人如何实现能力跃迁展开的底层能力指南。全书掰开揉碎地讲解了认知盲点与实践痛点,通过“认知用户”“创造价值”和“产品落地”三大核心板块,系统拆解了从建立用户模型、高质量决策到快速迭代验证的完整产品方法论。",rating:4.2,highlights:["三大核心板块系统拆解:完整覆盖“认知用户”“创造价值”与“产品落地”的产品闭环","直击痛点的一线实战经验:毫无保留地分享实战中新手迫切需要却难以获取的隐性知识","聚焦底层能力与思维升维:不仅教授落地方法,更注重决策质量与思维模式的跃迁"]},{id:"book-011",title:"产品思维:创新设计的六条法则(全彩)",author:"张印帅",cover:"https://wfqqreader-1252317822.image.myqcloud.com/cover/253/26687253/t6_26687253.jpg",wereadLink:"https://weread.qq.com/web/reader/a823297071973715a8202b0#outline?noScroll=1",link:"https://book.douban.com/subject/34859540/",tags:["产品设计","创新思维","方法论","设计灵感"],desc:"本书围绕作者张印帅多年产品设计实践总结出的6条创意公式展开,旨在帮助读者系统化地获取设计灵感并解决创新难题。全书通过大量经典案例,详细解析了从发散思考到重组创新的全过程,并在最后提供了从需求到草图再到最终方案的完整项目落地演示。",rating:4,highlights:["提炼6条实用的创新设计公式:将发散思考与重组创新系统化,打造可复用的设计灵感库","丰富的经典设计案例解析:详细展示“问题+方法”、“1+1>2”等法则在真实产品设计中的应用","呈现从需求到方案的落地全流程:通过综合案例演示概念打磨与草图设计的实战过程"]}],We=[{id:"book-012",title:"小而美:持续盈利的经营法则",author:"萨希尔·拉文吉亚",cover:"https://cdn.weread.qq.com/weread/cover/91/cpplatform_vl4abrrrqgxnry833gcrtt/t6_cpplatform_vl4abrrrqgxnry833gcrtt1677578056.jpg",wereadLink:"https://weread.qq.com/web/reader/02932980813ab7a43g012e77#outline?noScroll=1",link:"https://book.douban.com/subject/36280425/",tags:["创业","商业模式","极简主义"],desc:"本书打破了硅谷盲目追求“独角兽”的扩张迷思,聚焦于“规模不是唯一出路”的商业现实。作者结合创立Gumroad的亲身经历,提出了“极简创业经营”理念。全书指导创业者与管理者如何通过从社区切入、聚焦核心能力、精简团队等方式,用最少的资源打造出不仅能活下去,而且还能持续盈利的“慢公司”。",rating:5,highlights:["颠覆传统的扩张迷思:提出盈利至上而非规模至上,将持续赚钱和实际利润作为衡量企业成功的核心标准","可落地的极简法则:总结出“越少越好”“瞄准前100个客户”等7条创业清单,构建从定位、产品到销售的完整闭环","社区驱动的商业逻辑:提倡从虚拟社区入手,以“贡献-创作-教学”的方式低成本验证产品形态并获取早期信任","打造高韧性的“慢公司”:结合疫情与远程办公背景,展示如何通过精简组织和分布式协作,在不确定的时代保持稳定的现金流"]},{id:"book-013",title:"做难而正确的事:进步最快的方式",author:"尤里·莱文",cover:"https://cdn.weread.qq.com/weread/cover/53/cpplatform_bunxjyygj8m9stnwcgwqqk/t6_cpplatform_bunxjyygj8m9stnwcgwqqk1728876401.jpg",wereadLink:"https://weread.qq.com/web/reader/aa032fb0813ab9461g018406#outline?noScroll=1",link:"https://book.douban.com/subject/37054102/",tags:["创业","产品思维","商业管理"],desc:"Waze联合创始人尤里·莱文写给创业者和管理者的行动指南。作者结合连续打造两家估值超10亿美元公司的实战经验,提出“先做难事、再做正确事”的核心哲学。全书通过13个阶段的系统拆解,指导读者如何寻找真正的用户痛点、构建高价值产品,并在不确定的环境中通过不断复盘实现跨越式成长。",rating:4.9,highlights:["世界级创业者的实战复盘:连续打造两家独角兽公司的创始人亲授,提供极具可信度的第一手商业洞察与落地经验","践行“难而正确”的核心哲学:强调不追逐短期热点,而是去解决效率极低却被忽视的痛点,以此建立坚实的商业护城河","覆盖从0到1的全周期指南:系统拆解从寻找痛点、产品构建、融资运作到团队管理的13个关键阶段,提供可操作的行动清单","直面失败的心理韧性建设:不回避挫折,将“从错误中学习”提炼为核心方法,为身处高压环境的读者提供情感共鸣与心理支持","广泛的跨场景应用价值:书中给出的决策工具不仅适用于初创团队,同样能为大公司内部创新及个人职业认知升级提供指导"]},{id:"book-015",title:"创新公司:皮克斯的启示",author:"艾德·卡特姆",cover:"https://cdn.weread.qq.com/weread/cover/20/YueWen_814380/t6_YueWen_814380.jpg",wereadLink:"https://weread.qq.com/web/reader/2ef329605c6d2c2efeeb70d#outline?noScroll=1",link:"https://book.douban.com/subject/26314955/",tags:["创新思维","组织文化","企业管理"],desc:"皮克斯联合创始人艾德·卡特姆结合《玩具总动员》《机器人瓦力》等经典动画的幕后制作故事,深度揭示了皮克斯如何长期保持创意领先的秘密。本书不仅详述了皮克斯从初创到壮大的历程,更抽丝剥茧地解析了其在团队文化、跨部门协作、人才培养和允许失败等方面的独特创意管理机制,为各类组织提供了可复制的创新指南。",rating:4.5,highlights:["揭秘“皮克斯奇迹”背后的管理哲学:通过14部经典动画的真实幕后故事,展示创意从无到有、再到票房口碑双赢的全过程","深度解析创新土壤的搭建:阐述如何通过允许失败的文化、流程设计和激励机制,将“不断推动创新”彻底融入公司DNA","提供跨行业可复用的管理工具:总结项目立项、跨部门协作与风险控制的具体做法,为不同规模和行业的企业提供落地的实战模板"]},{id:"book-017",title:"重来:更为简单的商业思维",author:"贾森·弗里德 / 戴维·海涅迈尔·汉森",cover:"https://cdn.weread.qq.com/weread/cover/1/YueWen_635904/t6_YueWen_635904.jpg",wereadLink:"https://weread.qq.com/web/reader/0363228059b4000363b29e9#outline?noScroll=1",link:"https://book.douban.com/subject/5320866/",tags:["商业思维","创业","企业管理","极简主义"],desc:"37signals联合创始人基于十年创业实战经验,写给职场人与创业者的极简商业法则。本书摒弃了传统的MBA术语与复杂的商业教条,以“辛辣、直接、靠谱”的语言,颠覆了关于项目管理、人才招聘、产品设计与企业文化的常规认知,教导读者如何在真实的商业世界中“做更少,但创造更多价值”。",rating:4.3,highlights:["颠覆传统的极简商业哲学:反叛复杂的商业教条,主张“做更少,创造更多”,通过最小可行步骤降低试错成本并快速迭代","源自37signals的十年实战精髓:覆盖从项目管理、产品设计到市场营销的完整链条,提供不讲废话、拿来即用的行动指南","重塑职场与团队管理的认知:提出诸多务实且反常规的观点(如严苛的简历筛选标准),打造基于信任与结果导向的高效团队","适用面极广的实操手册:无论是寻求突破的精英企业家、小团队创业者,还是渴望提升工作效率的普通职场人,都能直接对照落地"]},{id:"book-018",title:"重来2:更为简单高效的远程工作方式",author:"贾森·弗里德 / 戴维·海涅迈尔·汉森",cover:"https://cdn.weread.qq.com/weread/cover/38/YueWen_635721/t6_YueWen_635721.jpg",wereadLink:"https://weread.qq.com/web/reader/46b3220059b34946b517012#outline?noScroll=1",link:"https://book.douban.com/subject/25861795/",tags:["企业管理","远程工作","工作方式","团队协作"],desc:"Basecamp(原37signals)创始人基于自身团队多年的全球分布式协作经验,为企业和个人提供的一套远程工作“思想升级包”。本书直面行业争议,破解了“创新只能面对面”及“文化会淡化”等常见误区,并系统提供了借助异步沟通、协作工具与流程设计来打造高效、人性化远程团队的实战指南。",rating:4.1,highlights:["提供思想层面的“升级包”:直击传统办公室痛点,用真实数据与反例打破关于远程办公的固有认知误区","第一手的分布式团队管理经验:Basecamp创始人亲授,展示如何突破地域限制招募顶尖人才,并保持健康、高效的工作节奏","系统可落地的工具与流程方法:详述如何利用协作工具降低管理成本,让远程工作从“特殊福利”真正转变为可持续的主流组织模式"]},{id:"book-019",title:"重来3:做得更少,但赚得更多",author:"贾森·弗里德 / 戴维·海涅迈尔·汉森",cover:"https://cdn.weread.qq.com/weread/cover/62/cpplatform_tqth8pnlq8h9ing5uciwhi/t6_cpplatform_tqth8pnlq8h9ing5uciwhi1748502715.jpg",wereadLink:"https://weread.qq.com/web/reader/b6a32ed0813ab9fb5g015181#outline?noScroll=1",link:"https://book.douban.com/subject/37367276/",tags:["工作方式","反内卷","企业文化"],desc:"Basecamp创始人带来的“反内卷”与“反过度忙碌”的管理指南。作者基于近20年带领54人团队服务全球10万家企业的成功经验,直击现代企业盲目扩张、无效加班等八大症结。全书主张以“冷静”颠覆“忙碌”文化,指导企业和个人通过40小时工作制、拒绝KPI和异步沟通等极简方式,在不牺牲生活质量的前提下实现健康发展与持续盈利。",rating:4.2,highlights:["以“冷静”颠覆“忙碌”文化:倡导高效比高产更重要,用稳定的节奏替代疯狂加班的内卷常态","直击现代企业八大症结:深度诊断快速扩张、无效加班、会议泛滥与目标绑架等痛点,提供对症下药的思路","提供四大可落地的管理工具:引入40小时工作制、拒绝硬性KPI、推行非实时沟通,坚持利润优先于规模","源自Basecamp的真实反向案例:展示“小而美”团队如何通过“少做但做好”的策略,跑赢新经济并保持高利润"]}],Ye=[{id:"book-024",title:"要事第一",author:"史蒂芬·柯维 / 罗杰·梅里尔 / 丽贝卡·梅里尔",cover:"https://cdn.weread.qq.com/weread/cover/57/yuewen_33091834/t6_yuewen_330918341686208943.jpg",wereadLink:"https://weread.qq.com/web/reader/f523268071f8f0faf52b806#outline?noScroll=1",link:"https://book.douban.com/subject/1028372/",tags:["时间管理","自我管理","经典思维"],desc:"作为《高效能人士的七个习惯》的延伸与加强版,本书提出了颠覆传统的“第四代时间管理”方法。作者强调,比提升做事速度(时钟)更重要的是找准人生的方向(罗盘)。全书指导读者通过自我意识的觉醒,以原则和价值观为中心,将精力聚焦于“重要而不紧急”的长期目标上,从而在繁忙的现代生活中真正做到“要事第一”。",rating:4.5,highlights:["从“时钟”到“罗盘”的思维跨越:打破一味追求“更快、更努力”的传统效率迷思,确立人生方向优先的哲学","经典的四象限时间管理矩阵:引导读者跳出紧急事务的“救火圈”,将核心精力倾注于第二象限(重要但不紧急)的高价值事务中","生动的“大石块”优先法则:通过“先放石头再倒水”的直观比喻,确保关键目标与核心使命在碎片化日程中得到绝对的优先落实","以原则为中心的自我驱动框架:不仅提供日程安排工具,更通过唤醒良知,帮助读者在工作、家庭等多元角色中实现真正的平衡与统合综效"]},{id:"book-025",title:"清单革命",author:"阿图·葛文德",cover:"https://cdn.weread.qq.com/weread/cover/12/cpPlatform_rudGZN3LDW5m9FBYr7rMBA/t6_cpPlatform_rudGZN3LDW5m9FBYr7rMBA.jpg",wereadLink:"https://weread.qq.com/web/reader/18332f80813ab7292g010065#outline?noScroll=1",link:"https://book.douban.com/subject/27168564/",tags:["管理学","认知科学","工作效率"],desc:"这是一部针对现代复杂世界所撰写的“认知防护手册”。作者阿图·葛文德通过医疗、建筑、投资等高风险领域的真实案例,揭示了人类在海量信息与高压环境下极易出现的判断疏忽。书中提出了“权力下放、简单至上、人为根本、持续改善”四大原则,指导读者将最佳实践外化为可操作的清单,从而在复杂系统中构建一道低成本、高回报的安全防线。",rating:4.6,highlights:["直面复杂时代的认知瓶颈:揭示在海量信息流中,清单如何作为“认知防护网”弥补人类记忆力与注意力分配的先天不足","提供兼具理念与落地的四大原则:通过“权力下放、简单至上、人为根本、持续改善”,构建一套可复用的清单设计哲学","扎实的医学实证背书:以手术感染率骤降等真实临床数据为支撑,证明清单思维在医疗、建筑、投资等高风险领域的跨行业普适性","简洁而具力量的流程创新:强调清单服务于人而非取代人,是帮助专业人士在高压环境下将复杂环节显性化、流程化的必备工具"]},{id:"book-020",title:"别让猴子跳回背上",author:"威廉·安肯三世",cover:"https://cdn.weread.qq.com/weread/cover/69/cpPlatform_7fFoBQ7dtqgABGSTskpJSN/t6_cpPlatform_7fFoBQ7dtqgABGSTskpJSN.jpg",wereadLink:"https://weread.qq.com/web/reader/9fc32010813ab7291g0196bd#outline?noScroll=1",link:"https://book.douban.com/subject/36103994/",tags:["时间管理","领导力","项目管理"],desc:"这是一部以“猴子”生动隐喻任务与责任的经典管理学著作。作者威廉·安肯三世深刻剖析了管理者常被琐事淹没的时间困境,并提出系统化的“猴子管理法”。通过明确任务归属、责任递减与有效授权,指导管理者如何把不属于自己的“猴子”交出去,从而释放精力专注于最高价值的战略思考,实现团队与个人的共同成长。",rating:4.3,highlights:["生动有趣的“猴子”隐喻:将枯燥的责任划分与任务流转具象化,直击职场中“忙碌却低效”的痛点","实用高效的“三步交接”法则:通过明确期望、授予资源与约定检查点,彻底避免下属的待办任务重新跳回自己背上","重塑时间管理与人才培养体系:指导高层放权、中层辅导、基层自发,将企业的成功真正建立在员工自主性的提升之上"]}],Te=[{id:"book-022",title:"学会提问(原书第12版)",author:"尼尔·布朗 / 斯图尔特·基利",cover:"https://cdn.weread.qq.com/weread/cover/68/YueWen_39980443/t6_YueWen_39980443.jpg",wereadLink:"https://weread.qq.com/web/reader/e6832d3072620d9be68aabf#outline?noScroll=1",link:"https://book.douban.com/subject/35513147/",tags:["批判性思维","逻辑学","认知科学","经典书"],desc:"这是一部培养批判性思维的经典实战指南。作者尼尔·布朗与斯图尔特·基利结合长期的教学与研究实践,提供了一套系统化、可操作的提问流程。全书通过大量真实情境案例,教导读者如何在信息泛滥的时代识别隐含假设、区分事实与观点,用高质量的“判断性问题”看透事物本质,从而做出更理性的决策。",rating:5,highlights:["聚焦批判性思考的核心能力:系统拆解“如何提出好问题”的思维过程,帮助读者在复杂信息中迅速抓住本质","提供可落地的提问与评估框架:从背景信息、关键概念到逻辑推理,构建一条完整的判断性问题链条","丰富的真实场景应用示范:结合课堂讨论、写作、日常沟通与职场决策等多元场景,让理论能“立即上手”","打造实用的思考检查单:不仅讲透“提问的价值”,更提供可直接转化为日常习惯的思维检查表,助你有效避开认知陷阱"]},{id:"book-026",title:"如何阅读一本书",author:"莫提默·J. 艾德勒 / 查尔斯·范多伦",cover:"https://wfqqreader-1252317822.image.myqcloud.com/cover/810/23723810/t6_23723810.jpg",wereadLink:"https://weread.qq.com/book-detail?type=1&senderVid=40710128&v=272326407169ff22272934f&wtheme=white&wfrom=app&wvid=40710128&scene=bottomSheetShare",link:"https://book.douban.com/subject/1013208/",tags:["阅读方法","思维训练","经典"],desc:"阅读领域的“元方法”指南。作者艾德勒与范多伦将阅读划分为基础阅读、检视阅读、分析阅读与主题阅读四个进阶层次,并强调阅读是一项主动的思考活动。本书不仅提供了从“快速略读”到“系统拆解论点”的实操技巧,更致力于通过提问、归纳与批判,将阅读转化为训练理解力、批判力与终身学习的终极工具。",rating:5,highlights:["构建系统的四级阅读框架:从检视阅读到分析阅读再到主题阅读,为读者提供了一套从入门到精通的进阶路径","强调“主动与批判”的阅读观:拒绝被动接收,教导读者如何通过提问、归纳与反思,真正将作者的洞见转化为自己的认知","高效的检视阅读技巧:提供如何在有限时间内通过看目录、挑重点等方式,快速筛选并判断书目价值的核心能力","跨时代的经典效能:自1940年问世以来长盛不衰,其对逻辑拆解与深度思考的指导,是提升所有知识吸收效率的“总开关”"]},{id:"book-023",title:"检索力:打破信息差的科学方法",author:"龚芙蓉",cover:"https://cdn.weread.qq.com/weread/cover/58/cpplatform_feaxemubry47bnkzylqzwv/t6_cpplatform_feaxemubry47bnkzylqzwv1716796541.jpg",wereadLink:"https://weread.qq.com/web/reader/9de32810813ab8e00g018130#outline?noScroll=1",link:"https://book.douban.com/subject/36899979/",tags:["信息素养","检索能力","思维认知"],desc:"本书聚焦“检索力”这一核心技能,旨在帮助读者在信息过载的时代主动掌握“逆风而行”的搜索能力。作者龚芙蓉结合二十余年实践经验,用生动的人文与诺贝尔奖级科学案例,将枯燥的检索工具化为有趣的故事。不仅教授非线性、迭代式的搜索技巧,更致力于重塑读者的探究精神,赋予其走出“信息茧房”的勇气。",rating:4.2,highlights:["丰富的跨学科趣味案例驱动:用“张冠李戴的马克思名言”等生动故事,将枯燥繁琐的检索步骤转化为轻松的探索之旅","重塑非线性与迭代的搜索思维:打破按部就班的线性流程误区,建立以耐心与热情驱动的多轮迭代搜索心态","直击科研与职场的实用痛点:提供可快速落地的实操指南,帮助读者切实缩短科研周期、大幅提升工作效率","兼顾技能训练与人文底色:在教授如何利用和创造信息的同时,注重培养读者的信息素养与打破信息差的认知勇气"]},{id:"book-027",title:"原则",author:"瑞·达利欧",cover:"https://cdn.weread.qq.com/weread/cover/23/YueWen_921568/t6_YueWen_921568.jpg",wereadLink:"https://weread.qq.com/web/reader/848324405e0fe08483ab6a4#outline?noScroll=1",link:"https://book.douban.com/subject/27608239/",tags:["投资","方法论","自我管理"],desc:"桥水基金创始人瑞·达利欧总结四十余年投资、管理与人生经验的集大成之作。作者提出将生活和工作像机器一样系统化,确立了“极度求真”与“极度透明”两大基石,并通过“创意择优”与“基于可信度的决策机制”来迭代思维。书中包含500多条可操作原则,旨在帮助读者在复杂世界中保持开放心态、看清现实,并做出最优决策。",rating:4.8,highlights:["“极度求真”与“极度透明”的基石:主张诚实面对现实,通过公开决策过程来获取外部反馈,达成高效协作","创意择优与可信度加权机制:摒弃个人权威,利用数据驱动的讨论与可信度权重,在团队中选出最优方案","500余条可落地的原则清单:涵盖自我认知、投资决策、团队治理等场景,构建出一套随时可查的行动指南","系统化的“机器”思维:将生活与组织管理拆解为可维护、可迭代的系统,有效规避情绪化干扰"]},{id:"book-031",title:"价值",author:"张磊",cover:"https://wfqqreader-1252317822.image.myqcloud.com/cover/958/33577958/t6_33577958.jpg",wereadLink:"https://weread.qq.com/web/reader/5be32a3072005be65bef195#outline?noScroll=1",link:"https://book.douban.com/subject/35188914/",tags:["价值投资","商业思维","创业"],desc:"高瓴资本创始人张磊首部个人及投资思想著作。全书通过回顾作者的个人求学与创业历程,系统阐释了“长期主义”与“重仓中国”的核心投资理念,并首次披露了高瓴投资的七大公式。作者将十余个典型投资案例与个人价值修养相结合,揭示了如何在不确定的商业环境中,通过坚持原则、敬畏规则与持续创新,创造长久、真实的价值。",rating:4.6,highlights:["系统构建长期主义哲学:首次系统化梳理“高瓴七大公式”,为读者提供从认知、决策到执行的价值投资实战模型","深度复盘经典实战案例:通过腾讯、货拉拉等真实商业案例,拆解如何在复杂市场中识别企业护城河与核心价值","投资之外的人文思考:延伸至教育、人才与科学观,展现作者作为顶尖投资者对社会责任与长期价值创造的深度思考","可视化的阅读体验:精选多幅手绘彩插与历史影像,将深刻的投资逻辑与企业成长叙事变得更加生动、直观"]},{id:"book-032",title:"纳瓦尔宝典",author:"埃里克·乔根森 / 纳瓦尔·拉维坎特",cover:"https://cdn.weread.qq.com/weread/cover/89/YueWen_44026191/t6_YueWen_44026191.jpg",wereadLink:"https://weread.qq.com/web/reader/e1e32b00729fc94fe1e824d#outline?noScroll=1",link:"https://book.douban.com/subject/35876121/",tags:["财富管理","个人成长","幸福哲学","思维认知"],desc:"这是一部汇集硅谷著名投资人纳瓦尔·拉维坎特过去十年关于财富与幸福思考的行动指南。全书摒弃了“致富靠运气”的传统观念,提出积累财富与幸福生活是可以通过学习掌握的技能。通过系统整理推特、播客与访谈中的智慧,本书为读者提供了如何在快速变化的科技与经济环境中,利用杠杆、发挥个人独特性,进而实现财务自由并获得持久内心满足的方法论。",rating:4.7,highlights:["将财富与幸福视为可习得的技能:打破运气论,强调通过建立杠杆、发挥个人独特性来获取非线性的回报","十年思想的系统化编纂:将碎片化的互联网智慧提炼为成体系的方法论,打造了数字时代个人的“行动指南”","兼顾财富积累与内心满足:不仅教导如何高效赚钱,更深入探讨如何通过阅读、冥想与长期主义,在职场成功中寻找内心的宁静","极具实操性的工具箱:提供如深度思考、刻意练习、构建个人品牌等具体路径,帮助读者在碎片化时代快速实现自我迭代"]},{id:"book-028",title:"优秀的绵羊",author:"威廉·德雷谢维奇",cover:"https://cdn.weread.qq.com/weread/cover/78/cpplatform_3ncoeekcuaectlzj9hf5nr/t6_cpplatform_3ncoeekcuaectlzj9hf5nr1744626569.jpg",wereadLink:"https://weread.qq.com/web/reader/1c0324c0813ab9d91g010aba#outline?noScroll=1",link:"https://book.douban.com/subject/26747208/",tags:["博雅教育","社会学","个人成长"],desc:"耶鲁大学前教授威廉·德雷谢维奇对美国常春藤精英教育体制的尖锐批判之作。作者通过二十余年的教学观察,指出顶尖学府培养出一群虽然聪明、优秀,但普遍焦虑、缺乏目标感且唯命是从的“优秀绵羊”。本书呼吁社会重新审视教育的本质,摆脱对名校与高薪的盲目崇拜,回归博雅教育,鼓励学生探索内在驱动力与自我价值。",rating:4.2,highlights:["犀利剖析精英教育弊端:直击常春藤体制培养出“聪明但没有灵魂”的学生的现实,反思唯名校与成绩论的单一评价体系","回归博雅教育的核心价值:批判应试化倾向,提倡给予学生更多探索、失败与重塑自我的空间,强调教育的本质在于帮助个体找到自我","提供挣脱外部期待的认知框架:既为迷茫的年轻人指明如何重建内在动力,也给家长和教育者敲响了关于“成功定义”的警钟","跨文化背景下的教育共鸣:尽管以美国精英教育为例,其对“教育内卷”与“缺乏目标感”的批判,引发了全球高压教育环境下的深层共鸣"]},{id:"book-029",title:"把自己变成稀缺资产",author:"何思平",cover:"https://cdn.weread.qq.com/weread/cover/98/cpplatform_ncqzerh3wdywn9mlc9cjna/t6_cpplatform_ncqzerh3wdywn9mlc9cjna1694085413.jpg",wereadLink:"https://weread.qq.com/web/reader/2fe326f0813ab821fg0146df#outline?noScroll=1",link:"https://book.douban.com/subject/36513648/",tags:["个人成长","思维认知","自我管理","投资理财"],desc:"这是一个将“人生”视作“公司”来经营的实战指南。作者何思平结合自身从严重口吃到演讲冠军、再到连续创业成功的跨越式经历,提出了“人生有限公司”的经营哲学。全书通过“生命立方体”模型,从认知、实践、精力管理三个维度拆解了如何通过持续输出与跨界学习,将自己打造为具有高壁垒、不可替代的“稀缺资产”。",rating:4.2,highlights:["提出“人生有限公司”经营哲学:倡导将自己视作最值得投资的上市公司,通过不断提升认知与能力壁垒,把“人生”经营成稀缺资产","系统化的“生命立方体”模型:从认知、实践、精力管理三个维度构建个人成长闭环,解决成长中的无序感与碎片化难题","聚焦个人核心竞争力:深度拆解认知力、学习力与共情力等稀缺能力的获取路径,教导读者在不同场景中通过实战验证自我价值","高度可操作的工具清单:摒弃鸡汤式说教,将自我成长拆解为具体的习惯改造与复盘清单,帮助读者在痛点与高光时刻都能通过反馈机制实现自我迭代"]},{id:"book-030",title:"成长第二曲线:跨越S型持续成长",author:"查尔斯·汉迪",cover:"https://cdn.weread.qq.com/weread/cover/65/YueWen_39427437/t6_YueWen_39427437.jpg",wereadLink:"https://weread.qq.com/web/reader/15d32ed072599d6d15daa86#outline?noScroll=1",link:"https://book.douban.com/subject/35531368/",tags:["管理学","个人成长","人生哲学","未来趋势"],desc:"管理大师查尔斯·汉迪的“人生长跑指南”。本书通过书信体形式,深度探讨了在数字时代背景下个人如何识别并跨越“第二曲线”。汉迪指出,无论组织还是个人,都受制于S型增长曲线,只有在第一曲线衰退前主动布局新的增长点,并保持内在价值的独立与进化,才能在不断变化的环境中获得持续且有意义的成长。",rating:4.5,highlights:["百岁管理大师的人生体悟:以书信体浓缩一生管理研究与个人经验,提供了从时间维度审视工作、学习与生活的全景视角","“第二曲线”理论的全面进阶:深刻揭示组织与个人的兴衰规律,教导读者如何在第一曲线的巅峰前就主动布局新的增长引擎","全场景下的持续进化方案:将第二曲线思维跨界应用于教育、职业规划、婚姻与家庭中,强调“变化才是常态”,鼓励持续自我重塑","面向Z世代的清醒处方:在科技高歌猛进的数字时代,提醒后人重视诚信、协作等软实力,保持独立判断,避免在算法与焦虑中迷失自我"]}],Me=[{id:"book-033",title:"枪炮、病菌与钢铁",author:"贾雷德·戴蒙德",cover:"https://cdn.weread.qq.com/weread/cover/99/YueWen_42766048/t6_YueWen_42766048.jpg",wereadLink:"https://weread.qq.com/web/reader/843329f0728c8ee08434fb1#outline?noScroll=1",link:"https://book.douban.com/subject/1813841/",tags:["人类历史","地理决定论","社会学","跨学科"],desc:"一部重新定义人类历史发展的宏大著作。作者贾雷德·戴蒙德通过生物学、地理学、人类学等多学科交叉视角,强有力地反驳了“种族决定论”和“西方文明优越论”。他提出,决定文明兴衰的关键并非种族,而是环境因素、地理格局以及动植物驯化的差异,这些自然条件的偶然性最终导致了技术、免疫力和权力结构的差异,从而重塑了现代世界的全球版图。",rating:4.8,highlights:["颠覆性的历史观:以环境与地理差异解释文明兴衰,有力冲击了长期流行的西方文明优越论,提供了理解人类历史的全新视角","跨学科的综合研究框架:巧妙融合生物学、地理学、历史学、社会学等多学科知识,重建人类文明演进的逻辑路径","系统揭示历史演变的机制:深入剖析农业、病菌传播与技术权力如何形成相互强化的循环,展示了文明发展背后复杂的资源互动","具备公共思想者的宏观视野:将严谨的科学研究转化为对人类命运与社会发展的深刻反思,为现代人理解自身在历史长河中的位置提供了绝佳参照"]},{id:"book-034",title:"中国社会各阶层分析",author:"梁晓声",cover:"https://cdn.weread.qq.com/weread/cover/0/yuewen_42682684/t6_yuewen_426826841728383400.jpg",wereadLink:"https://weread.qq.com/web/reader/085326e0728b493c085ade1#outline?noScroll=1",link:"https://book.douban.com/subject/35485315/",tags:["社会观察","阶层研究","现实主义"],desc:"茅盾文学奖得主梁晓声基于多年社会观察的现实题材力作。作者将快速变迁的中国社会划分为不同阶层,以平民视角细腻描摹各群体的生存状态、心理困境与阶层焦虑。全书不追求纯学术的枯燥分析,而是通过文学化的社会观察,勾勒出一幅当代中国社会的“浮世绘”,引导读者在时代坐标中找准定位,理解社会变迁背后的结构性逻辑。",rating:4.3,highlights:["平民视角下的社会“浮世绘”:通过细腻的笔触勾勒各阶层的生存逻辑与心理画像,帮助读者直观理解宏观社会结构","兼具现实痛点与精神深度:不仅呈现物质生活的差异,更深刻剖析阶层焦虑背后的价值困境,为理解当代社会提供人文参照","时代脉络中的命运书写:将个体命运置于历史事件的宏观背景中考察,展现了半个世纪以来社会变迁的深层脉络","文学笔触下的社会关怀:作为茅盾文学奖得主,作者通过富有故事性的叙事,既保留了批判性,又让文本充满了温暖的人文温度"]},{id:"book-021",title:"把自己作为方法",author:"项飙 / 吴琦",cover:"https://cdn.weread.qq.com/weread/cover/81/cpPlatform_3300003962/t6_cpPlatform_3300003962.jpg",wereadLink:"https://weread.qq.com/web/reader/d7532f80813ab680cg012708#outline?noScroll=1",link:"https://book.douban.com/subject/35092383/",tags:["社会学","访谈录","思想方法"],desc:"两代学人项飙与吴琦历时三年、跨越五地的深度对话实录。本书从项飙的个人经验切入,探讨了中国社会近半个世纪的变迁、全球化与民粹主义等宏大议题。在自我泛滥与思想受困的时代,作者提出“把自己作为方法”,指导读者如何在全球化年代重新定位自我、重建“附近”,并在个人体验与宏观叙事之间搭建起思考与行动的桥梁。",rating:4.6,highlights:["以“自我”切入回应宏大议题:示范如何在个人真实体验与全球化、社会变迁等宏观叙事之间搭建认知的桥梁","提供重建“附近”的行动指南:在自我泛滥的潮流中,指导读者如何审视现实,创造性地建设身边的小世界","兼具学术深度与极高可读性:将人类学、社会学的深刻理论洞察,巧妙融入生动的田野故事与双人生活化对谈中","跨越三年的思想碰撞:历时三年、跨越五地的持续对话结集,反思知识生产与公共讨论的真实处境"]}],$e=[{id:"book-035",title:"百岁人生:长寿时代的生活和工作",author:"琳达·格拉顿 / 安德鲁·斯科特",cover:"https://wfqqreader-1252317822.image.myqcloud.com/cover/860/22902860/t6_22902860.jpg",wereadLink:"https://weread.qq.com/web/reader/30c323e0715d784c30c1e1b#outline?noScroll=1",link:"https://book.douban.com/subject/30245089/",tags:["人生规划","长寿时代","社会学"],desc:"基于伦敦商学院的经典课程,作者琳达·格拉顿与安德鲁·斯科特提出,面对一半概率活到100岁的长寿时代,传统的“学习-工作-退休”三段式人生模式已彻底失效。本书指导读者如何重新设计人生,通过拥抱多阶段人生模型,在更长的生命周期中平衡工作、学习与休闲,并强调在财务资产之外,更要注重健康、友谊与知识等“无形资产”的持续投入与增值。",rating:4.3,highlights:["重构人生模式:打破传统的“三段式”生活范式,提出充满弹性的“多阶段人生”模型,让工作与学习不再是线性的重复","从关注财务到“无形资产”:除了养老金,强调健康、友谊、社交网络与心理韧性等“无形资产”才是维持长寿生活质量的核心动力","职场与转型的系统规划:提供针对长寿时代的职业设计思路,涵盖何时转型、如何投资自身、怎样应对不确定性等实战框架","社会与制度的深度洞察:探讨长寿如何冲击养老金体系、劳动力市场与企业模式,帮助个人在宏观变革中把握主动权"]},{id:"book-00043",title:"重启吧!我的健康人生",author:"兰根·查特吉",cover:"https://cdn.weread.qq.com/weread/cover/80/cpplatform_kbrswv3bm7cix2zlyo6wtx/t6_cpplatform_kbrswv3bm7cix2zlyo6wtx1716362285.jpg",wereadLink:"https://weread.qq.com/web/reader/e8a32e80813ab8de4g0191c2#outline?noScroll=1",link:"https://book.douban.com/subject/36899697/",tags:["生活方式","预防医学","身心健康","自我管理"],desc:"英国临床医生基于20多年行医经验写就。本书主张“生活方式即良药”,围绕休息、饮食、运动和睡眠四个领域设计了20个微小行动计划,帮助现代人通过低成本的习惯改变逆转慢性问题。",rating:4.6,highlights:["提出99%的健康取决于日常习惯而非医学治疗,强调整体干预","构建“4×5”微行动框架,涵盖休息、饮食、运动、睡眠四个维度的20个小改变","兼顾科学深度与极简实操,如“12小时进食窗口”、“10分钟高强度运动”","关注现代职场人痛点,提供“小投入、大回报”的可叠加身心健康投资策略"]},{id:"book-00040",title:"你是你吃出来的:吃对少生病,病了这样吃",author:"夏萌",cover:"https://cdn.weread.qq.com/weread/cover/86/YueWen_920661/t6_YueWen_920661.jpg",wereadLink:"https://weread.qq.com/web/reader/7bb32c305e0c557bbdeab81#outline?noScroll=1",link:"https://book.douban.com/subject/27590675/",tags:["饮食科普","营养学","健康管理"],desc:"前安贞医院营养科主任夏萌结合十余年临床经验写成。本书颠覆“低油低脂”误区,提出回归进化的“65%植物+35%动物”膳食配比,并针对14种常见慢病给出“四分法”饮食干预方案,帮助读者重建健康饮食观。",rating:5,highlights:["指出多数慢病源于“蛋白质缺乏式营养不良”,打破常规低油低脂迷思","提出清晰量化的“65%植物类+35%动物类”科学饮食结构","针对冠心病、高血压等14种常见慢病提供实操性极强的“四分法”菜单","源于十万+真实临床病例,强调“一日三餐才是真正的保健品”"]},{id:"book-00041",title:"你是你吃出来的2",author:"夏萌",cover:"https://wfqqreader-1252317822.image.myqcloud.com/cover/883/35905883/t6_35905883.jpg",wereadLink:"https://weread.qq.com/web/reader/40532d007223e15b4052fae#outline?noScroll=1",link:"https://book.douban.com/subject/35340053/",tags:["饮食指导","科普","疾病防治"],desc:"聚焦高血压、高脂血症、糖尿病等7大常见慢病,从临床营养医学角度逐一破除诸如“血压高不能吃肉”等饮食误区,提供系统的“上游-中游-下游”疾病防控思路与个体化营养处方。",rating:4.6,highlights:["专攻7大常见慢性病,为患者提供针对性的“生病了怎么吃”个体化指导","科学辟谣,破除“血压高不能吃肉”、“胆固醇高不能吃鸡蛋”等常见误区","梳理疾病发生因果链条,帮助读者从源头找到健康干预的着力点","提供从一日三餐、运动到心态调养的具体可操作生活方式清单"]}],Ge=JSON.parse('{"title":"好书推荐","description":"读书心得、推荐书籍和阅读技巧","frontmatter":{"title":"好书推荐","date":"2024-01-01T16:00:00.000Z","description":"读书心得、推荐书籍和阅读技巧","categories":["growth"],"coverImg":"https://insight-stack-1252300811.cos.ap-shanghai.myqcloud.com/img/cover/books_reading_bg.png","permalink":"/growth/books","tags":["悦读时光","资源推荐"]},"headers":[],"relativePath":"30.悦读时光/01.好书推荐.md","filePath":"30.悦读时光/01.好书推荐.md"}'),Ne={name:"30.悦读时光/01.好书推荐.md"},De=Object.assign(Ne,{setup(r){return(b,t)=>(a(),l("div",null,[t[0]||(t[0]=x("",4)),h(k,{books:g(Be)},null,8,["books"]),t[1]||(t[1]=x("",4)),h(k,{books:g(Ie)},null,8,["books"]),t[2]||(t[2]=e("h3",{id:"_2-2-商业化",tabindex:"-1"},[n("2.2 商业化 "),e("a",{class:"header-anchor",href:"#_2-2-商业化","aria-label":"Permalink to “2.2 商业化”"},"​")],-1)),t[3]||(t[3]=e("blockquote",null,[e("p",null,[n("在追逐“独角兽”和规模扩张的狂热迷思之后,真正的商业高手正在重新回归本质:"),e("strong",null,"盈利才是企业的核心护城河。"),n(" 这套书单为我们揭示了一种"),e("strong",null,"更具韧性的商业路径——“小而美”的极简经营"),n("。它教导我们如何拒绝低效的内卷与忙碌,通过“做更少但创造更多价值”的思维,打造在不确定时代下依然能保持稳定现金流的“慢公司”。")]),e("p",null,[e("strong",null,"商业的成功,往往源于敢于挑战“难而正确”的事"),n("。从皮克斯如何建立允许失败的创意土壤,到 Waze 如何通过解决被忽视的痛点实现跨越式成长,这些世界级案例证明了:卓越的组织不仅需要极简的流程与高效的分布式协作(远程办公),更需要一种“冷静”的文化,将利润置于规模之上。")])],-1)),h(k,{books:g(We)},null,8,["books"]),t[4]||(t[4]=e("h2",{id:"_3-效率与效能",tabindex:"-1"},[n("3. 效率与效能 "),e("a",{class:"header-anchor",href:"#_3-效率与效能","aria-label":"Permalink to “3. 效率与效能”"},"​")],-1)),t[5]||(t[5]=e("blockquote",null,[e("p",null,[n("在信息过载与高压竞争的现代环境中,平庸与卓越的分水岭不再是做事的速度,而是"),e("strong",null,"决策的精度与责任的边界"),n("。这套书单为我们提供了一套从个人认知到组织协作的“效能防线”:首先,它"),e("strong",null,"引导我们完成从“时钟”到“罗盘”的思维跨越,打破盲目追求速度的迷思,确保将核心精力倾注在真正产生长远复利的“重要非紧急”事务之上"),n("。 真正的效能源于对复杂性的科学驾驭:")]),e("ul",null,[e("li",null,"通过“清单革命”式的认知防护,我们将最佳实践外化为可靠的防错系统,弥补人类在极端环境下的认知局限;"),e("li",null,"“猴子管理法”则以生动的视角重塑了职场协作的责任逻辑,教我们通过有效授权拒绝无谓的干扰,释放战略思考的精力;")])],-1)),h(k,{books:g(Ye)},null,8,["books"]),t[6]||(t[6]=e("h2",{id:"_4-学习与成长",tabindex:"-1"},[n("4. 学习与成长 "),e("a",{class:"header-anchor",href:"#_4-学习与成长","aria-label":"Permalink to “4. 学习与成长”"},"​")],-1)),t[7]||(t[7]=e("blockquote",null,[e("p",null,[n("在信息爆炸与快速变革的时代,"),e("strong",null,"真正的成长不再是知识的被动堆砌,而是认知系统的彻底迭代"),n("。这套书单为我们构建了一个从底层思维到人生经营的闭环:")]),e("ul",null,[e("li",null,"首先,通过批判性思维与深度阅读夯实“元能力”,在泛滥的信息中识别本质,将他人的洞见转化为自己的血肉;"),e("li",null,"其次,利用“检索力”打破信息差,确保自己在任何领域都能快速获取高质量资源,掌握逆风而行的主动权。")]),e("p",null,[e("strong",null,"人生不是一场盲目的长跑,而是一场基于“原则”的精密经营"),n("。从达利欧的系统化决策,到纳瓦尔的财富与幸福逻辑,这些智者教导我们如何利用杠杆、坚持长期主义,将自己视作一家“人生有限公司”来经营。我们需要摆脱“优秀绵羊”式的被动驱动,通过识别成长的“第二曲线”,在巅峰时刻主动寻求突破,将自己打造成不可替代的稀缺资产。阅读这些经典,不仅是为了习得技能,更是为了在算法与焦虑的夹击中,重塑内心的宁静与独立判断的勇气。")])],-1)),h(k,{books:g(Te)},null,8,["books"]),t[8]||(t[8]=e("h2",{id:"_5-人文社科",tabindex:"-1"},[n("5. 人文社科 "),e("a",{class:"header-anchor",href:"#_5-人文社科","aria-label":"Permalink to “5. 人文社科”"},"​")],-1)),t[9]||(t[9]=e("blockquote",null,[e("p",null,"在宏观历史与微观现实间构建认知:在碎片化与不确定性并存的时代,穿透表象、直达本质的洞察力成为必需。这套单为我们开启了两扇窗:"),e("ul",null,[e("li",null,"一扇望向万年文明的宏大坐标,通过《枪炮、病菌与钢铁》的跨学科视野,拆解地理环境如何冷酷而偶然地重塑全球版图,彻底颠覆“文明优越论”的傲慢;"),e("li",null,"另一扇则照向当下社会的真实肌理,在梁晓声对各阶层生存困境的细腻描摹中,读懂大时代变革背后隐秘的结构性逻辑与阶层焦虑。")]),e("p",null,[e("strong",null,"人文思考的终极价值,在于如何将宏大叙事转化为个人的行动力量"),n("。正如项飙所倡导的“把自己作为方法”,这些著作不仅是知识的传递,更是思维的松绑。它们教导我们不再做时代的被动旁观者,而是学会在个人体验与宏观世界之间搭建桥梁,通过重建“附近”的小世界,在喧嚣中找准自我的定位。")])],-1)),h(k,{books:g(Me)},null,8,["books"]),t[10]||(t[10]=e("h2",{id:"_6-健康生活",tabindex:"-1"},[n("6. 健康生活 "),e("a",{class:"header-anchor",href:"#_6-健康生活","aria-label":"Permalink to “6. 健康生活”"},"​")],-1)),t[11]||(t[11]=e("img",{src:$,style:{width:"100%","border-radius":"8px","margin-bottom":"20px"},alt:"about site background"},null,-1)),t[12]||(t[12]=e("blockquote",null,[e("p",null,[n("在面临大概率活到100岁的“长寿时代”,传统的线性人生模式正在失效。我们需要对“健康”进行一次彻底的认知重构:"),e("strong",null,"健康不再仅仅是“没有疾病”,而是支撑我们跨越漫长生命周期、应对多阶段人生挑战的最核心“无形资产”"),n("。想要让这套生命系统长期平稳运行,真正的解法并不在医院的处方笺里,而是隐藏在我们每天的日常选择中。")]),e("p",null,[n("决定我们长期健康状态的,有 99 %取决于日常习惯。我们需要"),e("strong",null,"在休息、饮食、运动、睡眠这四个高频生活维度中,植入微小但杠杆率极高的改变"),n("(例如12小时进食窗口、10分钟高强度运动、睡前屏蔽数字通知等)。用最低的执行成本,置换身心状态的巨大回报。")])],-1)),h(k,{books:g($e)},null,8,["books"])]))}});export{Ge as __pageData,De as default}; +import{d as x,p as A,h as a,z as h,Y as B,s as I,g as r,y as _,v as P,i as e,W as v,x as c,F as p,t as f,S as l,T as W,_ as C,r as j,c as Y,k as $,U as M,l as g}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const T="/img/cover/health_bg.png",N={class:"book-panel__drawer"},V={class:"book-panel__header-meta"},G={class:"book-panel__title"},D={class:"book-panel__author"},F={class:"book-panel__body"},Z={class:"book-panel__top-bar"},H={class:"book-panel__top-left"},J={class:"book-panel__tags"},O={key:0,class:"book-panel__rating"},R={class:"stars"},E={key:0,viewBox:"0 0 24 24",fill:"currentColor"},K={key:1,viewBox:"0 0 24 24",class:"half-star"},Q=["id"],X=["clip-path"],U={key:2,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"1.5"},ee={class:"rating-text"},te={class:"book-panel__links"},oe=["href"],ae={width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",style:{"flex-shrink":"0"}},le=["href"],re={width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",style:{"flex-shrink":"0"}},ne={class:"book-panel__section"},se={class:"book-panel__desc"},ie={key:0,class:"book-panel__section"},de={class:"book-panel__highlights"},ce=x({__name:"BookDetailPanel",props:{book:{},open:{type:Boolean},heroColor:{},tagColors:{}},emits:["close"],setup(n,{emit:b}){const t=b;return(w,o)=>(a(),A(W,{to:"body"},[h(B,{name:"panel-slide"},{default:I(()=>[n.open&&n.book?(a(),r("div",{key:0,class:"book-panel",onClick:o[2]||(o[2]=P(i=>t("close"),["self"]))},[e("div",{class:"book-panel__overlay",onClick:o[0]||(o[0]=i=>t("close"))}),e("div",N,[e("div",{class:"book-panel__header",style:v({background:n.heroColor})},[e("button",{class:"book-panel__close",title:"关闭",onClick:o[1]||(o[1]=i=>t("close"))},[...o[3]||(o[3]=[e("svg",{width:"14",height:"14",viewBox:"0 0 16 16",fill:"none"},[e("path",{d:"M12 4L4 12M4 4l8 8",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round"})],-1)])]),e("div",V,[e("h2",G,c(n.book.title),1),e("p",D,c(n.book.author),1)])],4),e("div",F,[e("div",Z,[e("div",H,[e("div",J,[(a(!0),r(p,null,f(n.book.tags,(i,m)=>(a(),r("span",{key:i,class:"book-panel__tag",style:v({background:n.tagColors[m%n.tagColors.length].bg,color:n.tagColors[m%n.tagColors.length].text})},c(i),5))),128))]),n.book.rating!=null?(a(),r("div",O,[o[8]||(o[8]=e("span",{class:"rating-label"},"推荐指数:",-1)),e("div",R,[(a(),r(p,null,f(5,i=>e("span",{key:i,class:"star"},[i<=Math.floor(n.book.rating)?(a(),r("svg",E,[...o[4]||(o[4]=[e("path",{d:"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"},null,-1)])])):i===Math.ceil(n.book.rating)&&n.book.rating%1!==0?(a(),r("svg",K,[e("defs",null,[e("clipPath",{id:"clip-"+n.book.id},[...o[5]||(o[5]=[e("rect",{x:"0",y:"0",width:"12",height:"24"},null,-1)])],8,Q)]),o[6]||(o[6]=e("path",{class:"star-empty",d:"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z",fill:"none",stroke:"currentColor","stroke-width":"1.5"},null,-1)),e("path",{class:"star-filled",d:"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z",fill:"currentColor","clip-path":"url(#clip-"+n.book.id+")"},null,8,X)])):(a(),r("svg",U,[...o[7]||(o[7]=[e("path",{d:"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"},null,-1)])]))])),64))]),e("span",ee,c(n.book.rating.toFixed(1)),1)])):_("",!0)]),e("div",te,[e("a",{href:n.book.link,target:"_blank",rel:"noopener",class:"book-panel__link-btn"},[(a(),r("svg",ae,[...o[9]||(o[9]=[e("path",{d:"M18 13v6a2 2 0 01-2 2H5a2 2 0 01-2-2V8a2 2 0 012-2h6M15 3h6v6M10 14L21 3",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},null,-1)])])),o[10]||(o[10]=l(" 豆瓣 ",-1))],8,oe),n.book.wereadLink?(a(),r("a",{key:0,href:n.book.wereadLink,target:"_blank",rel:"noopener",class:"book-panel__link-btn"},[(a(),r("svg",re,[...o[11]||(o[11]=[e("path",{d:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z",fill:"currentColor"},null,-1)])])),o[12]||(o[12]=l(" 微信读书 ",-1))],8,le)):_("",!0)])]),o[15]||(o[15]=e("div",{class:"book-panel__divider"},null,-1)),e("section",ne,[o[13]||(o[13]=e("h3",{class:"book-panel__section-title"},[e("span",{class:"book-panel__section-icon"},"📖"),l(" 内容简介 ")],-1)),e("p",se,c(n.book.desc),1)]),n.book.highlights&&n.book.highlights.length>0?(a(),r("section",ie,[o[14]||(o[14]=e("h3",{class:"book-panel__section-title"},[e("span",{class:"book-panel__section-icon"},"✨"),l(" 书籍亮点 ")],-1)),e("ul",de,[(a(!0),r(p,null,f(n.book.highlights,(i,m)=>(a(),r("li",{key:m,class:"book-panel__highlight-item"},c(i),1))),128))])])):_("",!0)])])])):_("",!0)]),_:1})]))}}),he=C(ce,[["__scopeId","data-v-1ddfc013"]]),be={class:"book-list"},ue=["onClick"],ge=["src","alt"],ke={class:"book-cover__overlay"},pe={key:0,class:"book-cover__hint"},we=["href"],me={class:"book-info"},_e={class:"book-info__title"},fe={class:"book-info__author"},qe={key:0,class:"book-info__rating"},ve={class:"stars"},je={key:0,viewBox:"0 0 24 24",fill:"currentColor"},Le={key:1,viewBox:"0 0 24 24",class:"half-star"},ye=["id"],Se=["clip-path"],xe={key:2,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"1.5"},Pe={class:"rating-text"},Ce={class:"book-info__tags"},ze={class:"book-info__desc"},Ae=x({__name:"BookRecommend",props:{books:{}},setup(n){const b=["linear-gradient(135deg, #e8f0fe 0%, #c7d9fd 100%)","linear-gradient(135deg, #e6f4ea 0%, #b7dfc4 100%)","linear-gradient(135deg, #fff3e0 0%, #ffd9a0 100%)","linear-gradient(135deg, #fce4ec 0%, #f8b4c8 100%)","linear-gradient(135deg, #ede7f6 0%, #cdb8ee 100%)","linear-gradient(135deg, #e0f7fa 0%, #9ee8f0 100%)"],t=[{bg:"#e8f0fe",text:"#3b5bdb"},{bg:"#e6f4ea",text:"#2e7d32"},{bg:"#fff3e0",text:"#e65100"},{bg:"#fce4ec",text:"#c2185b"},{bg:"#ede7f6",text:"#6a1b9a"},{bg:"#e0f7fa",text:"#00838f"}],w=j(null),o=j(0),i=j(!1),m=Y(()=>b[o.value%b.length]);function z(q,d){q.withPanel!==!1&&(w.value?.id===q.id&&i.value?L():(w.value=q,o.value=d,i.value=!0))}function L(){i.value=!1,setTimeout(()=>{w.value=null},300)}return(q,d)=>(a(),r(p,null,[e("div",be,[(a(!0),r(p,null,f(n.books,(s,y)=>(a(),r("div",{key:s.id,class:$(["book-card",{"book-card--active":w.value?.id===s.id&&i.value}]),onClick:u=>z(s,y)},[e("div",{class:"book-cover",style:v({background:b[y%b.length]})},[s.cover?(a(),r("img",{key:0,src:s.cover,alt:s.title,class:"book-cover__img"},null,8,ge)):_("",!0),e("div",ke,[s.withPanel!==!1?(a(),r("span",pe,"点击查看详情")):(a(),r("a",{key:1,href:s.link,target:"_blank",rel:"noopener",class:"book-cover__hint",onClick:d[0]||(d[0]=P(()=>{},["stop"]))},"查看豆瓣",8,we))])],4),e("div",me,[e("div",_e,"《"+c(s.title)+"》",1),e("div",fe,c(s.author),1),s.rating!=null?(a(),r("div",qe,[e("div",ve,[(a(),r(p,null,f(5,u=>e("span",{key:u,class:"star"},[u<=Math.floor(s.rating)?(a(),r("svg",je,[...d[1]||(d[1]=[e("path",{d:"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"},null,-1)])])):u===Math.ceil(s.rating)&&s.rating%1!==0?(a(),r("svg",Le,[e("defs",null,[e("clipPath",{id:"card-clip-"+s.id},[...d[2]||(d[2]=[e("rect",{x:"0",y:"0",width:"12",height:"24"},null,-1)])],8,ye)]),d[3]||(d[3]=e("path",{class:"star-empty",d:"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z",fill:"none",stroke:"currentColor","stroke-width":"1.5"},null,-1)),e("path",{class:"star-filled",d:"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z",fill:"currentColor","clip-path":"url(#card-clip-"+s.id+")"},null,8,Se)])):(a(),r("svg",xe,[...d[4]||(d[4]=[e("path",{d:"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"},null,-1)])]))])),64))]),e("span",Pe,c(s.rating.toFixed(1)),1)])):_("",!0),e("div",Ce,[(a(!0),r(p,null,f(s.tags,(u,S)=>(a(),r("span",{key:u,class:"tag",style:v({background:t[S%t.length].bg,color:t[S%t.length].text})},c(u),5))),128))]),e("p",ze,c(s.desc),1)])],10,ue))),128))]),h(he,{book:w.value,open:i.value,"hero-color":m.value,"tag-colors":t,onClose:L},null,8,["book","open","hero-color"])],64))}}),k=C(Ae,[["__scopeId","data-v-fd79cd55"]]),Be=[{id:"book-001",title:"心中有数:生活中的数学思维",author:"刘雪峰",cover:"https://cdn.weread.qq.com/weread/cover/39/3300018939/t6_3300018939.jpg",wereadLink:"https://weread.qq.com/web/reader/df6323a0813ab6de5g019a31#outline?noScroll=1",link:"https://book.douban.com/subject/35749693/",tags:["数学思维","科普","决策"],desc:"本书通过大量贴近日常的例子,展示数学思维如何优化我们的生活决策。作者用概率、统计、最优化等数学工具,为生活、职场、人际交往中的权衡问题提供分析框架,帮助读者在面对不确定性时像计算机一样找到“最优解”。",rating:4.9,highlights:["将大数定律、最小二乘法等硬核数学概念与日常生活巧妙结合","提供应对不确定性和多目标抉择的科学决策框架","强调数学不仅是公式计算,更是看世界、优化人生的高效思维工具"]},{id:"book-0020",title:"智慧的疆界:从图灵机到人工智能",author:"周志明",cover:"https://cdn.weread.qq.com/weread/cover/92/YueWen_23637052/t6_YueWen_23637052.jpg",wereadLink:"https://weread.qq.com/web/reader/b9732f007168ac3cb976eca#outline?noScroll=1",link:"https://book.douban.com/subject/30379536/",tags:["人工智能","科技史","通识读物"],desc:"本书是一部面向大众的人工智能通识读物。作者周明以时间为主线,将人工智能的发展历程、关键人物与里程碑事件串联起来,从五个维度展开:学术理论、历史沿革、技术应用、研究成果以及面临的困难与未来挑战。全书旨在用通俗的语言和巧妙的结构,把人工智能从“阳春白雪”的学术殿堂带到公众视野,帮助读者理解 AI 能做什么、做不到什么,以及背后的技术与思想根源。",rating:5,highlights:["以时间为主线,清晰梳理人工智能的发展脉络与里程碑","深入浅出,用通俗语言将复杂的学术理论带入公众视野","客观剖析,帮助读者准确界定AI“能做什么”与“做不到什么”"]},{id:"book-004",title:"为什么伟大不能被计划",author:"肯尼斯·斯坦利 / 乔尔·雷曼",cover:"https://cdn.weread.qq.com/weread/cover/22/cpplatform_wfdzhk1dx7ig9aep4gagof/t6_cpplatform_wfdzhk1dx7ig9aep4gagof1686304376.jpg",wereadLink:"https://weread.qq.com/web/reader/0bf32020813ab7e6bg016510#outline?noScroll=1",link:"https://book.douban.com/subject/36357804/",tags:["人工智能","创新思维","认知科学"],desc:"本书由两位前沿AI科学家合著,提出了颠覆传统“目标-计划”思维的全新视角。结合AI研究实践,书中论证了伟大成就往往并非出自精心设计的蓝图,而是源于对未知的好奇、随机探索与不断试错。通过“寻宝者思维”和“踏脚石模型”等方法,为读者在高度不确定的环境中激发突破性创新提供了具体的行动框架。",rating:4.5,highlights:["颠覆传统的“目标论”,论证伟大成就源自对未知的好奇与无边界的探索","提供“寻宝者思维”“踏脚石模型”“新奇性探索”三大可操作的认知与实践工具","扎根OpenAI等前沿机构的实证背景,其启发意义跨学科适用于科研、商业及人生规划"]},{id:"book-003",title:"这就是ChatGPT",author:"斯蒂芬·沃尔弗拉姆",cover:"https://cdn.weread.qq.com/weread/cover/24/cpplatform_4cn8w4tmgzntjobg9ffeny/t6_cpplatform_4cn8w4tmgzntjobg9ffeny1703648785.jpg",wereadLink:"https://weread.qq.com/web/reader/74332a90813ab86c4g019d98#outline?noScroll=1",link:"https://book.douban.com/subject/36449803/",tags:["人工智能","大模型","ChatGPT"],desc:"本书由著名科学家斯蒂芬·沃尔弗拉姆撰写,全景式拆解了ChatGPT的内部工作机制。作者用通俗语言解释了神经网络和自回归架构等核心技术,探讨了简单的计算规则如何涌现出令人惊叹的智能,帮助读者深刻理解大语言模型为何能生成高质量的人类水平文本。",rating:4.3,highlights:["全景拆解核心技术:深入浅出地讲清ChatGPT背后的神经网络与自回归架构","独特的大师视角:将大模型视为“简单的计算规则”涌现复杂智能的绝佳范例","兼顾技术与商业影响:结合算力规模与行业冲击,全面探讨AI时代的机遇与挑战"]},{id:"book-0030",title:"人工智能:现代方法(第4版)(上下册)",author:"[美]斯图尔特·罗素(Stuart Russell) / [美]彼得·诺维格(Peter Norvig)",cover:"https://cdn.weread.qq.com/weread/cover/33/cpplatform_8rthznqfhsjuz5fswwn6kx/t6_cpplatform_8rthznqfhsjuz5fswwn6kx1675928213.jpg",wereadLink:"https://weread.qq.com/web/reader/fc332020813ab7942g0102ad#outline?noScroll=1",link:"https://book.douban.com/subject/36152133",tags:["人工智能","教材","理论实践结合","经典著作","计算机科学"],desc:"本书是人工智能领域的经典权威教材,系统、深入地探讨AI领域的理论与实践,以统一风格融合当今流行的AI思想与术语到前沿应用中,真正实现理论与实践相结合。全书分7个部分共28章,理论部分涵盖逻辑、概率、连续数学、感知、推理、学习、行动及公平、信任、社会公益和安全等社会议题;实践部分选取微电子设备、机器人行星探测器、在线服务、AlphaZero、人形机器人、自动驾驶、AI辅助医疗等热门场景。由加州大学伯克利分校教授斯图尔特·罗素与前谷歌研究总监彼得·诺维格联合撰写,被全球1500多所高校采用,适合作为AI相关专业本科生和研究生教材,也可作为专业人员的参考书。",rating:5,highlights:["体系完整覆盖面广,7个部分28章构成自洽的AI理论主线,涵盖核心理论与前沿议题","理论与实践并重,既阐述核心算法与模型,又展示在热门场景中的落地实例,便于知识迁移","紧跟前沿关注社会议题,专门讨论AI伦理与安全,引导思考技术与社会的交互责任","一站式权威参考,兼具教材属性与专业参考价值,适配高校教学与产业实践双重需求","现代理念贯穿始终,通过最新案例体现AI进展与行业趋势,呈现“活”的AI生态"]},{id:"book-0031",title:"模型思维:简化世界的人工智能模型",author:"龚才春",cover:"https://cdn.weread.qq.com/weread/cover/26/YueWen_38601826/t6_YueWen_38601826.jpg",wereadLink:"https://weread.qq.com/web/reader/5a8326e0724d04625a8e740#outline?noScroll=1",link:"https://book.douban.com/subject/35488925/",tags:["模型思维","人工智能","算法模型","机器学习","入门实践"],desc:"本书聚焦“如何用模型简化世界”的核心主题,将人工智能在现实业务中面临的难题归纳为权重、状态、序列、表示、相似、分类六大问题,并围绕该框架讲解对应模型思路与算法。书中弱化复杂数学公式,以大量生活化、业务化案例阐释模型理论与落地场景,帮助读者建立“模型—场景”映射关系,降低AI模型学习门槛,既是人工智能初学者的入门读物,也可为企业工程师、科研人员提供实践参考,适合各类读者学习并将模型思维应用到生活与工作中。",rating:4.8,highlights:["以“六大问题”框架串联AI模型,可按场景快速检索适配的模型思路","侧重落地实践,搭配大量生活化与业务案例,助力建立“模型—场景”映射","降低学习门槛,少数学公式、多直观案例,兼顾初学者与工程落地需求","受众群体广泛,适配工程师、科研人员及普通读者,可迁移模型思维至实际场景"]},{id:"book-005",title:"你看起来好像……我爱你:AI的工作原理以及它为这个世界带来的稀奇古怪",author:"贾内尔·沙内",cover:"https://wfqqreader-1252317822.image.myqcloud.com/cover/970/39481970/t6_39481970.jpg",wereadLink:"https://weread.qq.com/book-detail?type=1&senderVid=40710128&v=f9a32c10725a7272f9a14f9&wtheme=white&wfrom=app&wvid=40710128&scene=bottomSheetShare",link:"https://book.douban.com/subject/35407136/",tags:["人工智能","趣味科普","漫画算法"],desc:"这是一部写给普通读者的人工智能趣味科普读物。作者贾内尔·沙内结合生活化的比喻和超级可爱的漫画,深入浅出地讲解了AI的基本工作原理、实际应用及其局限性。书中通过大量幽默的AI实验与“翻车”案例,带领读者在轻松捧腹的氛围中,准确理解算法能做什么、不能做什么。",rating:4.2,highlights:["幽默可爱的漫画导览:用插图和通俗语言将“深度学习”“神经网络”等抽象概念可视化","丰富的趣味实验案例:通过精选的AI“翻车”故事,直观揭示算法背后的逻辑与潜在偏差","客观建立AI认知:在展示AI强大能力的同时,明确指出其在语境理解和处理模糊信息时的短板"]},{id:"book-006",title:"AI经济:机器人时代的工作、财富和社会福利",author:"罗杰·布特尔",cover:"https://cdn.weread.qq.com/weread/cover/30/YueWen_38229387/t6_YueWen_38229387.jpg",wereadLink:"https://weread.qq.com/web/reader/653320207247558b65332f5#outline?noScroll=1",link:"https://book.douban.com/subject/35433060/",tags:["人工智能","经济学","社会学","未来趋势"],desc:"本书由知名经济学家罗杰·布特尔撰写,聚焦AI与机器人技术对经济和社会的深远影响。作者拨开艰涩的科技术语,从经济增长、通货膨胀及财富分配等宏观视角,理性剖析AI革命将如何重塑我们的工作、教育与休闲方式,以乐观的姿态为迎接未来的社会变革指明路径。",rating:4.1,highlights:["宏观经济视角解析:深入探讨AI对经济增长、通货膨胀、财富与权力分配的真实影响","全景式社会洞察:全面检视机器人时代下,人类教育体系、工作模式与休闲形态的深刻变革","理性乐观的未来指南:拒绝技术恐慌,为个人与社会在变迁的世界中提供清晰可行的应对计划"]}],Ie=[{id:"book-007",title:"做对产品",author:"阿尔贝托·索维亚",cover:"https://cdn.weread.qq.com/weread/cover/53/YueWen_40877841/t6_YueWen_40877841.jpg",wereadLink:"https://weread.qq.com/web/reader/254322a0726fbf1125472c9#outline?noScroll=1",link:"https://book.douban.com/subject/35607961/",tags:["产品思维","创业","商业方法论"],slogan:"为什么有些产品注定失败,有些产品却能大获成功?来自谷歌与斯坦福的产品工具和产品战术。",desc:"谷歌首任产品总监阿尔贝托·索维亚结合在谷歌、斯坦福的实战经验与自身代价高昂的创业失败经历,总结出的一套防败手册。书中揭示了新产品高达90%的“市场失败律”,并创新性地提出了“预型”(Pre型)理念,指导团队在正式开发前,以极低的成本和真实数据快速验证关键假设,确保把创意打磨成“正确的它”。",rating:4.8,highlights:["揭示残酷的市场失败律:正视90%新产品必然失败的商业常态,并以此倒推破局的实战方法论","首创“预型”(Pre型)概念:提供8大测试工具,主张用极低成本和小规模试错快速逼近正确的产品形态","强调真实数据驱动决策:辅以特斯拉、谷歌等完整案例回溯,教导团队将决策建立在客观证据而非主观直觉之上"]},{id:"book-009",title:"俞军产品方法论",author:"俞军",cover:"https://cdn.weread.qq.com/weread/cover/47/YueWen_28165041/t6_YueWen_28165041.jpg",wereadLink:"https://weread.qq.com/web/reader/1cc3252071adc3b11cc0162#outline?noScroll=1",link:"https://book.douban.com/subject/34907971/",tags:["产品思维","产品经理","互联网","方法论"],desc:"“百度贴吧之父”俞军二十余年产品实践与思考的系统总结。本书将产品经理定义为“以科学方法研究人性并转化为商业方案”的交叉学科,深入解析了用户模型、交易模型和决策模型三大核心框架,为产品人提供了一套在不确定环境中权衡多方利益的实战指南。",rating:4.4,highlights:["沉淀二十年行业经验:从广为流传的“PM12条”到系统化的产品哲学,展现顶尖产品经理的认知迭代史","三大核心模型拆解:深度剖析用户模型与交易模型,指导如何通过让交易发生来创造“有利可图”的真实用户价值","兼顾科学与人文视角:强调批判性思维的运用,并清晰梳理了从新人到顶尖大牛的能力进阶路径"]},{id:"book-016",title:"策略产品经理:模型与方法论",author:"青十五",cover:"https://cdn.weread.qq.com/weread/cover/31/cpplatform_gheeqe7hjb2czyzthzf5nm/t6_cpplatform_gheeqe7hjb2czyzthzf5nm1735654872.jpg",wereadLink:"https://weread.qq.com/web/reader/4de32800813ab98d5g01286b#outline?noScroll=1",link:"https://book.douban.com/subject/35218721/",tags:["产品经理","策略产品","算法思维"],desc:"本书围绕“策略产品经理”这一复合角色,系统性地构建了从理念到实践的完整知识框架。作者从机器学习理论与经济学视角出发,结合推荐、搜索、广告、风控等核心业务场景,深入浅出地讲解了函数建模与策略应用,并对策略产品经理的核心能力与团队建设给出了详尽指导。",rating:3.9,highlights:["系统化的角色认知建构:清晰界定策略产品经理的时代背景、职责边界与工作内容,为从业者夯实概念基础","跨学科的模型与业务结合:利用机器学习的函数方法论与经济学理论,深度剖析推荐、搜索、广告、风控及定价等真实业务场景的解法","硬核算法的通俗化解析:深入浅出地拆解机器学习本质、常见算法及深度学习前沿技术,帮助产品经理真正理解策略背后的技术支撑","可落地的团队建设指南:全面拆解数据分析、沟通与项目管理等核心能力项,并针对不同产品生命周期提供策略团队的组建思路"]},{id:"book-008",title:"创造:用非传统方式做有价值的事",author:"托尼·法德尔",cover:"https://cdn.weread.qq.com/weread/cover/53/cpPlatform_tzdqT27m3vyaHnX5o8Vbwk/t6_cpPlatform_tzdqT27m3vyaHnX5o8Vbwk.jpg",wereadLink:"https://weread.qq.com/web/reader/13832ac0813ab725fg018645#outline?noScroll=1",link:"https://book.douban.com/subject/36071759/",tags:["产品思维","管理学","创业"],desc:"本书是iPod、iPhone、Nest等爆款产品幕后推手托尼·法德尔30余年职业经历的智慧结晶。作者毫无保留地分享了他在产品设计、团队管理、职业选择和公司经营等方面的“非传统”方法论,帮助读者在各自的领域内刻意练习创造力,做真正有价值的事。",rating:4.9,highlights:["源自顶级创新者的实战经验:连续打造iPod、iPhone等划时代产品的亲历复盘与真实反面教训","覆盖从个人到公司的完整路径:系统解答职业选择、产品设计、团队管理与企业经营等核心问题","提供可复制的“非传统”方法论:强调“亮点思维”与持续复盘,教导读者以反常规的视角刻意练习创造力"]},{id:"book-010",title:"产品思维",author:"刘飞",cover:"https://cdn.weread.qq.com/weread/cover/56/YueWen_25568738/t6_YueWen_25568738.jpg",wereadLink:"https://weread.qq.com/web/reader/38332ce0718625e23831fe7#outline?noScroll=1",link:"https://book.douban.com/subject/33456375/",tags:["产品思维","产品经理","个人成长","互联网"],desc:"实战派产品经理刘飞结合在一线大厂的丰富经验,围绕产品人如何实现能力跃迁展开的底层能力指南。全书掰开揉碎地讲解了认知盲点与实践痛点,通过“认知用户”“创造价值”和“产品落地”三大核心板块,系统拆解了从建立用户模型、高质量决策到快速迭代验证的完整产品方法论。",rating:4.2,highlights:["三大核心板块系统拆解:完整覆盖“认知用户”“创造价值”与“产品落地”的产品闭环","直击痛点的一线实战经验:毫无保留地分享实战中新手迫切需要却难以获取的隐性知识","聚焦底层能力与思维升维:不仅教授落地方法,更注重决策质量与思维模式的跃迁"]},{id:"book-011",title:"产品思维:创新设计的六条法则(全彩)",author:"张印帅",cover:"https://wfqqreader-1252317822.image.myqcloud.com/cover/253/26687253/t6_26687253.jpg",wereadLink:"https://weread.qq.com/web/reader/a823297071973715a8202b0#outline?noScroll=1",link:"https://book.douban.com/subject/34859540/",tags:["产品设计","创新思维","方法论","设计灵感"],desc:"本书围绕作者张印帅多年产品设计实践总结出的6条创意公式展开,旨在帮助读者系统化地获取设计灵感并解决创新难题。全书通过大量经典案例,详细解析了从发散思考到重组创新的全过程,并在最后提供了从需求到草图再到最终方案的完整项目落地演示。",rating:4,highlights:["提炼6条实用的创新设计公式:将发散思考与重组创新系统化,打造可复用的设计灵感库","丰富的经典设计案例解析:详细展示“问题+方法”、“1+1>2”等法则在真实产品设计中的应用","呈现从需求到方案的落地全流程:通过综合案例演示概念打磨与草图设计的实战过程"]}],We=[{id:"book-012",title:"小而美:持续盈利的经营法则",author:"萨希尔·拉文吉亚",cover:"https://cdn.weread.qq.com/weread/cover/91/cpplatform_vl4abrrrqgxnry833gcrtt/t6_cpplatform_vl4abrrrqgxnry833gcrtt1677578056.jpg",wereadLink:"https://weread.qq.com/web/reader/02932980813ab7a43g012e77#outline?noScroll=1",link:"https://book.douban.com/subject/36280425/",tags:["创业","商业模式","极简主义"],desc:"本书打破了硅谷盲目追求“独角兽”的扩张迷思,聚焦于“规模不是唯一出路”的商业现实。作者结合创立Gumroad的亲身经历,提出了“极简创业经营”理念。全书指导创业者与管理者如何通过从社区切入、聚焦核心能力、精简团队等方式,用最少的资源打造出不仅能活下去,而且还能持续盈利的“慢公司”。",rating:5,highlights:["颠覆传统的扩张迷思:提出盈利至上而非规模至上,将持续赚钱和实际利润作为衡量企业成功的核心标准","可落地的极简法则:总结出“越少越好”“瞄准前100个客户”等7条创业清单,构建从定位、产品到销售的完整闭环","社区驱动的商业逻辑:提倡从虚拟社区入手,以“贡献-创作-教学”的方式低成本验证产品形态并获取早期信任","打造高韧性的“慢公司”:结合疫情与远程办公背景,展示如何通过精简组织和分布式协作,在不确定的时代保持稳定的现金流"]},{id:"book-013",title:"做难而正确的事:进步最快的方式",author:"尤里·莱文",cover:"https://cdn.weread.qq.com/weread/cover/53/cpplatform_bunxjyygj8m9stnwcgwqqk/t6_cpplatform_bunxjyygj8m9stnwcgwqqk1728876401.jpg",wereadLink:"https://weread.qq.com/web/reader/aa032fb0813ab9461g018406#outline?noScroll=1",link:"https://book.douban.com/subject/37054102/",tags:["创业","产品思维","商业管理"],desc:"Waze联合创始人尤里·莱文写给创业者和管理者的行动指南。作者结合连续打造两家估值超10亿美元公司的实战经验,提出“先做难事、再做正确事”的核心哲学。全书通过13个阶段的系统拆解,指导读者如何寻找真正的用户痛点、构建高价值产品,并在不确定的环境中通过不断复盘实现跨越式成长。",rating:4.9,highlights:["世界级创业者的实战复盘:连续打造两家独角兽公司的创始人亲授,提供极具可信度的第一手商业洞察与落地经验","践行“难而正确”的核心哲学:强调不追逐短期热点,而是去解决效率极低却被忽视的痛点,以此建立坚实的商业护城河","覆盖从0到1的全周期指南:系统拆解从寻找痛点、产品构建、融资运作到团队管理的13个关键阶段,提供可操作的行动清单","直面失败的心理韧性建设:不回避挫折,将“从错误中学习”提炼为核心方法,为身处高压环境的读者提供情感共鸣与心理支持","广泛的跨场景应用价值:书中给出的决策工具不仅适用于初创团队,同样能为大公司内部创新及个人职业认知升级提供指导"]},{id:"book-015",title:"创新公司:皮克斯的启示",author:"艾德·卡特姆",cover:"https://cdn.weread.qq.com/weread/cover/20/YueWen_814380/t6_YueWen_814380.jpg",wereadLink:"https://weread.qq.com/web/reader/2ef329605c6d2c2efeeb70d#outline?noScroll=1",link:"https://book.douban.com/subject/26314955/",tags:["创新思维","组织文化","企业管理"],desc:"皮克斯联合创始人艾德·卡特姆结合《玩具总动员》《机器人瓦力》等经典动画的幕后制作故事,深度揭示了皮克斯如何长期保持创意领先的秘密。本书不仅详述了皮克斯从初创到壮大的历程,更抽丝剥茧地解析了其在团队文化、跨部门协作、人才培养和允许失败等方面的独特创意管理机制,为各类组织提供了可复制的创新指南。",rating:4.5,highlights:["揭秘“皮克斯奇迹”背后的管理哲学:通过14部经典动画的真实幕后故事,展示创意从无到有、再到票房口碑双赢的全过程","深度解析创新土壤的搭建:阐述如何通过允许失败的文化、流程设计和激励机制,将“不断推动创新”彻底融入公司DNA","提供跨行业可复用的管理工具:总结项目立项、跨部门协作与风险控制的具体做法,为不同规模和行业的企业提供落地的实战模板"]},{id:"book-017",title:"重来:更为简单的商业思维",author:"贾森·弗里德 / 戴维·海涅迈尔·汉森",cover:"https://cdn.weread.qq.com/weread/cover/1/YueWen_635904/t6_YueWen_635904.jpg",wereadLink:"https://weread.qq.com/web/reader/0363228059b4000363b29e9#outline?noScroll=1",link:"https://book.douban.com/subject/5320866/",tags:["商业思维","创业","企业管理","极简主义"],desc:"37signals联合创始人基于十年创业实战经验,写给职场人与创业者的极简商业法则。本书摒弃了传统的MBA术语与复杂的商业教条,以“辛辣、直接、靠谱”的语言,颠覆了关于项目管理、人才招聘、产品设计与企业文化的常规认知,教导读者如何在真实的商业世界中“做更少,但创造更多价值”。",rating:4.3,highlights:["颠覆传统的极简商业哲学:反叛复杂的商业教条,主张“做更少,创造更多”,通过最小可行步骤降低试错成本并快速迭代","源自37signals的十年实战精髓:覆盖从项目管理、产品设计到市场营销的完整链条,提供不讲废话、拿来即用的行动指南","重塑职场与团队管理的认知:提出诸多务实且反常规的观点(如严苛的简历筛选标准),打造基于信任与结果导向的高效团队","适用面极广的实操手册:无论是寻求突破的精英企业家、小团队创业者,还是渴望提升工作效率的普通职场人,都能直接对照落地"]},{id:"book-018",title:"重来2:更为简单高效的远程工作方式",author:"贾森·弗里德 / 戴维·海涅迈尔·汉森",cover:"https://cdn.weread.qq.com/weread/cover/38/YueWen_635721/t6_YueWen_635721.jpg",wereadLink:"https://weread.qq.com/web/reader/46b3220059b34946b517012#outline?noScroll=1",link:"https://book.douban.com/subject/25861795/",tags:["企业管理","远程工作","工作方式","团队协作"],desc:"Basecamp(原37signals)创始人基于自身团队多年的全球分布式协作经验,为企业和个人提供的一套远程工作“思想升级包”。本书直面行业争议,破解了“创新只能面对面”及“文化会淡化”等常见误区,并系统提供了借助异步沟通、协作工具与流程设计来打造高效、人性化远程团队的实战指南。",rating:4.1,highlights:["提供思想层面的“升级包”:直击传统办公室痛点,用真实数据与反例打破关于远程办公的固有认知误区","第一手的分布式团队管理经验:Basecamp创始人亲授,展示如何突破地域限制招募顶尖人才,并保持健康、高效的工作节奏","系统可落地的工具与流程方法:详述如何利用协作工具降低管理成本,让远程工作从“特殊福利”真正转变为可持续的主流组织模式"]},{id:"book-019",title:"重来3:做得更少,但赚得更多",author:"贾森·弗里德 / 戴维·海涅迈尔·汉森",cover:"https://cdn.weread.qq.com/weread/cover/62/cpplatform_tqth8pnlq8h9ing5uciwhi/t6_cpplatform_tqth8pnlq8h9ing5uciwhi1748502715.jpg",wereadLink:"https://weread.qq.com/web/reader/b6a32ed0813ab9fb5g015181#outline?noScroll=1",link:"https://book.douban.com/subject/37367276/",tags:["工作方式","反内卷","企业文化"],desc:"Basecamp创始人带来的“反内卷”与“反过度忙碌”的管理指南。作者基于近20年带领54人团队服务全球10万家企业的成功经验,直击现代企业盲目扩张、无效加班等八大症结。全书主张以“冷静”颠覆“忙碌”文化,指导企业和个人通过40小时工作制、拒绝KPI和异步沟通等极简方式,在不牺牲生活质量的前提下实现健康发展与持续盈利。",rating:4.2,highlights:["以“冷静”颠覆“忙碌”文化:倡导高效比高产更重要,用稳定的节奏替代疯狂加班的内卷常态","直击现代企业八大症结:深度诊断快速扩张、无效加班、会议泛滥与目标绑架等痛点,提供对症下药的思路","提供四大可落地的管理工具:引入40小时工作制、拒绝硬性KPI、推行非实时沟通,坚持利润优先于规模","源自Basecamp的真实反向案例:展示“小而美”团队如何通过“少做但做好”的策略,跑赢新经济并保持高利润"]}],Ye=[{id:"book-024",title:"要事第一",author:"史蒂芬·柯维 / 罗杰·梅里尔 / 丽贝卡·梅里尔",cover:"https://cdn.weread.qq.com/weread/cover/57/yuewen_33091834/t6_yuewen_330918341686208943.jpg",wereadLink:"https://weread.qq.com/web/reader/f523268071f8f0faf52b806#outline?noScroll=1",link:"https://book.douban.com/subject/1028372/",tags:["时间管理","自我管理","经典思维"],desc:"作为《高效能人士的七个习惯》的延伸与加强版,本书提出了颠覆传统的“第四代时间管理”方法。作者强调,比提升做事速度(时钟)更重要的是找准人生的方向(罗盘)。全书指导读者通过自我意识的觉醒,以原则和价值观为中心,将精力聚焦于“重要而不紧急”的长期目标上,从而在繁忙的现代生活中真正做到“要事第一”。",rating:4.5,highlights:["从“时钟”到“罗盘”的思维跨越:打破一味追求“更快、更努力”的传统效率迷思,确立人生方向优先的哲学","经典的四象限时间管理矩阵:引导读者跳出紧急事务的“救火圈”,将核心精力倾注于第二象限(重要但不紧急)的高价值事务中","生动的“大石块”优先法则:通过“先放石头再倒水”的直观比喻,确保关键目标与核心使命在碎片化日程中得到绝对的优先落实","以原则为中心的自我驱动框架:不仅提供日程安排工具,更通过唤醒良知,帮助读者在工作、家庭等多元角色中实现真正的平衡与统合综效"]},{id:"book-025",title:"清单革命",author:"阿图·葛文德",cover:"https://cdn.weread.qq.com/weread/cover/12/cpPlatform_rudGZN3LDW5m9FBYr7rMBA/t6_cpPlatform_rudGZN3LDW5m9FBYr7rMBA.jpg",wereadLink:"https://weread.qq.com/web/reader/18332f80813ab7292g010065#outline?noScroll=1",link:"https://book.douban.com/subject/27168564/",tags:["管理学","认知科学","工作效率"],desc:"这是一部针对现代复杂世界所撰写的“认知防护手册”。作者阿图·葛文德通过医疗、建筑、投资等高风险领域的真实案例,揭示了人类在海量信息与高压环境下极易出现的判断疏忽。书中提出了“权力下放、简单至上、人为根本、持续改善”四大原则,指导读者将最佳实践外化为可操作的清单,从而在复杂系统中构建一道低成本、高回报的安全防线。",rating:4.6,highlights:["直面复杂时代的认知瓶颈:揭示在海量信息流中,清单如何作为“认知防护网”弥补人类记忆力与注意力分配的先天不足","提供兼具理念与落地的四大原则:通过“权力下放、简单至上、人为根本、持续改善”,构建一套可复用的清单设计哲学","扎实的医学实证背书:以手术感染率骤降等真实临床数据为支撑,证明清单思维在医疗、建筑、投资等高风险领域的跨行业普适性","简洁而具力量的流程创新:强调清单服务于人而非取代人,是帮助专业人士在高压环境下将复杂环节显性化、流程化的必备工具"]},{id:"book-020",title:"别让猴子跳回背上",author:"威廉·安肯三世",cover:"https://cdn.weread.qq.com/weread/cover/69/cpPlatform_7fFoBQ7dtqgABGSTskpJSN/t6_cpPlatform_7fFoBQ7dtqgABGSTskpJSN.jpg",wereadLink:"https://weread.qq.com/web/reader/9fc32010813ab7291g0196bd#outline?noScroll=1",link:"https://book.douban.com/subject/36103994/",tags:["时间管理","领导力","项目管理"],desc:"这是一部以“猴子”生动隐喻任务与责任的经典管理学著作。作者威廉·安肯三世深刻剖析了管理者常被琐事淹没的时间困境,并提出系统化的“猴子管理法”。通过明确任务归属、责任递减与有效授权,指导管理者如何把不属于自己的“猴子”交出去,从而释放精力专注于最高价值的战略思考,实现团队与个人的共同成长。",rating:4.3,highlights:["生动有趣的“猴子”隐喻:将枯燥的责任划分与任务流转具象化,直击职场中“忙碌却低效”的痛点","实用高效的“三步交接”法则:通过明确期望、授予资源与约定检查点,彻底避免下属的待办任务重新跳回自己背上","重塑时间管理与人才培养体系:指导高层放权、中层辅导、基层自发,将企业的成功真正建立在员工自主性的提升之上"]}],$e=[{id:"book-022",title:"学会提问(原书第12版)",author:"尼尔·布朗 / 斯图尔特·基利",cover:"https://cdn.weread.qq.com/weread/cover/68/YueWen_39980443/t6_YueWen_39980443.jpg",wereadLink:"https://weread.qq.com/web/reader/e6832d3072620d9be68aabf#outline?noScroll=1",link:"https://book.douban.com/subject/35513147/",tags:["批判性思维","逻辑学","认知科学","经典书"],desc:"这是一部培养批判性思维的经典实战指南。作者尼尔·布朗与斯图尔特·基利结合长期的教学与研究实践,提供了一套系统化、可操作的提问流程。全书通过大量真实情境案例,教导读者如何在信息泛滥的时代识别隐含假设、区分事实与观点,用高质量的“判断性问题”看透事物本质,从而做出更理性的决策。",rating:5,highlights:["聚焦批判性思考的核心能力:系统拆解“如何提出好问题”的思维过程,帮助读者在复杂信息中迅速抓住本质","提供可落地的提问与评估框架:从背景信息、关键概念到逻辑推理,构建一条完整的判断性问题链条","丰富的真实场景应用示范:结合课堂讨论、写作、日常沟通与职场决策等多元场景,让理论能“立即上手”","打造实用的思考检查单:不仅讲透“提问的价值”,更提供可直接转化为日常习惯的思维检查表,助你有效避开认知陷阱"]},{id:"book-026",title:"如何阅读一本书",author:"莫提默·J. 艾德勒 / 查尔斯·范多伦",cover:"https://wfqqreader-1252317822.image.myqcloud.com/cover/810/23723810/t6_23723810.jpg",wereadLink:"https://weread.qq.com/book-detail?type=1&senderVid=40710128&v=272326407169ff22272934f&wtheme=white&wfrom=app&wvid=40710128&scene=bottomSheetShare",link:"https://book.douban.com/subject/1013208/",tags:["阅读方法","思维训练","经典"],desc:"阅读领域的“元方法”指南。作者艾德勒与范多伦将阅读划分为基础阅读、检视阅读、分析阅读与主题阅读四个进阶层次,并强调阅读是一项主动的思考活动。本书不仅提供了从“快速略读”到“系统拆解论点”的实操技巧,更致力于通过提问、归纳与批判,将阅读转化为训练理解力、批判力与终身学习的终极工具。",rating:5,highlights:["构建系统的四级阅读框架:从检视阅读到分析阅读再到主题阅读,为读者提供了一套从入门到精通的进阶路径","强调“主动与批判”的阅读观:拒绝被动接收,教导读者如何通过提问、归纳与反思,真正将作者的洞见转化为自己的认知","高效的检视阅读技巧:提供如何在有限时间内通过看目录、挑重点等方式,快速筛选并判断书目价值的核心能力","跨时代的经典效能:自1940年问世以来长盛不衰,其对逻辑拆解与深度思考的指导,是提升所有知识吸收效率的“总开关”"]},{id:"book-023",title:"检索力:打破信息差的科学方法",author:"龚芙蓉",cover:"https://cdn.weread.qq.com/weread/cover/58/cpplatform_feaxemubry47bnkzylqzwv/t6_cpplatform_feaxemubry47bnkzylqzwv1716796541.jpg",wereadLink:"https://weread.qq.com/web/reader/9de32810813ab8e00g018130#outline?noScroll=1",link:"https://book.douban.com/subject/36899979/",tags:["信息素养","检索能力","思维认知"],desc:"本书聚焦“检索力”这一核心技能,旨在帮助读者在信息过载的时代主动掌握“逆风而行”的搜索能力。作者龚芙蓉结合二十余年实践经验,用生动的人文与诺贝尔奖级科学案例,将枯燥的检索工具化为有趣的故事。不仅教授非线性、迭代式的搜索技巧,更致力于重塑读者的探究精神,赋予其走出“信息茧房”的勇气。",rating:4.2,highlights:["丰富的跨学科趣味案例驱动:用“张冠李戴的马克思名言”等生动故事,将枯燥繁琐的检索步骤转化为轻松的探索之旅","重塑非线性与迭代的搜索思维:打破按部就班的线性流程误区,建立以耐心与热情驱动的多轮迭代搜索心态","直击科研与职场的实用痛点:提供可快速落地的实操指南,帮助读者切实缩短科研周期、大幅提升工作效率","兼顾技能训练与人文底色:在教授如何利用和创造信息的同时,注重培养读者的信息素养与打破信息差的认知勇气"]},{id:"book-027",title:"原则",author:"瑞·达利欧",cover:"https://cdn.weread.qq.com/weread/cover/23/YueWen_921568/t6_YueWen_921568.jpg",wereadLink:"https://weread.qq.com/web/reader/848324405e0fe08483ab6a4#outline?noScroll=1",link:"https://book.douban.com/subject/27608239/",tags:["投资","方法论","自我管理"],desc:"桥水基金创始人瑞·达利欧总结四十余年投资、管理与人生经验的集大成之作。作者提出将生活和工作像机器一样系统化,确立了“极度求真”与“极度透明”两大基石,并通过“创意择优”与“基于可信度的决策机制”来迭代思维。书中包含500多条可操作原则,旨在帮助读者在复杂世界中保持开放心态、看清现实,并做出最优决策。",rating:4.8,highlights:["“极度求真”与“极度透明”的基石:主张诚实面对现实,通过公开决策过程来获取外部反馈,达成高效协作","创意择优与可信度加权机制:摒弃个人权威,利用数据驱动的讨论与可信度权重,在团队中选出最优方案","500余条可落地的原则清单:涵盖自我认知、投资决策、团队治理等场景,构建出一套随时可查的行动指南","系统化的“机器”思维:将生活与组织管理拆解为可维护、可迭代的系统,有效规避情绪化干扰"]},{id:"book-031",title:"价值",author:"张磊",cover:"https://wfqqreader-1252317822.image.myqcloud.com/cover/958/33577958/t6_33577958.jpg",wereadLink:"https://weread.qq.com/web/reader/5be32a3072005be65bef195#outline?noScroll=1",link:"https://book.douban.com/subject/35188914/",tags:["价值投资","商业思维","创业"],desc:"高瓴资本创始人张磊首部个人及投资思想著作。全书通过回顾作者的个人求学与创业历程,系统阐释了“长期主义”与“重仓中国”的核心投资理念,并首次披露了高瓴投资的七大公式。作者将十余个典型投资案例与个人价值修养相结合,揭示了如何在不确定的商业环境中,通过坚持原则、敬畏规则与持续创新,创造长久、真实的价值。",rating:4.6,highlights:["系统构建长期主义哲学:首次系统化梳理“高瓴七大公式”,为读者提供从认知、决策到执行的价值投资实战模型","深度复盘经典实战案例:通过腾讯、货拉拉等真实商业案例,拆解如何在复杂市场中识别企业护城河与核心价值","投资之外的人文思考:延伸至教育、人才与科学观,展现作者作为顶尖投资者对社会责任与长期价值创造的深度思考","可视化的阅读体验:精选多幅手绘彩插与历史影像,将深刻的投资逻辑与企业成长叙事变得更加生动、直观"]},{id:"book-032",title:"纳瓦尔宝典",author:"埃里克·乔根森 / 纳瓦尔·拉维坎特",cover:"https://cdn.weread.qq.com/weread/cover/89/YueWen_44026191/t6_YueWen_44026191.jpg",wereadLink:"https://weread.qq.com/web/reader/e1e32b00729fc94fe1e824d#outline?noScroll=1",link:"https://book.douban.com/subject/35876121/",tags:["财富管理","个人成长","幸福哲学","思维认知"],desc:"这是一部汇集硅谷著名投资人纳瓦尔·拉维坎特过去十年关于财富与幸福思考的行动指南。全书摒弃了“致富靠运气”的传统观念,提出积累财富与幸福生活是可以通过学习掌握的技能。通过系统整理推特、播客与访谈中的智慧,本书为读者提供了如何在快速变化的科技与经济环境中,利用杠杆、发挥个人独特性,进而实现财务自由并获得持久内心满足的方法论。",rating:4.7,highlights:["将财富与幸福视为可习得的技能:打破运气论,强调通过建立杠杆、发挥个人独特性来获取非线性的回报","十年思想的系统化编纂:将碎片化的互联网智慧提炼为成体系的方法论,打造了数字时代个人的“行动指南”","兼顾财富积累与内心满足:不仅教导如何高效赚钱,更深入探讨如何通过阅读、冥想与长期主义,在职场成功中寻找内心的宁静","极具实操性的工具箱:提供如深度思考、刻意练习、构建个人品牌等具体路径,帮助读者在碎片化时代快速实现自我迭代"]},{id:"book-028",title:"优秀的绵羊",author:"威廉·德雷谢维奇",cover:"https://cdn.weread.qq.com/weread/cover/78/cpplatform_3ncoeekcuaectlzj9hf5nr/t6_cpplatform_3ncoeekcuaectlzj9hf5nr1744626569.jpg",wereadLink:"https://weread.qq.com/web/reader/1c0324c0813ab9d91g010aba#outline?noScroll=1",link:"https://book.douban.com/subject/26747208/",tags:["博雅教育","社会学","个人成长"],desc:"耶鲁大学前教授威廉·德雷谢维奇对美国常春藤精英教育体制的尖锐批判之作。作者通过二十余年的教学观察,指出顶尖学府培养出一群虽然聪明、优秀,但普遍焦虑、缺乏目标感且唯命是从的“优秀绵羊”。本书呼吁社会重新审视教育的本质,摆脱对名校与高薪的盲目崇拜,回归博雅教育,鼓励学生探索内在驱动力与自我价值。",rating:4.2,highlights:["犀利剖析精英教育弊端:直击常春藤体制培养出“聪明但没有灵魂”的学生的现实,反思唯名校与成绩论的单一评价体系","回归博雅教育的核心价值:批判应试化倾向,提倡给予学生更多探索、失败与重塑自我的空间,强调教育的本质在于帮助个体找到自我","提供挣脱外部期待的认知框架:既为迷茫的年轻人指明如何重建内在动力,也给家长和教育者敲响了关于“成功定义”的警钟","跨文化背景下的教育共鸣:尽管以美国精英教育为例,其对“教育内卷”与“缺乏目标感”的批判,引发了全球高压教育环境下的深层共鸣"]},{id:"book-029",title:"把自己变成稀缺资产",author:"何思平",cover:"https://cdn.weread.qq.com/weread/cover/98/cpplatform_ncqzerh3wdywn9mlc9cjna/t6_cpplatform_ncqzerh3wdywn9mlc9cjna1694085413.jpg",wereadLink:"https://weread.qq.com/web/reader/2fe326f0813ab821fg0146df#outline?noScroll=1",link:"https://book.douban.com/subject/36513648/",tags:["个人成长","思维认知","自我管理","投资理财"],desc:"这是一个将“人生”视作“公司”来经营的实战指南。作者何思平结合自身从严重口吃到演讲冠军、再到连续创业成功的跨越式经历,提出了“人生有限公司”的经营哲学。全书通过“生命立方体”模型,从认知、实践、精力管理三个维度拆解了如何通过持续输出与跨界学习,将自己打造为具有高壁垒、不可替代的“稀缺资产”。",rating:4.2,highlights:["提出“人生有限公司”经营哲学:倡导将自己视作最值得投资的上市公司,通过不断提升认知与能力壁垒,把“人生”经营成稀缺资产","系统化的“生命立方体”模型:从认知、实践、精力管理三个维度构建个人成长闭环,解决成长中的无序感与碎片化难题","聚焦个人核心竞争力:深度拆解认知力、学习力与共情力等稀缺能力的获取路径,教导读者在不同场景中通过实战验证自我价值","高度可操作的工具清单:摒弃鸡汤式说教,将自我成长拆解为具体的习惯改造与复盘清单,帮助读者在痛点与高光时刻都能通过反馈机制实现自我迭代"]},{id:"book-030",title:"成长第二曲线:跨越S型持续成长",author:"查尔斯·汉迪",cover:"https://cdn.weread.qq.com/weread/cover/65/YueWen_39427437/t6_YueWen_39427437.jpg",wereadLink:"https://weread.qq.com/web/reader/15d32ed072599d6d15daa86#outline?noScroll=1",link:"https://book.douban.com/subject/35531368/",tags:["管理学","个人成长","人生哲学","未来趋势"],desc:"管理大师查尔斯·汉迪的“人生长跑指南”。本书通过书信体形式,深度探讨了在数字时代背景下个人如何识别并跨越“第二曲线”。汉迪指出,无论组织还是个人,都受制于S型增长曲线,只有在第一曲线衰退前主动布局新的增长点,并保持内在价值的独立与进化,才能在不断变化的环境中获得持续且有意义的成长。",rating:4.5,highlights:["百岁管理大师的人生体悟:以书信体浓缩一生管理研究与个人经验,提供了从时间维度审视工作、学习与生活的全景视角","“第二曲线”理论的全面进阶:深刻揭示组织与个人的兴衰规律,教导读者如何在第一曲线的巅峰前就主动布局新的增长引擎","全场景下的持续进化方案:将第二曲线思维跨界应用于教育、职业规划、婚姻与家庭中,强调“变化才是常态”,鼓励持续自我重塑","面向Z世代的清醒处方:在科技高歌猛进的数字时代,提醒后人重视诚信、协作等软实力,保持独立判断,避免在算法与焦虑中迷失自我"]}],Me=[{id:"book-033",title:"枪炮、病菌与钢铁",author:"贾雷德·戴蒙德",cover:"https://cdn.weread.qq.com/weread/cover/99/YueWen_42766048/t6_YueWen_42766048.jpg",wereadLink:"https://weread.qq.com/web/reader/843329f0728c8ee08434fb1#outline?noScroll=1",link:"https://book.douban.com/subject/1813841/",tags:["人类历史","地理决定论","社会学","跨学科"],desc:"一部重新定义人类历史发展的宏大著作。作者贾雷德·戴蒙德通过生物学、地理学、人类学等多学科交叉视角,强有力地反驳了“种族决定论”和“西方文明优越论”。他提出,决定文明兴衰的关键并非种族,而是环境因素、地理格局以及动植物驯化的差异,这些自然条件的偶然性最终导致了技术、免疫力和权力结构的差异,从而重塑了现代世界的全球版图。",rating:4.8,highlights:["颠覆性的历史观:以环境与地理差异解释文明兴衰,有力冲击了长期流行的西方文明优越论,提供了理解人类历史的全新视角","跨学科的综合研究框架:巧妙融合生物学、地理学、历史学、社会学等多学科知识,重建人类文明演进的逻辑路径","系统揭示历史演变的机制:深入剖析农业、病菌传播与技术权力如何形成相互强化的循环,展示了文明发展背后复杂的资源互动","具备公共思想者的宏观视野:将严谨的科学研究转化为对人类命运与社会发展的深刻反思,为现代人理解自身在历史长河中的位置提供了绝佳参照"]},{id:"book-034",title:"中国社会各阶层分析",author:"梁晓声",cover:"https://cdn.weread.qq.com/weread/cover/0/yuewen_42682684/t6_yuewen_426826841728383400.jpg",wereadLink:"https://weread.qq.com/web/reader/085326e0728b493c085ade1#outline?noScroll=1",link:"https://book.douban.com/subject/35485315/",tags:["社会观察","阶层研究","现实主义"],desc:"茅盾文学奖得主梁晓声基于多年社会观察的现实题材力作。作者将快速变迁的中国社会划分为不同阶层,以平民视角细腻描摹各群体的生存状态、心理困境与阶层焦虑。全书不追求纯学术的枯燥分析,而是通过文学化的社会观察,勾勒出一幅当代中国社会的“浮世绘”,引导读者在时代坐标中找准定位,理解社会变迁背后的结构性逻辑。",rating:4.3,highlights:["平民视角下的社会“浮世绘”:通过细腻的笔触勾勒各阶层的生存逻辑与心理画像,帮助读者直观理解宏观社会结构","兼具现实痛点与精神深度:不仅呈现物质生活的差异,更深刻剖析阶层焦虑背后的价值困境,为理解当代社会提供人文参照","时代脉络中的命运书写:将个体命运置于历史事件的宏观背景中考察,展现了半个世纪以来社会变迁的深层脉络","文学笔触下的社会关怀:作为茅盾文学奖得主,作者通过富有故事性的叙事,既保留了批判性,又让文本充满了温暖的人文温度"]},{id:"book-021",title:"把自己作为方法",author:"项飙 / 吴琦",cover:"https://cdn.weread.qq.com/weread/cover/81/cpPlatform_3300003962/t6_cpPlatform_3300003962.jpg",wereadLink:"https://weread.qq.com/web/reader/d7532f80813ab680cg012708#outline?noScroll=1",link:"https://book.douban.com/subject/35092383/",tags:["社会学","访谈录","思想方法"],desc:"两代学人项飙与吴琦历时三年、跨越五地的深度对话实录。本书从项飙的个人经验切入,探讨了中国社会近半个世纪的变迁、全球化与民粹主义等宏大议题。在自我泛滥与思想受困的时代,作者提出“把自己作为方法”,指导读者如何在全球化年代重新定位自我、重建“附近”,并在个人体验与宏观叙事之间搭建起思考与行动的桥梁。",rating:4.6,highlights:["以“自我”切入回应宏大议题:示范如何在个人真实体验与全球化、社会变迁等宏观叙事之间搭建认知的桥梁","提供重建“附近”的行动指南:在自我泛滥的潮流中,指导读者如何审视现实,创造性地建设身边的小世界","兼具学术深度与极高可读性:将人类学、社会学的深刻理论洞察,巧妙融入生动的田野故事与双人生活化对谈中","跨越三年的思想碰撞:历时三年、跨越五地的持续对话结集,反思知识生产与公共讨论的真实处境"]}],Te=[{id:"book-035",title:"百岁人生:长寿时代的生活和工作",author:"琳达·格拉顿 / 安德鲁·斯科特",cover:"https://wfqqreader-1252317822.image.myqcloud.com/cover/860/22902860/t6_22902860.jpg",wereadLink:"https://weread.qq.com/web/reader/30c323e0715d784c30c1e1b#outline?noScroll=1",link:"https://book.douban.com/subject/30245089/",tags:["人生规划","长寿时代","社会学"],desc:"基于伦敦商学院的经典课程,作者琳达·格拉顿与安德鲁·斯科特提出,面对一半概率活到100岁的长寿时代,传统的“学习-工作-退休”三段式人生模式已彻底失效。本书指导读者如何重新设计人生,通过拥抱多阶段人生模型,在更长的生命周期中平衡工作、学习与休闲,并强调在财务资产之外,更要注重健康、友谊与知识等“无形资产”的持续投入与增值。",rating:4.3,highlights:["重构人生模式:打破传统的“三段式”生活范式,提出充满弹性的“多阶段人生”模型,让工作与学习不再是线性的重复","从关注财务到“无形资产”:除了养老金,强调健康、友谊、社交网络与心理韧性等“无形资产”才是维持长寿生活质量的核心动力","职场与转型的系统规划:提供针对长寿时代的职业设计思路,涵盖何时转型、如何投资自身、怎样应对不确定性等实战框架","社会与制度的深度洞察:探讨长寿如何冲击养老金体系、劳动力市场与企业模式,帮助个人在宏观变革中把握主动权"]},{id:"book-00043",title:"重启吧!我的健康人生",author:"兰根·查特吉",cover:"https://cdn.weread.qq.com/weread/cover/80/cpplatform_kbrswv3bm7cix2zlyo6wtx/t6_cpplatform_kbrswv3bm7cix2zlyo6wtx1716362285.jpg",wereadLink:"https://weread.qq.com/web/reader/e8a32e80813ab8de4g0191c2#outline?noScroll=1",link:"https://book.douban.com/subject/36899697/",tags:["生活方式","预防医学","身心健康","自我管理"],desc:"英国临床医生基于20多年行医经验写就。本书主张“生活方式即良药”,围绕休息、饮食、运动和睡眠四个领域设计了20个微小行动计划,帮助现代人通过低成本的习惯改变逆转慢性问题。",rating:4.6,highlights:["提出99%的健康取决于日常习惯而非医学治疗,强调整体干预","构建“4×5”微行动框架,涵盖休息、饮食、运动、睡眠四个维度的20个小改变","兼顾科学深度与极简实操,如“12小时进食窗口”、“10分钟高强度运动”","关注现代职场人痛点,提供“小投入、大回报”的可叠加身心健康投资策略"]},{id:"book-00040",title:"你是你吃出来的:吃对少生病,病了这样吃",author:"夏萌",cover:"https://cdn.weread.qq.com/weread/cover/86/YueWen_920661/t6_YueWen_920661.jpg",wereadLink:"https://weread.qq.com/web/reader/7bb32c305e0c557bbdeab81#outline?noScroll=1",link:"https://book.douban.com/subject/27590675/",tags:["饮食科普","营养学","健康管理"],desc:"前安贞医院营养科主任夏萌结合十余年临床经验写成。本书颠覆“低油低脂”误区,提出回归进化的“65%植物+35%动物”膳食配比,并针对14种常见慢病给出“四分法”饮食干预方案,帮助读者重建健康饮食观。",rating:5,highlights:["指出多数慢病源于“蛋白质缺乏式营养不良”,打破常规低油低脂迷思","提出清晰量化的“65%植物类+35%动物类”科学饮食结构","针对冠心病、高血压等14种常见慢病提供实操性极强的“四分法”菜单","源于十万+真实临床病例,强调“一日三餐才是真正的保健品”"]},{id:"book-00041",title:"你是你吃出来的2",author:"夏萌",cover:"https://wfqqreader-1252317822.image.myqcloud.com/cover/883/35905883/t6_35905883.jpg",wereadLink:"https://weread.qq.com/web/reader/40532d007223e15b4052fae#outline?noScroll=1",link:"https://book.douban.com/subject/35340053/",tags:["饮食指导","科普","疾病防治"],desc:"聚焦高血压、高脂血症、糖尿病等7大常见慢病,从临床营养医学角度逐一破除诸如“血压高不能吃肉”等饮食误区,提供系统的“上游-中游-下游”疾病防控思路与个体化营养处方。",rating:4.6,highlights:["专攻7大常见慢性病,为患者提供针对性的“生病了怎么吃”个体化指导","科学辟谣,破除“血压高不能吃肉”、“胆固醇高不能吃鸡蛋”等常见误区","梳理疾病发生因果链条,帮助读者从源头找到健康干预的着力点","提供从一日三餐、运动到心态调养的具体可操作生活方式清单"]}],Ge=JSON.parse('{"title":"好书推荐","description":"读书心得、推荐书籍和阅读技巧","frontmatter":{"title":"好书推荐","date":"2024-01-01T16:00:00.000Z","description":"读书心得、推荐书籍和阅读技巧","categories":["growth"],"coverImg":"https://insight-stack-1252300811.cos.ap-shanghai.myqcloud.com/img/cover/books_reading_bg.png","permalink":"/growth/books","tags":["悦读时光","资源推荐"]},"headers":[],"relativePath":"growth/books.md","filePath":"30.悦读时光/01.好书推荐.md"}'),Ne={name:"growth/books.md"},De=Object.assign(Ne,{setup(n){return(b,t)=>(a(),r("div",null,[t[0]||(t[0]=e("h1",{id:"好书推荐",tabindex:"-1"},[l("好书推荐 "),e("a",{class:"header-anchor",href:"#好书推荐","aria-label":"Permalink to “好书推荐”"},"​")],-1)),t[1]||(t[1]=e("h2",{id:"_1-ai-与数学思维",tabindex:"-1"},[l("1. AI 与数学思维 "),e("a",{class:"header-anchor",href:"#_1-ai-与数学思维","aria-label":"Permalink to “1. AI 与数学思维”"},"​")],-1)),t[2]||(t[2]=e("blockquote",null,[e("p",null,[l("在大模型发展日新月异的今天,理解 AI 本质上是在升级我们资深的“认知操作系统”, "),e("strong",null,"理解 AI,本质上是理解数据、数学与逻辑如何重构这个世界"),l("。")]),e("p",null,"这套书单从数学思维的底层逻辑出发,让我们理解 ChatGPT 等大模型背后的计算机制,将硬核的神经网络与概率统计转化为优化生活的决策工具。它不仅能界定机器智能的边界,更颠覆了传统的“目标论”,倡导在不确定性中通过“踏脚石”思维寻找突破性创新的可能。AI 的研究实践告诉我们,伟大的突破往往无法被预设,唯有拥抱“寻宝者思维”才能在未知中偶遇奇迹,我们需要颠覆传统的创新范式。")],-1)),h(k,{books:g(Be)},null,8,["books"]),t[3]||(t[3]=M("",4)),h(k,{books:g(Ie)},null,8,["books"]),t[4]||(t[4]=e("h3",{id:"_2-2-商业化",tabindex:"-1"},[l("2.2 商业化 "),e("a",{class:"header-anchor",href:"#_2-2-商业化","aria-label":"Permalink to “2.2 商业化”"},"​")],-1)),t[5]||(t[5]=e("blockquote",null,[e("p",null,[l("在追逐“独角兽”和规模扩张的狂热迷思之后,真正的商业高手正在重新回归本质:"),e("strong",null,"盈利才是企业的核心护城河。"),l(" 这套书单为我们揭示了一种"),e("strong",null,"更具韧性的商业路径——“小而美”的极简经营"),l("。它教导我们如何拒绝低效的内卷与忙碌,通过“做更少但创造更多价值”的思维,打造在不确定时代下依然能保持稳定现金流的“慢公司”。")]),e("p",null,[e("strong",null,"商业的成功,往往源于敢于挑战“难而正确”的事"),l("。从皮克斯如何建立允许失败的创意土壤,到 Waze 如何通过解决被忽视的痛点实现跨越式成长,这些世界级案例证明了:卓越的组织不仅需要极简的流程与高效的分布式协作(远程办公),更需要一种“冷静”的文化,将利润置于规模之上。")])],-1)),h(k,{books:g(We)},null,8,["books"]),t[6]||(t[6]=e("h2",{id:"_3-效率与效能",tabindex:"-1"},[l("3. 效率与效能 "),e("a",{class:"header-anchor",href:"#_3-效率与效能","aria-label":"Permalink to “3. 效率与效能”"},"​")],-1)),t[7]||(t[7]=e("blockquote",null,[e("p",null,[l("在信息过载与高压竞争的现代环境中,平庸与卓越的分水岭不再是做事的速度,而是"),e("strong",null,"决策的精度与责任的边界"),l("。这套书单为我们提供了一套从个人认知到组织协作的“效能防线”:首先,它"),e("strong",null,"引导我们完成从“时钟”到“罗盘”的思维跨越,打破盲目追求速度的迷思,确保将核心精力倾注在真正产生长远复利的“重要非紧急”事务之上"),l("。 真正的效能源于对复杂性的科学驾驭:")]),e("ul",null,[e("li",null,"通过“清单革命”式的认知防护,我们将最佳实践外化为可靠的防错系统,弥补人类在极端环境下的认知局限;"),e("li",null,"“猴子管理法”则以生动的视角重塑了职场协作的责任逻辑,教我们通过有效授权拒绝无谓的干扰,释放战略思考的精力;")])],-1)),h(k,{books:g(Ye)},null,8,["books"]),t[8]||(t[8]=e("h2",{id:"_4-学习与成长",tabindex:"-1"},[l("4. 学习与成长 "),e("a",{class:"header-anchor",href:"#_4-学习与成长","aria-label":"Permalink to “4. 学习与成长”"},"​")],-1)),t[9]||(t[9]=e("blockquote",null,[e("p",null,[l("在信息爆炸与快速变革的时代,"),e("strong",null,"真正的成长不再是知识的被动堆砌,而是认知系统的彻底迭代"),l("。这套书单为我们构建了一个从底层思维到人生经营的闭环:")]),e("ul",null,[e("li",null,"首先,通过批判性思维与深度阅读夯实“元能力”,在泛滥的信息中识别本质,将他人的洞见转化为自己的血肉;"),e("li",null,"其次,利用“检索力”打破信息差,确保自己在任何领域都能快速获取高质量资源,掌握逆风而行的主动权。")]),e("p",null,[e("strong",null,"人生不是一场盲目的长跑,而是一场基于“原则”的精密经营"),l("。从达利欧的系统化决策,到纳瓦尔的财富与幸福逻辑,这些智者教导我们如何利用杠杆、坚持长期主义,将自己视作一家“人生有限公司”来经营。我们需要摆脱“优秀绵羊”式的被动驱动,通过识别成长的“第二曲线”,在巅峰时刻主动寻求突破,将自己打造成不可替代的稀缺资产。阅读这些经典,不仅是为了习得技能,更是为了在算法与焦虑的夹击中,重塑内心的宁静与独立判断的勇气。")])],-1)),h(k,{books:g($e)},null,8,["books"]),t[10]||(t[10]=e("h2",{id:"_5-人文社科",tabindex:"-1"},[l("5. 人文社科 "),e("a",{class:"header-anchor",href:"#_5-人文社科","aria-label":"Permalink to “5. 人文社科”"},"​")],-1)),t[11]||(t[11]=e("blockquote",null,[e("p",null,"在宏观历史与微观现实间构建认知:在碎片化与不确定性并存的时代,穿透表象、直达本质的洞察力成为必需。这套单为我们开启了两扇窗:"),e("ul",null,[e("li",null,"一扇望向万年文明的宏大坐标,通过《枪炮、病菌与钢铁》的跨学科视野,拆解地理环境如何冷酷而偶然地重塑全球版图,彻底颠覆“文明优越论”的傲慢;"),e("li",null,"另一扇则照向当下社会的真实肌理,在梁晓声对各阶层生存困境的细腻描摹中,读懂大时代变革背后隐秘的结构性逻辑与阶层焦虑。")]),e("p",null,[e("strong",null,"人文思考的终极价值,在于如何将宏大叙事转化为个人的行动力量"),l("。正如项飙所倡导的“把自己作为方法”,这些著作不仅是知识的传递,更是思维的松绑。它们教导我们不再做时代的被动旁观者,而是学会在个人体验与宏观世界之间搭建桥梁,通过重建“附近”的小世界,在喧嚣中找准自我的定位。")])],-1)),h(k,{books:g(Me)},null,8,["books"]),t[12]||(t[12]=e("h2",{id:"_6-健康生活",tabindex:"-1"},[l("6. 健康生活 "),e("a",{class:"header-anchor",href:"#_6-健康生活","aria-label":"Permalink to “6. 健康生活”"},"​")],-1)),t[13]||(t[13]=e("img",{src:T,style:{width:"100%","border-radius":"8px","margin-bottom":"20px"},alt:"about site background"},null,-1)),t[14]||(t[14]=e("blockquote",null,[e("p",null,[l("在面临大概率活到100岁的“长寿时代”,传统的线性人生模式正在失效。我们需要对“健康”进行一次彻底的认知重构:"),e("strong",null,"健康不再仅仅是“没有疾病”,而是支撑我们跨越漫长生命周期、应对多阶段人生挑战的最核心“无形资产”"),l("。想要让这套生命系统长期平稳运行,真正的解法并不在医院的处方笺里,而是隐藏在我们每天的日常选择中。")]),e("p",null,[l("决定我们长期健康状态的,有 99 %取决于日常习惯。我们需要"),e("strong",null,"在休息、饮食、运动、睡眠这四个高频生活维度中,植入微小但杠杆率极高的改变"),l("(例如12小时进食窗口、10分钟高强度运动、睡前屏蔽数字通知等)。用最低的执行成本,置换身心状态的巨大回报。")])],-1)),h(k,{books:g(Te)},null,8,["books"])]))}});export{Ge as __pageData,De as default}; diff --git a/assets/growth_distinguish-useful-information.md.CwjMB2nE.js b/assets/growth_distinguish-useful-information.md.CwjMB2nE.js new file mode 100644 index 00000000..5548ebd7 --- /dev/null +++ b/assets/growth_distinguish-useful-information.md.CwjMB2nE.js @@ -0,0 +1 @@ +import{_ as e,g as r,h as t,U as i}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const c=JSON.parse('{"title":"如何甄别真正有用的信息","description":"摘要总结:在信息高度透明的时代,浅层信息差已被彻底抹平,信息本身的价值不断稀释。人与人的核心差距不再是获取信息的渠道,而是高信噪比信息的甄别能力、深度思考能力与落地执行力,唯有以思考校验信息、以执行验证价值,形成“信息-判断-实践-反馈”的思考与执行闭环,才能突破信息壁垒、创造真正价值。","frontmatter":{"date":"2025-11-10T12:52:28.000Z","title":"如何甄别真正有用的信息","description":"摘要总结:在信息高度透明的时代,浅层信息差已被彻底抹平,信息本身的价值不断稀释。人与人的核心差距不再是获取信息的渠道,而是高信噪比信息的甄别能力、深度思考能力与落地执行力,唯有以思考校验信息、以执行验证价值,形成“信息-判断-实践-反馈”的思考与执行闭环,才能突破信息壁垒、创造真正价值。","permalink":"/growth/distinguish-useful-information","categories":["资源推荐"],"tags":["信息筛选","个人成长"]},"headers":[],"relativePath":"growth/distinguish-useful-information.md","filePath":"30.悦读时光/21.如何甄别真正有用的信息.md"}'),l={name:"growth/distinguish-useful-information.md"};function o(n,a,s,h,_,d){return t(),r("div",null,[...a[0]||(a[0]=[i('

    如何甄别真正有用的信息

    摘要总结:在信息高度透明的时代,浅层信息差已被彻底抹平,信息本身的价值不断稀释。人与人的核心差距不再是获取信息的渠道,而是高信噪比信息的甄别能力、深度思考能力与落地执行力,唯有以思考校验信息、以执行验证价值,形成“信息-判断-实践-反馈”的思考与执行闭环,才能突破信息壁垒、创造真正价值。

    在互联网技术普及的当下,信息已从“稀缺资源”转变为“泛滥资源”。过去依赖地域差、稀缺性的浅表层信息差逐渐被抹平,开发者通过网络可轻松获取各类技术文档、行业动态、赚钱模式,但真正能将信息转化为价值的仍是少数人。核心矛盾已从“获取信息”转变为“驾驭信息”——信息本身的价值弱化,而信息解读能力、行动执行力、筛选甄别力成为拉开差距的关键

    1. 打破“信息差”的系统性错觉

    过去,由于地域限制和传播介质的稀缺,赚钱或成功的模式往往是粗放的,建立在浅表层的“信息不对称”上,但随着技术的演进,这种低维度的信息差正在被迅速抹平。人们经常陷入“赚不到钱/抓不住机会是因为缺少信息差”的认知偏差,但本质问题在于“人本身的差距”,具体体现在三个层面:

    1.1 表面是你在筛选信息,实际是信息在筛选人

    举个最常见的例子:大家都知道做技术输出、写独立博客或做个人产品能带来长期的复利,但为什么真正跑通全栈并沉淀下来的人凤毛麟角?

    阻碍多数人的原因通常有三个:

    • 缺乏持久化机制、执行断层:无法在短期内看到正向反馈(ROI),导致进程中途中断,缺乏持续输出的执行力(如技术文章更新、用户运营)。
    • 缺乏深度计算:只是浮于表面的搬运,没有沉下心来对技术或业务进行深度解析与架构思考。
    • 对不确定性(Uncertainty)的恐惧:看不到确定性的回报,对投入产出比产生动摇,导致长期投入的决策被取消。

    面对这些公开的“赚钱/成长路径”,看似是我们在评估它,实际上是这些高门槛的路径在天然地筛选掉那些缺乏定力和长远产品嗅觉的人。

    1.2 警惕算法构建的“信息茧房”

    在网络推荐算法和同温层环境的双重作用下,我们每天接收的输入往往带有严重的偏置。这种不够客观的环境,容易导致我们在遇到真正有价值、但与既有认知冲突的客观观点时,产生本能的防御和抵触。

    对于开发者和内容创作者而言,打破认知茧房本身就是一种巨大的信息差。任何技术栈或商业模式,都需要博采众长。不要对非本领域的观点一味抛出异常,而是要建立辩证的“中间件”来过滤和吸收,做好信息的甄别与筛选。

    2. 信息泛滥与脑力带宽的消耗

    信息即权力,掌握高维信息的人确实拥有更强的资源调配能力。但关键在于,没有人有义务把复杂的底层逻辑拆解成现成的方法论,手把手教到完全理解为止。真正造成人与人之间差距的,是解析和编译信息的能力——同样的信息,不同的人能提炼出完全不同的价值。

    2.1 从“追求差”到“对抗泛滥”

    如今的问题早已不是信息匮乏,而是信息熵增与泛滥。这不仅带来了极度内卷的竞争,还伴随着传播过程中的信息失真。市面上很多被大肆宣扬的“风口”,仔细扒开源码就会发现:你所看到的,其实都是别人精心设计好让你看到的。

    当一个赛道人人都争先恐后时,如果你真想创造价值,不如“反者道之动”,静观其变,等待系统重构的新机会。拥挤的赛道最终必然走向卷利润、卷价格的“劣币驱逐良币”死循环。

    2.2 无效信息是对算力的极大消耗

    很多人把赚不到钱、做不成事归结于“信息积累不够”,于是疯狂地囤积资料、拼命地订阅各种干货,试图通过扩大信息摄入量来超越别人。 这是一个极其危险的谬论。获取和处理信息,本质上是一件极其消耗系统资源(精力和能量)的事情。

    如果一个人单凭拼凑信息就能战胜市场,那大家都不需要埋头精耕细作了。人的脑容量和认知带宽是有限的,一旦缓存(Cache)被大量低质、无用的噪音占满,真正高价值的信号就无法进入,想得太多、做得太少,只会引发严重的内耗。

    3. 价值创造的核心:思考+执行,突破信息壁垒

    信息本质是工具,而非目的,人的核心竞争力永远是“思考+执行”,二者形成的能力壁垒,远高于单纯的信息壁垒:思考 + 执行 > 纯执行 + 不思考 > 纯思考 + 不执行 > 不思考 + 不执行

    • 思考+执行:通过思考判断信息价值,通过执行验证选择,形成“信息-判断-实践-反馈”的闭环
    • 执行+不思考:机械落地但缺乏方向,效率低下但可能偶然踩中机会。
    • 思考+不执行:仅停留在“知道”阶段,信息无法转化为任何价值。
    • 不思考+不执行:完全被动接收信息,与机会绝缘。

    “思考+执行”之所以重要,是因为它们构成了反馈闭环:思考是为了对输入的信息进行校验和逻辑判断,执行是为了将假设放入真实环境中跑通测试,从而向目标逼近

    信息不对称的根源,其实是“内部能力不对称”。将相同的技术趋势、项目机会放在两位开发者面前:前者能通过思考拆解落地路径、通过执行验证可行性;后者仅停留在“了解”层面,差距便由此产生。人们最终能获得的价值,取决于自身的思考深度、执行力度、认知高度——想要获得更多,唯一路径是“精进自身”,让能力匹配目标。

    真正有价值的信息,如果传达给一个没有执行力的人,就永远停留在“已知”的内存态,无法落盘,吸收、运用和产生价值的任何一个环节都不会发生。

    我们通常以为自己没成事是因为缺少某个关键的“信息差”,实际上连这个“以为”的诊断都错了。真正的原因,往往是思考的深度和执行的颗粒度不到位,导致机会流失。人终归只能赚到自己系统架构支撑得起的那部分收益,想要获得更多,唯一的路径是重构和精进自己。

    4. 行动指南

    4.1 信息筛选:果断做减法,锚定核心目标

    • 停止抱怨外界信息的真伪,主动建立个人过滤机制,拒绝"信息焦虑",定期清理无效信息源(如低价值技术社群、重复资讯推送)。
    • 明确自身阶段目标(如“3个月掌握某框架落地”“半年实现副业变现”),仅筛选与目标强相关的信息,把有限的算力留给最高优的任务。

    4.2 信息解读:穿透表象,洞察未言之意

    • 接收信息时(如技术文章、行业分享),不仅要关注"说了什么",更要洞察"没说什么"(如技术的适用场景、潜在坑点、变现逻辑的隐藏环节)。
    • 优先与高信噪比人群深度交流(如资深开发者、落地型创业者、领域专家),这类沟通往往直击本质、减少冗余,能快速触达核心信息与隐性经验,同时反向倒逼自身思考质量的提升。

    4.3 差异破局:向内求索,强化“思考+执行”

    与其说世界上存在信息差,不如说是"人差"。将同样的文档和源码置于两人面前,由于"底层编译器"(认知框架与执行系统)的差异,前者的洞察与后者的产出必然判若云泥。一切信息不对称的表象之下,真正分野的永远是内在的认知深度与执行密度。我们只有通过持续的思考和执行提升自己的能力,才能在信息时代中获得价值。

    • 停止抱怨"信息不真实"这类外部归因,把精力放在自己能掌控的事情上——提升思考深度和执行效率。
    • 建立"信息落地清单":每当获得有价值的信息,立刻拆解成三个部分——思考要点(比如是否适合自己)、执行步骤(比如本周验证什么)、反馈节点(比如两周后复盘效果),别让信息躺在那里吃灰。
    ',36)])])}const u=e(l,[["render",o]]);export{c as __pageData,u as default}; diff --git "a/assets/30.\346\202\246\350\257\273\346\227\266\345\205\211_21.\345\246\202\344\275\225\347\224\204\345\210\253\347\234\237\346\255\243\346\234\211\347\224\250\347\232\204\344\277\241\346\201\257.md.C7EJFVmA.lean.js" b/assets/growth_distinguish-useful-information.md.CwjMB2nE.lean.js similarity index 71% rename from "assets/30.\346\202\246\350\257\273\346\227\266\345\205\211_21.\345\246\202\344\275\225\347\224\204\345\210\253\347\234\237\346\255\243\346\234\211\347\224\250\347\232\204\344\277\241\346\201\257.md.C7EJFVmA.lean.js" rename to assets/growth_distinguish-useful-information.md.CwjMB2nE.lean.js index 6fa6e791..d776ef4c 100644 --- "a/assets/30.\346\202\246\350\257\273\346\227\266\345\205\211_21.\345\246\202\344\275\225\347\224\204\345\210\253\347\234\237\346\255\243\346\234\211\347\224\250\347\232\204\344\277\241\346\201\257.md.C7EJFVmA.lean.js" +++ b/assets/growth_distinguish-useful-information.md.CwjMB2nE.lean.js @@ -1 +1 @@ -import{_ as e,g as r,h as t,U as i}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const c=JSON.parse('{"title":"如何甄别真正有用的信息","description":"摘要总结:在信息高度透明的时代,浅层信息差已被彻底抹平,信息本身的价值不断稀释。人与人的核心差距不再是获取信息的渠道,而是高信噪比信息的甄别能力、深度思考能力与落地执行力,唯有以思考校验信息、以执行验证价值,形成“信息-判断-实践-反馈”的思考与执行闭环,才能突破信息壁垒、创造真正价值。","frontmatter":{"date":"2025-11-10T12:52:28.000Z","title":"如何甄别真正有用的信息","description":"摘要总结:在信息高度透明的时代,浅层信息差已被彻底抹平,信息本身的价值不断稀释。人与人的核心差距不再是获取信息的渠道,而是高信噪比信息的甄别能力、深度思考能力与落地执行力,唯有以思考校验信息、以执行验证价值,形成“信息-判断-实践-反馈”的思考与执行闭环,才能突破信息壁垒、创造真正价值。","permalink":"/growth/distinguish-useful-information","categories":["资源推荐"],"tags":["信息筛选","个人成长"]},"headers":[],"relativePath":"30.悦读时光/21.如何甄别真正有用的信息.md","filePath":"30.悦读时光/21.如何甄别真正有用的信息.md"}'),l={name:"30.悦读时光/21.如何甄别真正有用的信息.md"};function o(n,a,s,h,d,_){return t(),r("div",null,[...a[0]||(a[0]=[i("",37)])])}const u=e(l,[["render",o]]);export{c as __pageData,u as default}; +import{_ as e,g as r,h as t,U as i}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const c=JSON.parse('{"title":"如何甄别真正有用的信息","description":"摘要总结:在信息高度透明的时代,浅层信息差已被彻底抹平,信息本身的价值不断稀释。人与人的核心差距不再是获取信息的渠道,而是高信噪比信息的甄别能力、深度思考能力与落地执行力,唯有以思考校验信息、以执行验证价值,形成“信息-判断-实践-反馈”的思考与执行闭环,才能突破信息壁垒、创造真正价值。","frontmatter":{"date":"2025-11-10T12:52:28.000Z","title":"如何甄别真正有用的信息","description":"摘要总结:在信息高度透明的时代,浅层信息差已被彻底抹平,信息本身的价值不断稀释。人与人的核心差距不再是获取信息的渠道,而是高信噪比信息的甄别能力、深度思考能力与落地执行力,唯有以思考校验信息、以执行验证价值,形成“信息-判断-实践-反馈”的思考与执行闭环,才能突破信息壁垒、创造真正价值。","permalink":"/growth/distinguish-useful-information","categories":["资源推荐"],"tags":["信息筛选","个人成长"]},"headers":[],"relativePath":"growth/distinguish-useful-information.md","filePath":"30.悦读时光/21.如何甄别真正有用的信息.md"}'),l={name:"growth/distinguish-useful-information.md"};function o(n,a,s,h,_,d){return t(),r("div",null,[...a[0]||(a[0]=[i("",36)])])}const u=e(l,[["render",o]]);export{c as __pageData,u as default}; diff --git a/assets/growth_reading-tips.md.Dg4fAO7r.js b/assets/growth_reading-tips.md.Dg4fAO7r.js new file mode 100644 index 00000000..5744c350 --- /dev/null +++ b/assets/growth_reading-tips.md.Dg4fAO7r.js @@ -0,0 +1 @@ +import{_ as o,g as a,h as r,U as l}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const d=JSON.parse('{"title":"读书“三要”和“三不要”","description":"摘要总结:在信息爆炸的时代,读书依然是获取深度知识最高效的方式之一。但“捧起书”并不等于“有收获”,怎么读往往比读什么更重要。本文总结了高效阅读的“三要”与“三不要”:从完整阅读观摩大师思维、带着问题构建知识树,到通过讨论检验理解;同时提醒阅读者警惕哀怨心态对阅读初衷的异化、避免陷入对物理媒介的“玩物丧志”,以及切忌脱离现实的“真空”阅读。阅读不仅是向内探索的精神之旅,更是向外理解真实世界、创造社会价值的实用工具。","frontmatter":{"date":"2025-03-06T11:42:20.000Z","title":"读书“三要”和“三不要”","description":"摘要总结:在信息爆炸的时代,读书依然是获取深度知识最高效的方式之一。但“捧起书”并不等于“有收获”,怎么读往往比读什么更重要。本文总结了高效阅读的“三要”与“三不要”:从完整阅读观摩大师思维、带着问题构建知识树,到通过讨论检验理解;同时提醒阅读者警惕哀怨心态对阅读初衷的异化、避免陷入对物理媒介的“玩物丧志”,以及切忌脱离现实的“真空”阅读。阅读不仅是向内探索的精神之旅,更是向外理解真实世界、创造社会价值的实用工具。","coverImg":"https://insight-stack-1252300811.cos.ap-shanghai.myqcloud.com/img/growth/reading_need.png","permalink":"/growth/reading-tips","sticky":1,"top":true,"categories":["悦读时光"],"tags":["悦读时光"]},"headers":[],"relativePath":"growth/reading-tips.md","filePath":"30.悦读时光/10.读书三要三不要.md"}'),e={name:"growth/reading-tips.md"};function i(n,t,s,p,g,h){return r(),a("div",null,[...t[0]||(t[0]=[l('

    读书“三要”和“三不要”

    摘要总结:在信息爆炸的时代,读书依然是获取深度知识最高效的方式之一。但“捧起书”并不等于“有收获”,怎么读往往比读什么更重要。本文总结了读书的“三要”与“三不要”:从完整阅读观摩大师思维、带着问题构建知识树,到通过讨论检验理解;同时提醒阅读者警惕哀怨心态对阅读初衷的异化、避免陷入对物理媒介的“玩物丧志”,以及切忌脱离现实的“真空”阅读。阅读不仅是向内探索的精神之旅,更是向外理解真实世界、创造社会价值的实用工具。

    about site background

    1. 我们为什么需要读书?

    读书是从外界接受信息的一种方式,与聊天、浏览网页、听播客、看电视并无本质区别。但书这种媒介与其他信息媒介相比,有其独有的优势:

    • 深度与严谨:书籍往往是创作者多年思考、长期写作的产物,经过专业编辑反复修改校对,知识密度远高于日常谈话或碎片内容。
    • 专注与反刍:读书允许读者专注其中,书中的信息因此往往条理清晰、逻辑严密,语言也更为精练紧凑。读者可以随时停下翻回反复琢磨、推敲。相比之下,电视画面一闪而过,很难进行层层递进的深入分析。
    • 知识密度高:沉淀在书中的信息,往往逻辑性强、语言精练紧凑(即所谓的“书面语”),知识含量远超日常碎片化信息。认真读完一本好书,获得的知识与思考深度,往往超过看几部剧、刷几小时短视频,甚至聊几个小时天的总和。

    认真读一本好书,往往比看一部电视剧或漫无目的地浏览网页能获得更多知识。但这并不意味着“只要捧起书就一定有收获”,关键在于怎么读

    2. 读书"三要"

    第一“要”:完整地读,整本地读

    对于好书,要完整地读、整本地读,不要只捡结论。

    很多人习惯直接看结论和观点,觉得这样效率高。但这样做有一个根本缺陷:你只得到了答案,却错过了思考方法本身

    掌握思考方法的唯一途径,是通过完整地阅读来观摩优秀的大师是如何思考的——他们如何一步步推导出结论,如何分析和批判不同的观点,遇到困难时又如何转换视角。看得多了,自然能渐渐窥见门道,再辅以勤恳的思考训练,才能真正将思维方法内化。

    相反,只知道观点、不掌握方法的后果,是"刻舟求剑"

    • 理论的适用条件只要稍有些变化,便无所适从,只会把那几条观点反复背诵套用。
    • 经典著作往往具有复杂性,读起来必须动脑筋。只背诵结论不是传授学问的方法,而是培养盲从信徒的方法,而不是做学问的路径。

    第二“要”:带着问题去读,构建知识树

    要带着问题去读书,将散乱的信息构建成清晰的知识树。

    每一本知识性书籍,背后都有一个(或一组)核心问题。知识性书籍的诞生,往往是为了解答、批驳或赞同某个特定的观点,好的作者会先把他要回答的问题交代清楚,再展开论述。

    • 还原“问题情境”:很多流传至今的名著,现代人之所以读不进去,是因为对当时的“问题情境”一无所知。许多经典在当年都是锋芒毕露、针锋相对的论辩性作品,是为了解决当时的痛点而生。一旦你了解了这些背景,事先知道了这本书在学科谱系中的位置,阅读就会变得像追踪一场精彩的辩论一样有趣。

    • 连点成树:带着亟待回答的问题去读书,不但不会觉得枯燥,反而能充分享受新知的乐趣。这样吸收进来的知识不再是无意义的堆积物,而是沿着“批判—反批判—再批判”线索生长出来的、清晰的知识树。有了知识树,才能真正形成自己的思想观念,才能条理清晰地理解世界。

    • 善用指引:老师或导读无法代替你读书,但可以帮你解释问题情境、指明知识门径、交代语境(所谓“师傅领进门,修行在个人”),大大提高你的阅读效率和理解深度。

    第三“要”:与人(或AI)讨论,检验理解的试金石

    读完一本书,要找人讨论(也可以与能力较强的 AI 工具深度对话),讨论是检验理解的试金石。

    独自阅读常形成模糊的理解链条,容易产生“我懂了”的幻觉,唯有能用自己的语言让别人听懂,才算真正理解。

    真正的理解有一个更高的标准:把书中的观点用自己的话讲给别人听,让对方也能听懂。"看懂"和"讲清楚"之间,差着十万八千里。很多时候,所谓"看懂",不过是在脑中形成了一条模糊、不连贯的"理解链"。只有当你必须用自己的语言向别人复述,并且要做到言之成理、自圆其说时,那些薄弱、缺失的环节才会立刻暴露出来(含糊的地方你会直接卡壳)。

    在“刁难”中查漏补缺,讲述的过程会倒逼你:

    1. 把逻辑理清楚,确保"因为"和"所以"之间真的成立;
    2. 发现自己还没搞懂的地方,带着新问题回去再读;
    3. 在他人的追问和质疑中,不断深化理解。

    我曾尝试将几本书的内容讲给没时间阅读的朋友听。他们可不会把我当“老师”来尊敬,遇到疑问或不同意见就会随时打断,甚至以把我“问倒”为乐。结果是,我原以为完全看懂的书,被他们一通“胡搅蛮缠”后,发现竟然还有那么多没吃透的地方,只能回去重读。下一次见面时,我必须把他们的质疑解释清楚。但也正因如此,那几本书成了我书架上理解最透彻、收获最大的书。

    这里的讲述不是单方面的课堂宣讲,而是面对面的平等讨论、寻找高质量的对话。如果对话者水平高、讨论深入,效果极佳。在如今,你甚至可以把逻辑推理能力较强的 AI 工具当作你的“讨论搭子”,让它对你的观点进行提问和反驳,以此来迫使自己真正透彻地掌握知识。

    3. 读书"三不要"

    第一“不要”:不要怀揣哀怨心态,避免读书目的被异化

    不要有哀怨心态,被哀怨情绪控制,就失去了读书的平常心和客观理解力。

    读书多不等于人才,未提供社会价值则难致富。若因此怨天尤人,读书将异化为排解情绪与博取关注的工具。

    一个人一旦被哀怨情绪控制,就会彻底失去读书的平常心和客观理解力。

    • 警惕“价值转化”的幻觉:有些人确实读了不少书,说起话来头头是道,也时常能得到他人的赞许。这容易让人产生一种幻觉,自认是个“被埋没的人才”。但实际上,读书多不等于人才,真正的财富来源于你能否为别人提供有价值的商品或服务。得到别人的口头赞许,与让别人掏钱买你的服务之间,有着巨大的鸿沟。

    • 警惕心态失衡与怨天尤人:当自诩为“人才”却迟迟未能发家致富时,很多人不会反思自己是否创造了真正的社会价值,而是将原因归咎于外界,静等着“伯乐”来发掘。当看到身边不读书的人纷纷买车买房时,这种着急就会演变成气急败坏、鄙夷与哀怨,甚至觉得“社会太不公平”。

    • 防止阅读初衷的异化:这是最致命的一点。当怨气占据大脑,读书对于这类人来说,就不再是客观接受信息、理解世界的方式了,而是沦为了一种排解郁闷、打发时间的消极手段。他们的关注点会从书本内容彻底转移到别人的眼光上,内心的潜台词变成了表演:“你们还没看到我刻苦读书的身姿吗?还不承认我是个人才吗?还不提高我的收入吗?”

    第二“不要”:不要玩物丧志,陷入对物理媒介的过度迷恋

    不要玩物丧志,过度沉溺书籍细节与附属品会导致“玩物丧志”。若读书脱离获取信息的目的,则难以在知识学问上有所成就。

    • 回归阅读的本质:读书的核心目的是为了获取信息、汲取知识,而不是为了把玩那一束装订起来的纸张。随着阅读的深入,很多人容易沉溺于书籍带来的附加体验(如纸张的手感、油墨的香气、版本的考究)。这种对物理形态的偏好可以理解,但必须有所节制,一旦喧宾夺主,甚至因此拒绝更高效的媒介,就是南辕北辙了。

    • 顺应媒介演进的效率趋势,时代趋势不可逆:纵观历史,从丝绸、竹简到纸张,再到如今的电子书,信息媒介的演进始终朝着“更低成本、更高效率”的方向发展。在信息时代,电子书在便携性、易储性、内容可检索性(如一键全文搜索)以及知识共享方面,拥有纸质书无法比拟的优势,这对于快速定位关键信息、构建个人知识树而言是极大的助力。

    • 警惕被“旧习惯”绑架:很多抗拒电子书的人,强调的种种理由其实与“读书”本身关系不大,更多是不愿改变旧有的阅读习惯,不愿放弃读书以外的把玩乐趣。为了坚持这种旧习惯,而不惜牺牲信息流转和获取的效率,这在信息爆炸的时代是得不偿失的。

    • 积极拥抱新媒介的红利:真正以求知为目的的人,从来都会积极拥抱新的传播工具。在这个时代,固守传统媒介的人获取知识的成本会越来越高、效率越来越低;而愿意接纳新媒介的阅读者,则能以更轻松、愉快的方式,获取最丰沛的知识。

    第三“不要”:不要只读书不知现实,避免知识结构陷入“真空”

    书籍仅承载极少知识,大量隐性知识存于现实社会。只读书会导致知识结构缺陷,难以应对实务,故不可脱离现实。

    书本知识只是认识世界的一小部分,脱离现实的纯粹阅读,会导致知识结构的严重扭曲。

    • 认清书籍的局限性:知识以各种方式存在于社会的各个角落,书籍所承载的仅仅是世界知识总量中极小的一部分。由于书籍要求书面化、系统且连贯,它必然无法记录下大量不稳定、转瞬即逝、碎片化或难以用语言明确表达的知识。

    • 重视庞大的“隐性知识”:在现实社会中,存在着诸如谈话交流、个人经验、行为方式、商业模式及人际关系等海量的非书本知识。如果一个人只是一味读书而极少参与社会实践,就会完全错失这部分在数量上更为庞大的知识宝库,导致知识结构出现重大缺陷。

    • 警惕脱离现实的“扭曲认知”:如果只读书而不参与社会实践,会导致知识结构存在重大缺陷,在处理现实事务时会暴露无遗。在数学、计算机或棋类等高度抽象、无需太多社会经验的领域,仅凭逻辑推演确实可以成就“少年天才”。但真实世界的绝大多数领域(如法律、商业、服务业等)极度依赖从业者的社会经验和现实感。只读书不仅会造成处理实际事务时能力低下,更会以一小部分取代整体,形成对真实世界的扭曲认知。仅靠抽象逻辑是无法解决复杂现实问题的,这也是为什么世界上会有15岁的黑客,却绝不会有15岁的人事经理或法官。

    4. 让书籍成为连接自我与现实的桥梁

    读书从来不是为了把自己变成一个装满各类观点的“两脚书橱”,而是为了升级我们思考现实、解决问题的“底层操作系统”。

    无论是坚持“三要”(掌握方法、构建体系、检验真知),还是警惕“三不要”(拒绝异化、拥抱高效、扎根现实),最终的指向都是同一个:打破书本与现实的壁垒,让知识真正为你所用。 在获取信息门槛越来越低的今天,独立思考和将知识转化为实际价值的能力愈发珍贵。

    愿我们都能带着平常心去阅读,在书中观摩大师的智慧,在现实中创造真实的价值,享受纯粹而充实的悦读时光。

    ',42)])])}const u=o(e,[["render",i]]);export{d as __pageData,u as default}; diff --git "a/assets/30.\346\202\246\350\257\273\346\227\266\345\205\211_10.\350\257\273\344\271\246\344\270\211\350\246\201\344\270\211\344\270\215\350\246\201.md.BQj2m1KY.lean.js" b/assets/growth_reading-tips.md.Dg4fAO7r.lean.js similarity index 70% rename from "assets/30.\346\202\246\350\257\273\346\227\266\345\205\211_10.\350\257\273\344\271\246\344\270\211\350\246\201\344\270\211\344\270\215\350\246\201.md.BQj2m1KY.lean.js" rename to assets/growth_reading-tips.md.Dg4fAO7r.lean.js index beedd845..ed532b51 100644 --- "a/assets/30.\346\202\246\350\257\273\346\227\266\345\205\211_10.\350\257\273\344\271\246\344\270\211\350\246\201\344\270\211\344\270\215\350\246\201.md.BQj2m1KY.lean.js" +++ b/assets/growth_reading-tips.md.Dg4fAO7r.lean.js @@ -1 +1 @@ -import{_ as o,g as a,h as r,U as e}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const c=JSON.parse('{"title":"读书“三要”和“三不要”","description":"摘要总结:在信息爆炸的时代,读书依然是获取深度知识最高效的方式之一。但“捧起书”并不等于“有收获”,怎么读往往比读什么更重要。本文总结了高效阅读的“三要”与“三不要”:从完整阅读观摩大师思维、带着问题构建知识树,到通过讨论检验理解;同时提醒阅读者警惕哀怨心态对阅读初衷的异化、避免陷入对物理媒介的“玩物丧志”,以及切忌脱离现实的“真空”阅读。阅读不仅是向内探索的精神之旅,更是向外理解真实世界、创造社会价值的实用工具。","frontmatter":{"date":"2025-03-06T11:42:20.000Z","title":"读书“三要”和“三不要”","description":"摘要总结:在信息爆炸的时代,读书依然是获取深度知识最高效的方式之一。但“捧起书”并不等于“有收获”,怎么读往往比读什么更重要。本文总结了高效阅读的“三要”与“三不要”:从完整阅读观摩大师思维、带着问题构建知识树,到通过讨论检验理解;同时提醒阅读者警惕哀怨心态对阅读初衷的异化、避免陷入对物理媒介的“玩物丧志”,以及切忌脱离现实的“真空”阅读。阅读不仅是向内探索的精神之旅,更是向外理解真实世界、创造社会价值的实用工具。","coverImg":"https://insight-stack-1252300811.cos.ap-shanghai.myqcloud.com/img/growth/reading_need.png","permalink":"/pages/growth/reading-tips","sticky":1,"top":true,"categories":["悦读时光"],"tags":["悦读时光"]},"headers":[],"relativePath":"30.悦读时光/10.读书三要三不要.md","filePath":"30.悦读时光/10.读书三要三不要.md"}'),i={name:"30.悦读时光/10.读书三要三不要.md"};function l(n,t,s,p,g,h){return r(),a("div",null,[...t[0]||(t[0]=[e("",43)])])}const u=o(i,[["render",l]]);export{c as __pageData,u as default}; +import{_ as o,g as a,h as r,U as l}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const d=JSON.parse('{"title":"读书“三要”和“三不要”","description":"摘要总结:在信息爆炸的时代,读书依然是获取深度知识最高效的方式之一。但“捧起书”并不等于“有收获”,怎么读往往比读什么更重要。本文总结了高效阅读的“三要”与“三不要”:从完整阅读观摩大师思维、带着问题构建知识树,到通过讨论检验理解;同时提醒阅读者警惕哀怨心态对阅读初衷的异化、避免陷入对物理媒介的“玩物丧志”,以及切忌脱离现实的“真空”阅读。阅读不仅是向内探索的精神之旅,更是向外理解真实世界、创造社会价值的实用工具。","frontmatter":{"date":"2025-03-06T11:42:20.000Z","title":"读书“三要”和“三不要”","description":"摘要总结:在信息爆炸的时代,读书依然是获取深度知识最高效的方式之一。但“捧起书”并不等于“有收获”,怎么读往往比读什么更重要。本文总结了高效阅读的“三要”与“三不要”:从完整阅读观摩大师思维、带着问题构建知识树,到通过讨论检验理解;同时提醒阅读者警惕哀怨心态对阅读初衷的异化、避免陷入对物理媒介的“玩物丧志”,以及切忌脱离现实的“真空”阅读。阅读不仅是向内探索的精神之旅,更是向外理解真实世界、创造社会价值的实用工具。","coverImg":"https://insight-stack-1252300811.cos.ap-shanghai.myqcloud.com/img/growth/reading_need.png","permalink":"/growth/reading-tips","sticky":1,"top":true,"categories":["悦读时光"],"tags":["悦读时光"]},"headers":[],"relativePath":"growth/reading-tips.md","filePath":"30.悦读时光/10.读书三要三不要.md"}'),e={name:"growth/reading-tips.md"};function i(n,t,s,p,g,h){return r(),a("div",null,[...t[0]||(t[0]=[l("",42)])])}const u=o(e,[["render",i]]);export{d as __pageData,u as default}; diff --git a/assets/index.md.CZC8OIc5.js b/assets/index.md.CZC8OIc5.js deleted file mode 100644 index 182d4341..00000000 --- a/assets/index.md.CZC8OIc5.js +++ /dev/null @@ -1 +0,0 @@ -import{d as o,u as n,o as s,g as c,h as a,i as l,S as r,x as d,l as m}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const h={id:"hero-text",style:{display:"inline-block",position:"relative"}},u={style:{color:"var(--vp-c-brand)",position:"absolute","z-index":"-1",top:"1em",left:"0.2em",width:"calc(100% - 0.7em)",height:"auto"},width:"240",height:"11",viewBox:"0 0 240 11",fill:"currentColor",xmlns:"http://www.w3.org/2000/svg"},f=JSON.parse('{"title":"首页","titleTemplate":":title | Insight Stack Blog","description":"","frontmatter":{"layout":"home","title":"首页","titleTemplate":":title | Insight Stack Blog","tk":{"teekHome":true,"features":[{"title":"全栈","details":"Engineering × Product × AI","link":"/fullstack/overview","image":"https://insight-stack-1252300811.cos.ap-shanghai.myqcloud.com/topic/icon_full_stack_circle.webp"},{"title":"AI 学习与实践","details":"Model × Agent × Engineering","link":"/ai-learning/overview","image":"https://insight-stack-1252300811.cos.ap-shanghai.myqcloud.com/topic/icon_llm_circle.webp"},{"title":"产品 Sense","details":"Impact × Simplicity","link":"/product-sense","image":"https://insight-stack-1252300811.cos.ap-shanghai.myqcloud.com/topic/icon_product_sense_circle.webp"}]},"hero":{"name":"Insight Stack Blog","text":"AI & 全栈技术 & 产品思考与成长记录","tagline":"✨探索技术前沿,沉淀产品思考,记录成长点滴,相信时间的力量","actions":[{"theme":"brand","text":"关于我","link":"/about/me"},{"theme":"alt","text":"资源推荐","link":"/growth/sites"},{"theme":"alt","text":"书籍推荐","link":"/growth/books"}],"image":{"src":"/img/full-stack/insight_stack.png","alt":"Insight Stack Blog"}},"features":[{"icon":"📖","title":"全栈技术","details":"前端 & NodeJS & Python 等","link":"/fullstack/overview"},{"icon":"🎉","title":"产品 Sense","details":"产品 Sense = 用户价值洞察 × 商业可行性 × 技术可实现性","link":"/product-sense"},{"icon":"🎇","title":"LLM 应用学习与实践","details":"梳理大语言模型应用、Agent 技术、上下文工程与AI编程等专题,探索 AI 时代的技术与应用。","link":"/ai-learning/overview"},{"icon":"📝","title":"个人成长","details":"收录一些不错的站点、技术周刊、AI 等资源,总结个人在时间管理、效率工具、健康管理等方面的成长经验。","link":"/about/me"}]},"headers":[],"relativePath":"index.md","filePath":"index.md"}'),p={name:"index.md"},x=o({...p,setup(g){const{frontmatter:i}=n();return s(()=>{const e=document.querySelector(".VPHero .text"),t=document.querySelector("#hero-text");if(!(!e||!t)){for(;e.lastChild;)e.lastChild.remove();e.append(t)}}),(e,t)=>(a(),c("div",null,[t[1]||(t[1]=l("div",{style:{display:"none"},hidden:"true","aria-hidden":"true"},"Are you an LLM? View /llms.txt for optimized Markdown documentation, or /llms-full.txt for full documentation bundle",-1)),l("span",h,[r(d(m(i).hero.text)+" ",1),(a(),c("svg",u,[...t[0]||(t[0]=[l("path",{d:"M20.766 10.187c.939-.024.386-.885.552-1.401 1.105-.301.553.626.962 1.061.685-.263 1.171-1.1 1.696-1.085.044.144.15.191.044.378.697-.736 2.21-.134 2.995-1.052a.55.55 0 0 1 .127.215 3.35 3.35 0 0 1-.204-1.204c.42-.034.751-.593.94 0-.255 0-.266.23-.377.416l.426-.273c.448.813-.586.316-.553.927.84-.306 1.802-1.037 2.476-.831.182.803-1.525.339-.608 1.023l-1.033-.268c.85 1.248-.625-.057.171 1.276 1.348.177 1.47-.478 2.818-.3.276-.479-.132-.66.144-1.124 1.857-.885 1.602 1.984 2.94.846.337-.555.42-1.582 1.442-1.08l-.276.889c1.298.038.668-1.348 2.06-.784-.226.368-1.005.344-.8.444.917.689.59-.545 1.27-.569l.16.827c1.371-.181 2.863-.827 4.388-1.037-.072.249-.326.512.044.746 1.912-.478 4.123-.058 6.007.368l.68-.727c.05.015.095.04.132.074a.275.275 0 0 1 .077.118c.014.044.015.091.004.136a.27.27 0 0 1-.07.122c.74.243 0-.445.354-.732.414-.062.552.383.315.603 1.248-.636 3.586-1.401 4.973-.694l-.254.22c1.06.249 1.105-1.477 2.127-.855l-.182.129c2.293.23 4.785-.478 6.564.52.293-1.017 2.272.393 2.365-1.022 1.327.664.967.927 2.813 1.348.492.052.702-.899 1.299-1.061l.044.731.79-.794.47.87.552-.205a.66.66 0 0 1-.332-.2.517.517 0 0 1-.132-.33c.873-.354 2.177.477 2.21.831l2.078-.679c-.039.301-.387.411-.657.607 1.105-.779.226.77 1.232.053-.144-.163.06-.44.077-.588.553.435 1.691.416 2.547.205l-.149.512c1.558.1 3.271-.31 5.018-.335-.636-.224-.514-1.109 0-1.204l.226.774c.32-.478-.552-.282.122-.884.652.076.464.875.094 1.138l.784-.287c.056.23-.127.358-.165.655.309-.478 1.387.75 1.834-.096l.05.23c1.746-.03 2.53-.316 3.95-.383 0-.674.553-.535.984-1.085 1.05.196 2.21.707 3.482.63.878-.343.243-.568.635-.955.077.612 1.332.535.69.985a15.353 15.353 0 0 0 3.83-.68c-.21-.243-.447-.353-.331-.563a.738.738 0 0 1 .275.01c.09.02.173.058.245.11a.58.58 0 0 1 .169.188c.04.072.061.151.062.232l-.088.067c2.127-.956 4.973 1.706 6.669.41l-.099.068 1.763-.684c.817.1-.481.478.127.842 1.9-1.043 3.022.12 4.586-.574 1.243 1.793 4.327-.167 5.979.956l-.1-.42c.426-.421.52.234.835.33-.05-.33-.464-.378-.205-.613 3.598-.545 7.438.598 11.129.956 1.348.11.757-2.203 2.465-1.195l-.481.794c2.719-.956 5.564 0 8.233-.77-.154.182-.16.416-.425.416.552.574 2.083.034 2.094-.435.42.053.1.425.354.665.552.339 1.42-.732 1.718-.158.05.09-.16.186-.265.23.37-.278 1.719.076 1.365-.589 1 .32 1.917-.287 2.713.105.553-.736 1.713.364 1.884-.683-.077 1.08 1.752.875 2.387.377-.215.326.553.345.299.794.718 0 1.381-.206 1.265-.76 1.315 1.305 2.686-1.018 3.415.645a45.888 45.888 0 0 1 6.078-1.17c-.082 1.075-2.138.09-2.066 1.218 1.834-.425 2.906-1.343 4.719-1.066.47.153-.276.478-.437.65 1.835-.43 3.537.148 5.172-.42 0 .1-.182.21-.348.291.321-.033.741.167.713-.325l-.315.13c-.497-.718 1.304-1.468 1.365-1.841-.553 1.396 1.602.377.707 2.137a.73.73 0 0 0 .337-.263.58.58 0 0 0 .1-.383c.315.1.409.297.083.665 1.155-.254.757-.78 1.801-.75 0 .233-.221.324-.337.601.553-.478 1.078-.908 1.951-.697-.056.143.044.33-.216.325 1.509-.048 2.603-1.195 4.249-.722-.513 1.023.553.349.625 1.243l.895-.254-.348-.44c.785.034 1.492-.602 2.155-.296l-.591.354 1.47-.139-.824-.354c.807-.444-.055-1.132.978-.86-.21.086.785.029 1.177.56.398-.278.801-.57 1.376-.335.138.291-.149.984-.055 1.176.398-.736 1.834-.168 2.337-.956-.143.227-.192.49-.138.745l.337-.597c.359.2.409.296.337.669 1.105.134-.309-1.138.967-.626-.105.048-.055.138-.27.23 1.287.277 2.519-.335 3.702 0 .326.903-1.05.195-.669.955 1.724-.129 3.592-.999 5.25-.74l-.31-.106c.277-1.262 1.221.66 2.083.086-.21.086-.298.693-.237.555 1.105.234 2.343-.249 4.083-.603l-.226.32c.657.311 1.763.216 2.481.383.226-.315.641-.253.403-.731 2.166 1.912 4.305-.89 6.228.726-.238 0-.553.268-.387.273l1.702-.244c-.111-.554-.21-.34-.553-.784.124-.163.292-.298.489-.392.198-.094.419-.145.644-.148-.774.34-.028.884.287 1.205-.049-.173.072-.354.05-.526.846 1.008.199-1.11 1.376-.407l-.077.287c.458-.134.889-.478 1.37-.401.177.645-.492.282-.552.803.685 0 1.403-1.162 1.994-.507-.298.167-.718.158-1.016.325.641.77.729.583 1.221.717h-.044l1.138.378-.282-.21c.928-1.635 1.752-.25 2.951-1.3-1.166.994-.21.592-.332 1.309.288.21.724.454.586.65.553-.564.89.478 1.696-.34 0 .235.581.044.431.627.713-.163-.149-.411-.077-.703 1.133-.76 2.514 1.061 4.139.029 1.376-.397 1.658-1.171 2.94-1.515.403.392-.393.836-.393.836.267.161.581.255.906.27a1.97 1.97 0 0 0 .934-.184c-.138.196 0 .373.172.64.519-.038.386-.831 1.05-.477a3.24 3.24 0 0 1-.553.918c.619-.192 1.243-.603 1.884-.79.149.412-.409.603-.646.856.718-.153 1.851-.296 2.105-.927l-.442-.248c.26 0 .105.559-.094.669-.63.478-.862-.258-.884-.478l.459-.134c-.387-1.382-1.818.148-2.719.033l.431-.956-.973.784c-.182-.263-.287-.822.166-.956-.624-.516-.591.33-1.105-.239-.055-.086-.028-.134.033-.172l-.646.273c.132-.201-.072-.703.309-.545-1.105-.617-1.873.674-2.26-.096l.099-.057c-1.596.272-.193.721-1.414 1.534l-.713-1.83-.188.721c-.16-.033-.481-.1-.409-.387-.63.478.089.32-.287.78-.752-.699-2.172.229-2.293-.957-.31.545.729.478-.127.813-.183-1.258-.978.181-1.658-.416.254-.636.917-.273.226-.875-.486 1.076-1.386-.282-2-.096-.066.87-1.332.32-2.354.579.078-.292-1.89-.54-2.818-.885l.033-.148c-.221.87-1.182.674-1.901.832a.906.906 0 0 1 .132-.55c.102-.169.258-.31.449-.406h-.669a.979.979 0 0 1-.34.327 1.167 1.167 0 0 1-.478.151l.194-.65c-.885 0-1.813.712-2.94.244-.083.607.84 1.725-.381 2.103-.034-.335-.056-.899.27-1.028-.105.043-.381.263-.585.12l.502-.545c-.508-.258-.287.478-.701.397 0-.478-.293-.35-.221-.722.11-.038.359.205.525 0a1.931 1.931 0 0 1-.691-.264 1.649 1.649 0 0 1-.503-.487c.028.268-.028.636-.37.684-.89 0-.282-.574-.79-.832-.227.325-.78-.033-.824.674-.259 0-.293-.34-.387-.535-.469.3-2.149.033-1.657.793l.116.053s-.05 0-.078.033c-1.525.66-3.105-.478-4.608-.224V3.34c-.895.244-1.984.106-2.636.593a.711.711 0 0 1-.402-.28.553.553 0 0 1-.084-.442c-.691.158-.774.416-1.746 0 .701-.396-.221-.373.713-.287-.879-.224-1.067-.607-2.039 0 .342-.597-.641-.774-1.067-.602l.608.445c-.436.053-.88.039-1.31-.043l.254-.794c-1.784-1.004-3.315 1.578-4.647-.067-.497.545.973.411.553 1.052-.829-.124-1.658-1.286-1.929-1.29-1.132-.479-1.105 1.137-2.282.812a.818.818 0 0 1 .031.774.938.938 0 0 1-.264.323 1.11 1.11 0 0 1-.397.198c-.829-.124-.994-1.214-.464-1.434.205 0 .299.072.288.168.27-.096.629-.21.303-.526l-.116.282c-.403-.297-1.552-.292-1.271-.75-.635.257-.281.477.183.616-1.061-.435-1.658-.053-2.763-.344.171.162.326.478.155.478-1.608-.378-.724.526-1.824.636-.608-.445.249-1.033-.862-.684-.668-.306-.127-.755.149-.985-1.016.536-1.867-.387-2.442-.478l.553-.22a1.892 1.892 0 0 1-.846.12l.293.573c-.309-.105-.553-.11-.553-.348-.326.368.227.956-.42 1.434-.403-.297-1.265.286-1.392-.478 1.298.272-.127-.76.978-.866a1.102 1.102 0 0 1-.851.024c-.044-.086.044-.157.133-.2-1.233-.689-.592.846-1.879.807.171-.42-.287-.808-.497-.721.519 0 .237.712-.249 1.027-.823-.34-.906.235-1.337.187l.491.162c-.176.426-.585.364-1.165.478-.045-.33.524-.22.326-.368-.652.736-1.437-.793-2.338-.306-.409-.291-.027-.798-.387-.999-1.011.54-1.077-.588-2.133-.148.293.574.349.435-.403.985l1.735-.387-1.105.822c.525 0 1.105-.35 1.42-.249-.553.478-.481.316-.238.794-.701-.86-1.425.478-2.21-.1l.044-1.41c-1.232-.641-2.21.702-3.823.334l.513.248c-.221.56-.994.072-1.519.292.055-.478-.271-.645-.492-.956.028.349-1.177-.043-1.337.899l-.707-.627c-1.305-.267-1.503 1.33-2.763 1.157.381-.507-.183-.846.657-1.21-.414 0-.79-.095-.801.23-.276-.263-1.199.646-1.575.215-.182.206-.243.698-.713.655a.337.337 0 0 1 0-.234c0 .234-.735.31-.331.837-1.271-1.478-3.592.095-4.708-1.172-.936.165-1.883.277-2.835.335.05-.139 0-.234.16-.186-1.143-.44-.707 1.352-2.005.86-.664-.765.69-.411.276-.703-.171-1.553-1.564.21-2.437-.702l.21-.091c-.663-.555-1.608.564-2.713.454a.326.326 0 0 0 0-.234c-.746.784-2.155 1.051-3.205 1.271.326-.607.475-.32.276-.956-.47.091.138.99-.801 1.167-.304-.33-.984-.622-1.078-1.282l.89-.019c-.459-.85-1.149.034-1.613-.114l.055-.368c-1.36.124-1.376 1.06-2.835.999l.155.282c-.796.956-.674-.521-1.465.172l-.248-.956c-.871.453-1.797.82-2.763 1.094.552-.698 1.658-1.06 2.315-1.477-.519 0-1.774.072-2.044.54.21-.09.475-.325.685-.181a2.832 2.832 0 0 1-1.094.83 3.298 3.298 0 0 1-1.42.27c.171-1.832-2.713-.455-3.482-1.865-1.834.693-3.652-.258-5.796-.13.774 1.435-.625.049-.481 1.507-.497.1-.685.076-.729 0l-1.525-.86c-.365-.421.469-.326.42-.65-1.106-.106-.465-.618-1.194-1 .155.521-.37.75-1 .56l.901.659c-1.52.793-1.338-1.214-2.868-.43l.48-.478c-.79.277-2.917 0-3.674 1.204-.144-.167-.332-.564 0-.674-1.89-.148-4.183 1.31-5.664.612l.138-.358c-.348.105-.602.678-1.05.325 0-.148.138-.359 0-.378-.182.124-.923.64-1.392.44l.386-.411c-1.85-.44-2.807 1.023-4.343 1.29 0-1.051-1.475-1.376-2.21-1.53V.685c-2.15-.086-3.625.956-5.598 1.4-1.265-1.118-4.188-.392-6.194-.99.31.182 0 .818-.37.957-.475-.206-1.266.755-1.221-.21h.165c-.375-.957-1.326-.67-2.072-.675l-.083 1.267c-2.006-1.778-5.106.813-6.227-.803-.459.33-1.045.34-1.498.67v-.68a12.396 12.396 0 0 0-3.575 0l.31-.478c-.912 0-1.072 1.98-1.912 2.042l-.288-1c-1.591.053-3.232-.774-4.763.192 0-.148.055-.445.31-.478-.746 0-2.918-.588-2.587.788-.06-.903-1.657-.038-2.48.388l.104-.689c-.685.875-.701 1.11-1.696 1.377-.243-.076-.238-.526.088-.368-.812-.32-.59.655-1.574.33l.342-.435c-.823-.029-.746.2-1.177.707-.503.287-1.564-.114-1.713-.712-.094.368-.52.875-1.011.717a.38.38 0 0 1 .013-.245.442.442 0 0 1 .164-.2c-1.393-.406-2 .851-2.973.235a.553.553 0 0 0-.182-.392 9.431 9.431 0 0 1 1.89.028c0-.616-.912-.688-.255-1.563-.685.478-1.845 1.54-2.713 1.286a.84.84 0 0 1-.1-.215l.061-.072a.668.668 0 0 0-.295 0 .61.61 0 0 0-.257.125 1.992 1.992 0 0 0-.718-.158c-.128-.507-1.023-.234-1.465-.244.072.67-.508.583.06 1.119-.07-.048.078-.086.366-.125a.528.528 0 0 0 .188-.076l-.028.062c.287-.033.663-.062 1.105-.09-.332.358-.68.654-1.183.3-.204.445-.43.894-.552 1.11-.647-.914-1.83-1.377-2.022-1.946-1.321.43-3.145.368-3.918 1.663-.376.177-.459-.344-.614-.535.216-.139.476-.13.586-.316-.74.354-2.249.216-2.381 1.105-.984-.364.491-.837-.818-.636l.166-.277c-2.675-1.291-4.09 2.433-7.068.755.204.105.304.148.354.296-3.316-.645-6.709 1.038-10.018-.062-.94-.205-1 .359-1.531.818l-.249-.713-.906.88c-1.315.679-2.47-1.65-4.117-.411l.254.478c-.624-.058-1.939.387-1.873-.177-.055.09-.166.516-.425.272l-.044-.372-1.487.712c-1.199-.215.078-1.506-1.658-1.492C.895 5.105-.22 6.114.04 6.362c.178.01.347.073.478.179a.645.645 0 0 1 .24.4l-.558.225C.17 8.279-.194 9.44 1.304 10.144l.917-.732.36.521-.818.1c.513.479.784 0 1.105-.305.07.225.233.42.458.55l.907-1.114c.149.43-.376.884.292 1.094.426-.516-.502-.956.233-1.314.513.478.403.898.933.44a.447.447 0 0 1 .012.336.525.525 0 0 1-.233.27c.476-.367 1.304-.214 1.525-.817.553.598 1.658-.248 1.691.808.29-.433.74-.77 1.277-.956-.752 1.3 1.724 0 1.591 1.348.553-1.162 2.21-.617 3.255-1.3-.055.095-.16.282-.265.23.624.061.823.391 1.237.592 0-.956.967-1.195 1.448-1.797.812.87-.392 1.118-.1 1.974-.082-.755 1.272-.813.973-1.434.614.53.514.248.862 1.008.028-1.17.553-.22.962-.956.873.54.282 1.086 1.182.689.453.354-.342.808-.342.808Zm21.793-2.93-.447.057.447-.058Zm1.818-.091a7.552 7.552 0 0 0-.801 0c-.072-.23 0-.478.171-.478-.083.186.348.305.63.478Zm-4.128-4.49c.288-.109.393 0 .442.159-.172.02-.343.053-.508.1v.081a.973.973 0 0 1 .066-.34Z"},null,-1)])]))])]))}});export{f as __pageData,x as default}; diff --git a/assets/index.md.CZC8OIc5.lean.js b/assets/index.md.CZC8OIc5.lean.js deleted file mode 100644 index 182d4341..00000000 --- a/assets/index.md.CZC8OIc5.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{d as o,u as n,o as s,g as c,h as a,i as l,S as r,x as d,l as m}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const h={id:"hero-text",style:{display:"inline-block",position:"relative"}},u={style:{color:"var(--vp-c-brand)",position:"absolute","z-index":"-1",top:"1em",left:"0.2em",width:"calc(100% - 0.7em)",height:"auto"},width:"240",height:"11",viewBox:"0 0 240 11",fill:"currentColor",xmlns:"http://www.w3.org/2000/svg"},f=JSON.parse('{"title":"首页","titleTemplate":":title | Insight Stack Blog","description":"","frontmatter":{"layout":"home","title":"首页","titleTemplate":":title | Insight Stack Blog","tk":{"teekHome":true,"features":[{"title":"全栈","details":"Engineering × Product × AI","link":"/fullstack/overview","image":"https://insight-stack-1252300811.cos.ap-shanghai.myqcloud.com/topic/icon_full_stack_circle.webp"},{"title":"AI 学习与实践","details":"Model × Agent × Engineering","link":"/ai-learning/overview","image":"https://insight-stack-1252300811.cos.ap-shanghai.myqcloud.com/topic/icon_llm_circle.webp"},{"title":"产品 Sense","details":"Impact × Simplicity","link":"/product-sense","image":"https://insight-stack-1252300811.cos.ap-shanghai.myqcloud.com/topic/icon_product_sense_circle.webp"}]},"hero":{"name":"Insight Stack Blog","text":"AI & 全栈技术 & 产品思考与成长记录","tagline":"✨探索技术前沿,沉淀产品思考,记录成长点滴,相信时间的力量","actions":[{"theme":"brand","text":"关于我","link":"/about/me"},{"theme":"alt","text":"资源推荐","link":"/growth/sites"},{"theme":"alt","text":"书籍推荐","link":"/growth/books"}],"image":{"src":"/img/full-stack/insight_stack.png","alt":"Insight Stack Blog"}},"features":[{"icon":"📖","title":"全栈技术","details":"前端 & NodeJS & Python 等","link":"/fullstack/overview"},{"icon":"🎉","title":"产品 Sense","details":"产品 Sense = 用户价值洞察 × 商业可行性 × 技术可实现性","link":"/product-sense"},{"icon":"🎇","title":"LLM 应用学习与实践","details":"梳理大语言模型应用、Agent 技术、上下文工程与AI编程等专题,探索 AI 时代的技术与应用。","link":"/ai-learning/overview"},{"icon":"📝","title":"个人成长","details":"收录一些不错的站点、技术周刊、AI 等资源,总结个人在时间管理、效率工具、健康管理等方面的成长经验。","link":"/about/me"}]},"headers":[],"relativePath":"index.md","filePath":"index.md"}'),p={name:"index.md"},x=o({...p,setup(g){const{frontmatter:i}=n();return s(()=>{const e=document.querySelector(".VPHero .text"),t=document.querySelector("#hero-text");if(!(!e||!t)){for(;e.lastChild;)e.lastChild.remove();e.append(t)}}),(e,t)=>(a(),c("div",null,[t[1]||(t[1]=l("div",{style:{display:"none"},hidden:"true","aria-hidden":"true"},"Are you an LLM? View /llms.txt for optimized Markdown documentation, or /llms-full.txt for full documentation bundle",-1)),l("span",h,[r(d(m(i).hero.text)+" ",1),(a(),c("svg",u,[...t[0]||(t[0]=[l("path",{d:"M20.766 10.187c.939-.024.386-.885.552-1.401 1.105-.301.553.626.962 1.061.685-.263 1.171-1.1 1.696-1.085.044.144.15.191.044.378.697-.736 2.21-.134 2.995-1.052a.55.55 0 0 1 .127.215 3.35 3.35 0 0 1-.204-1.204c.42-.034.751-.593.94 0-.255 0-.266.23-.377.416l.426-.273c.448.813-.586.316-.553.927.84-.306 1.802-1.037 2.476-.831.182.803-1.525.339-.608 1.023l-1.033-.268c.85 1.248-.625-.057.171 1.276 1.348.177 1.47-.478 2.818-.3.276-.479-.132-.66.144-1.124 1.857-.885 1.602 1.984 2.94.846.337-.555.42-1.582 1.442-1.08l-.276.889c1.298.038.668-1.348 2.06-.784-.226.368-1.005.344-.8.444.917.689.59-.545 1.27-.569l.16.827c1.371-.181 2.863-.827 4.388-1.037-.072.249-.326.512.044.746 1.912-.478 4.123-.058 6.007.368l.68-.727c.05.015.095.04.132.074a.275.275 0 0 1 .077.118c.014.044.015.091.004.136a.27.27 0 0 1-.07.122c.74.243 0-.445.354-.732.414-.062.552.383.315.603 1.248-.636 3.586-1.401 4.973-.694l-.254.22c1.06.249 1.105-1.477 2.127-.855l-.182.129c2.293.23 4.785-.478 6.564.52.293-1.017 2.272.393 2.365-1.022 1.327.664.967.927 2.813 1.348.492.052.702-.899 1.299-1.061l.044.731.79-.794.47.87.552-.205a.66.66 0 0 1-.332-.2.517.517 0 0 1-.132-.33c.873-.354 2.177.477 2.21.831l2.078-.679c-.039.301-.387.411-.657.607 1.105-.779.226.77 1.232.053-.144-.163.06-.44.077-.588.553.435 1.691.416 2.547.205l-.149.512c1.558.1 3.271-.31 5.018-.335-.636-.224-.514-1.109 0-1.204l.226.774c.32-.478-.552-.282.122-.884.652.076.464.875.094 1.138l.784-.287c.056.23-.127.358-.165.655.309-.478 1.387.75 1.834-.096l.05.23c1.746-.03 2.53-.316 3.95-.383 0-.674.553-.535.984-1.085 1.05.196 2.21.707 3.482.63.878-.343.243-.568.635-.955.077.612 1.332.535.69.985a15.353 15.353 0 0 0 3.83-.68c-.21-.243-.447-.353-.331-.563a.738.738 0 0 1 .275.01c.09.02.173.058.245.11a.58.58 0 0 1 .169.188c.04.072.061.151.062.232l-.088.067c2.127-.956 4.973 1.706 6.669.41l-.099.068 1.763-.684c.817.1-.481.478.127.842 1.9-1.043 3.022.12 4.586-.574 1.243 1.793 4.327-.167 5.979.956l-.1-.42c.426-.421.52.234.835.33-.05-.33-.464-.378-.205-.613 3.598-.545 7.438.598 11.129.956 1.348.11.757-2.203 2.465-1.195l-.481.794c2.719-.956 5.564 0 8.233-.77-.154.182-.16.416-.425.416.552.574 2.083.034 2.094-.435.42.053.1.425.354.665.552.339 1.42-.732 1.718-.158.05.09-.16.186-.265.23.37-.278 1.719.076 1.365-.589 1 .32 1.917-.287 2.713.105.553-.736 1.713.364 1.884-.683-.077 1.08 1.752.875 2.387.377-.215.326.553.345.299.794.718 0 1.381-.206 1.265-.76 1.315 1.305 2.686-1.018 3.415.645a45.888 45.888 0 0 1 6.078-1.17c-.082 1.075-2.138.09-2.066 1.218 1.834-.425 2.906-1.343 4.719-1.066.47.153-.276.478-.437.65 1.835-.43 3.537.148 5.172-.42 0 .1-.182.21-.348.291.321-.033.741.167.713-.325l-.315.13c-.497-.718 1.304-1.468 1.365-1.841-.553 1.396 1.602.377.707 2.137a.73.73 0 0 0 .337-.263.58.58 0 0 0 .1-.383c.315.1.409.297.083.665 1.155-.254.757-.78 1.801-.75 0 .233-.221.324-.337.601.553-.478 1.078-.908 1.951-.697-.056.143.044.33-.216.325 1.509-.048 2.603-1.195 4.249-.722-.513 1.023.553.349.625 1.243l.895-.254-.348-.44c.785.034 1.492-.602 2.155-.296l-.591.354 1.47-.139-.824-.354c.807-.444-.055-1.132.978-.86-.21.086.785.029 1.177.56.398-.278.801-.57 1.376-.335.138.291-.149.984-.055 1.176.398-.736 1.834-.168 2.337-.956-.143.227-.192.49-.138.745l.337-.597c.359.2.409.296.337.669 1.105.134-.309-1.138.967-.626-.105.048-.055.138-.27.23 1.287.277 2.519-.335 3.702 0 .326.903-1.05.195-.669.955 1.724-.129 3.592-.999 5.25-.74l-.31-.106c.277-1.262 1.221.66 2.083.086-.21.086-.298.693-.237.555 1.105.234 2.343-.249 4.083-.603l-.226.32c.657.311 1.763.216 2.481.383.226-.315.641-.253.403-.731 2.166 1.912 4.305-.89 6.228.726-.238 0-.553.268-.387.273l1.702-.244c-.111-.554-.21-.34-.553-.784.124-.163.292-.298.489-.392.198-.094.419-.145.644-.148-.774.34-.028.884.287 1.205-.049-.173.072-.354.05-.526.846 1.008.199-1.11 1.376-.407l-.077.287c.458-.134.889-.478 1.37-.401.177.645-.492.282-.552.803.685 0 1.403-1.162 1.994-.507-.298.167-.718.158-1.016.325.641.77.729.583 1.221.717h-.044l1.138.378-.282-.21c.928-1.635 1.752-.25 2.951-1.3-1.166.994-.21.592-.332 1.309.288.21.724.454.586.65.553-.564.89.478 1.696-.34 0 .235.581.044.431.627.713-.163-.149-.411-.077-.703 1.133-.76 2.514 1.061 4.139.029 1.376-.397 1.658-1.171 2.94-1.515.403.392-.393.836-.393.836.267.161.581.255.906.27a1.97 1.97 0 0 0 .934-.184c-.138.196 0 .373.172.64.519-.038.386-.831 1.05-.477a3.24 3.24 0 0 1-.553.918c.619-.192 1.243-.603 1.884-.79.149.412-.409.603-.646.856.718-.153 1.851-.296 2.105-.927l-.442-.248c.26 0 .105.559-.094.669-.63.478-.862-.258-.884-.478l.459-.134c-.387-1.382-1.818.148-2.719.033l.431-.956-.973.784c-.182-.263-.287-.822.166-.956-.624-.516-.591.33-1.105-.239-.055-.086-.028-.134.033-.172l-.646.273c.132-.201-.072-.703.309-.545-1.105-.617-1.873.674-2.26-.096l.099-.057c-1.596.272-.193.721-1.414 1.534l-.713-1.83-.188.721c-.16-.033-.481-.1-.409-.387-.63.478.089.32-.287.78-.752-.699-2.172.229-2.293-.957-.31.545.729.478-.127.813-.183-1.258-.978.181-1.658-.416.254-.636.917-.273.226-.875-.486 1.076-1.386-.282-2-.096-.066.87-1.332.32-2.354.579.078-.292-1.89-.54-2.818-.885l.033-.148c-.221.87-1.182.674-1.901.832a.906.906 0 0 1 .132-.55c.102-.169.258-.31.449-.406h-.669a.979.979 0 0 1-.34.327 1.167 1.167 0 0 1-.478.151l.194-.65c-.885 0-1.813.712-2.94.244-.083.607.84 1.725-.381 2.103-.034-.335-.056-.899.27-1.028-.105.043-.381.263-.585.12l.502-.545c-.508-.258-.287.478-.701.397 0-.478-.293-.35-.221-.722.11-.038.359.205.525 0a1.931 1.931 0 0 1-.691-.264 1.649 1.649 0 0 1-.503-.487c.028.268-.028.636-.37.684-.89 0-.282-.574-.79-.832-.227.325-.78-.033-.824.674-.259 0-.293-.34-.387-.535-.469.3-2.149.033-1.657.793l.116.053s-.05 0-.078.033c-1.525.66-3.105-.478-4.608-.224V3.34c-.895.244-1.984.106-2.636.593a.711.711 0 0 1-.402-.28.553.553 0 0 1-.084-.442c-.691.158-.774.416-1.746 0 .701-.396-.221-.373.713-.287-.879-.224-1.067-.607-2.039 0 .342-.597-.641-.774-1.067-.602l.608.445c-.436.053-.88.039-1.31-.043l.254-.794c-1.784-1.004-3.315 1.578-4.647-.067-.497.545.973.411.553 1.052-.829-.124-1.658-1.286-1.929-1.29-1.132-.479-1.105 1.137-2.282.812a.818.818 0 0 1 .031.774.938.938 0 0 1-.264.323 1.11 1.11 0 0 1-.397.198c-.829-.124-.994-1.214-.464-1.434.205 0 .299.072.288.168.27-.096.629-.21.303-.526l-.116.282c-.403-.297-1.552-.292-1.271-.75-.635.257-.281.477.183.616-1.061-.435-1.658-.053-2.763-.344.171.162.326.478.155.478-1.608-.378-.724.526-1.824.636-.608-.445.249-1.033-.862-.684-.668-.306-.127-.755.149-.985-1.016.536-1.867-.387-2.442-.478l.553-.22a1.892 1.892 0 0 1-.846.12l.293.573c-.309-.105-.553-.11-.553-.348-.326.368.227.956-.42 1.434-.403-.297-1.265.286-1.392-.478 1.298.272-.127-.76.978-.866a1.102 1.102 0 0 1-.851.024c-.044-.086.044-.157.133-.2-1.233-.689-.592.846-1.879.807.171-.42-.287-.808-.497-.721.519 0 .237.712-.249 1.027-.823-.34-.906.235-1.337.187l.491.162c-.176.426-.585.364-1.165.478-.045-.33.524-.22.326-.368-.652.736-1.437-.793-2.338-.306-.409-.291-.027-.798-.387-.999-1.011.54-1.077-.588-2.133-.148.293.574.349.435-.403.985l1.735-.387-1.105.822c.525 0 1.105-.35 1.42-.249-.553.478-.481.316-.238.794-.701-.86-1.425.478-2.21-.1l.044-1.41c-1.232-.641-2.21.702-3.823.334l.513.248c-.221.56-.994.072-1.519.292.055-.478-.271-.645-.492-.956.028.349-1.177-.043-1.337.899l-.707-.627c-1.305-.267-1.503 1.33-2.763 1.157.381-.507-.183-.846.657-1.21-.414 0-.79-.095-.801.23-.276-.263-1.199.646-1.575.215-.182.206-.243.698-.713.655a.337.337 0 0 1 0-.234c0 .234-.735.31-.331.837-1.271-1.478-3.592.095-4.708-1.172-.936.165-1.883.277-2.835.335.05-.139 0-.234.16-.186-1.143-.44-.707 1.352-2.005.86-.664-.765.69-.411.276-.703-.171-1.553-1.564.21-2.437-.702l.21-.091c-.663-.555-1.608.564-2.713.454a.326.326 0 0 0 0-.234c-.746.784-2.155 1.051-3.205 1.271.326-.607.475-.32.276-.956-.47.091.138.99-.801 1.167-.304-.33-.984-.622-1.078-1.282l.89-.019c-.459-.85-1.149.034-1.613-.114l.055-.368c-1.36.124-1.376 1.06-2.835.999l.155.282c-.796.956-.674-.521-1.465.172l-.248-.956c-.871.453-1.797.82-2.763 1.094.552-.698 1.658-1.06 2.315-1.477-.519 0-1.774.072-2.044.54.21-.09.475-.325.685-.181a2.832 2.832 0 0 1-1.094.83 3.298 3.298 0 0 1-1.42.27c.171-1.832-2.713-.455-3.482-1.865-1.834.693-3.652-.258-5.796-.13.774 1.435-.625.049-.481 1.507-.497.1-.685.076-.729 0l-1.525-.86c-.365-.421.469-.326.42-.65-1.106-.106-.465-.618-1.194-1 .155.521-.37.75-1 .56l.901.659c-1.52.793-1.338-1.214-2.868-.43l.48-.478c-.79.277-2.917 0-3.674 1.204-.144-.167-.332-.564 0-.674-1.89-.148-4.183 1.31-5.664.612l.138-.358c-.348.105-.602.678-1.05.325 0-.148.138-.359 0-.378-.182.124-.923.64-1.392.44l.386-.411c-1.85-.44-2.807 1.023-4.343 1.29 0-1.051-1.475-1.376-2.21-1.53V.685c-2.15-.086-3.625.956-5.598 1.4-1.265-1.118-4.188-.392-6.194-.99.31.182 0 .818-.37.957-.475-.206-1.266.755-1.221-.21h.165c-.375-.957-1.326-.67-2.072-.675l-.083 1.267c-2.006-1.778-5.106.813-6.227-.803-.459.33-1.045.34-1.498.67v-.68a12.396 12.396 0 0 0-3.575 0l.31-.478c-.912 0-1.072 1.98-1.912 2.042l-.288-1c-1.591.053-3.232-.774-4.763.192 0-.148.055-.445.31-.478-.746 0-2.918-.588-2.587.788-.06-.903-1.657-.038-2.48.388l.104-.689c-.685.875-.701 1.11-1.696 1.377-.243-.076-.238-.526.088-.368-.812-.32-.59.655-1.574.33l.342-.435c-.823-.029-.746.2-1.177.707-.503.287-1.564-.114-1.713-.712-.094.368-.52.875-1.011.717a.38.38 0 0 1 .013-.245.442.442 0 0 1 .164-.2c-1.393-.406-2 .851-2.973.235a.553.553 0 0 0-.182-.392 9.431 9.431 0 0 1 1.89.028c0-.616-.912-.688-.255-1.563-.685.478-1.845 1.54-2.713 1.286a.84.84 0 0 1-.1-.215l.061-.072a.668.668 0 0 0-.295 0 .61.61 0 0 0-.257.125 1.992 1.992 0 0 0-.718-.158c-.128-.507-1.023-.234-1.465-.244.072.67-.508.583.06 1.119-.07-.048.078-.086.366-.125a.528.528 0 0 0 .188-.076l-.028.062c.287-.033.663-.062 1.105-.09-.332.358-.68.654-1.183.3-.204.445-.43.894-.552 1.11-.647-.914-1.83-1.377-2.022-1.946-1.321.43-3.145.368-3.918 1.663-.376.177-.459-.344-.614-.535.216-.139.476-.13.586-.316-.74.354-2.249.216-2.381 1.105-.984-.364.491-.837-.818-.636l.166-.277c-2.675-1.291-4.09 2.433-7.068.755.204.105.304.148.354.296-3.316-.645-6.709 1.038-10.018-.062-.94-.205-1 .359-1.531.818l-.249-.713-.906.88c-1.315.679-2.47-1.65-4.117-.411l.254.478c-.624-.058-1.939.387-1.873-.177-.055.09-.166.516-.425.272l-.044-.372-1.487.712c-1.199-.215.078-1.506-1.658-1.492C.895 5.105-.22 6.114.04 6.362c.178.01.347.073.478.179a.645.645 0 0 1 .24.4l-.558.225C.17 8.279-.194 9.44 1.304 10.144l.917-.732.36.521-.818.1c.513.479.784 0 1.105-.305.07.225.233.42.458.55l.907-1.114c.149.43-.376.884.292 1.094.426-.516-.502-.956.233-1.314.513.478.403.898.933.44a.447.447 0 0 1 .012.336.525.525 0 0 1-.233.27c.476-.367 1.304-.214 1.525-.817.553.598 1.658-.248 1.691.808.29-.433.74-.77 1.277-.956-.752 1.3 1.724 0 1.591 1.348.553-1.162 2.21-.617 3.255-1.3-.055.095-.16.282-.265.23.624.061.823.391 1.237.592 0-.956.967-1.195 1.448-1.797.812.87-.392 1.118-.1 1.974-.082-.755 1.272-.813.973-1.434.614.53.514.248.862 1.008.028-1.17.553-.22.962-.956.873.54.282 1.086 1.182.689.453.354-.342.808-.342.808Zm21.793-2.93-.447.057.447-.058Zm1.818-.091a7.552 7.552 0 0 0-.801 0c-.072-.23 0-.478.171-.478-.083.186.348.305.63.478Zm-4.128-4.49c.288-.109.393 0 .442.159-.172.02-.343.053-.508.1v.081a.973.973 0 0 1 .066-.34Z"},null,-1)])]))])]))}});export{f as __pageData,x as default}; diff --git a/assets/index.md.D7QupwhI.js b/assets/index.md.D7QupwhI.js new file mode 100644 index 00000000..24d5765b --- /dev/null +++ b/assets/index.md.D7QupwhI.js @@ -0,0 +1 @@ +import{d as o,u as n,o as s,g as c,h as l,i as a,S as r,x as h,l as d}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const m={id:"hero-text",style:{display:"inline-block",position:"relative"}},p={style:{color:"var(--vp-c-brand)",position:"absolute","z-index":"-1",top:"1em",left:"0.2em",width:"calc(100% - 0.7em)",height:"auto"},width:"240",height:"11",viewBox:"0 0 240 11",fill:"currentColor",xmlns:"http://www.w3.org/2000/svg"},v=JSON.parse('{"title":"首页","titleTemplate":":title | Insight Stack Blog","description":"","frontmatter":{"layout":"home","title":"首页","titleTemplate":":title | Insight Stack Blog","tk":{"teekHome":true,"features":[{"title":"全栈","details":"Engineering × Product × AI","link":"/fullstack/overview","image":"https://insight-stack-1252300811.cos.ap-shanghai.myqcloud.com/topic/icon_full_stack_circle.webp"},{"title":"AI 学习与实践","details":"Model × Agent × Engineering","link":"/ai/overview","image":"https://insight-stack-1252300811.cos.ap-shanghai.myqcloud.com/topic/icon_llm_circle.webp"},{"title":"产品 Sense","details":"Impact × Simplicity","link":"/product-sense/overview","image":"https://insight-stack-1252300811.cos.ap-shanghai.myqcloud.com/topic/icon_product_sense_circle.webp"}]},"hero":{"name":"Insight Stack Blog","text":"AI & 全栈技术 & 产品思考与成长记录","tagline":"✨探索技术前沿,沉淀产品思考,记录成长点滴,相信时间的力量","actions":[{"theme":"brand","text":"关于我","link":"/about/me"},{"theme":"alt","text":"资源推荐","link":"/growth/sites"},{"theme":"alt","text":"书籍推荐","link":"/growth/books"}],"image":{"src":"/img/full-stack/insight_stack.png","alt":"Insight Stack Blog"}},"features":[{"icon":"📖","title":"全栈技术","details":"前端 & NodeJS & Python 等","link":"/fullstack/overview"},{"icon":"🎉","title":"产品 Sense","details":"产品 Sense = 用户价值洞察 × 商业可行性 × 技术可实现性","link":"/product-sense/overview"},{"icon":"🎇","title":"LLM 应用学习与实践","details":"梳理大语言模型应用、Agent 技术、上下文工程与AI编程等专题,探索 AI 时代的技术与应用。","link":"/ai/overview"},{"icon":"📝","title":"个人成长","details":"收录一些不错的站点、技术周刊、AI 等资源,总结个人在时间管理、效率工具、健康管理等方面的成长经验。","link":"/about/me"}]},"headers":[],"relativePath":"index.md","filePath":"index.md"}'),g={name:"index.md"},_=o({...g,setup(u){const{frontmatter:i}=n();return s(()=>{const t=document.querySelector(".VPHero .text"),e=document.querySelector("#hero-text");if(!(!t||!e)){for(;t.lastChild;)t.lastChild.remove();t.append(e)}}),(t,e)=>(l(),c("div",null,[a("span",m,[r(h(d(i).hero.text)+" ",1),(l(),c("svg",p,[...e[0]||(e[0]=[a("path",{d:"M20.766 10.187c.939-.024.386-.885.552-1.401 1.105-.301.553.626.962 1.061.685-.263 1.171-1.1 1.696-1.085.044.144.15.191.044.378.697-.736 2.21-.134 2.995-1.052a.55.55 0 0 1 .127.215 3.35 3.35 0 0 1-.204-1.204c.42-.034.751-.593.94 0-.255 0-.266.23-.377.416l.426-.273c.448.813-.586.316-.553.927.84-.306 1.802-1.037 2.476-.831.182.803-1.525.339-.608 1.023l-1.033-.268c.85 1.248-.625-.057.171 1.276 1.348.177 1.47-.478 2.818-.3.276-.479-.132-.66.144-1.124 1.857-.885 1.602 1.984 2.94.846.337-.555.42-1.582 1.442-1.08l-.276.889c1.298.038.668-1.348 2.06-.784-.226.368-1.005.344-.8.444.917.689.59-.545 1.27-.569l.16.827c1.371-.181 2.863-.827 4.388-1.037-.072.249-.326.512.044.746 1.912-.478 4.123-.058 6.007.368l.68-.727c.05.015.095.04.132.074a.275.275 0 0 1 .077.118c.014.044.015.091.004.136a.27.27 0 0 1-.07.122c.74.243 0-.445.354-.732.414-.062.552.383.315.603 1.248-.636 3.586-1.401 4.973-.694l-.254.22c1.06.249 1.105-1.477 2.127-.855l-.182.129c2.293.23 4.785-.478 6.564.52.293-1.017 2.272.393 2.365-1.022 1.327.664.967.927 2.813 1.348.492.052.702-.899 1.299-1.061l.044.731.79-.794.47.87.552-.205a.66.66 0 0 1-.332-.2.517.517 0 0 1-.132-.33c.873-.354 2.177.477 2.21.831l2.078-.679c-.039.301-.387.411-.657.607 1.105-.779.226.77 1.232.053-.144-.163.06-.44.077-.588.553.435 1.691.416 2.547.205l-.149.512c1.558.1 3.271-.31 5.018-.335-.636-.224-.514-1.109 0-1.204l.226.774c.32-.478-.552-.282.122-.884.652.076.464.875.094 1.138l.784-.287c.056.23-.127.358-.165.655.309-.478 1.387.75 1.834-.096l.05.23c1.746-.03 2.53-.316 3.95-.383 0-.674.553-.535.984-1.085 1.05.196 2.21.707 3.482.63.878-.343.243-.568.635-.955.077.612 1.332.535.69.985a15.353 15.353 0 0 0 3.83-.68c-.21-.243-.447-.353-.331-.563a.738.738 0 0 1 .275.01c.09.02.173.058.245.11a.58.58 0 0 1 .169.188c.04.072.061.151.062.232l-.088.067c2.127-.956 4.973 1.706 6.669.41l-.099.068 1.763-.684c.817.1-.481.478.127.842 1.9-1.043 3.022.12 4.586-.574 1.243 1.793 4.327-.167 5.979.956l-.1-.42c.426-.421.52.234.835.33-.05-.33-.464-.378-.205-.613 3.598-.545 7.438.598 11.129.956 1.348.11.757-2.203 2.465-1.195l-.481.794c2.719-.956 5.564 0 8.233-.77-.154.182-.16.416-.425.416.552.574 2.083.034 2.094-.435.42.053.1.425.354.665.552.339 1.42-.732 1.718-.158.05.09-.16.186-.265.23.37-.278 1.719.076 1.365-.589 1 .32 1.917-.287 2.713.105.553-.736 1.713.364 1.884-.683-.077 1.08 1.752.875 2.387.377-.215.326.553.345.299.794.718 0 1.381-.206 1.265-.76 1.315 1.305 2.686-1.018 3.415.645a45.888 45.888 0 0 1 6.078-1.17c-.082 1.075-2.138.09-2.066 1.218 1.834-.425 2.906-1.343 4.719-1.066.47.153-.276.478-.437.65 1.835-.43 3.537.148 5.172-.42 0 .1-.182.21-.348.291.321-.033.741.167.713-.325l-.315.13c-.497-.718 1.304-1.468 1.365-1.841-.553 1.396 1.602.377.707 2.137a.73.73 0 0 0 .337-.263.58.58 0 0 0 .1-.383c.315.1.409.297.083.665 1.155-.254.757-.78 1.801-.75 0 .233-.221.324-.337.601.553-.478 1.078-.908 1.951-.697-.056.143.044.33-.216.325 1.509-.048 2.603-1.195 4.249-.722-.513 1.023.553.349.625 1.243l.895-.254-.348-.44c.785.034 1.492-.602 2.155-.296l-.591.354 1.47-.139-.824-.354c.807-.444-.055-1.132.978-.86-.21.086.785.029 1.177.56.398-.278.801-.57 1.376-.335.138.291-.149.984-.055 1.176.398-.736 1.834-.168 2.337-.956-.143.227-.192.49-.138.745l.337-.597c.359.2.409.296.337.669 1.105.134-.309-1.138.967-.626-.105.048-.055.138-.27.23 1.287.277 2.519-.335 3.702 0 .326.903-1.05.195-.669.955 1.724-.129 3.592-.999 5.25-.74l-.31-.106c.277-1.262 1.221.66 2.083.086-.21.086-.298.693-.237.555 1.105.234 2.343-.249 4.083-.603l-.226.32c.657.311 1.763.216 2.481.383.226-.315.641-.253.403-.731 2.166 1.912 4.305-.89 6.228.726-.238 0-.553.268-.387.273l1.702-.244c-.111-.554-.21-.34-.553-.784.124-.163.292-.298.489-.392.198-.094.419-.145.644-.148-.774.34-.028.884.287 1.205-.049-.173.072-.354.05-.526.846 1.008.199-1.11 1.376-.407l-.077.287c.458-.134.889-.478 1.37-.401.177.645-.492.282-.552.803.685 0 1.403-1.162 1.994-.507-.298.167-.718.158-1.016.325.641.77.729.583 1.221.717h-.044l1.138.378-.282-.21c.928-1.635 1.752-.25 2.951-1.3-1.166.994-.21.592-.332 1.309.288.21.724.454.586.65.553-.564.89.478 1.696-.34 0 .235.581.044.431.627.713-.163-.149-.411-.077-.703 1.133-.76 2.514 1.061 4.139.029 1.376-.397 1.658-1.171 2.94-1.515.403.392-.393.836-.393.836.267.161.581.255.906.27a1.97 1.97 0 0 0 .934-.184c-.138.196 0 .373.172.64.519-.038.386-.831 1.05-.477a3.24 3.24 0 0 1-.553.918c.619-.192 1.243-.603 1.884-.79.149.412-.409.603-.646.856.718-.153 1.851-.296 2.105-.927l-.442-.248c.26 0 .105.559-.094.669-.63.478-.862-.258-.884-.478l.459-.134c-.387-1.382-1.818.148-2.719.033l.431-.956-.973.784c-.182-.263-.287-.822.166-.956-.624-.516-.591.33-1.105-.239-.055-.086-.028-.134.033-.172l-.646.273c.132-.201-.072-.703.309-.545-1.105-.617-1.873.674-2.26-.096l.099-.057c-1.596.272-.193.721-1.414 1.534l-.713-1.83-.188.721c-.16-.033-.481-.1-.409-.387-.63.478.089.32-.287.78-.752-.699-2.172.229-2.293-.957-.31.545.729.478-.127.813-.183-1.258-.978.181-1.658-.416.254-.636.917-.273.226-.875-.486 1.076-1.386-.282-2-.096-.066.87-1.332.32-2.354.579.078-.292-1.89-.54-2.818-.885l.033-.148c-.221.87-1.182.674-1.901.832a.906.906 0 0 1 .132-.55c.102-.169.258-.31.449-.406h-.669a.979.979 0 0 1-.34.327 1.167 1.167 0 0 1-.478.151l.194-.65c-.885 0-1.813.712-2.94.244-.083.607.84 1.725-.381 2.103-.034-.335-.056-.899.27-1.028-.105.043-.381.263-.585.12l.502-.545c-.508-.258-.287.478-.701.397 0-.478-.293-.35-.221-.722.11-.038.359.205.525 0a1.931 1.931 0 0 1-.691-.264 1.649 1.649 0 0 1-.503-.487c.028.268-.028.636-.37.684-.89 0-.282-.574-.79-.832-.227.325-.78-.033-.824.674-.259 0-.293-.34-.387-.535-.469.3-2.149.033-1.657.793l.116.053s-.05 0-.078.033c-1.525.66-3.105-.478-4.608-.224V3.34c-.895.244-1.984.106-2.636.593a.711.711 0 0 1-.402-.28.553.553 0 0 1-.084-.442c-.691.158-.774.416-1.746 0 .701-.396-.221-.373.713-.287-.879-.224-1.067-.607-2.039 0 .342-.597-.641-.774-1.067-.602l.608.445c-.436.053-.88.039-1.31-.043l.254-.794c-1.784-1.004-3.315 1.578-4.647-.067-.497.545.973.411.553 1.052-.829-.124-1.658-1.286-1.929-1.29-1.132-.479-1.105 1.137-2.282.812a.818.818 0 0 1 .031.774.938.938 0 0 1-.264.323 1.11 1.11 0 0 1-.397.198c-.829-.124-.994-1.214-.464-1.434.205 0 .299.072.288.168.27-.096.629-.21.303-.526l-.116.282c-.403-.297-1.552-.292-1.271-.75-.635.257-.281.477.183.616-1.061-.435-1.658-.053-2.763-.344.171.162.326.478.155.478-1.608-.378-.724.526-1.824.636-.608-.445.249-1.033-.862-.684-.668-.306-.127-.755.149-.985-1.016.536-1.867-.387-2.442-.478l.553-.22a1.892 1.892 0 0 1-.846.12l.293.573c-.309-.105-.553-.11-.553-.348-.326.368.227.956-.42 1.434-.403-.297-1.265.286-1.392-.478 1.298.272-.127-.76.978-.866a1.102 1.102 0 0 1-.851.024c-.044-.086.044-.157.133-.2-1.233-.689-.592.846-1.879.807.171-.42-.287-.808-.497-.721.519 0 .237.712-.249 1.027-.823-.34-.906.235-1.337.187l.491.162c-.176.426-.585.364-1.165.478-.045-.33.524-.22.326-.368-.652.736-1.437-.793-2.338-.306-.409-.291-.027-.798-.387-.999-1.011.54-1.077-.588-2.133-.148.293.574.349.435-.403.985l1.735-.387-1.105.822c.525 0 1.105-.35 1.42-.249-.553.478-.481.316-.238.794-.701-.86-1.425.478-2.21-.1l.044-1.41c-1.232-.641-2.21.702-3.823.334l.513.248c-.221.56-.994.072-1.519.292.055-.478-.271-.645-.492-.956.028.349-1.177-.043-1.337.899l-.707-.627c-1.305-.267-1.503 1.33-2.763 1.157.381-.507-.183-.846.657-1.21-.414 0-.79-.095-.801.23-.276-.263-1.199.646-1.575.215-.182.206-.243.698-.713.655a.337.337 0 0 1 0-.234c0 .234-.735.31-.331.837-1.271-1.478-3.592.095-4.708-1.172-.936.165-1.883.277-2.835.335.05-.139 0-.234.16-.186-1.143-.44-.707 1.352-2.005.86-.664-.765.69-.411.276-.703-.171-1.553-1.564.21-2.437-.702l.21-.091c-.663-.555-1.608.564-2.713.454a.326.326 0 0 0 0-.234c-.746.784-2.155 1.051-3.205 1.271.326-.607.475-.32.276-.956-.47.091.138.99-.801 1.167-.304-.33-.984-.622-1.078-1.282l.89-.019c-.459-.85-1.149.034-1.613-.114l.055-.368c-1.36.124-1.376 1.06-2.835.999l.155.282c-.796.956-.674-.521-1.465.172l-.248-.956c-.871.453-1.797.82-2.763 1.094.552-.698 1.658-1.06 2.315-1.477-.519 0-1.774.072-2.044.54.21-.09.475-.325.685-.181a2.832 2.832 0 0 1-1.094.83 3.298 3.298 0 0 1-1.42.27c.171-1.832-2.713-.455-3.482-1.865-1.834.693-3.652-.258-5.796-.13.774 1.435-.625.049-.481 1.507-.497.1-.685.076-.729 0l-1.525-.86c-.365-.421.469-.326.42-.65-1.106-.106-.465-.618-1.194-1 .155.521-.37.75-1 .56l.901.659c-1.52.793-1.338-1.214-2.868-.43l.48-.478c-.79.277-2.917 0-3.674 1.204-.144-.167-.332-.564 0-.674-1.89-.148-4.183 1.31-5.664.612l.138-.358c-.348.105-.602.678-1.05.325 0-.148.138-.359 0-.378-.182.124-.923.64-1.392.44l.386-.411c-1.85-.44-2.807 1.023-4.343 1.29 0-1.051-1.475-1.376-2.21-1.53V.685c-2.15-.086-3.625.956-5.598 1.4-1.265-1.118-4.188-.392-6.194-.99.31.182 0 .818-.37.957-.475-.206-1.266.755-1.221-.21h.165c-.375-.957-1.326-.67-2.072-.675l-.083 1.267c-2.006-1.778-5.106.813-6.227-.803-.459.33-1.045.34-1.498.67v-.68a12.396 12.396 0 0 0-3.575 0l.31-.478c-.912 0-1.072 1.98-1.912 2.042l-.288-1c-1.591.053-3.232-.774-4.763.192 0-.148.055-.445.31-.478-.746 0-2.918-.588-2.587.788-.06-.903-1.657-.038-2.48.388l.104-.689c-.685.875-.701 1.11-1.696 1.377-.243-.076-.238-.526.088-.368-.812-.32-.59.655-1.574.33l.342-.435c-.823-.029-.746.2-1.177.707-.503.287-1.564-.114-1.713-.712-.094.368-.52.875-1.011.717a.38.38 0 0 1 .013-.245.442.442 0 0 1 .164-.2c-1.393-.406-2 .851-2.973.235a.553.553 0 0 0-.182-.392 9.431 9.431 0 0 1 1.89.028c0-.616-.912-.688-.255-1.563-.685.478-1.845 1.54-2.713 1.286a.84.84 0 0 1-.1-.215l.061-.072a.668.668 0 0 0-.295 0 .61.61 0 0 0-.257.125 1.992 1.992 0 0 0-.718-.158c-.128-.507-1.023-.234-1.465-.244.072.67-.508.583.06 1.119-.07-.048.078-.086.366-.125a.528.528 0 0 0 .188-.076l-.028.062c.287-.033.663-.062 1.105-.09-.332.358-.68.654-1.183.3-.204.445-.43.894-.552 1.11-.647-.914-1.83-1.377-2.022-1.946-1.321.43-3.145.368-3.918 1.663-.376.177-.459-.344-.614-.535.216-.139.476-.13.586-.316-.74.354-2.249.216-2.381 1.105-.984-.364.491-.837-.818-.636l.166-.277c-2.675-1.291-4.09 2.433-7.068.755.204.105.304.148.354.296-3.316-.645-6.709 1.038-10.018-.062-.94-.205-1 .359-1.531.818l-.249-.713-.906.88c-1.315.679-2.47-1.65-4.117-.411l.254.478c-.624-.058-1.939.387-1.873-.177-.055.09-.166.516-.425.272l-.044-.372-1.487.712c-1.199-.215.078-1.506-1.658-1.492C.895 5.105-.22 6.114.04 6.362c.178.01.347.073.478.179a.645.645 0 0 1 .24.4l-.558.225C.17 8.279-.194 9.44 1.304 10.144l.917-.732.36.521-.818.1c.513.479.784 0 1.105-.305.07.225.233.42.458.55l.907-1.114c.149.43-.376.884.292 1.094.426-.516-.502-.956.233-1.314.513.478.403.898.933.44a.447.447 0 0 1 .012.336.525.525 0 0 1-.233.27c.476-.367 1.304-.214 1.525-.817.553.598 1.658-.248 1.691.808.29-.433.74-.77 1.277-.956-.752 1.3 1.724 0 1.591 1.348.553-1.162 2.21-.617 3.255-1.3-.055.095-.16.282-.265.23.624.061.823.391 1.237.592 0-.956.967-1.195 1.448-1.797.812.87-.392 1.118-.1 1.974-.082-.755 1.272-.813.973-1.434.614.53.514.248.862 1.008.028-1.17.553-.22.962-.956.873.54.282 1.086 1.182.689.453.354-.342.808-.342.808Zm21.793-2.93-.447.057.447-.058Zm1.818-.091a7.552 7.552 0 0 0-.801 0c-.072-.23 0-.478.171-.478-.083.186.348.305.63.478Zm-4.128-4.49c.288-.109.393 0 .442.159-.172.02-.343.053-.508.1v.081a.973.973 0 0 1 .066-.34Z"},null,-1)])]))])]))}});export{v as __pageData,_ as default}; diff --git a/assets/index.md.D7QupwhI.lean.js b/assets/index.md.D7QupwhI.lean.js new file mode 100644 index 00000000..24d5765b --- /dev/null +++ b/assets/index.md.D7QupwhI.lean.js @@ -0,0 +1 @@ +import{d as o,u as n,o as s,g as c,h as l,i as a,S as r,x as h,l as d}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const m={id:"hero-text",style:{display:"inline-block",position:"relative"}},p={style:{color:"var(--vp-c-brand)",position:"absolute","z-index":"-1",top:"1em",left:"0.2em",width:"calc(100% - 0.7em)",height:"auto"},width:"240",height:"11",viewBox:"0 0 240 11",fill:"currentColor",xmlns:"http://www.w3.org/2000/svg"},v=JSON.parse('{"title":"首页","titleTemplate":":title | Insight Stack Blog","description":"","frontmatter":{"layout":"home","title":"首页","titleTemplate":":title | Insight Stack Blog","tk":{"teekHome":true,"features":[{"title":"全栈","details":"Engineering × Product × AI","link":"/fullstack/overview","image":"https://insight-stack-1252300811.cos.ap-shanghai.myqcloud.com/topic/icon_full_stack_circle.webp"},{"title":"AI 学习与实践","details":"Model × Agent × Engineering","link":"/ai/overview","image":"https://insight-stack-1252300811.cos.ap-shanghai.myqcloud.com/topic/icon_llm_circle.webp"},{"title":"产品 Sense","details":"Impact × Simplicity","link":"/product-sense/overview","image":"https://insight-stack-1252300811.cos.ap-shanghai.myqcloud.com/topic/icon_product_sense_circle.webp"}]},"hero":{"name":"Insight Stack Blog","text":"AI & 全栈技术 & 产品思考与成长记录","tagline":"✨探索技术前沿,沉淀产品思考,记录成长点滴,相信时间的力量","actions":[{"theme":"brand","text":"关于我","link":"/about/me"},{"theme":"alt","text":"资源推荐","link":"/growth/sites"},{"theme":"alt","text":"书籍推荐","link":"/growth/books"}],"image":{"src":"/img/full-stack/insight_stack.png","alt":"Insight Stack Blog"}},"features":[{"icon":"📖","title":"全栈技术","details":"前端 & NodeJS & Python 等","link":"/fullstack/overview"},{"icon":"🎉","title":"产品 Sense","details":"产品 Sense = 用户价值洞察 × 商业可行性 × 技术可实现性","link":"/product-sense/overview"},{"icon":"🎇","title":"LLM 应用学习与实践","details":"梳理大语言模型应用、Agent 技术、上下文工程与AI编程等专题,探索 AI 时代的技术与应用。","link":"/ai/overview"},{"icon":"📝","title":"个人成长","details":"收录一些不错的站点、技术周刊、AI 等资源,总结个人在时间管理、效率工具、健康管理等方面的成长经验。","link":"/about/me"}]},"headers":[],"relativePath":"index.md","filePath":"index.md"}'),g={name:"index.md"},_=o({...g,setup(u){const{frontmatter:i}=n();return s(()=>{const t=document.querySelector(".VPHero .text"),e=document.querySelector("#hero-text");if(!(!t||!e)){for(;t.lastChild;)t.lastChild.remove();t.append(e)}}),(t,e)=>(l(),c("div",null,[a("span",m,[r(h(d(i).hero.text)+" ",1),(l(),c("svg",p,[...e[0]||(e[0]=[a("path",{d:"M20.766 10.187c.939-.024.386-.885.552-1.401 1.105-.301.553.626.962 1.061.685-.263 1.171-1.1 1.696-1.085.044.144.15.191.044.378.697-.736 2.21-.134 2.995-1.052a.55.55 0 0 1 .127.215 3.35 3.35 0 0 1-.204-1.204c.42-.034.751-.593.94 0-.255 0-.266.23-.377.416l.426-.273c.448.813-.586.316-.553.927.84-.306 1.802-1.037 2.476-.831.182.803-1.525.339-.608 1.023l-1.033-.268c.85 1.248-.625-.057.171 1.276 1.348.177 1.47-.478 2.818-.3.276-.479-.132-.66.144-1.124 1.857-.885 1.602 1.984 2.94.846.337-.555.42-1.582 1.442-1.08l-.276.889c1.298.038.668-1.348 2.06-.784-.226.368-1.005.344-.8.444.917.689.59-.545 1.27-.569l.16.827c1.371-.181 2.863-.827 4.388-1.037-.072.249-.326.512.044.746 1.912-.478 4.123-.058 6.007.368l.68-.727c.05.015.095.04.132.074a.275.275 0 0 1 .077.118c.014.044.015.091.004.136a.27.27 0 0 1-.07.122c.74.243 0-.445.354-.732.414-.062.552.383.315.603 1.248-.636 3.586-1.401 4.973-.694l-.254.22c1.06.249 1.105-1.477 2.127-.855l-.182.129c2.293.23 4.785-.478 6.564.52.293-1.017 2.272.393 2.365-1.022 1.327.664.967.927 2.813 1.348.492.052.702-.899 1.299-1.061l.044.731.79-.794.47.87.552-.205a.66.66 0 0 1-.332-.2.517.517 0 0 1-.132-.33c.873-.354 2.177.477 2.21.831l2.078-.679c-.039.301-.387.411-.657.607 1.105-.779.226.77 1.232.053-.144-.163.06-.44.077-.588.553.435 1.691.416 2.547.205l-.149.512c1.558.1 3.271-.31 5.018-.335-.636-.224-.514-1.109 0-1.204l.226.774c.32-.478-.552-.282.122-.884.652.076.464.875.094 1.138l.784-.287c.056.23-.127.358-.165.655.309-.478 1.387.75 1.834-.096l.05.23c1.746-.03 2.53-.316 3.95-.383 0-.674.553-.535.984-1.085 1.05.196 2.21.707 3.482.63.878-.343.243-.568.635-.955.077.612 1.332.535.69.985a15.353 15.353 0 0 0 3.83-.68c-.21-.243-.447-.353-.331-.563a.738.738 0 0 1 .275.01c.09.02.173.058.245.11a.58.58 0 0 1 .169.188c.04.072.061.151.062.232l-.088.067c2.127-.956 4.973 1.706 6.669.41l-.099.068 1.763-.684c.817.1-.481.478.127.842 1.9-1.043 3.022.12 4.586-.574 1.243 1.793 4.327-.167 5.979.956l-.1-.42c.426-.421.52.234.835.33-.05-.33-.464-.378-.205-.613 3.598-.545 7.438.598 11.129.956 1.348.11.757-2.203 2.465-1.195l-.481.794c2.719-.956 5.564 0 8.233-.77-.154.182-.16.416-.425.416.552.574 2.083.034 2.094-.435.42.053.1.425.354.665.552.339 1.42-.732 1.718-.158.05.09-.16.186-.265.23.37-.278 1.719.076 1.365-.589 1 .32 1.917-.287 2.713.105.553-.736 1.713.364 1.884-.683-.077 1.08 1.752.875 2.387.377-.215.326.553.345.299.794.718 0 1.381-.206 1.265-.76 1.315 1.305 2.686-1.018 3.415.645a45.888 45.888 0 0 1 6.078-1.17c-.082 1.075-2.138.09-2.066 1.218 1.834-.425 2.906-1.343 4.719-1.066.47.153-.276.478-.437.65 1.835-.43 3.537.148 5.172-.42 0 .1-.182.21-.348.291.321-.033.741.167.713-.325l-.315.13c-.497-.718 1.304-1.468 1.365-1.841-.553 1.396 1.602.377.707 2.137a.73.73 0 0 0 .337-.263.58.58 0 0 0 .1-.383c.315.1.409.297.083.665 1.155-.254.757-.78 1.801-.75 0 .233-.221.324-.337.601.553-.478 1.078-.908 1.951-.697-.056.143.044.33-.216.325 1.509-.048 2.603-1.195 4.249-.722-.513 1.023.553.349.625 1.243l.895-.254-.348-.44c.785.034 1.492-.602 2.155-.296l-.591.354 1.47-.139-.824-.354c.807-.444-.055-1.132.978-.86-.21.086.785.029 1.177.56.398-.278.801-.57 1.376-.335.138.291-.149.984-.055 1.176.398-.736 1.834-.168 2.337-.956-.143.227-.192.49-.138.745l.337-.597c.359.2.409.296.337.669 1.105.134-.309-1.138.967-.626-.105.048-.055.138-.27.23 1.287.277 2.519-.335 3.702 0 .326.903-1.05.195-.669.955 1.724-.129 3.592-.999 5.25-.74l-.31-.106c.277-1.262 1.221.66 2.083.086-.21.086-.298.693-.237.555 1.105.234 2.343-.249 4.083-.603l-.226.32c.657.311 1.763.216 2.481.383.226-.315.641-.253.403-.731 2.166 1.912 4.305-.89 6.228.726-.238 0-.553.268-.387.273l1.702-.244c-.111-.554-.21-.34-.553-.784.124-.163.292-.298.489-.392.198-.094.419-.145.644-.148-.774.34-.028.884.287 1.205-.049-.173.072-.354.05-.526.846 1.008.199-1.11 1.376-.407l-.077.287c.458-.134.889-.478 1.37-.401.177.645-.492.282-.552.803.685 0 1.403-1.162 1.994-.507-.298.167-.718.158-1.016.325.641.77.729.583 1.221.717h-.044l1.138.378-.282-.21c.928-1.635 1.752-.25 2.951-1.3-1.166.994-.21.592-.332 1.309.288.21.724.454.586.65.553-.564.89.478 1.696-.34 0 .235.581.044.431.627.713-.163-.149-.411-.077-.703 1.133-.76 2.514 1.061 4.139.029 1.376-.397 1.658-1.171 2.94-1.515.403.392-.393.836-.393.836.267.161.581.255.906.27a1.97 1.97 0 0 0 .934-.184c-.138.196 0 .373.172.64.519-.038.386-.831 1.05-.477a3.24 3.24 0 0 1-.553.918c.619-.192 1.243-.603 1.884-.79.149.412-.409.603-.646.856.718-.153 1.851-.296 2.105-.927l-.442-.248c.26 0 .105.559-.094.669-.63.478-.862-.258-.884-.478l.459-.134c-.387-1.382-1.818.148-2.719.033l.431-.956-.973.784c-.182-.263-.287-.822.166-.956-.624-.516-.591.33-1.105-.239-.055-.086-.028-.134.033-.172l-.646.273c.132-.201-.072-.703.309-.545-1.105-.617-1.873.674-2.26-.096l.099-.057c-1.596.272-.193.721-1.414 1.534l-.713-1.83-.188.721c-.16-.033-.481-.1-.409-.387-.63.478.089.32-.287.78-.752-.699-2.172.229-2.293-.957-.31.545.729.478-.127.813-.183-1.258-.978.181-1.658-.416.254-.636.917-.273.226-.875-.486 1.076-1.386-.282-2-.096-.066.87-1.332.32-2.354.579.078-.292-1.89-.54-2.818-.885l.033-.148c-.221.87-1.182.674-1.901.832a.906.906 0 0 1 .132-.55c.102-.169.258-.31.449-.406h-.669a.979.979 0 0 1-.34.327 1.167 1.167 0 0 1-.478.151l.194-.65c-.885 0-1.813.712-2.94.244-.083.607.84 1.725-.381 2.103-.034-.335-.056-.899.27-1.028-.105.043-.381.263-.585.12l.502-.545c-.508-.258-.287.478-.701.397 0-.478-.293-.35-.221-.722.11-.038.359.205.525 0a1.931 1.931 0 0 1-.691-.264 1.649 1.649 0 0 1-.503-.487c.028.268-.028.636-.37.684-.89 0-.282-.574-.79-.832-.227.325-.78-.033-.824.674-.259 0-.293-.34-.387-.535-.469.3-2.149.033-1.657.793l.116.053s-.05 0-.078.033c-1.525.66-3.105-.478-4.608-.224V3.34c-.895.244-1.984.106-2.636.593a.711.711 0 0 1-.402-.28.553.553 0 0 1-.084-.442c-.691.158-.774.416-1.746 0 .701-.396-.221-.373.713-.287-.879-.224-1.067-.607-2.039 0 .342-.597-.641-.774-1.067-.602l.608.445c-.436.053-.88.039-1.31-.043l.254-.794c-1.784-1.004-3.315 1.578-4.647-.067-.497.545.973.411.553 1.052-.829-.124-1.658-1.286-1.929-1.29-1.132-.479-1.105 1.137-2.282.812a.818.818 0 0 1 .031.774.938.938 0 0 1-.264.323 1.11 1.11 0 0 1-.397.198c-.829-.124-.994-1.214-.464-1.434.205 0 .299.072.288.168.27-.096.629-.21.303-.526l-.116.282c-.403-.297-1.552-.292-1.271-.75-.635.257-.281.477.183.616-1.061-.435-1.658-.053-2.763-.344.171.162.326.478.155.478-1.608-.378-.724.526-1.824.636-.608-.445.249-1.033-.862-.684-.668-.306-.127-.755.149-.985-1.016.536-1.867-.387-2.442-.478l.553-.22a1.892 1.892 0 0 1-.846.12l.293.573c-.309-.105-.553-.11-.553-.348-.326.368.227.956-.42 1.434-.403-.297-1.265.286-1.392-.478 1.298.272-.127-.76.978-.866a1.102 1.102 0 0 1-.851.024c-.044-.086.044-.157.133-.2-1.233-.689-.592.846-1.879.807.171-.42-.287-.808-.497-.721.519 0 .237.712-.249 1.027-.823-.34-.906.235-1.337.187l.491.162c-.176.426-.585.364-1.165.478-.045-.33.524-.22.326-.368-.652.736-1.437-.793-2.338-.306-.409-.291-.027-.798-.387-.999-1.011.54-1.077-.588-2.133-.148.293.574.349.435-.403.985l1.735-.387-1.105.822c.525 0 1.105-.35 1.42-.249-.553.478-.481.316-.238.794-.701-.86-1.425.478-2.21-.1l.044-1.41c-1.232-.641-2.21.702-3.823.334l.513.248c-.221.56-.994.072-1.519.292.055-.478-.271-.645-.492-.956.028.349-1.177-.043-1.337.899l-.707-.627c-1.305-.267-1.503 1.33-2.763 1.157.381-.507-.183-.846.657-1.21-.414 0-.79-.095-.801.23-.276-.263-1.199.646-1.575.215-.182.206-.243.698-.713.655a.337.337 0 0 1 0-.234c0 .234-.735.31-.331.837-1.271-1.478-3.592.095-4.708-1.172-.936.165-1.883.277-2.835.335.05-.139 0-.234.16-.186-1.143-.44-.707 1.352-2.005.86-.664-.765.69-.411.276-.703-.171-1.553-1.564.21-2.437-.702l.21-.091c-.663-.555-1.608.564-2.713.454a.326.326 0 0 0 0-.234c-.746.784-2.155 1.051-3.205 1.271.326-.607.475-.32.276-.956-.47.091.138.99-.801 1.167-.304-.33-.984-.622-1.078-1.282l.89-.019c-.459-.85-1.149.034-1.613-.114l.055-.368c-1.36.124-1.376 1.06-2.835.999l.155.282c-.796.956-.674-.521-1.465.172l-.248-.956c-.871.453-1.797.82-2.763 1.094.552-.698 1.658-1.06 2.315-1.477-.519 0-1.774.072-2.044.54.21-.09.475-.325.685-.181a2.832 2.832 0 0 1-1.094.83 3.298 3.298 0 0 1-1.42.27c.171-1.832-2.713-.455-3.482-1.865-1.834.693-3.652-.258-5.796-.13.774 1.435-.625.049-.481 1.507-.497.1-.685.076-.729 0l-1.525-.86c-.365-.421.469-.326.42-.65-1.106-.106-.465-.618-1.194-1 .155.521-.37.75-1 .56l.901.659c-1.52.793-1.338-1.214-2.868-.43l.48-.478c-.79.277-2.917 0-3.674 1.204-.144-.167-.332-.564 0-.674-1.89-.148-4.183 1.31-5.664.612l.138-.358c-.348.105-.602.678-1.05.325 0-.148.138-.359 0-.378-.182.124-.923.64-1.392.44l.386-.411c-1.85-.44-2.807 1.023-4.343 1.29 0-1.051-1.475-1.376-2.21-1.53V.685c-2.15-.086-3.625.956-5.598 1.4-1.265-1.118-4.188-.392-6.194-.99.31.182 0 .818-.37.957-.475-.206-1.266.755-1.221-.21h.165c-.375-.957-1.326-.67-2.072-.675l-.083 1.267c-2.006-1.778-5.106.813-6.227-.803-.459.33-1.045.34-1.498.67v-.68a12.396 12.396 0 0 0-3.575 0l.31-.478c-.912 0-1.072 1.98-1.912 2.042l-.288-1c-1.591.053-3.232-.774-4.763.192 0-.148.055-.445.31-.478-.746 0-2.918-.588-2.587.788-.06-.903-1.657-.038-2.48.388l.104-.689c-.685.875-.701 1.11-1.696 1.377-.243-.076-.238-.526.088-.368-.812-.32-.59.655-1.574.33l.342-.435c-.823-.029-.746.2-1.177.707-.503.287-1.564-.114-1.713-.712-.094.368-.52.875-1.011.717a.38.38 0 0 1 .013-.245.442.442 0 0 1 .164-.2c-1.393-.406-2 .851-2.973.235a.553.553 0 0 0-.182-.392 9.431 9.431 0 0 1 1.89.028c0-.616-.912-.688-.255-1.563-.685.478-1.845 1.54-2.713 1.286a.84.84 0 0 1-.1-.215l.061-.072a.668.668 0 0 0-.295 0 .61.61 0 0 0-.257.125 1.992 1.992 0 0 0-.718-.158c-.128-.507-1.023-.234-1.465-.244.072.67-.508.583.06 1.119-.07-.048.078-.086.366-.125a.528.528 0 0 0 .188-.076l-.028.062c.287-.033.663-.062 1.105-.09-.332.358-.68.654-1.183.3-.204.445-.43.894-.552 1.11-.647-.914-1.83-1.377-2.022-1.946-1.321.43-3.145.368-3.918 1.663-.376.177-.459-.344-.614-.535.216-.139.476-.13.586-.316-.74.354-2.249.216-2.381 1.105-.984-.364.491-.837-.818-.636l.166-.277c-2.675-1.291-4.09 2.433-7.068.755.204.105.304.148.354.296-3.316-.645-6.709 1.038-10.018-.062-.94-.205-1 .359-1.531.818l-.249-.713-.906.88c-1.315.679-2.47-1.65-4.117-.411l.254.478c-.624-.058-1.939.387-1.873-.177-.055.09-.166.516-.425.272l-.044-.372-1.487.712c-1.199-.215.078-1.506-1.658-1.492C.895 5.105-.22 6.114.04 6.362c.178.01.347.073.478.179a.645.645 0 0 1 .24.4l-.558.225C.17 8.279-.194 9.44 1.304 10.144l.917-.732.36.521-.818.1c.513.479.784 0 1.105-.305.07.225.233.42.458.55l.907-1.114c.149.43-.376.884.292 1.094.426-.516-.502-.956.233-1.314.513.478.403.898.933.44a.447.447 0 0 1 .012.336.525.525 0 0 1-.233.27c.476-.367 1.304-.214 1.525-.817.553.598 1.658-.248 1.691.808.29-.433.74-.77 1.277-.956-.752 1.3 1.724 0 1.591 1.348.553-1.162 2.21-.617 3.255-1.3-.055.095-.16.282-.265.23.624.061.823.391 1.237.592 0-.956.967-1.195 1.448-1.797.812.87-.392 1.118-.1 1.974-.082-.755 1.272-.813.973-1.434.614.53.514.248.862 1.008.028-1.17.553-.22.962-.956.873.54.282 1.086 1.182.689.453.354-.342.808-.342.808Zm21.793-2.93-.447.057.447-.058Zm1.818-.091a7.552 7.552 0 0 0-.801 0c-.072-.23 0-.478.171-.478-.083.186.348.305.63.478Zm-4.128-4.49c.288-.109.393 0 .442.159-.172.02-.343.053-.508.1v.081a.973.973 0 0 1 .066-.34Z"},null,-1)])]))])]))}});export{v as __pageData,_ as default}; diff --git a/assets/product-sense_ai-native-composite-talents.md.B6c5Dih7.js b/assets/product-sense_ai-native-composite-talents.md.B6c5Dih7.js new file mode 100644 index 00000000..cc2255e5 --- /dev/null +++ b/assets/product-sense_ai-native-composite-talents.md.B6c5Dih7.js @@ -0,0 +1 @@ +import{_ as a,g as o,h as e,U as s}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const I=JSON.parse('{"title":"读后感:AI 原生时代的复合型人才,究竟需要怎样的特质?","description":"摘要总结:本文结合保罗・格雷厄姆《How to Do Great Work》核心观点,探讨 AI 原生时代复合型人才的核心特质。AI 让基础执行能力快速贬值,人才的核心壁垒不再是解决问题,而是提出优质问题、培养非共识品味。同时需坚守智力诚实,拥有打破常规的创新勇气,借助 AI 放大个人成长杠杆,以小切口实践实现指数级成长。人类独有的好奇心,是突破 AI 平庸、取得杰出成就的最终底气。","frontmatter":{"date":"2024-06-15T22:23:00.000Z","title":"读后感:AI 原生时代的复合型人才,究竟需要怎样的特质?","description":"摘要总结:本文结合保罗・格雷厄姆《How to Do Great Work》核心观点,探讨 AI 原生时代复合型人才的核心特质。AI 让基础执行能力快速贬值,人才的核心壁垒不再是解决问题,而是提出优质问题、培养非共识品味。同时需坚守智力诚实,拥有打破常规的创新勇气,借助 AI 放大个人成长杠杆,以小切口实践实现指数级成长。人类独有的好奇心,是突破 AI 平庸、取得杰出成就的最终底气。","coverImg":"/img/cover/product_sense_bg.png","permalink":"/product-sense/ai-native-composite-talents","categories":["产品 Sense"],"tags":["AI","成长"]},"headers":[],"relativePath":"product-sense/ai-native-composite-talents.md","filePath":"10.产品 Sense/02.新 T 型人/20.读后感:AI 原生时代的复合型人才,究竟需要怎样的特质?.md"}'),r={name:"product-sense/ai-native-composite-talents.md"};function l(i,t,p,n,c,_){return e(),o("div",null,[...t[0]||(t[0]=[s('

    读后感:AI 原生时代的复合型人才,究竟需要怎样的特质?

    原文标题:《How to Do Great Work》(如何取得杰出成就)

    原文地址https://paulgraham.com/greatwork.html

    原文作者:Paul Graham(保罗·格雷厄姆),硅谷顶级孵化器 Y Combinator 创始人,被誉为“硅谷创业教父”,也是经典技术哲学著作《黑客与画家》的作者。

    文章背景:原文是保罗·格雷厄姆之前准备了半年之久的重磅长文,他试图讲明白一个适用于每个人的主题——如何做成「大事」(great work)。通读全文,你会发现,这是一篇非常实用的工作指南,并且其中的许多内容,都与AI原生时代的复合型人才所需要具备的特质非常一致。

    1. 引言:当“执行”被 AI 填平,什么才是核心壁垒?

    通读保罗·格雷厄姆(以下简称 PG)这篇两万字的长文,笔者最大的感受是:这不仅是一份跨越领域的“伟大成就指南”,更是一份为 AI 原生时代量身定制的“复合型人才生存手册”。

    在 AI 爆发的当下,写代码、画图、撰写基础文案甚至简单的数据分析,这些曾经被视为专业技能的“执行动作”,正在迅速贬值。当 AI 把“解答问题”的门槛降到极低时,人与人之间的差距将被什么拉开?

    PG 在文章中给出了答案:找到正确的问题、保持非共识的好奇心、以及拥有极高的品味。以下是我结合 AI 时代浪潮,对文章核心观点的梳理与个人思考。

    2. 从“解决问题”到“发现问题”:提问力决定生产力

    【原文精髓】

    “问题不仅导向答案,而且也导向更多的问题。”

    PG 认为,人们在解决问题上表现出的原创性,远超在“决定解决哪些问题”上。很多人被困在时髦的漩涡里,而真正杰出的成就往往始于敏锐地注意到了知识边缘的“缺口”。

    【我的体会】

    在 AI 时代,这句话被赋予了史无前例的现实意义。大模型(LLM)本质上是一个超级“解答机”,它极其擅长顺着你给定的逻辑生成答案。这意味着,在未来,寻找答案的能力将不再稀缺,稀缺的是提出绝佳问题的能力

    一个 AI 原生时代的复合型人才,其核心特质就是成为一个高阶的“问题发现者”。我们需要利用 AI 快速跨越多个领域的知识盲区(即 PG 说的“到达领域前沿”),然后在前沿地带敏锐地嗅到那些被主流忽视的空白。"Prompt(提示词)质量"在某种程度上正是我们洞察力与品味的直接映射——它决定了我们能否从 AI 这座"超级解答机"中,挖掘出真正有价值的答案。

    3. 培养非共识的“品味”:逃离 AI 生成的“平均数”

    【原文精髓】

    PG 强调:“有意识地培养对自己领域工作的品味。除非我们知道什么是最好的,以及是什么使它成为最好的,否则我们并不知道自己在追求什么。”

    【我的体会】

    在这个信息大爆炸的时代,AI 正在批量生产海量的、无差别的“及格线以上”的内容与代码,这带来了两个极端的现象:

    • 下限被拔高了,平庸者可以利用 AI 瞬间看起来像个专家。

    • 上限变得更难突破了,因为所有由 AI 生成的东西,本质上都是在“历史数据的平均值”上做微小变异。

    这就使得 PG 提到的“品味(Taste)”变得无比重要。复合型人才必须拥有极高的审美眼光与判别能力,这种能力无法通过算法习得。当我们面对 AI 给出的多个解决方案时,需要敏锐地判断哪个方案不仅可行,而且足够“优雅”。品味,将成为我们在 AI 自动驾驶浪潮中把稳方向盘的核心资产

    4. 保持真诚与“打破规则”的勇气:抵抗 AI 的“幻觉”与平庸

    【原文精髓】

    “要找到新的想法,就必须抓住不合理的迹象,而不是避而不见。” PG 在文章中反复强调独立思考(无论是主动还是被动的)与真诚(Intellectual Honesty,智力诚实)的力量。一个好的新想法,一开始往往是不受待见的。

    【我的体会】

    大模型是基于“人类现有共识(语料库)”训练出来的产物,这也意味着如果只依赖 AI 的输出,我们将永远在已知的舒适区内打转。真正“伟大”的创新,必然是对现有常识的颠覆与补充。

    这就要求复合型人才必须具备极度的“智力诚实”。我们要把 AI 当作工具去验证假设,但在 AI 给出看似完美的常规解答时,我们要敢于说:“不,这里还有缺陷。”

    当所有人都沉浸在某种热门技术或框架中时,我们要敢于像 PG 说的那样,选择冷门但具有极大潜力的“问题空间”。在 AI 时代,你的原创性,恰恰体现在你敢于在 AI 给出“标准答案”时,按下暂停键,去追问一个看似疯狂但属于“正确类别”的问题。

    5. 复合指数增长:以小见大的行动力

    【原文精髓】

    “指数增长的问题在于曲线在开始时给人的感觉很平,但它不是。” PG 指出:杰出成就的累积效应是被严重低估的,关键在于一致性。同时,我们不需要做庞大的计划,只需要做“可能有用的最简单的东西”,并在实践中不断演化。

    【我的体会】

    在这一节,PG 的观点与“敏捷开发”不谋而合。但在今天,有了 AI 加持,个人开发者的“复合杠杆率”被无限放大了。

    过去,打造一个最小可行性产品(MVP)往往需要数周时间。如今,在 AI 编程工具的助力下,一个具备复合能力的人才或许只需一个周末就能完成原型的搭建与验证。这意味着"以项目为单位的拖延"在当下变得愈发不可承受

    AI 时代的复合型人才,不再是拥有单一深厚技能的螺丝钉,而是能够一人承担“产品经理 + 全栈工程师 + 运营”角色的超级个体。一旦找到那个令你产生深度兴趣的切入点,并持续深耕,你的成长曲线将在极短时间内迎来惊人的指数级跃升。

    6. 在算力面前保持敬畏,在机器面前保持好奇

    通读 PG 这篇万字长文,如果要问:在这个技术天翻地覆的时代,取得成就究竟有什么不可替代的秘诀?文章给出的最终答案是——好奇心。

    AI 可以模仿语气,可以生成代码,可以计算概率,却无法拥有真正自发的好奇心。它不会为一个微小的不合理现象而抓狂,也不会为了一个未知的答案彻夜难眠。

    这正是我们作为人类最后的底牌。去追寻那些让你兴奋不已、让你"过分"好奇的问题吧——借助 AI 的算力跨越执行的鸿沟,以极高的品味去甄别筛选,用不妥协的真诚去深入探索。

    剩下的,正如保罗·格雷厄姆所说:"还有很多发现正等待着被发现,为什么不由我们自己去发现呢?"

    ',23)])])}const A=a(r,[["render",l]]);export{I as __pageData,A as default}; diff --git "a/assets/10.\344\272\247\345\223\201 Sense_02.\346\226\260 T \345\236\213\344\272\272_20.\350\257\273\345\220\216\346\204\237\357\274\232AI \345\216\237\347\224\237\346\227\266\344\273\243\347\232\204\345\244\215\345\220\210\345\236\213\344\272\272\346\211\215\357\274\214\347\251\266\347\253\237\351\234\200\350\246\201\346\200\216\346\240\267\347\232\204\347\211\271\350\264\250\357\274\237.md.Xe0P5HJr.lean.js" b/assets/product-sense_ai-native-composite-talents.md.B6c5Dih7.lean.js similarity index 70% rename from "assets/10.\344\272\247\345\223\201 Sense_02.\346\226\260 T \345\236\213\344\272\272_20.\350\257\273\345\220\216\346\204\237\357\274\232AI \345\216\237\347\224\237\346\227\266\344\273\243\347\232\204\345\244\215\345\220\210\345\236\213\344\272\272\346\211\215\357\274\214\347\251\266\347\253\237\351\234\200\350\246\201\346\200\216\346\240\267\347\232\204\347\211\271\350\264\250\357\274\237.md.Xe0P5HJr.lean.js" rename to assets/product-sense_ai-native-composite-talents.md.B6c5Dih7.lean.js index 533e9eb9..16f4e074 100644 --- "a/assets/10.\344\272\247\345\223\201 Sense_02.\346\226\260 T \345\236\213\344\272\272_20.\350\257\273\345\220\216\346\204\237\357\274\232AI \345\216\237\347\224\237\346\227\266\344\273\243\347\232\204\345\244\215\345\220\210\345\236\213\344\272\272\346\211\215\357\274\214\347\251\266\347\253\237\351\234\200\350\246\201\346\200\216\346\240\267\347\232\204\347\211\271\350\264\250\357\274\237.md.Xe0P5HJr.lean.js" +++ b/assets/product-sense_ai-native-composite-talents.md.B6c5Dih7.lean.js @@ -1 +1 @@ -import{_ as a,g as o,h as e,U as s}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const A=JSON.parse('{"title":"读后感:AI 原生时代的复合型人才,究竟需要怎样的特质?","description":"摘要总结:本文结合保罗・格雷厄姆《How to Do Great Work》核心观点,探讨 AI 原生时代复合型人才的核心特质。AI 让基础执行能力快速贬值,人才的核心壁垒不再是解决问题,而是提出优质问题、培养非共识品味。同时需坚守智力诚实,拥有打破常规的创新勇气,借助 AI 放大个人成长杠杆,以小切口实践实现指数级成长。人类独有的好奇心,是突破 AI 平庸、取得杰出成就的最终底气。","frontmatter":{"date":"2024-06-15T22:23:00.000Z","title":"读后感:AI 原生时代的复合型人才,究竟需要怎样的特质?","description":"摘要总结:本文结合保罗・格雷厄姆《How to Do Great Work》核心观点,探讨 AI 原生时代复合型人才的核心特质。AI 让基础执行能力快速贬值,人才的核心壁垒不再是解决问题,而是提出优质问题、培养非共识品味。同时需坚守智力诚实,拥有打破常规的创新勇气,借助 AI 放大个人成长杠杆,以小切口实践实现指数级成长。人类独有的好奇心,是突破 AI 平庸、取得杰出成就的最终底气。","coverImg":"/img/cover/product_sense_bg.png","permalink":"/product-sense/ai-native-composite-talents","categories":["产品 Sense"],"tags":["AI","成长"]},"headers":[],"relativePath":"10.产品 Sense/02.新 T 型人/20.读后感:AI 原生时代的复合型人才,究竟需要怎样的特质?.md","filePath":"10.产品 Sense/02.新 T 型人/20.读后感:AI 原生时代的复合型人才,究竟需要怎样的特质?.md"}'),r={name:"10.产品 Sense/02.新 T 型人/20.读后感:AI 原生时代的复合型人才,究竟需要怎样的特质?.md"};function i(l,t,p,n,c,d){return e(),o("div",null,[...t[0]||(t[0]=[s("",24)])])}const I=a(r,[["render",i]]);export{A as __pageData,I as default}; +import{_ as a,g as o,h as e,U as s}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const I=JSON.parse('{"title":"读后感:AI 原生时代的复合型人才,究竟需要怎样的特质?","description":"摘要总结:本文结合保罗・格雷厄姆《How to Do Great Work》核心观点,探讨 AI 原生时代复合型人才的核心特质。AI 让基础执行能力快速贬值,人才的核心壁垒不再是解决问题,而是提出优质问题、培养非共识品味。同时需坚守智力诚实,拥有打破常规的创新勇气,借助 AI 放大个人成长杠杆,以小切口实践实现指数级成长。人类独有的好奇心,是突破 AI 平庸、取得杰出成就的最终底气。","frontmatter":{"date":"2024-06-15T22:23:00.000Z","title":"读后感:AI 原生时代的复合型人才,究竟需要怎样的特质?","description":"摘要总结:本文结合保罗・格雷厄姆《How to Do Great Work》核心观点,探讨 AI 原生时代复合型人才的核心特质。AI 让基础执行能力快速贬值,人才的核心壁垒不再是解决问题,而是提出优质问题、培养非共识品味。同时需坚守智力诚实,拥有打破常规的创新勇气,借助 AI 放大个人成长杠杆,以小切口实践实现指数级成长。人类独有的好奇心,是突破 AI 平庸、取得杰出成就的最终底气。","coverImg":"/img/cover/product_sense_bg.png","permalink":"/product-sense/ai-native-composite-talents","categories":["产品 Sense"],"tags":["AI","成长"]},"headers":[],"relativePath":"product-sense/ai-native-composite-talents.md","filePath":"10.产品 Sense/02.新 T 型人/20.读后感:AI 原生时代的复合型人才,究竟需要怎样的特质?.md"}'),r={name:"product-sense/ai-native-composite-talents.md"};function l(i,t,p,n,c,_){return e(),o("div",null,[...t[0]||(t[0]=[s("",23)])])}const A=a(r,[["render",l]]);export{I as __pageData,A as default}; diff --git a/assets/product-sense_engineer-build-product-sense.md.-nPPujxn.js b/assets/product-sense_engineer-build-product-sense.md.-nPPujxn.js new file mode 100644 index 00000000..b48cadf4 --- /dev/null +++ b/assets/product-sense_engineer-build-product-sense.md.-nPPujxn.js @@ -0,0 +1 @@ +import{_ as s,g as t,h as n,U as m}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const h=JSON.parse('{"title":"当“实现”不再是壁垒:工程师如何构建产品 Sense?","description":"摘要总结:当 AI 让代码生成的边际成本趋近于零,“技术实现”不再是不可逾越的壁垒,“产品洞察”能构筑起新的核心护城河。本文拒绝玄学,将抽象的 产品 Sense 解构为三个核心数学公式,并提供一套基于“逆向工程”的刻意练习指南,助力开发者在算力过剩的时代,完成从“代码工匠”到“价值创造者”的认知跃迁。","frontmatter":{"date":"2025-10-23T16:05:50.000Z","title":"当“实现”不再是壁垒:工程师如何构建产品 Sense?","description":"摘要总结:当 AI 让代码生成的边际成本趋近于零,“技术实现”不再是不可逾越的壁垒,“产品洞察”能构筑起新的核心护城河。本文拒绝玄学,将抽象的 产品 Sense 解构为三个核心数学公式,并提供一套基于“逆向工程”的刻意练习指南,助力开发者在算力过剩的时代,完成从“代码工匠”到“价值创造者”的认知跃迁。","sticky":1,"top":true,"categories":["产品 Sense","AI"],"coverImg":"https://insight-stack-1252300811.cos.ap-shanghai.myqcloud.com/img/cover/product_sense_bg.png","permalink":"/product-sense/engineer-build-product-sense"},"headers":[],"relativePath":"product-sense/engineer-build-product-sense.md","filePath":"10.产品 Sense/02.新 T 型人/21.工程师如何构建产品 Sense.md"}'),i={name:"product-sense/engineer-build-product-sense.md"};function o(l,a,e,r,p,d){return n(),t("div",null,[...a[0]||(a[0]=[m('

    当“实现”不再是壁垒:工程师如何构建产品 Sense?

    摘要总结:当 AI 让代码生成的边际成本趋近于零,“技术实现”不再是不可逾越的壁垒,“产品洞察”能构筑起新的核心护城河。本文拒绝玄学,将抽象的 产品 Sense 解构为三个核心数学公式,并提供一套基于“逆向工程”的刻意练习指南,助力开发者在算力过剩的时代,完成从“代码工匠”到“价值创造者”的认知跃迁。

    1. 引言

    在很长一段时间里,产品 Sense(产品感) 被视为一种玄学。它似乎是乔布斯式的灵光一现,或是张小龙式的“独断专行”。

    但对于大多数工程师、产品经理乃至独立开发者而言,将能力寄托于“天赋”是危险的。我认为,产品 Sense 并非不可捉摸的黑魔法,而是一套经过高频训练后内化为本能的思维算法。 就像资深程序员看到一段代码就能嗅出 "Code Smell"(代码异味),资深产品人也能在瞬间判断一个需求是“真痛点”还是“伪需求”。

    一个成功的产品决策,往往发生在三个维度的交汇点:

    • 用户价值洞察(User Value Insight):不仅听懂用户说“想要更快的马”,更能洞察他其实“想更快到达目的地”。
    • 商业可行性(Business Viability):不仅能做出来,还能算得过账。像 Dropbox 早期利用病毒式裂变降低获客成本,就是商业嗅觉的体现。
    • 技术可实现性(Technical Feasibility):在“完美的架构”和“明天就能上线”之间找到平衡。ChatGPT 的爆发,正是技术积累终于跨过了“可用性阈值”的临界点。

    产品 Sense 是产品经理、设计师乃至创业者经常被提及、却也难以量化的能力之一。它并非玄学,而是一套可拆解、可训练、可迭代的思维模型:在信息不完整、目标模糊、资源受限的情况下,依然能快速判断「做什么」与「不做什么」,并让用户愿意为之买单或停留

    2. 解构产品 Sense 的数学之美

    如果把产品 Sense 仅仅看作是“灵光一现”的艺术,那它就是不可复制的黑盒。作为工程师,我们更习惯于透过现象探寻底层的运行规律。

    事实上,那些看似玄妙的直觉判断,往往是潜意识在极短时间内完成的高维计算。为了让这个抽象概念变得可解构、可训练,我尝试用理性的数学语言来重构感性的产品直觉,将其提炼为以下三个核心公式。

    2.1. 极简杠杆公式:寻找 ROI 的最大解

    NOTE

    核心逻辑:卓越的产品嗅觉(产品 Sense)本质上是一种寻找“高杠杆解”的能力,对投入产出比(ROI)极致敏感。它要求我们敏锐地发现那些 “价值极高,但实现较低” 的低垂机会(Low Hanging Fruits),并果断放弃那些 “价值低又很难做” 的伪需求(看似美好,实则陷入技术泥潭)。

    适用场景:技术选型决策、Feature 排期优先级、MVP 边界界定。

    对于技术背景的开发者,最大的陷阱往往是“对过度设计的迷恋” 与 “为了技术而技术的自我感动”。因为掌握了某个新技术,就强行创造一个需求,但好的 Product Sense 其实是投入产出比(ROI)的直觉:

    Product Sense=User ValueComplexity\\mathbf{Product\\ Sense} \\; = \\; \\frac{\\mathbf{User\\ Value}}{\\mathbf{Complexity}}

    • 分子——用户价值(User Value): 痛点烈度 × 覆盖广度不仅仅是“这个问题痛不痛”,而是要量化思考:这是一个高频刚需,还是低频痒点?解决它能为业务带来多大的增量(留存、转化或效率提升)?
    • 分母——实现复杂度(Complexity): 开发成本 + 维护税复杂度不仅是 Coding 的时间,更包含未来的维护成本、系统熵增以及用户认知的负担。全栈的智慧在于:用最简单的技术栈(Low Complexity),去撬动最大的业务价值。敢于在非核心功能上使用“笨办法”,是为了在核心体验上以此换取“极致体验”。

    2.2. 洞察力公式:理智与情感的共舞

    NOTE

    核心逻辑:同理心提供"方向",批判性思维提供"导航"

    • 同理心告诉你"用户很痛苦"批判性思维告诉你"痛苦的根源是什么"
    • 同理心告诉你"用户想要什么"批判性思维告诉你"为什么想要"和"有没有更好的解决方案"

    适用场景:需求分析、用户调研、产品定位、功能设计、A/B 测试方案设计。

    仅有同理心,产品容易沦为“臃肿的许愿池”(用户要什么给什么,导致产品臃肿);仅有批判性思维,产品容易变成“冰冷的逻辑机器”(数据看似完美,却缺乏打动人心的人性温度)。因此,产品 Sense 本质上也是同理心与批判性思维的结合:

    例如,用户抱怨"App 太复杂",同理心让你感受到用户的挫败感,批判性思维让你追问:是功能太多?还是导航不清晰?还是学习成本太高?——不同的根源需要不同的解决方案。

    Product Sense=Empathy×Critical Thinking\\mathbf{Product\\ Sense} \\; = \\; \\mathbf{Empathy} \\; \\times \\; \\mathbf{Critical\\ Thinking}

    注意,这里是乘法关系而不是加法,意味着任何一个为零,整个结果都是零。只有同理心但缺乏批判性思维,会做出"用户要什么就给什么"的平庸产品;只有批判性思维但缺乏同理心,会做出"技术上完美但用户不买账"的产品。

    • 同理心 (Empathy): 感知用户真实感受的能力。同理心不是"我理解用户",而是"我能变成用户"。这意味着:

      • 情境代入:能够切换到用户的真实使用场景。例如,设计外卖 App 时,不是在办公室想象"用户想要什么功能",而是站在雨夜路边、手机电量 10% 的真实场景中思考。
      • 情绪捕捉:能够识别用户未说出口的情绪。用户抱怨"页面加载慢",背后的情绪可能是"我饿得不行了,还要等多久?"——解决方案不只是优化代码,更可能是优化"等待时的体验"(比如显示预计时间、播放动画)。
      • 认知对齐:不预设用户很聪明。用户不会像你一样熟悉产品,他们会在你意想不到的地方卡住。例如,注册页面的"密码强度"指示器,用户可能根本看不懂那些颜色代表什么。
      • 反面案例:某电商 App 在购物车页面放置了 20 个功能入口,产品经理觉得"功能很全",但用户只想要一个"快速结算"按钮。
    • 批判性思维 (Critical Thinking): 透过现象看本质的能力。批判性思维不是"质疑一切",而是"追问为什么"。这意味着:

      • 需求挖掘:用户说"想要"的不一定是他们"需要"的。经典的例子:用户说"我要一匹更快的马",背后的需求是"更快到达目的地"——解决方案可能是汽车、火车、飞机,而不是训练更快的马。
      • 数据解读:能够区分"相关性"和"因果关系"。数据显示"使用某功能的用户留存率更高",但究竟是"功能带来留存"还是"高留存用户恰好用了这个功能"?需要进一步验证。
      • 假设挑战:对每个功能假设都要问"如果不做会怎样?"。例如,增加"每日签到"功能前,先问:用户不签到的损失是什么?如果签到带来的价值不足以改变用户行为,那就是伪需求。 实际案例:Airbnb 早期发现用户不愿预订,不是因为价格或房源,而是因为"信任陌生房东"。于是他们投入大量精力做"房东验证""真实评价""照片认证",而不是优化搜索算法——这就是批判性思维带来的洞察。

    2.3. AI 前沿视角公式:从“功能产品”到“语境构建”

    NOTE

    核心洞察:AI 时代的稀缺资源不再是“生成答案的能力”(模型已经具备),而是“提出正确问题的能力”。Product Sense 的核心从“设计功能交互”转变为“设计隐性的思维路径”,我们需要同时具备 翻译官(将模糊需求结构化) 和 架构师(构建智能体工作流) 的双重能力。

    AI 模型本身是通用的引擎,我们需要为它设计底盘和方向盘,产品 Sense 在 AI 时代也就包含了新的特征:定义问题的能力——能把模糊的人类需求翻译成 AI 能理解的精确指令和环境:

    Product Sense=Problem Definition+Context Design\\mathbf{Product\\ Sense} \\; = \\; \\mathbf{Problem\\ Definition} \\; + \\; \\mathbf{Context\\ Design}

    • 定义问题(Problem Definiton):
      • 结构化歧义:AI 拥有无限的潜力,也伴随着无限的发散。Product Sense 在此处体现为 “收敛能力”——能否将一个模糊的业务痛点(如“分析用户情绪”),拆解为一组 AI 可理解、可执行的精准意图。
      • 工作流架构:这不仅仅是写出一句完美的 Prompt,更是设计 Agentic Workflow(智能体工作流)的过程。我们需要判断哪些环节利用 LLM 的逻辑推理(概率性),哪些环节必须由传统代码(确定性)来兜底,从而构建出稳定可靠的系统。
    • 语境设计(Context Design):从“喂数据”到“构建信息场域”
      • 无形界面设计:在 AI 应用中,真正的 UI 往往不是屏幕上的像素,而是看不见的 Context Window(上下文窗口)。Product Sense 就是设计这个“无形界面”的艺术——决定让 AI “看到”什么,以及“忽略”什么。
      • 约束与边界工程:Product Sense 在这里体现为:我们能否为 AI 构建一个“全知全能”且“专注当下”的上下文环境,使其输出精准且可控。核心挑战是:如何在有限的上下文窗口(Context Window)中,提供最关键的先验知识、约束条件和少样本(Few-Shot)案例,让 AI 在你预设的“语境场”里精准舞蹈,而不是胡乱幻觉。

    3. 刻意练习:如何从“凭感觉”到“有直觉”?

    很多人认为 Sense 是天赋,无法学习,但我坚信直觉是经验在潜意识里的压缩算法。我们可以通过以下三个步骤的“刻意练习”来训练这种算法:

    3.1. 建立“预测-验证”的反馈闭环

    这是最硬核的训练法,不要只是被动地看数据,要主动做预测。

    • 练习方法:在任何新功能上线前(或者观察竞品改版时),在笔记本上写下你的预测。
      • “我赌这个按钮改为红色,点击率会提升 5%。”
      • “我认为竞品推出这个功能是想解决留存问题,但可能会导致用户反感。”
    • 复盘:一周后,看真实数据或市场反馈。如果你猜对了,强化这个直觉。如果你猜错了,这才是最宝贵的时刻:去深究为什么?是高估了用户动力?还是低估了操作门槛?
    • 原理:大模型的训练依靠 Loss Function(损失函数)来收敛,人的直觉也一样。只有通过不断的“预测失败”,我们的大脑才能修正权重,从而获得更精准的 Sense。

    3.2. 培养“摩擦力日记”

    很多时候我们对痛点视而不见,是因为我们习惯了,要训练产品 Sense,就要恢复对“不舒服”的敏感度。

    • 练习方法:每天记录 3 个让自己感到“微小不爽”的时刻,无论是使用自家产品还是生活中的琐事。

      • “在这个 App 复制验证码居然不能自动跳转,还得我手动切回去,好烦。”
      • “这个报错提示说‘网络错误 404’,为什么不直接告诉我‘请检查 Wi-Fi’?”
    • 进阶:不只是抱怨,强迫自己构思一个 “最小改动解”

      • 解法:在复制验证码的短信里加一个 Deep Link,一键跳回 App。

    3.3. 解构“魔法”:从惊叹到复刻的逆向工程

    NOTE

    四步闭环: “记录-解剖-重构-沉淀”

    当我们遇到一个让自己惊叹的产品(比如初次使用 ChatGPT或沉迷于 Vibe Coding)时,千万不要只停留在消费者的视角感叹“真好用”。那是“魔法”生效的时刻,也是你作为魔术师学徒拆解戏法的最佳时机。

    若想将这种惊叹内化为自己的 Sense,我们需要执行一套完整的逆向工程循环:

    (1)记录 (Record):捕捉情绪颗粒度

    不要等回头再想,要在“惊叹”发生的当下,像捕捉蝴蝶一样捕捉你的情绪:

    • 截屏/录屏:记录下那个让你嘴角上扬或瞳孔放大的瞬间(Aha Moment)。
    • 微观情绪标注:问自己,“这一秒,为什么我觉得‘爽’?”是因为那个丝滑的转场动画,还是因为文案恰好击中了我的软肋,还是因为它的响应速度快得不可思议?
      • 案例:Linear 的官网之所以让人惊叹,不仅因为设计,更因为当你按 J / K 键时的毫秒级响应,这种“掌控感”是情绪的来源。

    (2)解剖 (Peel):上帝视角的逻辑拆解

    切换到产品经理的上帝视角,透过表皮看骨架。思考它做对了哪三件事:

    • 它满足了哪个层级的需求?是底层的生理/安全,还是顶层的自我实现/虚荣?它是帮你省了时间,还是帮你杀了时间?
    • 它极其大胆地“删减”了什么?伟大的产品往往由它不做什么来定义。TikTok 删减了用户“选择看什么”的权利,直接喂饭;Notion 早期删减了复杂的格式兼容,只保留 Block。
    • 它的核心增长飞轮是什么?它是如何让你忍不住想分享给别人的?是利用了你的炫耀欲,还是单纯的互利机制?

    (3)重构 (Reconstruct):全栈视角的复刻推演

    发挥全栈工程师的技术优势,在脑海中(或草稿纸上)尝试重建它。

    • 技术推演:为了实现这个丝滑体验,它的前端可能用了什么技术栈?后端是如何处理高并发的?如果你来做,你会怎么设计数据库 Schema?
    • 成本估算:它为了这个体验,付出了多大的工程代价?这个代价在商业上划算吗?

    (4)沉淀 (Crystallize):输出倒逼内化

    这是最关键、却最常被忽略的一步。没有输出的思考,就像没有 commit 的代码,随时会丢失。

    • 写一篇“产品验证报告”:不要只在脑子里想,要写下来。比如尝试写一篇《为什么 X 产品让我欲罢不能?》,强迫自己把模糊的感觉结构化为文字。

    • 发起一场“人机辩论” (Initiate a Human-AI Debate): 不要急着把观点发给同行,先让 AI 充当你的“红队”也就是“假想敌”。

      • 第一轮(AI 陪练):把自己的分析发给 GPT/Claude,并加上这句 Prompt:“如果你是这个产品的 CEO,请指出我分析中的漏洞,有哪些商业考量或技术限制是我没看到的?” AI 往往能从你忽略的历史背景、隐形成本或竞争格局角度给出惊人的补充。
      • 第二轮(真人验证):带着 AI 完善过的观点,再去社区或同行间交流。你会发现,你的洞察深度已经超越了 90% 的人,而真人的反馈则能补充 AI 无法触达的“隐秘行业潜规则”或“人性微妙之处”

    4. 结语:从“如何实现”的焦虑中解放,拥抱“为何而做”的自由

    在 AI 时代,代码生成的边际成本正在无限趋近于零。当“实现”不再是不可逾越的壁垒,“洞察”与“品位”便成了新的护城河。

    未来的全栈工程师将不再是 [前端 + 后端],而是 [技术理解力 x 产品敏锐度]的化学反应:

    • 技术是我们的压舱石,让我们知晓可能性的边界,不至于在天马行空中失重;
    • 产品 Sense 是我们的罗盘,让在生成的洪流中锁定航向,不至于在低价值的代码堆里荒废时光。

    产品 Sense 的终点从来不是“不做错的决定”——那是全知视角的奢望。它的终点是“拥有比别人更短的纠错半径”:在错误发生时,能以最低的成本感知并修正。

    保持敏锐,保持饥饿,对“用户下一秒的皱眉”心存敬畏。因为算法无法计算“痛点”,而那个皱眉的瞬间,往往就是下一款好产品的起点。

    ',58)])])}const b=s(i,[["render",o]]);export{h as __pageData,b as default}; diff --git "a/assets/10.\344\272\247\345\223\201 Sense_02.\346\226\260 T \345\236\213\344\272\272_21.\345\267\245\347\250\213\345\270\210\345\246\202\344\275\225\346\236\204\345\273\272\344\272\247\345\223\201 Sense.md.CO18rPj4.lean.js" b/assets/product-sense_engineer-build-product-sense.md.-nPPujxn.lean.js similarity index 72% rename from "assets/10.\344\272\247\345\223\201 Sense_02.\346\226\260 T \345\236\213\344\272\272_21.\345\267\245\347\250\213\345\270\210\345\246\202\344\275\225\346\236\204\345\273\272\344\272\247\345\223\201 Sense.md.CO18rPj4.lean.js" rename to assets/product-sense_engineer-build-product-sense.md.-nPPujxn.lean.js index 99335b96..0ac264c6 100644 --- "a/assets/10.\344\272\247\345\223\201 Sense_02.\346\226\260 T \345\236\213\344\272\272_21.\345\267\245\347\250\213\345\270\210\345\246\202\344\275\225\346\236\204\345\273\272\344\272\247\345\223\201 Sense.md.CO18rPj4.lean.js" +++ b/assets/product-sense_engineer-build-product-sense.md.-nPPujxn.lean.js @@ -1 +1 @@ -import{_ as s,g as t,h as n,U as m}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const h=JSON.parse('{"title":"当“实现”不再是壁垒:工程师如何构建产品 Sense?","description":"摘要总结:当 AI 让代码生成的边际成本趋近于零,“技术实现”不再是不可逾越的壁垒,“产品洞察”能构筑起新的核心护城河。本文拒绝玄学,将抽象的 产品 Sense 解构为三个核心数学公式,并提供一套基于“逆向工程”的刻意练习指南,助力开发者在算力过剩的时代,完成从“代码工匠”到“价值创造者”的认知跃迁。","frontmatter":{"date":"2025-10-23T16:05:50.000Z","title":"当“实现”不再是壁垒:工程师如何构建产品 Sense?","description":"摘要总结:当 AI 让代码生成的边际成本趋近于零,“技术实现”不再是不可逾越的壁垒,“产品洞察”能构筑起新的核心护城河。本文拒绝玄学,将抽象的 产品 Sense 解构为三个核心数学公式,并提供一套基于“逆向工程”的刻意练习指南,助力开发者在算力过剩的时代,完成从“代码工匠”到“价值创造者”的认知跃迁。","sticky":1,"top":true,"categories":["产品 Sense","AI"],"coverImg":"https://insight-stack-1252300811.cos.ap-shanghai.myqcloud.com/img/cover/product_sense_bg.png","permalink":"/product-sense/engineer-build-product-sense"},"headers":[],"relativePath":"10.产品 Sense/02.新 T 型人/21.工程师如何构建产品 Sense.md","filePath":"10.产品 Sense/02.新 T 型人/21.工程师如何构建产品 Sense.md"}'),i={name:"10.产品 Sense/02.新 T 型人/21.工程师如何构建产品 Sense.md"};function o(e,a,l,r,p,d){return n(),t("div",null,[...a[0]||(a[0]=[m("",59)])])}const b=s(i,[["render",o]]);export{h as __pageData,b as default}; +import{_ as s,g as t,h as n,U as m}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const h=JSON.parse('{"title":"当“实现”不再是壁垒:工程师如何构建产品 Sense?","description":"摘要总结:当 AI 让代码生成的边际成本趋近于零,“技术实现”不再是不可逾越的壁垒,“产品洞察”能构筑起新的核心护城河。本文拒绝玄学,将抽象的 产品 Sense 解构为三个核心数学公式,并提供一套基于“逆向工程”的刻意练习指南,助力开发者在算力过剩的时代,完成从“代码工匠”到“价值创造者”的认知跃迁。","frontmatter":{"date":"2025-10-23T16:05:50.000Z","title":"当“实现”不再是壁垒:工程师如何构建产品 Sense?","description":"摘要总结:当 AI 让代码生成的边际成本趋近于零,“技术实现”不再是不可逾越的壁垒,“产品洞察”能构筑起新的核心护城河。本文拒绝玄学,将抽象的 产品 Sense 解构为三个核心数学公式,并提供一套基于“逆向工程”的刻意练习指南,助力开发者在算力过剩的时代,完成从“代码工匠”到“价值创造者”的认知跃迁。","sticky":1,"top":true,"categories":["产品 Sense","AI"],"coverImg":"https://insight-stack-1252300811.cos.ap-shanghai.myqcloud.com/img/cover/product_sense_bg.png","permalink":"/product-sense/engineer-build-product-sense"},"headers":[],"relativePath":"product-sense/engineer-build-product-sense.md","filePath":"10.产品 Sense/02.新 T 型人/21.工程师如何构建产品 Sense.md"}'),i={name:"product-sense/engineer-build-product-sense.md"};function o(l,a,e,r,p,d){return n(),t("div",null,[...a[0]||(a[0]=[m("",58)])])}const b=s(i,[["render",o]]);export{h as __pageData,b as default}; diff --git a/assets/product-sense_insight-model.md.Du_YgLvh.js b/assets/product-sense_insight-model.md.Du_YgLvh.js new file mode 100644 index 00000000..978d00f9 --- /dev/null +++ b/assets/product-sense_insight-model.md.Du_YgLvh.js @@ -0,0 +1 @@ +import{_ as a,g as r,h as s,U as o}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const d=JSON.parse('{"title":"洞察力模型:如何看透产品与技术背后的系统逻辑?","description":"摘要总结:无论是做产品、搞技术,还是应对日常工作中的各种挑战,你是否遇到过这样的困境:明明按经验行事,却屡屡踩坑;刚解决表面问题,隐患又卷土重来。问题未必出在努力程度,而在于我们只盯着表象,却忽略了背后真正起作用的系统,没有看懂藏在背后的系统。为什么同样是解决问题,有人只能“头痛医头”,有人却能直击本质?这篇文章将用通俗易懂的方式,带你拆解一套实用的洞察力模型,让我们学会透过现象抓住本质,从根源上解决问题。","frontmatter":{"date":"2025-11-14T16:00:00.000Z","title":"洞察力模型:如何看透产品与技术背后的系统逻辑?","description":"摘要总结:无论是做产品、搞技术,还是应对日常工作中的各种挑战,你是否遇到过这样的困境:明明按经验行事,却屡屡踩坑;刚解决表面问题,隐患又卷土重来。问题未必出在努力程度,而在于我们只盯着表象,却忽略了背后真正起作用的系统,没有看懂藏在背后的系统。为什么同样是解决问题,有人只能“头痛医头”,有人却能直击本质?这篇文章将用通俗易懂的方式,带你拆解一套实用的洞察力模型,让我们学会透过现象抓住本质,从根源上解决问题。","permalink":"/product-sense/insight-model","categories":["产品 Sense"],"tags":["产品 Sense","系统洞察力"]},"headers":[],"relativePath":"product-sense/insight-model.md","filePath":"10.产品 Sense/05.方法论/40.洞察力模型.md"}'),i={name:"product-sense/insight-model.md"};function n(e,t,p,l,g,c){return s(),r("div",null,[...t[0]||(t[0]=[o('

    洞察力模型:如何看透产品与技术背后的系统逻辑?

    摘要总结:无论是做产品、搞技术,还是应对日常工作中的各种挑战,你是否遇到过这样的困境:明明按经验行事,却屡屡踩坑;刚解决表面问题,隐患又卷土重来。问题未必出在努力程度,而在于我们只盯着表象,却忽略了背后真正起作用的系统,没有看懂藏在背后的系统。为什么同样是解决问题,有人只能“头痛医头”,有人却能直击本质?这篇文章将用通俗易懂的方式,带你拆解一套实用的洞察力模型,让我们学会透过现象抓住本质,从根源上解决问题。

    1. 表象背后藏着决定一切的“系统黑盒”

    我们在日常开发或产品设计中,总是被各种“表象”包围:DAU 突然下降了、线上出现了一个偶现的 Bug、某个功能的转化率不及预期。我们习惯了盯着这些看得见的结果找原因,却忽略了一个核心真相:每一个表象背后,其实都隐藏着一个运转复杂的“黑盒子”,正是这个黑盒子决定了事物发展的客观规律。我们可以把这个黑盒子,叫做“系统”。

    系统黑盒

    当系统运转正常时,我们可以遵循经验和规律按部就班地做事。可一旦系统出了问题,过往的经验往往会瞬间失效。如果我们无法破译表象背后的系统,就不可能知道问题到底出在哪一行“代码”上,更别提去修复它了。因此,所谓锻炼洞察力,本质上就是为了:理解“表象”背后的“系统”,从而在根源上解决问题。

    2. 系统的核心:要素 * 连接关系

    系统并不是一团乱麻,而是一组相互链接的要素,它是有公式可循:系统 = 要素 * 连接关系。举个经典的机械手表例子:表盘、表冠、几百个微小的齿轮和游丝,这些都是构成手表的“要素”。而这几百个零件是如何互相咬合、传递动力的,就是它们之间的“连接关系”。

    放到工作中也是同理:做产品的要素是用户、功能、流量、运营;做团队的要素是成员、岗位、目标、资源。然而,绝大多数人虽然能轻松看清这些要素,却往往习惯性忽略它们之间的连接关系——而90%的问题根源,恰恰就藏在这些看不见的连接之中。

    这也带来了洞察力新的定义:透过表象,不仅能看到系统的各个要素,更能看透要素之间错综复杂的连接关系。

    在现实中,我们往往很容易一眼看到“要素”(比如一个团队里有几个人,一个页面上有几个按钮),却极其容易忽略“连接关系”(比如这几个人之间的利益与权责分配,按钮背后的数据流向)。然而,真正高阶的解决方案,往往就藏在那些看不见的连接关系里

    想要练出这种能力,我们要拆解系统里的 5 个核心要点:变量、因果链、增强回路、调节回路、滞后效应。

    • 1 种要素:变量
    • 4 种连接关系:因果链、增强回路、调节回路、滞后效应
    洞察力模型

    3. 变量:系统里的“变化因子”

    变量,顾名思义,是系统中会随着时间发生变化的要素。一旦我们将变量放进时间轴里观察,它就会呈现出两种截然不同的状态:存量与流量。

    • 存量:是某一特定时刻,系统中积累的变量总和。

    • 流量:是一段时间内,变量流入或流出的速率。

    变量

    存量是系统的“家底”,流量决定存量的增减。看懂变量的存量与流量,才能找准系统变化的源头,而不是只盯着存量结果干着急。

    4. 因果链:搭建系统的骨架

    用因果链连接变量,是训练洞察力的基本功。

    如果说变量是独立的节点,那么将它们连接起来的线段就是“因果链”。因果链描述的是变量之间“增强”或“减弱”的关系。如果没有这些链条,再多的变量堆砌在一起,也只是一盘毫无生机的散沙,无法构成生生不息的系统。

    因果链

    行动小建议

    • 在日常复盘时,试着拿起两个看似相关的指标(比如“代码提测速度”和“线上故障率”),问问自己:它们之间是因增强果,还是因减弱果?
    • 看似简单的因果链,一段段咬合起来,最终就构成了复杂的商业或技术系统.

    5. 增强回路:造就指数级增长

    变量是节点,因果链是线段,但线段总有尽头,能量传到末端就结束了。如果我们能把结尾与开头也连接起来,形成一个闭环,会发生什么?于是回路诞生了。回路分为两种:增强回路与调节回路。

    增强回路

    不管是人生规划、产品迭代还是商业设计:小成功靠聪明才智,大成就靠建立正向的"增强回路"。所谓增强回路,就是两条或多条因果链首尾相连,形成的自我强化闭环:

    • 正向增强回路(因增强果,果又增强因):比如开源生态建设,你贡献的优质代码越多,吸引的用户就越多。用户越多,反馈和参与共建的开发者就越多,进而代码质量更高。长久以来,人们给这种现象起了无数霸气的名字“马太效应、赢家通吃、复利效应、指数级增长”

    • 负向增强回路(因减弱果,果又减弱因,即恶性循环):典型的就是“技术债”,为了赶进度写出烂代码,导致系统 Bug 频发。为了修 Bug 占用了新功能开发时间,时间不够又只能继续写烂代码……如此无限死循环。

    6. 调节回路:让系统回归平衡

    如果说增强回路的存在,是让这个世界走向极端;那么调节回路的存在,就是让这个世界回归平衡。凡是有“增强回路”的地方,七步之内,必然有“调节回路”。

    调节回路

    想象一家处于爆发期的小型科技公司:

    • 初期阶段:采用“无管理的管理”(不设层级、不设 KPI => 产品为王),依赖工程师文化和产品敏锐度,形成了“高效产出 -> 业务爆发”的增强回路。

    • 后期阶段:随着人员扩张,当初那套粗放模式失效了,跨部门沟通成本剧增,线上问题频发。此时,“产品为王”的增强回路,撞上了“管理复杂度”这条调节回路,导致业绩和研发效率徘徊不前。

    遇到这种情况该怎么办?

    答案是:切断“管理复杂度”这个“调节回路”,释放进一步增长的潜力。一旦你看懂了调节回路,你可能瞬间就顿悟了:很多时候,产品或个人的突破并不需要拼命猛踩油门,只要松开脚下的刹车就好了

    增强回路,追求极端。调节回路,回归平衡。增强回路和调节回路这对孪生兄弟,性格迥然不同,但却共同构建了最美妙的世界万物。

    7. 滞后效应:时间的迷雾

    因果不是瞬间连接,回路也不是瞬间闭合,它们之间有个时间差,有滞后效应

    在物理世界和现实系统中,因果并不是瞬间连接的,回路也不是瞬间闭合的,它们之间存在一个时间差,这时间差就是“滞后效应”。

    滞后效应让原本在空间维度上就很复杂的系统,又增加了时间维度的复杂性。它会让原因和结果在时空上错位,极大地误导我们的判断力。就像洗澡时调水温,你觉得水冷,往热水方向拧了一点,没反应,于是你继续猛拧,结果几秒后直接被烫伤。

    在试图洞察万事万物时,我们心里一定要装着一条“时间轴”。无论是发布一个新功能、重构一段底层代码,还是坚持写技术博客,效应的显现都需要时间。懂得等待,也是洞察力的一部分

    8. 总结:从观察者到洞察者

    当你下次在产品或代码中遇到棘手问题时,不妨在脑海里跑一遍这 5 个关键步骤(建议把它固化进你的思考框架中):

    • 找到核心存量

    • 找到关键因果链

    • 找到增强回路(你在踩油门吗?)

    • 找到调节回路(哪里有刹车?)

    • 考虑滞后效应(是不是子弹还要飞一会儿?)

    看看系统到底卡在哪一个节点,你可以重构哪些连接关系?做到这些,才算真正拥有了“产品 Sense”的最高形态——系统洞察力。

    普通人观察表象,优秀的人洞察系统,希望这套模型,能成为你升级认知操作系统的核心组件。

    ',48)])])}const m=a(i,[["render",n]]);export{d as __pageData,m as default}; diff --git "a/assets/10.\344\272\247\345\223\201 Sense_05.\346\226\271\346\263\225\350\256\272_40.\346\264\236\345\257\237\345\212\233\346\250\241\345\236\213.md.j-w2xxuV.lean.js" b/assets/product-sense_insight-model.md.Du_YgLvh.lean.js similarity index 75% rename from "assets/10.\344\272\247\345\223\201 Sense_05.\346\226\271\346\263\225\350\256\272_40.\346\264\236\345\257\237\345\212\233\346\250\241\345\236\213.md.j-w2xxuV.lean.js" rename to assets/product-sense_insight-model.md.Du_YgLvh.lean.js index a977001e..390a276a 100644 --- "a/assets/10.\344\272\247\345\223\201 Sense_05.\346\226\271\346\263\225\350\256\272_40.\346\264\236\345\257\237\345\212\233\346\250\241\345\236\213.md.j-w2xxuV.lean.js" +++ b/assets/product-sense_insight-model.md.Du_YgLvh.lean.js @@ -1 +1 @@ -import{_ as a,g as r,h as o,U as s}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const c=JSON.parse('{"title":"洞察力模型:如何看透产品与技术背后的系统逻辑?","description":"摘要总结:无论是做产品、搞技术,还是应对日常工作中的各种挑战,你是否遇到过这样的困境:明明按经验行事,却屡屡踩坑;刚解决表面问题,隐患又卷土重来。问题未必出在努力程度,而在于我们只盯着表象,却忽略了背后真正起作用的系统,没有看懂藏在背后的系统。为什么同样是解决问题,有人只能“头痛医头”,有人却能直击本质?这篇文章将用通俗易懂的方式,带你拆解一套实用的洞察力模型,让我们学会透过现象抓住本质,从根源上解决问题。","frontmatter":{"date":"2025-11-14T16:00:00.000Z","title":"洞察力模型:如何看透产品与技术背后的系统逻辑?","description":"摘要总结:无论是做产品、搞技术,还是应对日常工作中的各种挑战,你是否遇到过这样的困境:明明按经验行事,却屡屡踩坑;刚解决表面问题,隐患又卷土重来。问题未必出在努力程度,而在于我们只盯着表象,却忽略了背后真正起作用的系统,没有看懂藏在背后的系统。为什么同样是解决问题,有人只能“头痛医头”,有人却能直击本质?这篇文章将用通俗易懂的方式,带你拆解一套实用的洞察力模型,让我们学会透过现象抓住本质,从根源上解决问题。","permalink":"/product-sense/insight-model","categories":["产品 Sense"],"tags":["产品 Sense","系统洞察力"]},"headers":[],"relativePath":"10.产品 Sense/05.方法论/40.洞察力模型.md","filePath":"10.产品 Sense/05.方法论/40.洞察力模型.md"}'),i={name:"10.产品 Sense/05.方法论/40.洞察力模型.md"};function e(n,t,p,l,g,d){return o(),r("div",null,[...t[0]||(t[0]=[s("",49)])])}const m=a(i,[["render",e]]);export{c as __pageData,m as default}; +import{_ as a,g as r,h as s,U as o}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const d=JSON.parse('{"title":"洞察力模型:如何看透产品与技术背后的系统逻辑?","description":"摘要总结:无论是做产品、搞技术,还是应对日常工作中的各种挑战,你是否遇到过这样的困境:明明按经验行事,却屡屡踩坑;刚解决表面问题,隐患又卷土重来。问题未必出在努力程度,而在于我们只盯着表象,却忽略了背后真正起作用的系统,没有看懂藏在背后的系统。为什么同样是解决问题,有人只能“头痛医头”,有人却能直击本质?这篇文章将用通俗易懂的方式,带你拆解一套实用的洞察力模型,让我们学会透过现象抓住本质,从根源上解决问题。","frontmatter":{"date":"2025-11-14T16:00:00.000Z","title":"洞察力模型:如何看透产品与技术背后的系统逻辑?","description":"摘要总结:无论是做产品、搞技术,还是应对日常工作中的各种挑战,你是否遇到过这样的困境:明明按经验行事,却屡屡踩坑;刚解决表面问题,隐患又卷土重来。问题未必出在努力程度,而在于我们只盯着表象,却忽略了背后真正起作用的系统,没有看懂藏在背后的系统。为什么同样是解决问题,有人只能“头痛医头”,有人却能直击本质?这篇文章将用通俗易懂的方式,带你拆解一套实用的洞察力模型,让我们学会透过现象抓住本质,从根源上解决问题。","permalink":"/product-sense/insight-model","categories":["产品 Sense"],"tags":["产品 Sense","系统洞察力"]},"headers":[],"relativePath":"product-sense/insight-model.md","filePath":"10.产品 Sense/05.方法论/40.洞察力模型.md"}'),i={name:"product-sense/insight-model.md"};function n(e,t,p,l,g,c){return s(),r("div",null,[...t[0]||(t[0]=[o("",48)])])}const m=a(i,[["render",n]]);export{d as __pageData,m as default}; diff --git a/assets/product-sense_overview.md.yd9f580t.js b/assets/product-sense_overview.md.yd9f580t.js new file mode 100644 index 00000000..48b3a587 --- /dev/null +++ b/assets/product-sense_overview.md.yd9f580t.js @@ -0,0 +1 @@ +import{A as t}from"./chunks/ArticleCardList.DLUMmOfr.js";import{g as r,h as s,U as o,z as i,l as n}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const l=[{id:"product-observation",title:"产品观察与拆解分析",icon:"🔍",color:"#6366f1",articles:[{title:"AI-powered 搜索引擎观察分析:Perplexity 与知识工作者",url:"/product-sense/perplexity-knowledge-worker",description:"从产品 Sense 与工程逻辑的双重视角,深入分析 Perplexity 如何重新定义搜索体验."}]},{id:"new-talents",title:"新 T 型人:AI 时代的复合型人才",icon:"🌟",color:"#8b5cf6",articles:[{title:"AI 原生时代的复合型人才,究竟需要怎样的特质?",url:"/product-sense/ai-native-composite-talents/",description:"一篇阅读 Paul Graham 深度长文后的思考,探寻 AI 时代下跨界能力的构建路径。"},{title:'当"实现"不再是壁垒:工程师如何构建 Product Sense?',url:"/product-sense/engineer-build-product-sense",description:"工程师视角下的产品思维构建指南——将抽象的 产品 Sense 解构为三个核心数学公式,并提供一套基于“逆向工程”的刻意练习指南,助力开发者在算力过剩的时代,完成从“代码工匠”到“价值创造者”的认知跃迁。"}]},{id:"product-creation",title:"产品创造与商业化",icon:"💡",color:"#f59e0b",articles:[{title:"放弃增长执念,为什么“小而美”才是可持续之路?",url:"/product-sense/small-rule-learn",description:"本文结合《小而美:持续盈利的经营法则》书中提出的一种不同的商业视角:企业存在的首要目的不是为了融资和扩张,而是为了通过解决问题来获得持续的盈利。从自身的研发视角,把将这本书背后的经营逻辑与产品哲学梳理为几个核心层面的思考"},{title:"好书籍汇总与推荐",url:"/growth/books#_2-产品与商业",description:"系统整理了产品 Sense 与创造、商业化相关的必读书籍清单,便于开发者和产品经理学习和应用产品 Sense 的理论和实践。"}]},{id:"methodology",title:"方法论学习与总结:洞察力与经济学思维",icon:"📊",color:"#10b981",articles:[{title:"洞察力模型:如何看透产品与技术背后的系统逻辑?",url:"/product-sense/insight-model",description:"用通俗易懂的方式,带你拆解一套实用的洞察力模型,让我们学会透过现象抓住本质,建立透过现象看本质的思维框架,从根源上解决问题。"},{title:"用经济学思维做产品",url:"/product-sense/using-economics-thinking",description:"通过拆解日常生活中的经典案例,提炼成本收益、博弈均衡、有限理性、效率改进等核心经济学原理,并系统地将其应用到产品生命周期的核心环节——定义定位、定价策略、体验锁定及生态构建。"}]}],g=JSON.parse('{"title":"学习与实践全景","description":"产品 Sense 学习与实践全景一览,涵盖 AI 产品观察、复合型人才成长、商业化思考及方法论总结等。","frontmatter":{"date":"2026-03-19T23:05:50.000Z","title":"学习与实践全景","description":"产品 Sense 学习与实践全景一览,涵盖 AI 产品观察、复合型人才成长、商业化思考及方法论总结等。","categories":["产品 Sense","AI"],"coverImg":"https://insight-stack-1252300811.cos.ap-shanghai.myqcloud.com/img/cover/product_sense_bg.png","permalink":"/product-sense/overview"},"headers":[],"relativePath":"product-sense/overview.md","filePath":"10.产品 Sense/00.学习与实践全景.md"}'),a={name:"product-sense/overview.md"},m=Object.assign(a,{setup(c){return(d,e)=>(s(),r("div",null,[e[0]||(e[0]=o('

    学习与实践全景

    产品 Sense 的精髓在于用最小投入撬动最大价值,同时精准洞察人性

    • 追求高杠杆——以极简技术解决复杂问题,拒绝为炫技而设计的伪需求;
    • 平衡感性与理性——既共情用户的真实场景与情绪,又冷静追溯痛点本质,让产品既有温度,又不至于沦为功能的堆砌。

    解构这种产品 Sense 的基础在于对投入产出比(ROI)的极致追求与对人性的深度剖析

    • 一方面,卓越的产品嗅觉意味着寻找“高杠杆解”,用最克制的技术复杂度去撬动最广泛且强烈的用户价值,果断规避为了技术而技术的伪需求陷阱。
    • 另一方面,既需要设身处地感知用户的真实使用场景与情绪,又必须保持理性去追问痛点的根源,确保产品既不沦为臃肿的需求许愿池,也不变成缺乏人性温度的冰冷机器。
    about site background

    在产品成功率不足 10% 的残酷市场中,产品 Sense 往往被误认为是某种不可复制的玄妙“直觉”。然而,它本质上是一套可拆解、可训练的思维模式,核心在于:在信息不完整、资源受限的环境下,依然能精准判断“做什么”与“不做什么”,从而确保团队在投入开发前始终是在“做对产品”。

    2.精选专题

    ',7)),i(t,{categories:n(l)},null,8,["categories"])]))}});export{g as __pageData,m as default}; diff --git a/assets/product-sense_overview.md.yd9f580t.lean.js b/assets/product-sense_overview.md.yd9f580t.lean.js new file mode 100644 index 00000000..b34f002e --- /dev/null +++ b/assets/product-sense_overview.md.yd9f580t.lean.js @@ -0,0 +1 @@ +import{A as t}from"./chunks/ArticleCardList.DLUMmOfr.js";import{g as r,h as s,U as o,z as i,l as n}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const l=[{id:"product-observation",title:"产品观察与拆解分析",icon:"🔍",color:"#6366f1",articles:[{title:"AI-powered 搜索引擎观察分析:Perplexity 与知识工作者",url:"/product-sense/perplexity-knowledge-worker",description:"从产品 Sense 与工程逻辑的双重视角,深入分析 Perplexity 如何重新定义搜索体验."}]},{id:"new-talents",title:"新 T 型人:AI 时代的复合型人才",icon:"🌟",color:"#8b5cf6",articles:[{title:"AI 原生时代的复合型人才,究竟需要怎样的特质?",url:"/product-sense/ai-native-composite-talents/",description:"一篇阅读 Paul Graham 深度长文后的思考,探寻 AI 时代下跨界能力的构建路径。"},{title:'当"实现"不再是壁垒:工程师如何构建 Product Sense?',url:"/product-sense/engineer-build-product-sense",description:"工程师视角下的产品思维构建指南——将抽象的 产品 Sense 解构为三个核心数学公式,并提供一套基于“逆向工程”的刻意练习指南,助力开发者在算力过剩的时代,完成从“代码工匠”到“价值创造者”的认知跃迁。"}]},{id:"product-creation",title:"产品创造与商业化",icon:"💡",color:"#f59e0b",articles:[{title:"放弃增长执念,为什么“小而美”才是可持续之路?",url:"/product-sense/small-rule-learn",description:"本文结合《小而美:持续盈利的经营法则》书中提出的一种不同的商业视角:企业存在的首要目的不是为了融资和扩张,而是为了通过解决问题来获得持续的盈利。从自身的研发视角,把将这本书背后的经营逻辑与产品哲学梳理为几个核心层面的思考"},{title:"好书籍汇总与推荐",url:"/growth/books#_2-产品与商业",description:"系统整理了产品 Sense 与创造、商业化相关的必读书籍清单,便于开发者和产品经理学习和应用产品 Sense 的理论和实践。"}]},{id:"methodology",title:"方法论学习与总结:洞察力与经济学思维",icon:"📊",color:"#10b981",articles:[{title:"洞察力模型:如何看透产品与技术背后的系统逻辑?",url:"/product-sense/insight-model",description:"用通俗易懂的方式,带你拆解一套实用的洞察力模型,让我们学会透过现象抓住本质,建立透过现象看本质的思维框架,从根源上解决问题。"},{title:"用经济学思维做产品",url:"/product-sense/using-economics-thinking",description:"通过拆解日常生活中的经典案例,提炼成本收益、博弈均衡、有限理性、效率改进等核心经济学原理,并系统地将其应用到产品生命周期的核心环节——定义定位、定价策略、体验锁定及生态构建。"}]}],g=JSON.parse('{"title":"学习与实践全景","description":"产品 Sense 学习与实践全景一览,涵盖 AI 产品观察、复合型人才成长、商业化思考及方法论总结等。","frontmatter":{"date":"2026-03-19T23:05:50.000Z","title":"学习与实践全景","description":"产品 Sense 学习与实践全景一览,涵盖 AI 产品观察、复合型人才成长、商业化思考及方法论总结等。","categories":["产品 Sense","AI"],"coverImg":"https://insight-stack-1252300811.cos.ap-shanghai.myqcloud.com/img/cover/product_sense_bg.png","permalink":"/product-sense/overview"},"headers":[],"relativePath":"product-sense/overview.md","filePath":"10.产品 Sense/00.学习与实践全景.md"}'),a={name:"product-sense/overview.md"},m=Object.assign(a,{setup(c){return(d,e)=>(s(),r("div",null,[e[0]||(e[0]=o("",7)),i(t,{categories:n(l)},null,8,["categories"])]))}});export{g as __pageData,m as default}; diff --git a/assets/product-sense_perplexity-knowledge-worker.md.VS0_MKCD.js b/assets/product-sense_perplexity-knowledge-worker.md.VS0_MKCD.js new file mode 100644 index 00000000..ef3b3427 --- /dev/null +++ b/assets/product-sense_perplexity-knowledge-worker.md.VS0_MKCD.js @@ -0,0 +1 @@ +import{_ as r,g as t,h as l,U as a}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const _=JSON.parse('{"title":"AI-powered 搜索引擎观察分析:Perplexity 与知识工作者","description":"摘要总结:在大模型重塑互联网交互的当下,Perplexity 并未选择成为“下一个 Google”,而是以“知识发现引擎”的全新定位,精准切入知识工作者的核心工作流。本文跳出单纯的模型能力对比,从产品 Sense 与工程逻辑的双重视角,深度拆解 Perplexity 的破局之道。我们将探讨它如何通过反直觉的 UI 创新重塑交互起点,如何在工程层面死磕尾部延迟与幻觉控制,以及它如何利用巨头的利润率护城河实现错位竞争。最终,我们将视线投向未来,一窥 AI 从被动响应走向主动探索的演进蓝图。","frontmatter":{"date":"2024-05-08T08:56:21.000Z","title":"AI-powered 搜索引擎观察分析:Perplexity 与知识工作者","description":"摘要总结:在大模型重塑互联网交互的当下,Perplexity 并未选择成为“下一个 Google”,而是以“知识发现引擎”的全新定位,精准切入知识工作者的核心工作流。本文跳出单纯的模型能力对比,从产品 Sense 与工程逻辑的双重视角,深度拆解 Perplexity 的破局之道。我们将探讨它如何通过反直觉的 UI 创新重塑交互起点,如何在工程层面死磕尾部延迟与幻觉控制,以及它如何利用巨头的利润率护城河实现错位竞争。最终,我们将视线投向未来,一窥 AI 从被动响应走向主动探索的演进蓝图。","permalink":"/product-sense/perplexity-knowledge-worker","categories":["产品 Sense"],"tags":["AI 搜索","知识发现","产品 Sense"]},"headers":[],"relativePath":"product-sense/perplexity-knowledge-worker.md","filePath":"10.产品 Sense/01.产品观察与分析/11.AI-powered 搜索引擎观察分析:Perplexity 与知识工作者.md"}'),o={name:"product-sense/perplexity-knowledge-worker.md"};function i(n,e,p,s,g,d){return l(),t("div",null,[...e[0]||(e[0]=[a('

    AI-powered 搜索引擎观察分析:Perplexity 与知识工作者

    摘要总结:在大模型重塑互联网交互的当下,Perplexity 并未选择成为“下一个 Google”,而是以“知识发现引擎”的全新定位,精准切入知识工作者的核心工作流。本文跳出单纯的模型能力对比,从产品 Sense 与工程逻辑的双重视角,拆解 Perplexity 的破局之道。我们将探讨它如何通过反直觉的 UI 创新重塑交互起点,如何在工程层面死磕尾部延迟与幻觉控制,以及它如何利用巨头的利润率护城河实现错位竞争。最终,我们将视线投向未来,一窥 AI 从被动响应走向主动探索的演进蓝图。

    1. 引言

    在 AI 浪潮下,搜索引擎的范式正在发生转移。作为当前备受瞩目的 AI 搜索产品,Perplexity 并没有试图成为“下一个 Google”,而是将自己定义为知识发现引擎。

    对于每天需要处理海量信息、进行复杂决策的知识工作者而言,如何高效地“去噪”并获取高信度知识是核心诉求。笔者将从产品交互、技术工程、商业逻辑与未来演进四个维度,分析 Perplexity 是如何重塑信息获取工作流的。

    本文旨在通过对 Perplexity 的深度产品观察与分析,帮助读者理解 AI 搜索产品的设计逻辑与用户体验优化路径,同时为知识工作者提供可落地的效率提升方法,并在过程中培养结构化产品分析思维。

    2. 核心定位:从“链接导航”到“知识发现”

    传统搜索引擎的本质是流量分发与链接导航,而 Perplexity 的第一性原理是直接提供具有事实支撑的答案

    • 学术级的严谨性:Perplexity 借鉴了学术论文的引用机制。它不仅提取相关网页段落,还要求大语言模型(LLM)在生成简明答案时,每一句话都必须带有准确的脚注来源。这种设计降低了知识工作者二次核查信息的成本

    • 非替代关系: Perplexity 与 Google 并非零和博弈。Google 擅长处理具有确定性 UI 需求的查询(如天气、股价、标准导航),而 Perplexity 则专注于解答需要跨信息源整合、总结的复杂问题

    3. 产品交互重构:反直觉的 UI 创新

    Perplexity 在交互设计上做出了几个违背传统搜索常理的决策:

    • 降级链接的视觉权重:在传统搜索中,10 条蓝色链接是绝对的主角。Perplexity 内部曾经历过激烈的争论,最终决定将核心位置让给“生成的答案”,哪怕早期模型偶尔会出现幻觉(Hallucination)。这种反其道而行之的勇气,确立了其作为“问答引擎”的心智

    • 将交互起点后置:传统搜索在用户点击链接后结束,而 Perplexity 认为,用户得到答案后,交互才刚刚开始。通过在底部提供“相关问题(People also ask)”,它充当了用户的思考辅助工具,帮助不擅长提问的用户将模糊的“好奇心”具象化为清晰的 Prompt。

    • 聚焦“魔力指标”: 相比于关注用户的停留时长,Perplexity 的核心指标是让用户感到满意的查询次数快速、准确、易读,是驱动知识工作者留存的唯一动力

    4. 技术护城河:搜索是一项工程与模型的交响

    很多人误以为 AI 搜索只是大模型的“套壳”,但实际上,做好搜索需要深厚的领域 Know-how 和极致的工程优化。

    4.1 驯服幻觉(Hallucination)的四个维度

    Perplexity 坚持比标准 RAG(检索增强生成)更严苛的原则:如果检索到的文档信息不足,系统必须直接拒绝回答,而不是任由模型编造。 减少幻觉需要从以下几个工程节点切入:

    • 检索质量:提升索引的新鲜度和全面性,避免提取过时或冲突的信息。

    • 上下文控制:避免一次性将海量文档全部丢给模型导致“注意力涣散”,精确控制摘录的颗粒度。

    • 模型理解力: 提升模型对深层语义的理解,确保其能从一堆相关度不高的文档中,精准识别出隐藏的正确答案。

    4.2 极致的性能优化:追踪尾部延迟(Tail Latency)

    知识工作者对效率极其敏感。Perplexity 在性能优化上借鉴了 Google 的理念,不仅看平均响应时间,更死磕 P90 和 P99 的尾部延迟。

    • 采用自研的 Sonar 模型(基于 Llama 3 结合 Post-training)。

    • LLM 层:在 LLM 层,核心关注首字生成时间(TTFT)和数据流式传输的吞吐量。

    • 通过与 NVIDIA 合作开发 TensorRT-LLM 框架,甚至深入内核级别编写代码,确保在最差的网络环境下也能实现极低的延迟。

    5. 商业逻辑:你的利润率,就是我的机会

    Google 拥有过去 50 年最伟大的商业模式——广告竞价。这不仅是其利润来源,也成了其在 AI 搜索转型时的历史包袱。对于 Google 而言,为每一个长尾查询生成 AI 答案的算力成本极高,且会破坏现有的高利润广告位。

    Perplexity 巧妙地利用了这一点(正如 Amazon AWS 当年切入低利润率的云市场一样):

    • 放弃传统广告位:基于“答案”的产品形态天然排斥传统的插入式链接广告。

    • 订阅制先行:专注于打造可持续的订阅模式(如 Pro 档服务)。未来可能会借鉴 Netflix 的“订阅+广告”混合模式,在不牺牲答案真实性和用户体验的前提下探索商业化。

    6. 未来演进:从被动响应到主动 Agent

    搜索的终局不仅仅是回答问题,而是知识的生成与自主探索

    • Perplexity Pages:这是其迈向“知识发现引擎”的重要一步。用户的优质提问和搜索会话不仅对自己有价值,将其转化为结构化的文章发布,可以极大降低新知识创造的门槛,构建类似 AI 时代的维基百科。

    • 赋予 AI 好奇心:当前的 AI 仍是被动响应的。未来的想象空间在于,当推理成本进一步降低,AI Agent 可以带着“好奇心”在互联网上自主穿梭。用户只需抛出一个宏大的目标(如“分析某项新技术的 ROI 并生成研报”),AI 就能自行拆解问题、进行多轮搜索验证,最终带着提纯后的知识返回。

    写在最后

    Perplexity 的成功证明了,在巨头林立的赛道中,依然可以通过重新定义产品边界和极致的工程打磨撕开缺口。对于知识工作者而言,它不仅仅是一个搜索工具,更是一个能大幅降低信息噪音、提升信息处理转化率的“外脑”。

    ',29)])])}const c=r(o,[["render",i]]);export{_ as __pageData,c as default}; diff --git "a/assets/10.\344\272\247\345\223\201 Sense_01.\344\272\247\345\223\201\350\247\202\345\257\237\344\270\216\345\210\206\346\236\220_11.AI-powered \346\220\234\347\264\242\345\274\225\346\223\216\350\247\202\345\257\237\345\210\206\346\236\220\357\274\232Perplexity \344\270\216\347\237\245\350\257\206\345\267\245\344\275\234\350\200\205.md.BRTIJ78C.lean.js" b/assets/product-sense_perplexity-knowledge-worker.md.VS0_MKCD.lean.js similarity index 71% rename from "assets/10.\344\272\247\345\223\201 Sense_01.\344\272\247\345\223\201\350\247\202\345\257\237\344\270\216\345\210\206\346\236\220_11.AI-powered \346\220\234\347\264\242\345\274\225\346\223\216\350\247\202\345\257\237\345\210\206\346\236\220\357\274\232Perplexity \344\270\216\347\237\245\350\257\206\345\267\245\344\275\234\350\200\205.md.BRTIJ78C.lean.js" rename to assets/product-sense_perplexity-knowledge-worker.md.VS0_MKCD.lean.js index c74021b1..445ac095 100644 --- "a/assets/10.\344\272\247\345\223\201 Sense_01.\344\272\247\345\223\201\350\247\202\345\257\237\344\270\216\345\210\206\346\236\220_11.AI-powered \346\220\234\347\264\242\345\274\225\346\223\216\350\247\202\345\257\237\345\210\206\346\236\220\357\274\232Perplexity \344\270\216\347\237\245\350\257\206\345\267\245\344\275\234\350\200\205.md.BRTIJ78C.lean.js" +++ b/assets/product-sense_perplexity-knowledge-worker.md.VS0_MKCD.lean.js @@ -1 +1 @@ -import{_ as r,g as t,h as a,U as l}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const _=JSON.parse('{"title":"AI-powered 搜索引擎观察分析:Perplexity 与知识工作者","description":"摘要总结:在大模型重塑互联网交互的当下,Perplexity 并未选择成为“下一个 Google”,而是以“知识发现引擎”的全新定位,精准切入知识工作者的核心工作流。本文跳出单纯的模型能力对比,从产品 Sense 与工程逻辑的双重视角,深度拆解 Perplexity 的破局之道。我们将探讨它如何通过反直觉的 UI 创新重塑交互起点,如何在工程层面死磕尾部延迟与幻觉控制,以及它如何利用巨头的利润率护城河实现错位竞争。最终,我们将视线投向未来,一窥 AI 从被动响应走向主动探索的演进蓝图。","frontmatter":{"date":"2024-05-08T08:56:21.000Z","title":"AI-powered 搜索引擎观察分析:Perplexity 与知识工作者","description":"摘要总结:在大模型重塑互联网交互的当下,Perplexity 并未选择成为“下一个 Google”,而是以“知识发现引擎”的全新定位,精准切入知识工作者的核心工作流。本文跳出单纯的模型能力对比,从产品 Sense 与工程逻辑的双重视角,深度拆解 Perplexity 的破局之道。我们将探讨它如何通过反直觉的 UI 创新重塑交互起点,如何在工程层面死磕尾部延迟与幻觉控制,以及它如何利用巨头的利润率护城河实现错位竞争。最终,我们将视线投向未来,一窥 AI 从被动响应走向主动探索的演进蓝图。","permalink":"/product-sense/perplexity-knowledge-worker","categories":["产品 Sense"],"tags":["AI 搜索","知识发现","产品 Sense"]},"headers":[],"relativePath":"10.产品 Sense/01.产品观察与分析/11.AI-powered 搜索引擎观察分析:Perplexity 与知识工作者.md","filePath":"10.产品 Sense/01.产品观察与分析/11.AI-powered 搜索引擎观察分析:Perplexity 与知识工作者.md"}'),o={name:"10.产品 Sense/01.产品观察与分析/11.AI-powered 搜索引擎观察分析:Perplexity 与知识工作者.md"};function i(n,e,p,s,g,d){return a(),t("div",null,[...e[0]||(e[0]=[l("",30)])])}const P=r(o,[["render",i]]);export{_ as __pageData,P as default}; +import{_ as r,g as t,h as l,U as a}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const _=JSON.parse('{"title":"AI-powered 搜索引擎观察分析:Perplexity 与知识工作者","description":"摘要总结:在大模型重塑互联网交互的当下,Perplexity 并未选择成为“下一个 Google”,而是以“知识发现引擎”的全新定位,精准切入知识工作者的核心工作流。本文跳出单纯的模型能力对比,从产品 Sense 与工程逻辑的双重视角,深度拆解 Perplexity 的破局之道。我们将探讨它如何通过反直觉的 UI 创新重塑交互起点,如何在工程层面死磕尾部延迟与幻觉控制,以及它如何利用巨头的利润率护城河实现错位竞争。最终,我们将视线投向未来,一窥 AI 从被动响应走向主动探索的演进蓝图。","frontmatter":{"date":"2024-05-08T08:56:21.000Z","title":"AI-powered 搜索引擎观察分析:Perplexity 与知识工作者","description":"摘要总结:在大模型重塑互联网交互的当下,Perplexity 并未选择成为“下一个 Google”,而是以“知识发现引擎”的全新定位,精准切入知识工作者的核心工作流。本文跳出单纯的模型能力对比,从产品 Sense 与工程逻辑的双重视角,深度拆解 Perplexity 的破局之道。我们将探讨它如何通过反直觉的 UI 创新重塑交互起点,如何在工程层面死磕尾部延迟与幻觉控制,以及它如何利用巨头的利润率护城河实现错位竞争。最终,我们将视线投向未来,一窥 AI 从被动响应走向主动探索的演进蓝图。","permalink":"/product-sense/perplexity-knowledge-worker","categories":["产品 Sense"],"tags":["AI 搜索","知识发现","产品 Sense"]},"headers":[],"relativePath":"product-sense/perplexity-knowledge-worker.md","filePath":"10.产品 Sense/01.产品观察与分析/11.AI-powered 搜索引擎观察分析:Perplexity 与知识工作者.md"}'),o={name:"product-sense/perplexity-knowledge-worker.md"};function i(n,e,p,s,g,d){return l(),t("div",null,[...e[0]||(e[0]=[a("",29)])])}const c=r(o,[["render",i]]);export{_ as __pageData,c as default}; diff --git a/assets/product-sense_small-rule-learn.md.CojjSdfB.js b/assets/product-sense_small-rule-learn.md.CojjSdfB.js new file mode 100644 index 00000000..c425b44f --- /dev/null +++ b/assets/product-sense_small-rule-learn.md.CojjSdfB.js @@ -0,0 +1 @@ +import{_ as s,g as t,h as n,U as e}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const g=JSON.parse('{"title":"放弃增长执念,为什么“小而美”才是可持续之路","description":"摘要总结:在很长一段时间里,科技互联网行业的叙事都被“不惜一切代价实现超线性增长”所主导。仿佛只有拿到巨额融资、疯狂招人、成为估值破百亿的庞然大物,才算得上是成功的创业。然而,读完萨希尔·拉文吉亚的《小而美:持续盈利的经营法则》后,笔者获得了一种截然不同的商业视角:企业存在的首要目的不是为了融资和扩张,而是为了通过解决问题来获得持续的盈利。 本文结合书中的核心论点与自身的研发视角,把将这本书背后的经营逻辑与产品哲学梳理为几个核心层面的思考。","frontmatter":{"date":"2025-11-24T21:50:00.000Z","title":"放弃增长执念,为什么“小而美”才是可持续之路","description":"摘要总结:在很长一段时间里,科技互联网行业的叙事都被“不惜一切代价实现超线性增长”所主导。仿佛只有拿到巨额融资、疯狂招人、成为估值破百亿的庞然大物,才算得上是成功的创业。然而,读完萨希尔·拉文吉亚的《小而美:持续盈利的经营法则》后,笔者获得了一种截然不同的商业视角:企业存在的首要目的不是为了融资和扩张,而是为了通过解决问题来获得持续的盈利。 本文结合书中的核心论点与自身的研发视角,把将这本书背后的经营逻辑与产品哲学梳理为几个核心层面的思考。","coverImg":"https://insight-stack-1252300811.cos.ap-shanghai.myqcloud.com/img/cover/product_sense_bg.png","permalink":"/product-sense/small-rule-learn","categories":["产品 Sense"],"tags":["产品 Sense","商业化"]},"headers":[],"relativePath":"product-sense/small-rule-learn.md","filePath":"10.产品 Sense/04.产品创造与商业化/30.《小而美:持续盈利的经营法则》读后感.md"}'),r={name:"product-sense/small-rule-learn.md"};function o(p,a,i,l,c,m){return n(),t("div",null,[...a[0]||(a[0]=[e('

    放弃增长执念,为什么“小而美”才是可持续之路

    摘要总结:在很长一段时间里,科技互联网行业的叙事都被“不惜一切代价实现超线性增长”所主导。仿佛只有拿到巨额融资、疯狂招人、成为估值破百亿的庞然大物,才算得上是成功的创业。然而,读完萨希尔·拉文吉亚的《小而美:持续盈利的经营法则》后,笔者获得了一种截然不同的商业视角:企业存在的首要目的不是为了融资和扩张,而是为了通过解决问题来获得持续的盈利。 本文结合书中的核心论点与自身的研发视角,把将这本书背后的经营逻辑与产品哲学梳理为几个核心层面的思考。

    书籍信息

    书名:《小而美:持续盈利的经营法则》

    作者:[美] 萨希尔·拉文吉亚

    核心标签:极简创业|社区本位|持续盈利|创作者经济

    一句话简评:在盲目崇拜规模扩张的商业语境下,这是一份写给独立创作者与开发者的清醒指南,教会我们如何用最少的资源,解决真实的痛点,并获得长久的自由。

    更多书籍推荐信息可参考:产品 Sense 与商业化

    1. 社区先行:从“我是谁”到“我能为谁解决问题”

    传统商业逻辑往往是先构思一个宏大的点子,闭门造车打磨产品,最后再砸钱去市场上寻找目标用户。而本书提出了一个颠覆性的反向路径:社区 \\rightarrow 问题 \\rightarrow 流程 \\rightarrow 产品 \\rightarrow 商业

    极简主义创业者绝不是在真空里写代码的人,他们首先是某个社区的深度参与者和“创作者”。在动手构建任何复杂的软件架构之前,第一步永远是把自己沉浸到特定的人群中。只有当我们花时间去倾听、去贡献价值、甚至通过公开写作和分享去教授他人时,那些真实而具体的高价值痛点才会自然浮现。

    关系网社区参与

    对于致力于通过技术提效的开发者而言,这一逻辑尤为深刻。当我们试图构建智能化的知识管理工具,或是研发将非结构化数据自动化转换为标准代码的基建体系时,切入点不应是盲目堆砌前沿技术栈,而应深挖特定圈层里的真实痛点。当我们成为社区中那个"总能用技术手段帮大家搞定繁琐工作"的可靠支柱时,第一批种子用户会自然诞生。因此,我们要学着先做一个乐于助人的创作者,创业不过是水到渠成之事。

    2. 极简流转:用“克制”对抗“熵增”,用“自动化”替代“堆人力”

    书中另一个贯穿始终的理念是"少即是多"。在找到真实需求后,极简主义创业者不会立刻规划一个包罗万象的大型系统,而是先用最原始、最人工的“流程”去跑通闭环

    需要做的不分

    唯有当用户为这个人工流程付费后,才开始进入“产品化”阶段。此时的核心策略是将重复性的工作外包或交给代码,让机器替代重复,让外包承接繁琐。身处当下的技术变革期,这一点显得尤为契合时宜。借助大语言模型等智能化工具的辅助,我们不仅可以极大地降低开发成本,更能将很多以往需要极高人力成本的环节直接交给自动化程序处理。

    譬如,复杂的数据清洗、异常诊断与迭代优化,可委托给智能代理自主完成;日常的内容分发与用户服务,亦能通过技术手段实现无缝流转。无需奢华的办公场地,不必急于扩充团队规模,“雇佣软件而不是雇佣人力”,这种极度的克制不仅带来了极低的试错成本,更赋予了产品快速迭代、早早交付的敏捷性。

    3. 盈利自信:做时间的朋友,而非资本的奴隶

    书中提出了一个极具穿透力的概念——盈利自信

    当一家企业赚的钱大于花的钱时,它就拥有了无限长的跑道。这就意味着,你不再需要为了迎合资本的审美而扭曲产品的初衷,也不需要在没有想清楚商业模式的时候就去烧钱买流量。这种自信,是坚守长期主义和价值创造的客观根基。

    极简主义创业者瞄准的是前一百个愿意付费的真实客户,而不是成千上万个只索取不贡献的“僵尸粉”。他们把资金花在维护老客户和提升产品体验上,而不是虚无缥缈的广告创意上。当生存不再受制于人,我们就可以按照科学的节奏,安排好日常的专注时间,借助现代化的协同工具进行高效的异步沟通与知识沉淀,让企业的发展速度与个人的生活节奏达成一种健康的平衡。在笔者看来,这其实与全栈工程师们追求的代码高可用性与系统稳定性,在哲学层面是不谋而合的。

    4. 建造你想住的房子:真实的营销与价值观契合

    在营销与团队构建层面,拉文吉亚倡导“做最真实的自己”。营销不是为了制造博人眼球的头条新闻,而是通过“教学、激励、娱乐”三个层次,毫无保留地分享自己踩过的坑与获得的真知灼见,从而吸引气味相投的粉丝。这种公开构建的模式,本身就是一种极具穿透力的品牌资产。

    同样的逻辑也适用于团队。企业是一栋你建造的、且需要自己住进去的房子。比起用虚高的薪水去挖人,不如尽早且频繁地公开自己的价值观和工作流。明确告诉世界:我们追求的是极简、是结果导向、是每个人都要像经营者一样主动思考并承担责任。适合永远是双向的,当你坚守这种透明和真实,自然会吸引到那些愿意通过项目互助协作、追求长期成长的优秀同路人

    5. 总结与反思

    《小而美》不仅仅是一本商业指南,更是一场关于工作与生活方式的哲学探讨。它提醒我们,技术的进步与工具的完善,已经让个体有机会摆脱庞大组织的束缚,以极低的成本去解决一个具体的社会问题

    我们不必成为改变世界的庞然大物,只要能结合自身的优势,找准一个社区,用精湛的手艺和智能化的工具为他们扫除障碍,并在这个过程中保持盈利与内心的从容,这就已经是一次足够伟大的商业实践。小,绝不是格局的局限,而是克制、精准与持续繁荣的起点。

    ',23)])])}const d=s(r,[["render",o]]);export{g as __pageData,d as default}; diff --git "a/assets/10.\344\272\247\345\223\201 Sense_04.\344\272\247\345\223\201\345\210\233\351\200\240\344\270\216\345\225\206\344\270\232\345\214\226_30.\343\200\212\345\260\217\350\200\214\347\276\216\357\274\232\346\214\201\347\273\255\347\233\210\345\210\251\347\232\204\347\273\217\350\220\245\346\263\225\345\210\231\343\200\213\350\257\273\345\220\216\346\204\237.md.gAigzrX9.lean.js" b/assets/product-sense_small-rule-learn.md.CojjSdfB.lean.js similarity index 74% rename from "assets/10.\344\272\247\345\223\201 Sense_04.\344\272\247\345\223\201\345\210\233\351\200\240\344\270\216\345\225\206\344\270\232\345\214\226_30.\343\200\212\345\260\217\350\200\214\347\276\216\357\274\232\346\214\201\347\273\255\347\233\210\345\210\251\347\232\204\347\273\217\350\220\245\346\263\225\345\210\231\343\200\213\350\257\273\345\220\216\346\204\237.md.gAigzrX9.lean.js" rename to assets/product-sense_small-rule-learn.md.CojjSdfB.lean.js index 0d6355ce..f82b71cf 100644 --- "a/assets/10.\344\272\247\345\223\201 Sense_04.\344\272\247\345\223\201\345\210\233\351\200\240\344\270\216\345\225\206\344\270\232\345\214\226_30.\343\200\212\345\260\217\350\200\214\347\276\216\357\274\232\346\214\201\347\273\255\347\233\210\345\210\251\347\232\204\347\273\217\350\220\245\346\263\225\345\210\231\343\200\213\350\257\273\345\220\216\346\204\237.md.gAigzrX9.lean.js" +++ b/assets/product-sense_small-rule-learn.md.CojjSdfB.lean.js @@ -1 +1 @@ -import{_ as s,g as t,h as n,U as e}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const d=JSON.parse('{"title":"放弃增长执念,为什么“小而美”才是可持续之路","description":"摘要总结:在很长一段时间里,科技互联网行业的叙事都被“不惜一切代价实现超线性增长”所主导。仿佛只有拿到巨额融资、疯狂招人、成为估值破百亿的庞然大物,才算得上是成功的创业。然而,读完萨希尔·拉文吉亚的《小而美:持续盈利的经营法则》后,笔者获得了一种截然不同的商业视角:企业存在的首要目的不是为了融资和扩张,而是为了通过解决问题来获得持续的盈利。 本文结合书中的核心论点与自身的研发视角,把将这本书背后的经营逻辑与产品哲学梳理为几个核心层面的思考。","frontmatter":{"date":"2025-11-24T21:50:00.000Z","title":"放弃增长执念,为什么“小而美”才是可持续之路","description":"摘要总结:在很长一段时间里,科技互联网行业的叙事都被“不惜一切代价实现超线性增长”所主导。仿佛只有拿到巨额融资、疯狂招人、成为估值破百亿的庞然大物,才算得上是成功的创业。然而,读完萨希尔·拉文吉亚的《小而美:持续盈利的经营法则》后,笔者获得了一种截然不同的商业视角:企业存在的首要目的不是为了融资和扩张,而是为了通过解决问题来获得持续的盈利。 本文结合书中的核心论点与自身的研发视角,把将这本书背后的经营逻辑与产品哲学梳理为几个核心层面的思考。","coverImg":"https://insight-stack-1252300811.cos.ap-shanghai.myqcloud.com/img/cover/product_sense_bg.png","permalink":"/product-sense/small-rule-learn","categories":["产品 Sense"],"tags":["产品 Sense","商业化"]},"headers":[],"relativePath":"10.产品 Sense/04.产品创造与商业化/30.《小而美:持续盈利的经营法则》读后感.md","filePath":"10.产品 Sense/04.产品创造与商业化/30.《小而美:持续盈利的经营法则》读后感.md"}'),r={name:"10.产品 Sense/04.产品创造与商业化/30.《小而美:持续盈利的经营法则》读后感.md"};function o(i,a,p,l,c,m){return n(),t("div",null,[...a[0]||(a[0]=[e("",24)])])}const g=s(r,[["render",o]]);export{d as __pageData,g as default}; +import{_ as s,g as t,h as n,U as e}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const g=JSON.parse('{"title":"放弃增长执念,为什么“小而美”才是可持续之路","description":"摘要总结:在很长一段时间里,科技互联网行业的叙事都被“不惜一切代价实现超线性增长”所主导。仿佛只有拿到巨额融资、疯狂招人、成为估值破百亿的庞然大物,才算得上是成功的创业。然而,读完萨希尔·拉文吉亚的《小而美:持续盈利的经营法则》后,笔者获得了一种截然不同的商业视角:企业存在的首要目的不是为了融资和扩张,而是为了通过解决问题来获得持续的盈利。 本文结合书中的核心论点与自身的研发视角,把将这本书背后的经营逻辑与产品哲学梳理为几个核心层面的思考。","frontmatter":{"date":"2025-11-24T21:50:00.000Z","title":"放弃增长执念,为什么“小而美”才是可持续之路","description":"摘要总结:在很长一段时间里,科技互联网行业的叙事都被“不惜一切代价实现超线性增长”所主导。仿佛只有拿到巨额融资、疯狂招人、成为估值破百亿的庞然大物,才算得上是成功的创业。然而,读完萨希尔·拉文吉亚的《小而美:持续盈利的经营法则》后,笔者获得了一种截然不同的商业视角:企业存在的首要目的不是为了融资和扩张,而是为了通过解决问题来获得持续的盈利。 本文结合书中的核心论点与自身的研发视角,把将这本书背后的经营逻辑与产品哲学梳理为几个核心层面的思考。","coverImg":"https://insight-stack-1252300811.cos.ap-shanghai.myqcloud.com/img/cover/product_sense_bg.png","permalink":"/product-sense/small-rule-learn","categories":["产品 Sense"],"tags":["产品 Sense","商业化"]},"headers":[],"relativePath":"product-sense/small-rule-learn.md","filePath":"10.产品 Sense/04.产品创造与商业化/30.《小而美:持续盈利的经营法则》读后感.md"}'),r={name:"product-sense/small-rule-learn.md"};function o(p,a,i,l,c,m){return n(),t("div",null,[...a[0]||(a[0]=[e("",23)])])}const d=s(r,[["render",o]]);export{g as __pageData,d as default}; diff --git a/assets/product-sense_using-economics-thinking.md.Do__YKV9.js b/assets/product-sense_using-economics-thinking.md.Do__YKV9.js new file mode 100644 index 00000000..b76ac7ce --- /dev/null +++ b/assets/product-sense_using-economics-thinking.md.Do__YKV9.js @@ -0,0 +1 @@ +import{_ as e,g as n,h as r,U as i}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const d=JSON.parse('{"title":"用经济学思维做产品","description":"将经济学核心原理融合进产品设计全生命周期的方法论体系,构建理性的“产品Sense”。","frontmatter":{"date":"2024-01-01T16:00:00.000Z","title":"用经济学思维做产品","description":"将经济学核心原理融合进产品设计全生命周期的方法论体系,构建理性的“产品Sense”。","categories":["产品 Sense"],"permalink":"/product-sense/using-economics-thinking"},"headers":[],"relativePath":"product-sense/using-economics-thinking.md","filePath":"10.产品 Sense/05.方法论/50.用经济学思维做产品.md"}'),t={name:"product-sense/using-economics-thinking.md"};function s(o,a,l,p,g,h){return r(),n("div",null,[...a[0]||(a[0]=[i('

    用经济学思维做产品

    摘要总结:经济学不仅是分析宏观数据的工具,更是洞察人性、优化资源配置、在约束条件下求最优解的思维方式。本文通过拆解日常生活中的经典案例,提炼成本收益、博弈均衡、有限理性、效率改进等核心经济学原理,并系统地将其应用到产品生命周期的核心环节——定义定位、定价策略、体验锁定及生态构建。最终,我们将这些原理沉淀为一套系统的、具有“经济直觉”的产品方法论,助力产品人完成从单纯的“体验设计师”向具备商业格局的“微观经济学家”跨越。

    在产品管理的广阔天地中,我们往往强调“产品 Sense”(Product Sense)——一种对用户需求、市场风向和技术潜力的直觉性捕捉。然而,这种 Sense 绝非凭空而来的灵光乍现,它需要稳固的理性地基。在众多学科中,经济学无疑提供了最底层的逻辑支柱。

    经济学不仅仅是关于金钱和市场的科学,它更是一种解决问题、优化决策的方式。对产品人而言,借鉴经济学思维,意味着能够理智地权衡利弊,更精准地定价,更深刻地洞察人性,最终在错综复杂的约束条件下,求解出用户价值与商业价值并重的最优解。

    1. 生活里的经济学洞察——洞察不仅是关于需求,更是关于成本与博弈

    我们常被日常现象的“合理性”所迷惑,而经济学能帮我们拨开迷雾,看到冰山之下的成本收益权衡与竞争博弈。

    1.1 容器的形状:方盒与圆瓶背后的成本战术

    为什么牛奶通常装在方盒子里卖,而可乐却多装在圆瓶子里卖?用户提供的素材中,对使用习惯、包装物理属性(利乐纸易塑形,可乐高压圆柱均压)已有深刻见解。但深入思考,最核心的逻辑在于固定成本(Fixed Costs)与运营成本(Operating Costs)的权衡,以及资产特定性(Asset Specificity)

    超市里的软饮料多放在便宜的开放式货架上,运营成本极低。而牛奶需要低温储存,冰柜不仅昂贵(固定成本),且常年运行(运营成本)极高。冰柜里的存储空间不仅是资源,更是稀缺的、昂贵资产。方形容器能最大化冰柜的空间利用率,降低每单位体积的存储成本。可乐不惜牺牲这一优势,选择更趁手的圆瓶,是因为其开放式货架策略将存储成本降到了极低,可以用体验优势(使用习惯)来抵消额外的存储空间成本。

    这一案例启示:产品设计不仅是关乎前端的用户体验(使用习惯),更需要从后端运营链条出发,思考核心稀缺资源的配置效率。在冰柜这个“资产特定”场景下,方盒子就是帕累托改进。

    1.2 可乐的三十年价格迷局:双头垄断下的博弈均衡

    可乐好像一直没有涨价,这几乎成了都市传说。深度拆解,这正是经济学中双头垄断(Duopoly)下,尤其是Bertrand 竞争博弈的经典案例。

    • Bertrand 竞争(Bertrand Competition):假设两家公司生产同质化产品(如可口可乐和百事可乐),如果一家涨价,哪怕只涨一点点,精明的消费者就会全部流向另一家。为了维持市场份额,两家都不敢轻易涨价,最终价格趋向于接近零利润(或仅通过规模效应获得极低利润)的均衡状态。一旦形成博弈均衡,打破它需要巨大的替代成本和风险,例如涨价会被对方借低价抢占市场份额,且借助低利润将潜在进入者挡在门外。

    • 规模效应与锚定效应:可乐是典型的薄利多销产品,利润通过极致的规模化获得。同时,“肥宅快乐水”的高性价比已成为消费者心理中的一个强锚定(Anchoring Effect)。涨价不仅面临博弈风险,还可能瞬间激发消费者的损失厌恶心理,导致流失。

    经济学启示:在竞争激烈的成熟市场(尤其是产品高度同质化时),不仅要看用户价值,更要看博弈对手的行动边界。定价往往是竞争博弈后的动态平衡,而非单方面的价值宣称。此外,锁定效应(Lock-in Effect)不仅能锁定用户,有时也能通过“原汁原味”的营销锁定自身品牌策略。

    1.3 “来都来了”与沉没成本陷阱:有限理性的普遍胜利

    “来都来了,逛遍景点再说”,“来都来了,看完这昏昏欲睡的电影”。这种将错就错的思维模式,是人性的弱点,也是有限理性(Bounded Rationality)的证明。

    理性人假说认为人是绝对自私且理智的,始终寻求以最小代价获得最大收益,不感情用事。但在现实中,人们往往无法客观地从未来的成本收益出发做决策,而是被已经发生在过去的投入——沉没成本(Sunk Costs)——所束缚。

    经济学启示:沉没成本描述的是已经发生且与当前决策无关的费用。正确决策应“往日之不可追,来日之尚可期”,专注于未来的增量成本和收益。但对产品人而言,我们不仅要避免自己掉入沉没成本陷阱,更要深入研究用户的沉没感,将其转化为替代成本(Switching Costs),例如构建用户的网络效应、数据积累和品牌忠诚。

    1.4 帕累托优化与最优体验:在约束条件下求最优解

    租房案例中,兼顾价格便宜和交通便利在“既定状态”下,任何改变都不可能使一人变好而又不使另一人变坏,这便是帕累托最优(Pareto Efficiency)状态。

    在产品设计中,我们不可能无限增加功能(会导致复杂度提升和体验牺牲)、不能无限降低价格(会导致商业不可持续)。优秀的产品设计就是在无数个 Trade-off 之间寻找到帕累托效率点。例如,通过 A/B 测试寻找更优解,就是试图进行帕累托改进——找到一种既不伤害核心用户体验,又能提升商业变现或用户粘性的路径。

    2. 系统化方法论——将经济学思维系统化地应用到产品全生命周期

    2.1 产品定义与定位:深入市场洞察与价值发现

    • 寻找有效需求,利用供求关系发现市场蓝海:不仅要进行用户访谈,更要通过数据分析了解客户的需求、痛点和期望。深入研究市场意味着寻找那些未被满足的有效需求——即不仅有欲望且具备支付能力的(不管是金钱、时间还是隐私数据)需求。只有真正了解市场和客户,才能定位产品的核心功能和价值。

    • 确定竞争壁垒,利用比较优势寻找产品核心竞争优势:分析竞争对手的产品、策略、市场份额,是为了找出自己的优势和不足。不仅能制定竞争策略,还能避免不必要的失误。我们应该追求做“只有你能做”或者“你做得最好”的事情,这就是产品的比较优势(Comparative Advantage)。

    2.2 产品定价策略:最大化收益与捕获用户剩余

    用户提供的定价点集中在价格歧视,我们将其深化和系统化,引入更多心理经济学。

    • 基于价值的定价 (Value-Based Pricing):不仅是根据供求,更是寻找价值创造的核心环节,制定有效的价格策略。在方寸之间,见天地,在细微之处,察人性。

    • 价格歧视 (Price Discrimination):促使用户转化和付费。

      • 二级价格歧视(版本化定价):通过推出免费版 vs 专业版、标准会员 vs VIP 会员,根据用户的自我选择(Willingness to Pay)来划分群体。

      • 三级价格歧视(群体化定价):对特定群体提供优惠,如学生优惠、特定地区优惠。

    • 价格心理学应用

      • 锚定效应 (Anchoring Effect):设置一个高价锚点(例如高额的年费),让中间价(例如月费)看起来更具性价比。

      • 诱饵效应 (Decoy Effect):提供一个不如意但价格相近的选项,让真正想卖的选项脱颖而出。

    2.3 产品用户体验与留存:构建锁定效应与对抗边际效用递减

    • 利用沉没成本,利用沉没成本,利用替代成本构建锁定效应 (Lock-in Effect):通过引导用户在产品中积累数据(云盘)、网络关系(社交网络)、品牌忠诚(生态系统),将用户的沉没投入转化为极高的替代成本,从而吸引用户持续使用。

    • 利用边际效用递减,对抗边际效用递减增加用户活跃度。深度拆解发现:可以通过寻找帕累托改进空间,例如精细化精算法投放广告。更积极地,可以通过寻找非同质化体验、引入多阶梯奖励系统、持续迭代新功能来刺激用户,对抗边际效用递减(Diminishing Marginal Utility)带来的活跃度下降。

    2.4 产品商业化与生态构建:追求帕累托改进与管理外部性

    • 商业化路径优化:追求帕累托改进与外部性管理:通过不断学习和实践,我们需要保持敏锐。深入研究广告、会员等商业化模式。理想的商业化优化是在不降低核心用户体验的前提下,增加新的价值或收入流(帕累托改进)。

    • 外部性管理:平台型产品(如广告平台)具有强交叉外部性(Externalities)。需要平衡广告商的外部收益(对用户的负外部性)与用户的外部收益(对广告商的正外部性)。推荐多阅读读物,深入了解外部性管理策略。

    3. 总结:方法论提炼与职业修养——培养“经济直觉”

    经济学思维做产品,不是让你成为数学家,而是让你成为一名具备“经济直觉”的产品人。

    • 深入研究市场与竞争对手:这是获取准确决策信息的前提。

    • 持续创新与改进:市场是不断变化的,技术方法在不断更新,保持敏感度,核心目标不仅是体验更好,更是商业模型更健康。

    • 培养经济直觉(Sense):需要理论学习和大量实践。观察生活、拆解产品(例如:为什么某些软件只允许你用一个设备,而有些允许三个?这也是一种资产特定性权衡),从微观和宏观角度预判趋势,做出准确决策。推荐一些不错读物。

    • 关注外部环境与政策法规:宏观经济日新月异,政策、法规、行业环境(例如:数据隐私法规对精细化广告的影响)时刻影响着产品的发展边界。推荐多读读物,及时了解相关变化。

    • 不断学习和实践:在不断实践中,只有学习和总结,才能保持竞争力。经济学思维能让我们更理智地分配资源、更精准地定价、更深刻地洞察人性,最终打造出既符合用户价值又具有商业可持续性的产品。

    经济环境瞬息万变,技术方法迭代日新月异,但理性的微观经济学原理,始终是一盏指引方向的不灭灯塔。让我们从单纯的“体验设计师”向具备商业格局和深邃人性的“微观经济学家”跨越。

    ',35)])])}const _=e(t,[["render",s]]);export{d as __pageData,_ as default}; diff --git a/assets/product-sense_using-economics-thinking.md.Do__YKV9.lean.js b/assets/product-sense_using-economics-thinking.md.Do__YKV9.lean.js new file mode 100644 index 00000000..a43650cd --- /dev/null +++ b/assets/product-sense_using-economics-thinking.md.Do__YKV9.lean.js @@ -0,0 +1 @@ +import{_ as e,g as n,h as r,U as i}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const d=JSON.parse('{"title":"用经济学思维做产品","description":"将经济学核心原理融合进产品设计全生命周期的方法论体系,构建理性的“产品Sense”。","frontmatter":{"date":"2024-01-01T16:00:00.000Z","title":"用经济学思维做产品","description":"将经济学核心原理融合进产品设计全生命周期的方法论体系,构建理性的“产品Sense”。","categories":["产品 Sense"],"permalink":"/product-sense/using-economics-thinking"},"headers":[],"relativePath":"product-sense/using-economics-thinking.md","filePath":"10.产品 Sense/05.方法论/50.用经济学思维做产品.md"}'),t={name:"product-sense/using-economics-thinking.md"};function s(o,a,l,p,g,h){return r(),n("div",null,[...a[0]||(a[0]=[i("",35)])])}const _=e(t,[["render",s]]);export{d as __pageData,_ as default}; diff --git "a/assets/31.\345\274\200\346\272\220\346\264\236\345\257\237_01.fetch-event-source \346\272\220\347\240\201\350\247\243\350\257\273.md.BP_UYyAh.js" b/assets/repo-insight_fetch-event-source.md.TsCwUya2.js similarity index 95% rename from "assets/31.\345\274\200\346\272\220\346\264\236\345\257\237_01.fetch-event-source \346\272\220\347\240\201\350\247\243\350\257\273.md.BP_UYyAh.js" rename to assets/repo-insight_fetch-event-source.md.TsCwUya2.js index 6a6ffee8..1fb66468 100644 --- "a/assets/31.\345\274\200\346\272\220\346\264\236\345\257\237_01.fetch-event-source \346\272\220\347\240\201\350\247\243\350\257\273.md.BP_UYyAh.js" +++ b/assets/repo-insight_fetch-event-source.md.TsCwUya2.js @@ -1,4 +1,4 @@ -import{_ as a,g as n,h as i,U as p}from"./chunks/vitepress-theme-teek.CqY1sKvl.js";const E=JSON.parse('{"title":"fetch-event-source 源码解读","description":"","frontmatter":{"date":"2026-04-10T14:43:09.000Z","title":"fetch-event-source 源码解读","categories":["开源洞察"],"permalink":"/repo-insight/fetch-event-source"},"headers":[],"relativePath":"31.开源洞察/01.fetch-event-source 源码解读.md","filePath":"31.开源洞察/01.fetch-event-source 源码解读.md"}'),l={name:"31.开源洞察/01.fetch-event-source 源码解读.md"};function e(t,s,h,r,k,d){return i(),n("div",null,[...s[0]||(s[0]=[p(`

    fetch-event-source 源码解读

    第一部分: 业务价值篇

    项目定位

    @microsoft/fetch-event-source 是微软开源的一个基于 Fetch API 的 Server-Sent Events (SSE) 客户端库,为浏览器提供了更强大、更灵活的服务器推送事件接收能力。

    解决的核心痛点

    原生浏览器的 EventSource API 存在以下限制:

    限制说明
    仅支持 GET 请求无法使用 POST、PUT 等其他 HTTP 方法
    无法自定义请求头无法传递认证令牌、内容类型等自定义头部
    无法发送请求体所有参数必须编码在 URL 中,受限于浏览器 URL 长度限制(通常 2000 字符)
    重试策略不可控连接断开时浏览器自动重试但无法自定义重试逻辑
    错误处理能力有限无法优雅处理 API 网关返回的错误响应

    技术亮点

    技术亮点说明
    基于 Fetch API充分利用 Fetch API 的所有特性(自定义方法、头部、请求体等)
    完全兼容 SSE 格式与标准 Event Stream 格式 100% 兼容
    灵活的重试策略完全掌控连接断开时的重试逻辑
    页面可见性集成自动在页面隐藏时断开连接、显示时重连,减少服务器负载
    可替换的 fetch 实现支持注入自定义 fetch 函数
    TypeScript 原生支持完整的类型定义

    适用场景

    场景说明
    实时数据推送股票行情、实时新闻、即时消息
    进度更新长时间运行任务的进度追踪
    日志流实时日志查看和监控
    协作应用多人协作时的实时状态同步
    AI 应用大语言模型的流式响应输出

    典型使用 Case

    Case 1: 基础 SSE 连接

    typescript
    import { fetchEventSource } from '@microsoft/fetch-event-source';
    +import{_ as a,g as n,h as i,U as p}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const E=JSON.parse('{"title":"fetch-event-source 源码解读","description":"","frontmatter":{"date":"2026-04-10T14:43:09.000Z","title":"fetch-event-source 源码解读","categories":["开源洞察"],"permalink":"/repo-insight/fetch-event-source"},"headers":[],"relativePath":"repo-insight/fetch-event-source.md","filePath":"31.开源洞察/01.fetch-event-source 源码解读.md"}'),l={name:"repo-insight/fetch-event-source.md"};function e(h,s,t,r,k,d){return i(),n("div",null,[...s[0]||(s[0]=[p(`

    fetch-event-source 源码解读

    第一部分: 业务价值篇

    项目定位

    @microsoft/fetch-event-source 是微软开源的一个基于 Fetch API 的 Server-Sent Events (SSE) 客户端库,为浏览器提供了更强大、更灵活的服务器推送事件接收能力。

    解决的核心痛点

    原生浏览器的 EventSource API 存在以下限制:

    限制说明
    仅支持 GET 请求无法使用 POST、PUT 等其他 HTTP 方法
    无法自定义请求头无法传递认证令牌、内容类型等自定义头部
    无法发送请求体所有参数必须编码在 URL 中,受限于浏览器 URL 长度限制(通常 2000 字符)
    重试策略不可控连接断开时浏览器自动重试但无法自定义重试逻辑
    错误处理能力有限无法优雅处理 API 网关返回的错误响应

    技术亮点

    技术亮点说明
    基于 Fetch API充分利用 Fetch API 的所有特性(自定义方法、头部、请求体等)
    完全兼容 SSE 格式与标准 Event Stream 格式 100% 兼容
    灵活的重试策略完全掌控连接断开时的重试逻辑
    页面可见性集成自动在页面隐藏时断开连接、显示时重连,减少服务器负载
    可替换的 fetch 实现支持注入自定义 fetch 函数
    TypeScript 原生支持完整的类型定义

    适用场景

    场景说明
    实时数据推送股票行情、实时新闻、即时消息
    进度更新长时间运行任务的进度追踪
    日志流实时日志查看和监控
    协作应用多人协作时的实时状态同步
    AI 应用大语言模型的流式响应输出

    典型使用 Case

    Case 1: 基础 SSE 连接

    typescript
    import { fetchEventSource } from '@microsoft/fetch-event-source';
     
     await fetchEventSource('/api/sse', {
         onmessage(ev) {
    @@ -424,4 +424,4 @@ import{_ as a,g as n,h as i,U as p}from"./chunks/vitepress-theme-teek.CqY1sKvl.j
         onId: (id: string) => void,
         onRetry: (retry: number) => void,
         onMessage?: (msg: EventSourceMessage) => void
    -): (line: Uint8Array, fieldLength: number) => void;
    `,74)])])}const g=a(l,[["render",e]]);export{E as __pageData,g as default}; +): (line: Uint8Array, fieldLength: number) => void;
    `,73)])])}const g=a(l,[["render",e]]);export{E as __pageData,g as default}; diff --git a/assets/repo-insight_fetch-event-source.md.TsCwUya2.lean.js b/assets/repo-insight_fetch-event-source.md.TsCwUya2.lean.js new file mode 100644 index 00000000..8c29bc83 --- /dev/null +++ b/assets/repo-insight_fetch-event-source.md.TsCwUya2.lean.js @@ -0,0 +1 @@ +import{_ as a,g as n,h as i,U as p}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const E=JSON.parse('{"title":"fetch-event-source 源码解读","description":"","frontmatter":{"date":"2026-04-10T14:43:09.000Z","title":"fetch-event-source 源码解读","categories":["开源洞察"],"permalink":"/repo-insight/fetch-event-source"},"headers":[],"relativePath":"repo-insight/fetch-event-source.md","filePath":"31.开源洞察/01.fetch-event-source 源码解读.md"}'),l={name:"repo-insight/fetch-event-source.md"};function e(h,s,t,r,k,d){return i(),n("div",null,[...s[0]||(s[0]=[p("",73)])])}const g=a(l,[["render",e]]);export{E as __pageData,g as default}; diff --git a/assets/repo-insight_overview.md.BlcYlci7.js b/assets/repo-insight_overview.md.BlcYlci7.js new file mode 100644 index 00000000..e5b03090 --- /dev/null +++ b/assets/repo-insight_overview.md.BlcYlci7.js @@ -0,0 +1 @@ +import{_ as e,g as r,h as i,U as a}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const d=JSON.parse('{"title":"开源洞察","description":"","frontmatter":{"date":"2026-04-10T14:52:34.000Z","title":"开源洞察","permalink":"/repo-insight/overview","categories":["开源洞察"]},"headers":[],"relativePath":"repo-insight/overview.md","filePath":"31.开源洞察/00.overview.md"}'),o={name:"repo-insight/overview.md"};function n(s,t,l,h,g,p){return i(),r("div",null,[...t[0]||(t[0]=[a('

    开源洞察

    说明:

    本专栏所有源码解读文章,均借助了本人开源的 repo-insight Agent Skill 来辅助生成。

    repo-insight 是一款专注于优秀开源项目代码库解读的智能助手,提供 GitHub URL 或本地目录的一键深度分析能力。

    • 一键分析 - 支持 GitHub URL 或本地目录分析
    • 深度报告 - 生成项目概述、架构分析、核心模块解读
    • 中文支持 - 自动翻译 README、生成中文代码注释
    • 全自动执行 - 调用后无需中间交互

    两个 Skill 均具备以上能力,可根据需求选择使用。

    开源项目解读

    项目简介
    fetch-event-source微软开源的基于 Fetch API 的 SSE 客户端库,用于简化与服务器的实时通信。
    解读全文 →
    ',4)])])}const _=e(o,[["render",n]]);export{d as __pageData,_ as default}; diff --git a/assets/repo-insight_overview.md.BlcYlci7.lean.js b/assets/repo-insight_overview.md.BlcYlci7.lean.js new file mode 100644 index 00000000..053f8263 --- /dev/null +++ b/assets/repo-insight_overview.md.BlcYlci7.lean.js @@ -0,0 +1 @@ +import{_ as e,g as r,h as i,U as a}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const d=JSON.parse('{"title":"开源洞察","description":"","frontmatter":{"date":"2026-04-10T14:52:34.000Z","title":"开源洞察","permalink":"/repo-insight/overview","categories":["开源洞察"]},"headers":[],"relativePath":"repo-insight/overview.md","filePath":"31.开源洞察/00.overview.md"}'),o={name:"repo-insight/overview.md"};function n(s,t,l,h,g,p){return i(),r("div",null,[...t[0]||(t[0]=[a("",4)])])}const _=e(o,[["render",n]]);export{d as __pageData,_ as default}; diff --git a/assets/style.B2TtbaQT.css b/assets/style.B7G9DThe.css similarity index 92% rename from assets/style.B2TtbaQT.css rename to assets/style.B7G9DThe.css index de541b70..d92b7ced 100644 --- a/assets/style.B2TtbaQT.css +++ b/assets/style.B7G9DThe.css @@ -1 +1 @@ -@charset "UTF-8";@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/assets/inter-roman-cyrillic-ext.BBPuwvHQ.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/assets/inter-roman-cyrillic.C5lxZ8CY.woff2) format("woff2");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/assets/inter-roman-greek-ext.CqjqNYQ-.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/assets/inter-roman-greek.BBVDIX6e.woff2) format("woff2");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/assets/inter-roman-vietnamese.BjW4sHH5.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/assets/inter-roman-latin-ext.4ZJIpNVo.woff2) format("woff2");unicode-range:U+0100-02AF,U+0304,U+0308,U+0329,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/assets/inter-roman-latin.Di8DUHzh.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/assets/inter-italic-cyrillic-ext.r48I6akx.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/assets/inter-italic-cyrillic.By2_1cv3.woff2) format("woff2");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/assets/inter-italic-greek-ext.1u6EdAuj.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/assets/inter-italic-greek.DJ8dCoTZ.woff2) format("woff2");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/assets/inter-italic-vietnamese.BSbpV94h.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/assets/inter-italic-latin-ext.CN1xVJS-.woff2) format("woff2");unicode-range:U+0100-02AF,U+0304,U+0308,U+0329,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/assets/inter-italic-latin.C2AdPX0b.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Punctuation SC;font-weight:400;src:local("PingFang SC Regular"),local("Noto Sans CJK SC"),local("Microsoft YaHei");unicode-range:U+201C,U+201D,U+2018,U+2019,U+2E3A,U+2014,U+2013,U+2026,U+00B7,U+007E,U+002F}@font-face{font-family:Punctuation SC;font-weight:500;src:local("PingFang SC Medium"),local("Noto Sans CJK SC"),local("Microsoft YaHei");unicode-range:U+201C,U+201D,U+2018,U+2019,U+2E3A,U+2014,U+2013,U+2026,U+00B7,U+007E,U+002F}@font-face{font-family:Punctuation SC;font-weight:600;src:local("PingFang SC Semibold"),local("Noto Sans CJK SC Bold"),local("Microsoft YaHei Bold");unicode-range:U+201C,U+201D,U+2018,U+2019,U+2E3A,U+2014,U+2013,U+2026,U+00B7,U+007E,U+002F}@font-face{font-family:Punctuation SC;font-weight:700;src:local("PingFang SC Semibold"),local("Noto Sans CJK SC Bold"),local("Microsoft YaHei Bold");unicode-range:U+201C,U+201D,U+2018,U+2019,U+2E3A,U+2014,U+2013,U+2026,U+00B7,U+007E,U+002F}:root{--vp-c-white: #ffffff;--vp-c-black: #000000;--vp-c-neutral: var(--vp-c-black);--vp-c-neutral-inverse: var(--vp-c-white)}.dark{--vp-c-neutral: var(--vp-c-white);--vp-c-neutral-inverse: var(--vp-c-black)}:root{--vp-c-gray-1: #dddde3;--vp-c-gray-2: #e4e4e9;--vp-c-gray-3: #ebebef;--vp-c-gray-soft: rgba(142, 150, 170, .14);--vp-c-indigo-1: #3451b2;--vp-c-indigo-2: #3a5ccc;--vp-c-indigo-3: #5672cd;--vp-c-indigo-soft: rgba(100, 108, 255, .14);--vp-c-purple-1: #6f42c1;--vp-c-purple-2: #7e4cc9;--vp-c-purple-3: #8e5cd9;--vp-c-purple-soft: rgba(159, 122, 234, .14);--vp-c-green-1: #18794e;--vp-c-green-2: #299764;--vp-c-green-3: #30a46c;--vp-c-green-soft: rgba(16, 185, 129, .14);--vp-c-yellow-1: #915930;--vp-c-yellow-2: #946300;--vp-c-yellow-3: #9f6a00;--vp-c-yellow-soft: rgba(234, 179, 8, .14);--vp-c-red-1: #b8272c;--vp-c-red-2: #d5393e;--vp-c-red-3: #e0575b;--vp-c-red-soft: rgba(244, 63, 94, .14);--vp-c-sponsor: #db2777}.dark{--vp-c-gray-1: #515c67;--vp-c-gray-2: #414853;--vp-c-gray-3: #32363f;--vp-c-gray-soft: rgba(101, 117, 133, .16);--vp-c-indigo-1: #a8b1ff;--vp-c-indigo-2: #5c73e7;--vp-c-indigo-3: #3e63dd;--vp-c-indigo-soft: rgba(100, 108, 255, .16);--vp-c-purple-1: #c8abfa;--vp-c-purple-2: #a879e6;--vp-c-purple-3: #8e5cd9;--vp-c-purple-soft: rgba(159, 122, 234, .16);--vp-c-green-1: #3dd68c;--vp-c-green-2: #30a46c;--vp-c-green-3: #298459;--vp-c-green-soft: rgba(16, 185, 129, .16);--vp-c-yellow-1: #f9b44e;--vp-c-yellow-2: #da8b17;--vp-c-yellow-3: #a46a0a;--vp-c-yellow-soft: rgba(234, 179, 8, .16);--vp-c-red-1: #f66f81;--vp-c-red-2: #f14158;--vp-c-red-3: #b62a3c;--vp-c-red-soft: rgba(244, 63, 94, .16)}:root{--vp-c-bg: #ffffff;--vp-c-bg-alt: #f6f6f7;--vp-c-bg-elv: #ffffff;--vp-c-bg-soft: #f6f6f7}.dark{--vp-c-bg: #1b1b1f;--vp-c-bg-alt: #161618;--vp-c-bg-elv: #202127;--vp-c-bg-soft: #202127}:root{--vp-c-border: #c2c2c4;--vp-c-divider: #e2e2e3;--vp-c-gutter: #e2e2e3}.dark{--vp-c-border: #3c3f44;--vp-c-divider: #2e2e32;--vp-c-gutter: #000000}:root{--vp-c-text-1: #3c3c43;--vp-c-text-2: #67676c;--vp-c-text-3: #929295}.dark{--vp-c-text-1: #dfdfd6;--vp-c-text-2: #98989f;--vp-c-text-3: #6a6a71}:root{--vp-c-default-1: var(--vp-c-gray-1);--vp-c-default-2: var(--vp-c-gray-2);--vp-c-default-3: var(--vp-c-gray-3);--vp-c-default-soft: var(--vp-c-gray-soft);--vp-c-brand-1: var(--vp-c-indigo-1);--vp-c-brand-2: var(--vp-c-indigo-2);--vp-c-brand-3: var(--vp-c-indigo-3);--vp-c-brand-soft: var(--vp-c-indigo-soft);--vp-c-brand: var(--vp-c-brand-1);--vp-c-tip-1: var(--vp-c-brand-1);--vp-c-tip-2: var(--vp-c-brand-2);--vp-c-tip-3: var(--vp-c-brand-3);--vp-c-tip-soft: var(--vp-c-brand-soft);--vp-c-note-1: var(--vp-c-brand-1);--vp-c-note-2: var(--vp-c-brand-2);--vp-c-note-3: var(--vp-c-brand-3);--vp-c-note-soft: var(--vp-c-brand-soft);--vp-c-success-1: var(--vp-c-green-1);--vp-c-success-2: var(--vp-c-green-2);--vp-c-success-3: var(--vp-c-green-3);--vp-c-success-soft: var(--vp-c-green-soft);--vp-c-important-1: var(--vp-c-purple-1);--vp-c-important-2: var(--vp-c-purple-2);--vp-c-important-3: var(--vp-c-purple-3);--vp-c-important-soft: var(--vp-c-purple-soft);--vp-c-warning-1: var(--vp-c-yellow-1);--vp-c-warning-2: var(--vp-c-yellow-2);--vp-c-warning-3: var(--vp-c-yellow-3);--vp-c-warning-soft: var(--vp-c-yellow-soft);--vp-c-danger-1: var(--vp-c-red-1);--vp-c-danger-2: var(--vp-c-red-2);--vp-c-danger-3: var(--vp-c-red-3);--vp-c-danger-soft: var(--vp-c-red-soft);--vp-c-caution-1: var(--vp-c-red-1);--vp-c-caution-2: var(--vp-c-red-2);--vp-c-caution-3: var(--vp-c-red-3);--vp-c-caution-soft: var(--vp-c-red-soft)}:root{--vp-font-family-base: "Inter", ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--vp-font-family-mono: ui-monospace, "Menlo", "Monaco", "Consolas", "Liberation Mono", "Courier New", monospace;font-optical-sizing:auto}:root:where(:lang(zh)){--vp-font-family-base: "Punctuation SC", "Inter", ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"}:root{--vp-shadow-1: 0 1px 2px rgba(0, 0, 0, .04), 0 1px 2px rgba(0, 0, 0, .06);--vp-shadow-2: 0 3px 12px rgba(0, 0, 0, .07), 0 1px 4px rgba(0, 0, 0, .07);--vp-shadow-3: 0 12px 32px rgba(0, 0, 0, .1), 0 2px 6px rgba(0, 0, 0, .08);--vp-shadow-4: 0 14px 44px rgba(0, 0, 0, .12), 0 3px 9px rgba(0, 0, 0, .12);--vp-shadow-5: 0 18px 56px rgba(0, 0, 0, .16), 0 4px 12px rgba(0, 0, 0, .16)}:root{--vp-z-index-footer: 10;--vp-z-index-local-nav: 20;--vp-z-index-nav: 30;--vp-z-index-layout-top: 40;--vp-z-index-backdrop: 50;--vp-z-index-sidebar: 60}@media(min-width:960px){:root{--vp-z-index-sidebar: 25}}:root{--vp-layout-max-width: 1440px}:root{--vp-header-anchor-symbol: "#"}:root{--vp-code-line-height: 1.7;--vp-code-font-size: .875em;--vp-code-color: var(--vp-c-brand-1);--vp-code-link-color: var(--vp-c-brand-1);--vp-code-link-hover-color: var(--vp-c-brand-2);--vp-code-bg: var(--vp-c-default-soft);--vp-code-block-color: var(--vp-c-text-2);--vp-code-block-bg: var(--vp-c-bg-alt);--vp-code-block-divider-color: var(--vp-c-gutter);--vp-code-lang-color: var(--vp-c-text-2);--vp-code-line-highlight-color: var(--vp-c-default-soft);--vp-code-line-number-color: var(--vp-c-text-2);--vp-code-line-diff-add-color: var(--vp-c-success-soft);--vp-code-line-diff-add-symbol-color: var(--vp-c-success-1);--vp-code-line-diff-remove-color: var(--vp-c-danger-soft);--vp-code-line-diff-remove-symbol-color: var(--vp-c-danger-1);--vp-code-line-warning-color: var(--vp-c-warning-soft);--vp-code-line-error-color: var(--vp-c-danger-soft);--vp-code-copy-code-border-color: var(--vp-c-divider);--vp-code-copy-code-bg: var(--vp-c-bg-soft);--vp-code-copy-code-hover-border-color: var(--vp-c-divider);--vp-code-copy-code-hover-bg: var(--vp-c-bg);--vp-code-copy-code-active-text: var(--vp-c-text-2);--vp-code-copy-copied-text-content: "Copied";--vp-code-tab-divider: var(--vp-code-block-divider-color);--vp-code-tab-text-color: var(--vp-c-text-2);--vp-code-tab-bg: var(--vp-code-block-bg);--vp-code-tab-hover-text-color: var(--vp-c-text-1);--vp-code-tab-active-text-color: var(--vp-c-text-1);--vp-code-tab-active-bar-color: var(--vp-c-brand-1)}:lang(es),:lang(pt){--vp-code-copy-copied-text-content: "Copiado"}:lang(fa){--vp-code-copy-copied-text-content: "کپی شد"}:lang(ko){--vp-code-copy-copied-text-content: "복사됨"}:lang(ru){--vp-code-copy-copied-text-content: "Скопировано"}:lang(zh){--vp-code-copy-copied-text-content: "已复制"}:root{--vp-button-brand-border: transparent;--vp-button-brand-text: var(--vp-c-white);--vp-button-brand-bg: var(--vp-c-brand-3);--vp-button-brand-hover-border: transparent;--vp-button-brand-hover-text: var(--vp-c-white);--vp-button-brand-hover-bg: var(--vp-c-brand-2);--vp-button-brand-active-border: transparent;--vp-button-brand-active-text: var(--vp-c-white);--vp-button-brand-active-bg: var(--vp-c-brand-1);--vp-button-alt-border: transparent;--vp-button-alt-text: var(--vp-c-text-1);--vp-button-alt-bg: var(--vp-c-default-3);--vp-button-alt-hover-border: transparent;--vp-button-alt-hover-text: var(--vp-c-text-1);--vp-button-alt-hover-bg: var(--vp-c-default-2);--vp-button-alt-active-border: transparent;--vp-button-alt-active-text: var(--vp-c-text-1);--vp-button-alt-active-bg: var(--vp-c-default-1);--vp-button-sponsor-border: var(--vp-c-text-2);--vp-button-sponsor-text: var(--vp-c-text-2);--vp-button-sponsor-bg: transparent;--vp-button-sponsor-hover-border: var(--vp-c-sponsor);--vp-button-sponsor-hover-text: var(--vp-c-sponsor);--vp-button-sponsor-hover-bg: transparent;--vp-button-sponsor-active-border: var(--vp-c-sponsor);--vp-button-sponsor-active-text: var(--vp-c-sponsor);--vp-button-sponsor-active-bg: transparent}:root{--vp-custom-block-font-size: 14px;--vp-custom-block-code-font-size: 13px;--vp-custom-block-info-border: transparent;--vp-custom-block-info-text: var(--vp-c-text-1);--vp-custom-block-info-bg: var(--vp-c-default-soft);--vp-custom-block-info-code-bg: var(--vp-c-default-soft);--vp-custom-block-note-border: transparent;--vp-custom-block-note-text: var(--vp-c-text-1);--vp-custom-block-note-bg: var(--vp-c-default-soft);--vp-custom-block-note-code-bg: var(--vp-c-default-soft);--vp-custom-block-tip-border: transparent;--vp-custom-block-tip-text: var(--vp-c-text-1);--vp-custom-block-tip-bg: var(--vp-c-tip-soft);--vp-custom-block-tip-code-bg: var(--vp-c-tip-soft);--vp-custom-block-important-border: transparent;--vp-custom-block-important-text: var(--vp-c-text-1);--vp-custom-block-important-bg: var(--vp-c-important-soft);--vp-custom-block-important-code-bg: var(--vp-c-important-soft);--vp-custom-block-warning-border: transparent;--vp-custom-block-warning-text: var(--vp-c-text-1);--vp-custom-block-warning-bg: var(--vp-c-warning-soft);--vp-custom-block-warning-code-bg: var(--vp-c-warning-soft);--vp-custom-block-danger-border: transparent;--vp-custom-block-danger-text: var(--vp-c-text-1);--vp-custom-block-danger-bg: var(--vp-c-danger-soft);--vp-custom-block-danger-code-bg: var(--vp-c-danger-soft);--vp-custom-block-caution-border: transparent;--vp-custom-block-caution-text: var(--vp-c-text-1);--vp-custom-block-caution-bg: var(--vp-c-caution-soft);--vp-custom-block-caution-code-bg: var(--vp-c-caution-soft);--vp-custom-block-details-border: var(--vp-custom-block-info-border);--vp-custom-block-details-text: var(--vp-custom-block-info-text);--vp-custom-block-details-bg: var(--vp-custom-block-info-bg);--vp-custom-block-details-code-bg: var(--vp-custom-block-info-code-bg)}:root{--vp-input-border-color: var(--vp-c-border);--vp-input-bg-color: var(--vp-c-bg-alt);--vp-input-switch-bg-color: var(--vp-c-default-soft)}:root{--vp-nav-height: 64px;--vp-nav-bg-color: var(--vp-c-bg);--vp-nav-screen-bg-color: var(--vp-c-bg);--vp-nav-logo-height: 24px}.hide-nav{--vp-nav-height: 0px}.hide-nav .VPSidebar{--vp-nav-height: 22px}:root{--vp-local-nav-bg-color: var(--vp-c-bg)}:root{--vp-sidebar-width: 272px;--vp-sidebar-bg-color: var(--vp-c-bg-alt)}:root{--vp-backdrop-bg-color: rgba(0, 0, 0, .6)}:root{--vp-home-hero-name-color: var(--vp-c-brand-1);--vp-home-hero-name-background: transparent;--vp-home-hero-image-background-image: none;--vp-home-hero-image-filter: none}:root{--vp-badge-info-border: transparent;--vp-badge-info-text: var(--vp-c-text-2);--vp-badge-info-bg: var(--vp-c-default-soft);--vp-badge-tip-border: transparent;--vp-badge-tip-text: var(--vp-c-tip-1);--vp-badge-tip-bg: var(--vp-c-tip-soft);--vp-badge-warning-border: transparent;--vp-badge-warning-text: var(--vp-c-warning-1);--vp-badge-warning-bg: var(--vp-c-warning-soft);--vp-badge-danger-border: transparent;--vp-badge-danger-text: var(--vp-c-danger-1);--vp-badge-danger-bg: var(--vp-c-danger-soft)}:root{--vp-carbon-ads-text-color: var(--vp-c-text-1);--vp-carbon-ads-poweredby-color: var(--vp-c-text-2);--vp-carbon-ads-bg-color: var(--vp-c-bg-soft);--vp-carbon-ads-hover-text-color: var(--vp-c-brand-1);--vp-carbon-ads-hover-poweredby-color: var(--vp-c-text-1)}:root{--vp-local-search-bg: var(--vp-c-bg);--vp-local-search-result-bg: var(--vp-c-bg);--vp-local-search-result-border: var(--vp-c-divider);--vp-local-search-result-selected-bg: var(--vp-c-bg);--vp-local-search-result-selected-border: var(--vp-c-brand-1);--vp-local-search-highlight-bg: var(--vp-c-brand-1);--vp-local-search-highlight-text: var(--vp-c-neutral-inverse)}@media(prefers-reduced-motion:reduce){*,:before,:after{animation-delay:-1ms!important;animation-duration:1ms!important;animation-iteration-count:1!important;background-attachment:initial!important;scroll-behavior:auto!important;transition-duration:0s!important;transition-delay:0s!important}}*,:before,:after{box-sizing:border-box}html{line-height:1.4;font-size:16px;-webkit-text-size-adjust:100%}html.dark{color-scheme:dark}body{margin:0;width:100%;min-width:320px;min-height:100vh;line-height:24px;font-family:var(--vp-font-family-base);font-size:16px;font-weight:400;color:var(--vp-c-text-1);background-color:var(--vp-c-bg);font-synthesis:style;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}main{display:block}h1,h2,h3,h4,h5,h6{margin:0;line-height:24px;font-size:16px;font-weight:400}p{margin:0}strong,b{font-weight:600}a,area,button,[role=button],input,label,select,summary,textarea{touch-action:manipulation}a{color:inherit;text-decoration:inherit}ol,ul{list-style:none;margin:0;padding:0}blockquote{margin:0}pre,code,kbd,samp{font-family:var(--vp-font-family-mono)}img,svg,video,canvas,audio,iframe,embed,object{display:block}figure{margin:0}img,video{max-width:100%;height:auto}button,input,optgroup,select,textarea{border:0;padding:0;line-height:inherit;color:inherit}button{padding:0;font-family:inherit;background-color:transparent;background-image:none}button:enabled,[role=button]:enabled{cursor:pointer}button:focus,button:focus-visible{outline:1px dotted;outline:4px auto -webkit-focus-ring-color}button:focus:not(:focus-visible){outline:none!important}input:focus,textarea:focus,select:focus{outline:none}table{border-collapse:collapse}input{background-color:transparent}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:var(--vp-c-text-3)}input::-ms-input-placeholder,textarea::-ms-input-placeholder{color:var(--vp-c-text-3)}input::placeholder,textarea::placeholder{color:var(--vp-c-text-3)}input::-webkit-outer-spin-button,input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}input[type=number]{-moz-appearance:textfield}textarea{resize:vertical}select{-webkit-appearance:none}fieldset{margin:0;padding:0}h1,h2,h3,h4,h5,h6,li,p{overflow-wrap:break-word}vite-error-overlay{z-index:9999}mjx-container{overflow-x:auto}mjx-container>svg{display:inline-block;margin:auto}[class^=vpi-],[class*=" vpi-"],.vp-icon{width:1em;height:1em}[class^=vpi-].bg,[class*=" vpi-"].bg,.vp-icon.bg{background-size:100% 100%;background-color:transparent}[class^=vpi-]:not(.bg),[class*=" vpi-"]:not(.bg),.vp-icon:not(.bg){-webkit-mask:var(--icon) no-repeat;mask:var(--icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit}.vpi-align-left{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='none' stroke='black' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M15 12H3m14 6H3M21 6H3'/%3E%3C/svg%3E")}.vpi-arrow-right,.vpi-arrow-down,.vpi-arrow-left,.vpi-arrow-up{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='none' stroke='black' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M5 12h14m-7-7l7 7l-7 7'/%3E%3C/svg%3E")}.vpi-chevron-right,.vpi-chevron-down,.vpi-chevron-left,.vpi-chevron-up{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='none' stroke='black' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m9 18l6-6l-6-6'/%3E%3C/svg%3E")}.vpi-chevron-down,.vpi-arrow-down{transform:rotate(90deg)}.vpi-chevron-left,.vpi-arrow-left{transform:rotate(180deg)}.vpi-chevron-up,.vpi-arrow-up{transform:rotate(-90deg)}.vpi-square-pen{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='none' stroke='black' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7'/%3E%3Cpath d='M18.375 2.625a1 1 0 0 1 3 3l-9.013 9.014a2 2 0 0 1-.853.505l-2.873.84a.5.5 0 0 1-.62-.62l.84-2.873a2 2 0 0 1 .506-.852z'/%3E%3C/g%3E%3C/svg%3E")}.vpi-plus{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='none' stroke='black' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M5 12h14m-7-7v14'/%3E%3C/svg%3E")}.vpi-sun{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='none' stroke='black' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Ccircle cx='12' cy='12' r='4'/%3E%3Cpath d='M12 2v2m0 16v2M4.93 4.93l1.41 1.41m11.32 11.32l1.41 1.41M2 12h2m16 0h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41'/%3E%3C/g%3E%3C/svg%3E")}.vpi-moon{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='none' stroke='black' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M12 3a6 6 0 0 0 9 9a9 9 0 1 1-9-9'/%3E%3C/svg%3E")}.vpi-more-horizontal{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='none' stroke='black' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Ccircle cx='12' cy='12' r='1'/%3E%3Ccircle cx='19' cy='12' r='1'/%3E%3Ccircle cx='5' cy='12' r='1'/%3E%3C/g%3E%3C/svg%3E")}.vpi-languages{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='none' stroke='black' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m5 8l6 6m-7 0l6-6l2-3M2 5h12M7 2h1m14 20l-5-10l-5 10m2-4h6'/%3E%3C/svg%3E")}.vpi-heart{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='none' stroke='black' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2c-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z'/%3E%3C/svg%3E")}.vpi-search{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='none' stroke='black' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.6'%3E%3Cpath d='m21 21l-4.34-4.34'/%3E%3Ccircle cx='11' cy='11' r='8' stroke-width='1.4'/%3E%3C/g%3E%3C/svg%3E")}.vpi-layout-list{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='none' stroke='black' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Crect width='7' height='7' x='3' y='3' rx='1'/%3E%3Crect width='7' height='7' x='3' y='14' rx='1'/%3E%3Cpath d='M14 4h7m-7 5h7m-7 6h7m-7 5h7'/%3E%3C/g%3E%3C/svg%3E")}.vpi-delete{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='none' stroke='black' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M10 5a2 2 0 0 0-1.344.519l-6.328 5.74a1 1 0 0 0 0 1.481l6.328 5.741A2 2 0 0 0 10 19h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2zm2 4l6 6m0-6l-6 6'/%3E%3C/svg%3E")}.vpi-corner-down-left{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='none' stroke='black' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='M20 4v7a4 4 0 0 1-4 4H4'/%3E%3Cpath d='m9 10l-5 5l5 5'/%3E%3C/g%3E%3C/svg%3E")}:root{--vp-icon-copy: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='none' stroke='rgba(128,128,128,1)' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Crect width='8' height='4' x='8' y='2' rx='1' ry='1'/%3E%3Cpath d='M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2'/%3E%3C/g%3E%3C/svg%3E");--vp-icon-copied: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='none' stroke='rgba(128,128,128,1)' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Crect width='8' height='4' x='8' y='2' rx='1' ry='1'/%3E%3Cpath d='M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2'/%3E%3Cpath d='m9 14l2 2l4-4'/%3E%3C/g%3E%3C/svg%3E")}.visually-hidden{position:absolute;width:1px;height:1px;white-space:nowrap;clip:rect(0 0 0 0);clip-path:inset(50%);overflow:hidden}.custom-block{border:1px solid transparent;border-radius:8px;padding:16px 16px 8px;line-height:24px;font-size:var(--vp-custom-block-font-size);color:var(--vp-c-text-2)}.custom-block.info{border-color:var(--vp-custom-block-info-border);color:var(--vp-custom-block-info-text);background-color:var(--vp-custom-block-info-bg)}.custom-block.info a,.custom-block.info code{color:var(--vp-c-brand-1)}.custom-block.info a:hover,.custom-block.info a:hover>code{color:var(--vp-c-brand-2)}.custom-block.info code{background-color:var(--vp-custom-block-info-code-bg)}.custom-block.note{border-color:var(--vp-custom-block-note-border);color:var(--vp-custom-block-note-text);background-color:var(--vp-custom-block-note-bg)}.custom-block.note a,.custom-block.note code{color:var(--vp-c-brand-1)}.custom-block.note a:hover,.custom-block.note a:hover>code{color:var(--vp-c-brand-2)}.custom-block.note code{background-color:var(--vp-custom-block-note-code-bg)}.custom-block.tip{border-color:var(--vp-custom-block-tip-border);color:var(--vp-custom-block-tip-text);background-color:var(--vp-custom-block-tip-bg)}.custom-block.tip a,.custom-block.tip code{color:var(--vp-c-tip-1)}.custom-block.tip a:hover,.custom-block.tip a:hover>code{color:var(--vp-c-tip-2)}.custom-block.tip code{background-color:var(--vp-custom-block-tip-code-bg)}.custom-block.important{border-color:var(--vp-custom-block-important-border);color:var(--vp-custom-block-important-text);background-color:var(--vp-custom-block-important-bg)}.custom-block.important a,.custom-block.important code{color:var(--vp-c-important-1)}.custom-block.important a:hover,.custom-block.important a:hover>code{color:var(--vp-c-important-2)}.custom-block.important code{background-color:var(--vp-custom-block-important-code-bg)}.custom-block.warning{border-color:var(--vp-custom-block-warning-border);color:var(--vp-custom-block-warning-text);background-color:var(--vp-custom-block-warning-bg)}.custom-block.warning a,.custom-block.warning code{color:var(--vp-c-warning-1)}.custom-block.warning a:hover,.custom-block.warning a:hover>code{color:var(--vp-c-warning-2)}.custom-block.warning code{background-color:var(--vp-custom-block-warning-code-bg)}.custom-block.danger{border-color:var(--vp-custom-block-danger-border);color:var(--vp-custom-block-danger-text);background-color:var(--vp-custom-block-danger-bg)}.custom-block.danger a,.custom-block.danger code{color:var(--vp-c-danger-1)}.custom-block.danger a:hover,.custom-block.danger a:hover>code{color:var(--vp-c-danger-2)}.custom-block.danger code{background-color:var(--vp-custom-block-danger-code-bg)}.custom-block.caution{border-color:var(--vp-custom-block-caution-border);color:var(--vp-custom-block-caution-text);background-color:var(--vp-custom-block-caution-bg)}.custom-block.caution a,.custom-block.caution code{color:var(--vp-c-caution-1)}.custom-block.caution a:hover,.custom-block.caution a:hover>code{color:var(--vp-c-caution-2)}.custom-block.caution code{background-color:var(--vp-custom-block-caution-code-bg)}.custom-block.details{border-color:var(--vp-custom-block-details-border);color:var(--vp-custom-block-details-text);background-color:var(--vp-custom-block-details-bg)}.custom-block.details a{color:var(--vp-c-brand-1)}.custom-block.details a:hover,.custom-block.details a:hover>code{color:var(--vp-c-brand-2)}.custom-block.details code{background-color:var(--vp-custom-block-details-code-bg)}.custom-block-title{font-weight:600}.custom-block p+p{margin:8px 0}.custom-block.details summary{margin:0 0 8px;font-weight:700;cursor:pointer;-webkit-user-select:none;user-select:none}.custom-block.details summary+p{margin:8px 0}.custom-block a{color:inherit;font-weight:600;text-decoration:underline;text-underline-offset:2px;transition:opacity .25s}.custom-block a:hover{opacity:.75}.custom-block code{font-size:var(--vp-custom-block-code-font-size)}.custom-block.custom-block th,.custom-block.custom-block blockquote>p{font-size:var(--vp-custom-block-font-size);color:inherit}.dark .shiki span{color:var(--shiki-dark, inherit)}html:not(.dark) .shiki span{color:var(--shiki-light, inherit)}.vp-code-group{margin-top:16px}.vp-code-group .tabs{position:relative;display:flex;margin-right:-24px;margin-left:-24px;padding:0 12px;background-color:var(--vp-code-tab-bg);overflow-x:auto;overflow-y:hidden;box-shadow:inset 0 -1px var(--vp-code-tab-divider)}@media(min-width:640px){.vp-code-group .tabs{margin-right:0;margin-left:0;border-radius:8px 8px 0 0}}.vp-code-group .tabs input{position:fixed;opacity:0;pointer-events:none}.vp-code-group .tabs label{position:relative;display:inline-block;border-bottom:1px solid transparent;padding:0 12px;line-height:48px;font-size:14px;font-weight:500;color:var(--vp-code-tab-text-color);white-space:nowrap;cursor:pointer;transition:color .25s}.vp-code-group .tabs label:after{position:absolute;right:8px;bottom:-1px;left:8px;z-index:1;height:2px;border-radius:2px;content:"";background-color:transparent;transition:background-color .25s}.vp-code-group label:hover{color:var(--vp-code-tab-hover-text-color)}.vp-code-group input:checked+label{color:var(--vp-code-tab-active-text-color)}.vp-code-group input:checked+label:after{background-color:var(--vp-code-tab-active-bar-color)}.vp-code-group div[class*=language-],.vp-block{display:none;margin-top:0!important;border-top-left-radius:0!important;border-top-right-radius:0!important}.vp-code-group div[class*=language-].active,.vp-block.active{display:block}.vp-block{padding:20px 24px}.vp-doc h1,.vp-doc h2,.vp-doc h3,.vp-doc h4,.vp-doc h5,.vp-doc h6{position:relative;font-weight:600;outline:none}.vp-doc h1{letter-spacing:-.02em;line-height:40px;font-size:28px}.vp-doc h2{margin:48px 0 16px;border-top:1px solid var(--vp-c-divider);padding-top:24px;letter-spacing:-.02em;line-height:32px;font-size:24px}.vp-doc h3{margin:32px 0 0;letter-spacing:-.01em;line-height:28px;font-size:20px}.vp-doc h4{margin:24px 0 0;letter-spacing:-.01em;line-height:24px;font-size:18px}.vp-doc .header-anchor{position:absolute;top:0;left:0;margin-left:-.87em;font-weight:500;-webkit-user-select:none;user-select:none;opacity:0;text-decoration:none;transition:color .25s,opacity .25s}.vp-doc .header-anchor:before{content:var(--vp-header-anchor-symbol)}.vp-doc h1:hover .header-anchor,.vp-doc h1 .header-anchor:focus,.vp-doc h2:hover .header-anchor,.vp-doc h2 .header-anchor:focus,.vp-doc h3:hover .header-anchor,.vp-doc h3 .header-anchor:focus,.vp-doc h4:hover .header-anchor,.vp-doc h4 .header-anchor:focus,.vp-doc h5:hover .header-anchor,.vp-doc h5 .header-anchor:focus,.vp-doc h6:hover .header-anchor,.vp-doc h6 .header-anchor:focus{opacity:1}@media(min-width:768px){.vp-doc h1{letter-spacing:-.02em;line-height:40px;font-size:32px}}.vp-doc h2 .header-anchor{top:24px}.vp-doc p,.vp-doc summary{margin:16px 0}.vp-doc p{line-height:28px}.vp-doc blockquote{margin:16px 0;border-left:2px solid var(--vp-c-divider);padding-left:16px;transition:border-color .5s;color:var(--vp-c-text-2)}.vp-doc blockquote>p{margin:0;font-size:16px;transition:color .5s}.vp-doc a{font-weight:500;color:var(--vp-c-brand-1);text-decoration:underline;text-underline-offset:2px;transition:color .25s,opacity .25s}.vp-doc a:hover{color:var(--vp-c-brand-2)}.vp-doc strong{font-weight:600}.vp-doc ul,.vp-doc ol{padding-left:1.25rem;margin:16px 0}.vp-doc ul{list-style:disc}.vp-doc ol{list-style:decimal}.vp-doc li+li{margin-top:8px}.vp-doc li>ol,.vp-doc li>ul{margin:8px 0 0}.vp-doc table{display:block;border-collapse:collapse;margin:20px 0;overflow-x:auto}.vp-doc tr{background-color:var(--vp-c-bg);border-top:1px solid var(--vp-c-divider);transition:background-color .5s}.vp-doc tr:nth-child(2n){background-color:var(--vp-c-bg-soft)}.vp-doc th,.vp-doc td{border:1px solid var(--vp-c-divider);padding:8px 16px}.vp-doc th{text-align:left;font-size:14px;font-weight:600;color:var(--vp-c-text-2);background-color:var(--vp-c-bg-soft)}.vp-doc td{font-size:14px}.vp-doc hr{margin:16px 0;border:none;border-top:1px solid var(--vp-c-divider)}.vp-doc .custom-block{margin:16px 0}.vp-doc .custom-block p{margin:8px 0;line-height:24px}.vp-doc .custom-block p:first-child{margin:0}.vp-doc .custom-block div[class*=language-]{margin:8px 0!important;border-radius:8px}.vp-doc .custom-block div[class*=language-] code{font-weight:400;background-color:transparent}.vp-doc .custom-block .vp-code-group .tabs{margin:0;border-radius:8px 8px 0 0}.vp-doc :not(pre,h1,h2,h3,h4,h5,h6)>code{font-size:var(--vp-code-font-size);color:var(--vp-code-color)}.vp-doc :not(pre)>code{border-radius:4px;padding:3px 6px;background-color:var(--vp-code-bg);transition:color .25s,background-color .5s}.vp-doc a>code{color:var(--vp-code-link-color)}.vp-doc a:hover>code{color:var(--vp-code-link-hover-color)}.vp-doc h1>code,.vp-doc h2>code,.vp-doc h3>code,.vp-doc h4>code{font-size:.9em}.vp-doc div[class*=language-],.vp-block{position:relative;margin:16px -24px;background-color:var(--vp-code-block-bg);overflow-x:auto;transition:background-color .5s}@media(min-width:640px){.vp-doc div[class*=language-],.vp-block{border-radius:8px;margin:16px 0}}@media(max-width:639px){.vp-doc li div[class*=language-]{border-radius:8px 0 0 8px}}.vp-doc div[class*=language-]+div[class*=language-],.vp-doc div[class$=-api]+div[class*=language-],.vp-doc div[class*=language-]+div[class$=-api]>div[class*=language-]{margin-top:-8px}.vp-doc [class*=language-] pre,.vp-doc [class*=language-] code{-moz-tab-size:4;-o-tab-size:4;tab-size:4}.vp-doc [class*=language-] pre{position:relative;z-index:1;margin:0;padding:20px 0;background:transparent;overflow-x:auto;text-align:left}.vp-doc [class*=language-] code{display:block;padding:0 24px;width:fit-content;min-width:100%;line-height:var(--vp-code-line-height);font-size:var(--vp-code-font-size);color:var(--vp-code-block-color);transition:color .5s}.vp-doc [class*=language-] code .highlighted{background-color:var(--vp-code-line-highlight-color);transition:background-color .5s;margin:0 -24px;padding:0 24px;width:calc(100% + 48px);display:inline-block}.vp-doc [class*=language-] code .highlighted.error{background-color:var(--vp-code-line-error-color)}.vp-doc [class*=language-] code .highlighted.warning{background-color:var(--vp-code-line-warning-color)}.vp-doc [class*=language-] code .diff{transition:background-color .5s;margin:0 -24px;padding:0 24px;width:calc(100% + 48px);display:inline-block}.vp-doc [class*=language-] code .diff:before{position:absolute;left:10px}.vp-doc [class*=language-] .has-focused-lines .line:not(.has-focus){filter:blur(.095rem);opacity:.4;transition:filter .35s,opacity .35s}.vp-doc [class*=language-] .has-focused-lines .line:not(.has-focus){opacity:.7;transition:filter .35s,opacity .35s}.vp-doc [class*=language-]:hover .has-focused-lines .line:not(.has-focus){filter:blur(0);opacity:1}.vp-doc [class*=language-] code .diff.remove{background-color:var(--vp-code-line-diff-remove-color);opacity:.7}.vp-doc [class*=language-] code .diff.remove:before{content:"-";color:var(--vp-code-line-diff-remove-symbol-color)}.vp-doc [class*=language-] code .diff.add{background-color:var(--vp-code-line-diff-add-color)}.vp-doc [class*=language-] code .diff.add:before{content:"+";color:var(--vp-code-line-diff-add-symbol-color)}.vp-doc div[class*=language-].line-numbers-mode{padding-left:32px}.vp-doc .line-numbers-wrapper{position:absolute;top:0;bottom:0;left:0;z-index:3;border-right:1px solid var(--vp-code-block-divider-color);padding-top:20px;width:32px;text-align:center;font-family:var(--vp-font-family-mono);line-height:var(--vp-code-line-height);font-size:var(--vp-code-font-size);color:var(--vp-code-line-number-color);transition:border-color .5s,color .5s}.vp-doc [class*=language-]>button.copy{direction:ltr;position:absolute;top:12px;right:12px;z-index:3;border:1px solid var(--vp-code-copy-code-border-color);border-radius:4px;width:40px;height:40px;background-color:var(--vp-code-copy-code-bg);opacity:0;cursor:pointer;background-image:var(--vp-icon-copy);background-position:50%;background-size:20px;background-repeat:no-repeat;transition:border-color .25s,background-color .25s,opacity .25s}.vp-doc [class*=language-]:hover>button.copy,.vp-doc [class*=language-]>button.copy:focus{opacity:1}.vp-doc [class*=language-]>button.copy:hover,.vp-doc [class*=language-]>button.copy.copied{border-color:var(--vp-code-copy-code-hover-border-color);background-color:var(--vp-code-copy-code-hover-bg)}.vp-doc [class*=language-]>button.copy.copied,.vp-doc [class*=language-]>button.copy:hover.copied{border-radius:0 4px 4px 0;background-color:var(--vp-code-copy-code-hover-bg);background-image:var(--vp-icon-copied)}.vp-doc [class*=language-]>button.copy.copied:before,.vp-doc [class*=language-]>button.copy:hover.copied:before{position:relative;top:-1px;transform:translate(calc(-100% - 1px));display:flex;justify-content:center;align-items:center;border:1px solid var(--vp-code-copy-code-hover-border-color);border-right:0;border-radius:4px 0 0 4px;padding:0 10px;width:fit-content;height:40px;text-align:center;font-size:12px;font-weight:500;color:var(--vp-code-copy-code-active-text);background-color:var(--vp-code-copy-code-hover-bg);white-space:nowrap;content:var(--vp-code-copy-copied-text-content)}.vp-doc [class*=language-]>span.lang{position:absolute;top:2px;right:8px;z-index:2;font-size:12px;font-weight:500;-webkit-user-select:none;user-select:none;color:var(--vp-code-lang-color);transition:color .4s,opacity .4s}.vp-doc [class*=language-]:hover>button.copy+span.lang,.vp-doc [class*=language-]>button.copy:focus+span.lang{opacity:0}.vp-doc .VPTeamMembers{margin-top:24px}.vp-doc .VPTeamMembers.small.count-1 .container{margin:0!important;max-width:calc((100% - 24px)/2)!important}.vp-doc .VPTeamMembers.small.count-2 .container,.vp-doc .VPTeamMembers.small.count-3 .container{max-width:100%!important}.vp-doc .VPTeamMembers.medium.count-1 .container{margin:0!important;max-width:calc((100% - 24px)/2)!important}:is(.vp-external-link-icon,.vp-doc a[href*="://"],.vp-doc a[target=_blank]):not(:is(.no-icon,svg a,:has(img,svg))):after{display:inline-block;margin-top:-1px;margin-left:4px;width:11px;height:11px;background:currentColor;color:var(--vp-c-text-3);flex-shrink:0;--icon: url("data:image/svg+xml, %3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' %3E%3Cpath d='M0 0h24v24H0V0z' fill='none' /%3E%3Cpath d='M9 5v2h6.59L4 18.59 5.41 20 17 8.41V15h2V5H9z' /%3E%3C/svg%3E");-webkit-mask-image:var(--icon);mask-image:var(--icon)}.vp-external-link-icon:after{content:""}.external-link-icon-enabled :is(.vp-doc a[href*="://"],.vp-doc a[target=_blank]):not(:is(.no-icon,svg a,:has(img,svg))):after{content:"";color:currentColor}.vp-sponsor{border-radius:16px;overflow:hidden}.vp-sponsor.aside{border-radius:12px}.vp-sponsor-section+.vp-sponsor-section{margin-top:4px}.vp-sponsor-tier{margin:0 0 4px!important;text-align:center;letter-spacing:1px!important;line-height:24px;width:100%;font-weight:600;color:var(--vp-c-text-2);background-color:var(--vp-c-bg-soft)}.vp-sponsor.normal .vp-sponsor-tier{padding:13px 0 11px;font-size:14px}.vp-sponsor.aside .vp-sponsor-tier{padding:9px 0 7px;font-size:12px}.vp-sponsor-grid+.vp-sponsor-tier{margin-top:4px}.vp-sponsor-grid{display:flex;flex-wrap:wrap;gap:4px}.vp-sponsor-grid.xmini .vp-sponsor-grid-link{height:64px}.vp-sponsor-grid.xmini .vp-sponsor-grid-image{max-width:64px;max-height:22px}.vp-sponsor-grid.mini .vp-sponsor-grid-link{height:72px}.vp-sponsor-grid.mini .vp-sponsor-grid-image{max-width:96px;max-height:24px}.vp-sponsor-grid.small .vp-sponsor-grid-link{height:96px}.vp-sponsor-grid.small .vp-sponsor-grid-image{max-width:96px;max-height:24px}.vp-sponsor-grid.medium .vp-sponsor-grid-link{height:112px}.vp-sponsor-grid.medium .vp-sponsor-grid-image{max-width:120px;max-height:36px}.vp-sponsor-grid.big .vp-sponsor-grid-link{height:184px}.vp-sponsor-grid.big .vp-sponsor-grid-image{max-width:192px;max-height:56px}.vp-sponsor-grid[data-vp-grid="2"] .vp-sponsor-grid-item{width:calc((100% - 4px)/2)}.vp-sponsor-grid[data-vp-grid="3"] .vp-sponsor-grid-item{width:calc((100% - 4px * 2) / 3)}.vp-sponsor-grid[data-vp-grid="4"] .vp-sponsor-grid-item{width:calc((100% - 12px)/4)}.vp-sponsor-grid[data-vp-grid="5"] .vp-sponsor-grid-item{width:calc((100% - 16px)/5)}.vp-sponsor-grid[data-vp-grid="6"] .vp-sponsor-grid-item{width:calc((100% - 4px * 5) / 6)}.vp-sponsor-grid-item{flex-shrink:0;width:100%;background-color:var(--vp-c-bg-soft);transition:background-color .25s}.vp-sponsor-grid-item:hover{background-color:var(--vp-c-default-soft)}.vp-sponsor-grid-item:hover .vp-sponsor-grid-image{filter:grayscale(0) invert(0)}.vp-sponsor-grid-item.empty:hover{background-color:var(--vp-c-bg-soft)}.dark .vp-sponsor-grid-item:hover{background-color:var(--vp-c-white)}.dark .vp-sponsor-grid-item.empty:hover{background-color:var(--vp-c-bg-soft)}.vp-sponsor-grid-link{display:flex}.vp-sponsor-grid-box{display:flex;justify-content:center;align-items:center;width:100%}.vp-sponsor-grid-image{max-width:100%;filter:grayscale(1);transition:filter .25s}.dark .vp-sponsor-grid-image{filter:grayscale(1) invert(1)}.VPBadge{display:inline-block;margin-left:2px;border:1px solid transparent;border-radius:12px;padding:0 10px;line-height:22px;font-size:12px;font-weight:500;white-space:nowrap;transform:translateY(-2px)}.VPBadge.small{padding:0 6px;line-height:18px;font-size:10px;transform:translateY(-8px)}.VPDocFooter .VPBadge{display:none}.vp-doc h1>.VPBadge{margin-top:4px;vertical-align:top}.vp-doc h2>.VPBadge{margin-top:3px;padding:0 8px;vertical-align:top}.vp-doc h3>.VPBadge{vertical-align:middle}.vp-doc h4>.VPBadge,.vp-doc h5>.VPBadge,.vp-doc h6>.VPBadge{vertical-align:middle;line-height:18px}.VPBadge.info{border-color:var(--vp-badge-info-border);color:var(--vp-badge-info-text);background-color:var(--vp-badge-info-bg)}.VPBadge.tip{border-color:var(--vp-badge-tip-border);color:var(--vp-badge-tip-text);background-color:var(--vp-badge-tip-bg)}.VPBadge.warning{border-color:var(--vp-badge-warning-border);color:var(--vp-badge-warning-text);background-color:var(--vp-badge-warning-bg)}.VPBadge.danger{border-color:var(--vp-badge-danger-border);color:var(--vp-badge-danger-text);background-color:var(--vp-badge-danger-bg)}.NotFound[data-v-1b32e0f1]{padding:64px 24px 96px;text-align:center}@media(min-width:768px){.NotFound[data-v-1b32e0f1]{padding:96px 32px 168px}}.code[data-v-1b32e0f1]{line-height:64px;font-size:64px;font-weight:600}.title[data-v-1b32e0f1]{padding-top:12px;letter-spacing:2px;line-height:20px;font-size:20px;font-weight:700}.divider[data-v-1b32e0f1]{margin:24px auto 18px;width:64px;height:1px;background-color:var(--vp-c-divider)}.quote[data-v-1b32e0f1]{margin:0 auto;max-width:256px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.action[data-v-1b32e0f1]{padding-top:20px}.link[data-v-1b32e0f1]{display:inline-block;border:1px solid var(--vp-c-brand-1);border-radius:16px;padding:3px 16px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1);transition:border-color .25s,color .25s}.link[data-v-1b32e0f1]:hover{border-color:var(--vp-c-brand-2);color:var(--vp-c-brand-2)}.VPBackdrop[data-v-f703a812]{position:fixed;inset:0;z-index:var(--vp-z-index-backdrop);background:var(--vp-backdrop-bg-color);transition:opacity .5s}.VPBackdrop.fade-enter-from[data-v-f703a812],.VPBackdrop.fade-leave-to[data-v-f703a812]{opacity:0}.VPBackdrop.fade-leave-active[data-v-f703a812]{transition-duration:.25s}@media(min-width:1280px){.VPBackdrop[data-v-f703a812]{display:none}}.root[data-v-d90f9aed]{position:relative;z-index:1}.nested[data-v-d90f9aed]{padding-right:16px;padding-left:16px}.outline-link[data-v-d90f9aed]{display:block;line-height:32px;font-size:14px;font-weight:400;color:var(--vp-c-text-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:color .5s}.outline-link[data-v-d90f9aed]:hover,.outline-link.active[data-v-d90f9aed]{color:var(--vp-c-text-1);transition:color .25s}.outline-link.nested[data-v-d90f9aed]{padding-left:13px}.VPDocAsideOutline[data-v-3f819b94]{display:none}.VPDocAsideOutline.has-outline[data-v-3f819b94]{display:block}.content[data-v-3f819b94]{position:relative;border-left:1px solid var(--vp-c-divider);padding-left:16px;font-size:13px;font-weight:500}.outline-marker[data-v-3f819b94]{position:absolute;top:32px;left:-1px;z-index:0;opacity:0;width:2px;border-radius:2px;height:18px;background-color:var(--vp-c-brand-1);transition:top .25s cubic-bezier(0,1,.5,1),background-color .5s,opacity .25s}.outline-title[data-v-3f819b94]{line-height:32px;font-size:14px;font-weight:600}.VPDocAside[data-v-77a1b21d]{display:flex;flex-direction:column;flex-grow:1}.spacer[data-v-77a1b21d]{flex-grow:1}.VPDocAside[data-v-77a1b21d] .spacer+.VPDocAsideSponsors,.VPDocAside[data-v-77a1b21d] .spacer+.VPDocAsideCarbonAds{margin-top:24px}.VPDocAside[data-v-77a1b21d] .VPDocAsideSponsors+.VPDocAsideCarbonAds{margin-top:16px}.VPLastUpdated[data-v-8f712c9b]{line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}@media(min-width:640px){.VPLastUpdated[data-v-8f712c9b]{line-height:32px;font-size:14px;font-weight:500}}.VPDocFooter[data-v-af105c74]{margin-top:64px}.edit-info[data-v-af105c74]{padding-bottom:18px}@media(min-width:640px){.edit-info[data-v-af105c74]{display:flex;justify-content:space-between;align-items:center;padding-bottom:14px}}.edit-link-button[data-v-af105c74]{display:flex;align-items:center;border:0;line-height:32px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1);transition:color .25s}.edit-link-button[data-v-af105c74]:hover{color:var(--vp-c-brand-2)}.edit-link-icon[data-v-af105c74]{margin-right:8px}.prev-next[data-v-af105c74]{border-top:1px solid var(--vp-c-divider);padding-top:24px;display:grid;grid-row-gap:8px}@media(min-width:640px){.prev-next[data-v-af105c74]{grid-template-columns:repeat(2,1fr);grid-column-gap:16px}}.pager-link[data-v-af105c74]{display:block;border:1px solid var(--vp-c-divider);border-radius:8px;padding:11px 16px 13px;width:100%;height:100%;transition:border-color .25s}.pager-link[data-v-af105c74]:hover{border-color:var(--vp-c-brand-1)}.pager-link.next[data-v-af105c74]{margin-left:auto;text-align:right}.desc[data-v-af105c74]{display:block;line-height:20px;font-size:12px;font-weight:500;color:var(--vp-c-text-2)}.title[data-v-af105c74]{display:block;line-height:20px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1);transition:color .25s}.VPDoc[data-v-256763c0]{padding:32px 24px 96px;width:100%}@media(min-width:768px){.VPDoc[data-v-256763c0]{padding:48px 32px 128px}}@media(min-width:960px){.VPDoc[data-v-256763c0]{padding:48px 32px 0}.VPDoc:not(.has-sidebar) .container[data-v-256763c0]{display:flex;justify-content:center;max-width:992px}.VPDoc:not(.has-sidebar) .content[data-v-256763c0]{max-width:752px}}@media(min-width:1280px){.VPDoc .container[data-v-256763c0]{display:flex;justify-content:center}.VPDoc .aside[data-v-256763c0]{display:block}}@media(min-width:1440px){.VPDoc:not(.has-sidebar) .content[data-v-256763c0]{max-width:784px}.VPDoc:not(.has-sidebar) .container[data-v-256763c0]{max-width:1104px}}.container[data-v-256763c0]{margin:0 auto;width:100%}.aside[data-v-256763c0]{position:relative;display:none;order:2;flex-grow:1;padding-left:32px;width:100%;max-width:256px}.left-aside[data-v-256763c0]{order:1;padding-left:unset;padding-right:32px}.aside-container[data-v-256763c0]{position:fixed;top:0;padding-top:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + var(--vp-doc-top-height, 0px) + 48px);width:224px;height:100vh;overflow-x:hidden;overflow-y:auto;scrollbar-width:none}.aside-container[data-v-256763c0]::-webkit-scrollbar{display:none}.aside-curtain[data-v-256763c0]{position:fixed;bottom:0;z-index:10;width:224px;height:32px;background:linear-gradient(transparent,var(--vp-c-bg) 70%);pointer-events:none}.aside-content[data-v-256763c0]{display:flex;flex-direction:column;min-height:calc(100vh - (var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 48px));padding-bottom:32px}.content[data-v-256763c0]{position:relative;margin:0 auto;width:100%}@media(min-width:960px){.content[data-v-256763c0]{padding:0 32px 128px}}@media(min-width:1280px){.content[data-v-256763c0]{order:1;margin:0;min-width:640px}}.content-container[data-v-256763c0]{margin:0 auto}.VPDoc.has-aside .content-container[data-v-256763c0]{max-width:688px}.VPButton[data-v-b44745dc]{display:inline-block;border:1px solid transparent;text-align:center;font-weight:600;white-space:nowrap;transition:color .25s,border-color .25s,background-color .25s}.VPButton[data-v-b44745dc]:active{transition:color .1s,border-color .1s,background-color .1s}.VPButton.medium[data-v-b44745dc]{border-radius:20px;padding:0 20px;line-height:38px;font-size:14px}.VPButton.big[data-v-b44745dc]{border-radius:24px;padding:0 24px;line-height:46px;font-size:16px}.VPButton.brand[data-v-b44745dc]{border-color:var(--vp-button-brand-border);color:var(--vp-button-brand-text);background-color:var(--vp-button-brand-bg)}.VPButton.brand[data-v-b44745dc]:hover{border-color:var(--vp-button-brand-hover-border);color:var(--vp-button-brand-hover-text);background-color:var(--vp-button-brand-hover-bg)}.VPButton.brand[data-v-b44745dc]:active{border-color:var(--vp-button-brand-active-border);color:var(--vp-button-brand-active-text);background-color:var(--vp-button-brand-active-bg)}.VPButton.alt[data-v-b44745dc]{border-color:var(--vp-button-alt-border);color:var(--vp-button-alt-text);background-color:var(--vp-button-alt-bg)}.VPButton.alt[data-v-b44745dc]:hover{border-color:var(--vp-button-alt-hover-border);color:var(--vp-button-alt-hover-text);background-color:var(--vp-button-alt-hover-bg)}.VPButton.alt[data-v-b44745dc]:active{border-color:var(--vp-button-alt-active-border);color:var(--vp-button-alt-active-text);background-color:var(--vp-button-alt-active-bg)}.VPButton.sponsor[data-v-b44745dc]{border-color:var(--vp-button-sponsor-border);color:var(--vp-button-sponsor-text);background-color:var(--vp-button-sponsor-bg)}.VPButton.sponsor[data-v-b44745dc]:hover{border-color:var(--vp-button-sponsor-hover-border);color:var(--vp-button-sponsor-hover-text);background-color:var(--vp-button-sponsor-hover-bg)}.VPButton.sponsor[data-v-b44745dc]:active{border-color:var(--vp-button-sponsor-active-border);color:var(--vp-button-sponsor-active-text);background-color:var(--vp-button-sponsor-active-bg)}html:not(.dark) .VPImage.dark[data-v-e0e0d586]{display:none}.dark .VPImage.light[data-v-e0e0d586]{display:none}.VPHero[data-v-09867ed5]{margin-top:calc((var(--vp-nav-height) + var(--vp-layout-top-height, 0px)) * -1);padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 48px) 24px 48px}@media(min-width:640px){.VPHero[data-v-09867ed5]{padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 80px) 48px 64px}}@media(min-width:960px){.VPHero[data-v-09867ed5]{padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 80px) 64px 64px}}.container[data-v-09867ed5]{display:flex;flex-direction:column;margin:0 auto;max-width:1152px}@media(min-width:960px){.container[data-v-09867ed5]{flex-direction:row}}.main[data-v-09867ed5]{position:relative;z-index:10;order:2;flex-grow:1;flex-shrink:0}.VPHero.has-image .container[data-v-09867ed5]{text-align:center}@media(min-width:960px){.VPHero.has-image .container[data-v-09867ed5]{text-align:left}}@media(min-width:960px){.main[data-v-09867ed5]{order:1;width:calc((100% / 3) * 2)}.VPHero.has-image .main[data-v-09867ed5]{max-width:592px}}.heading[data-v-09867ed5]{display:flex;flex-direction:column}.name[data-v-09867ed5],.text[data-v-09867ed5]{width:fit-content;max-width:392px;letter-spacing:-.4px;line-height:40px;font-size:32px;font-weight:700;white-space:pre-wrap}.VPHero.has-image .name[data-v-09867ed5],.VPHero.has-image .text[data-v-09867ed5]{margin:0 auto}.name[data-v-09867ed5]{color:var(--vp-home-hero-name-color)}.clip[data-v-09867ed5]{background:var(--vp-home-hero-name-background);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:var(--vp-home-hero-name-color)}@media(min-width:640px){.name[data-v-09867ed5],.text[data-v-09867ed5]{max-width:576px;line-height:56px;font-size:48px}}@media(min-width:960px){.name[data-v-09867ed5],.text[data-v-09867ed5]{line-height:64px;font-size:56px}.VPHero.has-image .name[data-v-09867ed5],.VPHero.has-image .text[data-v-09867ed5]{margin:0}}.tagline[data-v-09867ed5]{padding-top:8px;max-width:392px;line-height:28px;font-size:18px;font-weight:500;white-space:pre-wrap;color:var(--vp-c-text-2)}.VPHero.has-image .tagline[data-v-09867ed5]{margin:0 auto}@media(min-width:640px){.tagline[data-v-09867ed5]{padding-top:12px;max-width:576px;line-height:32px;font-size:20px}}@media(min-width:960px){.tagline[data-v-09867ed5]{line-height:36px;font-size:24px}.VPHero.has-image .tagline[data-v-09867ed5]{margin:0}}.actions[data-v-09867ed5]{display:flex;flex-wrap:wrap;margin:-6px;padding-top:24px}.VPHero.has-image .actions[data-v-09867ed5]{justify-content:center}@media(min-width:640px){.actions[data-v-09867ed5]{padding-top:32px}}@media(min-width:960px){.VPHero.has-image .actions[data-v-09867ed5]{justify-content:flex-start}}.action[data-v-09867ed5]{flex-shrink:0;padding:6px}.image[data-v-09867ed5]{order:1;margin:-76px -24px -48px}@media(min-width:640px){.image[data-v-09867ed5]{margin:-108px -24px -48px}}@media(min-width:960px){.image[data-v-09867ed5]{flex-grow:1;order:2;margin:0;min-height:100%}}.image-container[data-v-09867ed5]{position:relative;margin:0 auto;width:320px;height:320px}@media(min-width:640px){.image-container[data-v-09867ed5]{width:392px;height:392px}}@media(min-width:960px){.image-container[data-v-09867ed5]{display:flex;justify-content:center;align-items:center;width:100%;height:100%;transform:translate(-32px,-32px)}}.image-bg[data-v-09867ed5]{position:absolute;top:50%;left:50%;border-radius:50%;width:192px;height:192px;background-image:var(--vp-home-hero-image-background-image);filter:var(--vp-home-hero-image-filter);transform:translate(-50%,-50%)}@media(min-width:640px){.image-bg[data-v-09867ed5]{width:256px;height:256px}}@media(min-width:960px){.image-bg[data-v-09867ed5]{width:320px;height:320px}}[data-v-09867ed5] .image-src{position:absolute;top:50%;left:50%;max-width:192px;max-height:192px;width:100%;height:100%;object-fit:contain;transform:translate(-50%,-50%)}@media(min-width:640px){[data-v-09867ed5] .image-src{max-width:256px;max-height:256px}}@media(min-width:960px){[data-v-09867ed5] .image-src{max-width:320px;max-height:320px}}.VPFeature[data-v-684de982]{display:block;border:1px solid var(--vp-c-bg-soft);border-radius:12px;height:100%;background-color:var(--vp-c-bg-soft);transition:border-color .25s,background-color .25s}.VPFeature.link[data-v-684de982]:hover{border-color:var(--vp-c-brand-1)}.box[data-v-684de982]{display:flex;flex-direction:column;padding:24px;height:100%}.box[data-v-684de982]>.VPImage{margin-bottom:20px}.icon[data-v-684de982]{display:flex;justify-content:center;align-items:center;margin-bottom:20px;border-radius:6px;background-color:var(--vp-c-default-soft);width:48px;height:48px;font-size:24px;transition:background-color .25s}.title[data-v-684de982]{line-height:24px;font-size:16px;font-weight:600}.details[data-v-684de982]{flex-grow:1;padding-top:8px;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.link-text[data-v-684de982]{padding-top:8px}.link-text-value[data-v-684de982]{display:flex;align-items:center;font-size:14px;font-weight:500;color:var(--vp-c-brand-1)}.link-text-icon[data-v-684de982]{margin-left:6px}.VPFeatures[data-v-4422ade5]{position:relative;padding:0 24px}@media(min-width:640px){.VPFeatures[data-v-4422ade5]{padding:0 48px}}@media(min-width:960px){.VPFeatures[data-v-4422ade5]{padding:0 64px}}.container[data-v-4422ade5]{margin:0 auto;max-width:1152px}.items[data-v-4422ade5]{display:flex;flex-wrap:wrap;margin:-8px}.item[data-v-4422ade5]{padding:8px;width:100%}@media(min-width:640px){.item.grid-2[data-v-4422ade5],.item.grid-4[data-v-4422ade5],.item.grid-6[data-v-4422ade5]{width:50%}}@media(min-width:768px){.item.grid-2[data-v-4422ade5],.item.grid-4[data-v-4422ade5]{width:50%}.item.grid-3[data-v-4422ade5],.item.grid-6[data-v-4422ade5]{width:calc(100% / 3)}}@media(min-width:960px){.item.grid-4[data-v-4422ade5]{width:25%}}.container[data-v-1b679879]{margin:auto;width:100%;max-width:1280px;padding:0 24px}@media(min-width:640px){.container[data-v-1b679879]{padding:0 48px}}@media(min-width:960px){.container[data-v-1b679879]{width:100%;padding:0 64px}}.vp-doc[data-v-1b679879] .VPHomeSponsors,.vp-doc[data-v-1b679879] .VPTeamPage{margin-left:var(--vp-offset, calc(50% - 50vw) );margin-right:var(--vp-offset, calc(50% - 50vw) )}.vp-doc[data-v-1b679879] .VPHomeSponsors h2{border-top:none;letter-spacing:normal}.vp-doc[data-v-1b679879] .VPHomeSponsors a,.vp-doc[data-v-1b679879] .VPTeamPage a{text-decoration:none}.VPHome[data-v-10bb9ea0]{margin-bottom:96px}@media(min-width:768px){.VPHome[data-v-10bb9ea0]{margin-bottom:128px}}.VPContent[data-v-19ca35aa]{flex-grow:1;flex-shrink:0;margin:var(--vp-layout-top-height, 0px) auto 0;width:100%}.VPContent.is-home[data-v-19ca35aa]{width:100%;max-width:100%}.VPContent.has-sidebar[data-v-19ca35aa]{margin:0}@media(min-width:960px){.VPContent[data-v-19ca35aa]{padding-top:var(--vp-nav-height)}.VPContent.has-sidebar[data-v-19ca35aa]{margin:var(--vp-layout-top-height, 0px) 0 0;padding-left:var(--vp-sidebar-width)}}@media(min-width:1440px){.VPContent.has-sidebar[data-v-19ca35aa]{padding-right:calc((100vw - var(--vp-layout-max-width)) / 2);padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.VPFooter[data-v-105f771f]{position:relative;z-index:var(--vp-z-index-footer);border-top:1px solid var(--vp-c-gutter);padding:32px 24px;background-color:var(--vp-c-bg)}.VPFooter.has-sidebar[data-v-105f771f]{display:none}.VPFooter[data-v-105f771f] a{text-decoration-line:underline;text-underline-offset:2px;transition:color .25s}.VPFooter[data-v-105f771f] a:hover{color:var(--vp-c-text-1)}@media(min-width:768px){.VPFooter[data-v-105f771f]{padding:32px}}.container[data-v-105f771f]{margin:0 auto;max-width:var(--vp-layout-max-width);text-align:center}.message[data-v-105f771f],.copyright[data-v-105f771f]{line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.VPLocalNavOutlineDropdown button[data-v-6ab9adca]{display:block;font-size:12px;font-weight:500;line-height:24px;color:var(--vp-c-text-2);transition:color .5s;position:relative}.VPLocalNavOutlineDropdown button[data-v-6ab9adca]:hover{color:var(--vp-c-text-1);transition:color .25s}.VPLocalNavOutlineDropdown button.open[data-v-6ab9adca]{color:var(--vp-c-text-1)}.icon[data-v-6ab9adca]{display:inline-block;vertical-align:middle;margin-left:2px;font-size:14px;transform:rotate(0);transition:transform .25s}@media(min-width:960px){.VPLocalNavOutlineDropdown button[data-v-6ab9adca]{font-size:14px}.icon[data-v-6ab9adca]{font-size:16px}}.open>.icon[data-v-6ab9adca]{transform:rotate(90deg)}.items[data-v-6ab9adca]{position:absolute;top:40px;right:16px;left:16px;display:grid;gap:1px;border:1px solid var(--vp-c-border);border-radius:8px;background-color:var(--vp-c-gutter);max-height:calc(var(--vp-vh, 100vh) - 86px);overflow:hidden auto;box-shadow:var(--vp-shadow-3)}@media(min-width:960px){.items[data-v-6ab9adca]{right:auto;left:calc(var(--vp-sidebar-width) + 32px);width:320px}}.header[data-v-6ab9adca]{background-color:var(--vp-c-bg-soft)}.top-link[data-v-6ab9adca]{display:block;padding:0 16px;line-height:48px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1)}.outline[data-v-6ab9adca]{padding:8px 0;background-color:var(--vp-c-bg-soft)}.flyout-enter-active[data-v-6ab9adca]{transition:all .2s ease-out}.flyout-leave-active[data-v-6ab9adca]{transition:all .15s ease-in}.flyout-enter-from[data-v-6ab9adca],.flyout-leave-to[data-v-6ab9adca]{opacity:0;transform:translateY(-16px)}.VPLocalNav[data-v-8f018525]{position:sticky;top:0;left:0;z-index:var(--vp-z-index-local-nav);border-bottom:1px solid var(--vp-c-gutter);padding-top:var(--vp-layout-top-height, 0px);width:100%;background-color:var(--vp-local-nav-bg-color)}.VPLocalNav.fixed[data-v-8f018525]{position:fixed}@media(min-width:960px){.VPLocalNav[data-v-8f018525]{top:var(--vp-nav-height)}.VPLocalNav.has-sidebar[data-v-8f018525]{padding-left:var(--vp-sidebar-width)}.VPLocalNav.empty[data-v-8f018525]{display:none}}@media(min-width:1280px){.VPLocalNav[data-v-8f018525]{display:none}}@media(min-width:1440px){.VPLocalNav.has-sidebar[data-v-8f018525]{padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.container[data-v-8f018525]{display:flex;justify-content:space-between;align-items:center}.menu[data-v-8f018525]{display:flex;align-items:center;line-height:24px;font-size:12px;font-weight:500;color:var(--vp-c-text-2);transition:color .5s}.menu[data-v-8f018525]:hover{color:var(--vp-c-text-1);transition:color .25s}@media(min-width:960px){.menu[data-v-8f018525]{display:none}}.menu-icon[data-v-8f018525]{margin-right:8px;font-size:14px}.menu[data-v-8f018525],[data-v-8f018525] .VPLocalNavOutlineDropdown>button{padding:12px 24px 11px}@media(min-width:768px){.menu[data-v-8f018525],[data-v-8f018525] .VPLocalNavOutlineDropdown>button{padding:12px 32px 11px}}.VPSwitch[data-v-5fd96198]{position:relative;border-radius:11px;display:block;width:40px;height:22px;flex-shrink:0;border:1px solid var(--vp-input-border-color);background-color:var(--vp-input-switch-bg-color);transition:border-color .25s!important}.VPSwitch[data-v-5fd96198]:hover{border-color:var(--vp-c-brand-1)}.check[data-v-5fd96198]{position:absolute;top:1px;left:1px;width:18px;height:18px;border-radius:50%;background-color:var(--vp-c-neutral-inverse);box-shadow:var(--vp-shadow-1);transition:transform .25s!important}.icon[data-v-5fd96198]{position:relative;display:block;width:18px;height:18px;border-radius:50%;overflow:hidden}.icon[data-v-5fd96198] [class^=vpi-]{position:absolute;top:3px;left:3px;width:12px;height:12px;color:var(--vp-c-text-2)}.dark .icon[data-v-5fd96198] [class^=vpi-]{color:var(--vp-c-text-1);transition:opacity .25s!important}.sun[data-v-fd2b5f2c]{opacity:1}.moon[data-v-fd2b5f2c],.dark .sun[data-v-fd2b5f2c]{opacity:0}.dark .moon[data-v-fd2b5f2c]{opacity:1}.dark .VPSwitchAppearance[data-v-fd2b5f2c] .check{transform:translate(18px)}.VPNavBarAppearance[data-v-0fac236d]{display:none}@media(min-width:1280px){.VPNavBarAppearance[data-v-0fac236d]{display:flex;align-items:center}}.VPMenuGroup+.VPMenuLink[data-v-c995c7e2]{margin:12px -12px 0;border-top:1px solid var(--vp-c-divider);padding:12px 12px 0}.link[data-v-c995c7e2]{display:block;border-radius:6px;padding:0 12px;line-height:32px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);text-align:left;white-space:nowrap;transition:background-color .25s,color .25s}.link[data-v-c995c7e2]:hover{color:var(--vp-c-brand-1);background-color:var(--vp-c-default-soft)}.link.active[data-v-c995c7e2]{color:var(--vp-c-brand-1)}.VPMenuGroup[data-v-0d91e4ea]{margin:12px -12px 0;border-top:1px solid var(--vp-c-divider);padding:12px 12px 0}.VPMenuGroup[data-v-0d91e4ea]:first-child{margin-top:0;border-top:0;padding-top:0}.VPMenuGroup+.VPMenuGroup[data-v-0d91e4ea]{margin-top:12px;border-top:1px solid var(--vp-c-divider)}.title[data-v-0d91e4ea]{padding:0 12px;line-height:32px;font-size:14px;font-weight:600;color:var(--vp-c-text-2);white-space:nowrap;transition:color .25s}.VPMenu[data-v-62da9740]{border-radius:12px;padding:12px;min-width:128px;border:1px solid var(--vp-c-divider);background-color:var(--vp-c-bg-elv);box-shadow:var(--vp-shadow-3);transition:background-color .5s;max-height:calc(100vh - var(--vp-nav-height));overflow-y:auto}.VPMenu[data-v-62da9740] .group{margin:0 -12px;padding:0 12px 12px}.VPMenu[data-v-62da9740] .group+.group{border-top:1px solid var(--vp-c-divider);padding:11px 12px 12px}.VPMenu[data-v-62da9740] .group:last-child{padding-bottom:0}.VPMenu[data-v-62da9740] .group+.item{border-top:1px solid var(--vp-c-divider);padding:11px 16px 0}.VPMenu[data-v-62da9740] .item{padding:0 16px;white-space:nowrap}.VPMenu[data-v-62da9740] .label{flex-grow:1;line-height:28px;font-size:12px;font-weight:500;color:var(--vp-c-text-2);transition:color .5s}.VPMenu[data-v-62da9740] .action{padding-left:24px}.VPFlyout[data-v-c0d6c551]{position:relative}.VPFlyout[data-v-c0d6c551]:hover{color:var(--vp-c-brand-1);transition:color .25s}.VPFlyout:hover .text[data-v-c0d6c551]{color:var(--vp-c-text-2)}.VPFlyout:hover .icon[data-v-c0d6c551]{fill:var(--vp-c-text-2)}.VPFlyout.active .text[data-v-c0d6c551]{color:var(--vp-c-brand-1)}.VPFlyout.active:hover .text[data-v-c0d6c551]{color:var(--vp-c-brand-2)}.button[aria-expanded=false]+.menu[data-v-c0d6c551]{opacity:0;visibility:hidden;transform:translateY(0)}.VPFlyout:hover .menu[data-v-c0d6c551],.button[aria-expanded=true]+.menu[data-v-c0d6c551]{opacity:1;visibility:visible;transform:translateY(0)}.button[data-v-c0d6c551]{display:flex;align-items:center;padding:0 12px;height:var(--vp-nav-height);color:var(--vp-c-text-1);transition:color .5s}.text[data-v-c0d6c551]{display:flex;align-items:center;line-height:var(--vp-nav-height);font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.option-icon[data-v-c0d6c551]{margin-right:0;font-size:16px}.text-icon[data-v-c0d6c551]{margin-left:4px;font-size:14px}.icon[data-v-c0d6c551]{font-size:20px;transition:fill .25s}.menu[data-v-c0d6c551]{position:absolute;top:calc(var(--vp-nav-height) / 2 + 20px);right:0;opacity:0;visibility:hidden;transition:opacity .25s,visibility .25s,transform .25s}.VPSocialLink[data-v-94c580ff]{display:flex;justify-content:center;align-items:center;width:36px;height:36px;color:var(--vp-c-text-2);transition:color .5s}.VPSocialLink[data-v-94c580ff]:hover{color:var(--vp-c-text-1);transition:color .25s}.VPSocialLink[data-v-94c580ff]>svg,.VPSocialLink[data-v-94c580ff]>[class^=vpi-social-]{width:20px;height:20px;fill:currentColor}.VPSocialLinks[data-v-0f495aab]{display:flex;justify-content:center}.VPNavBarExtra[data-v-cf5e177b]{display:none;margin-right:-12px}@media(min-width:768px){.VPNavBarExtra[data-v-cf5e177b]{display:block}}@media(min-width:1280px){.VPNavBarExtra[data-v-cf5e177b]{display:none}}.trans-title[data-v-cf5e177b]{padding:0 24px 0 12px;line-height:32px;font-size:14px;font-weight:700;color:var(--vp-c-text-1)}.item.appearance[data-v-cf5e177b],.item.social-links[data-v-cf5e177b]{display:flex;align-items:center;padding:0 12px}.item.appearance[data-v-cf5e177b]{min-width:176px}.appearance-action[data-v-cf5e177b]{margin-right:-2px}.social-links-list[data-v-cf5e177b]{margin:-4px -8px}.VPNavBarHamburger[data-v-1d142719]{display:flex;justify-content:center;align-items:center;width:48px;height:var(--vp-nav-height)}@media(min-width:768px){.VPNavBarHamburger[data-v-1d142719]{display:none}}.container[data-v-1d142719]{position:relative;width:16px;height:14px;overflow:hidden}.VPNavBarHamburger:hover .top[data-v-1d142719]{top:0;left:0;transform:translate(4px)}.VPNavBarHamburger:hover .middle[data-v-1d142719]{top:6px;left:0;transform:translate(0)}.VPNavBarHamburger:hover .bottom[data-v-1d142719]{top:12px;left:0;transform:translate(8px)}.VPNavBarHamburger.active .top[data-v-1d142719]{top:6px;transform:translate(0) rotate(225deg)}.VPNavBarHamburger.active .middle[data-v-1d142719]{top:6px;transform:translate(16px)}.VPNavBarHamburger.active .bottom[data-v-1d142719]{top:6px;transform:translate(0) rotate(135deg)}.VPNavBarHamburger.active:hover .top[data-v-1d142719],.VPNavBarHamburger.active:hover .middle[data-v-1d142719],.VPNavBarHamburger.active:hover .bottom[data-v-1d142719]{background-color:var(--vp-c-text-2);transition:top .25s,background-color .25s,transform .25s}.top[data-v-1d142719],.middle[data-v-1d142719],.bottom[data-v-1d142719]{position:absolute;width:16px;height:2px;background-color:var(--vp-c-text-1);transition:top .25s,background-color .5s,transform .25s}.top[data-v-1d142719]{top:0;left:0;transform:translate(0)}.middle[data-v-1d142719]{top:6px;left:0;transform:translate(8px)}.bottom[data-v-1d142719]{top:12px;left:0;transform:translate(4px)}.VPNavBarMenuLink[data-v-bf8a0d28]{display:flex;align-items:center;padding:0 12px;line-height:var(--vp-nav-height);font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.VPNavBarMenuLink.active[data-v-bf8a0d28],.VPNavBarMenuLink[data-v-bf8a0d28]:hover{color:var(--vp-c-brand-1)}.VPNavBarMenu[data-v-39023d39]{display:none}@media(min-width:768px){.VPNavBarMenu[data-v-39023d39]{display:flex}}:root{--docsearch-primary-color:#003dff;--docsearch-soft-primary-color:rgba(0,61,255,.1);--docsearch-subtle-color:#d6d6e7;--docsearch-text-color:#36395a;--docsearch-error-color:#ef5350;--docsearch-success-color:#e8f5e9;--docsearch-secondary-text-color:#5a5e9a;--docsearch-background-color:#f5f5fa;--docsearch-spacing:12px;--docsearch-icon-stroke-width:1.4;--docsearch-focus-color:#005fcc;--docsearch-highlight-color:#003dff;--docsearch-muted-color:#9698c3;--docsearch-muted-color-darker:rgba(120,122,165,.25);--docsearch-icon-color:#5a5e9a;--docsearch-container-background:rgba(101,108,133,.8);--docsearch-logo-color:#003dff;--docsearch-border-radius:4px;--docsearch-modal-width:800px;--docsearch-modal-height:600px;--docsearch-modal-variable-height:60dvh;--docsearch-modal-background:#f5f6f7;--docsearch-modal-shadow:rgba(0,0,0,.2) 0px 12px 28px 0px,rgba(0,0,0,.1) 0px 2px 4px 0px,hsla(0,0%,100%,.05) 0px 0px 0px 1px inset;--docsearch-searchbox-height:56px;--docsearch-searchbox-initial-height:56px;--docsearch-searchbox-background:#ffffffa6;--docsearch-searchbox-focus-background:#ffffffa6;--docsearch-actions-width:99px;--docsearch-actions-height:44px;--docsearch-hit-height:56px;--docsearch-hit-color:#444950;--docsearch-hit-highlight-color:rgba(0,61,255,.1);--docsearch-hit-background:#fff;--docsearch-key-background:#f5f5fa;--docsearch-key-color:#5a5e9a;--docsearch-key-pressed-shadow:inset 0 2px 4px rgba(120,122,165,.25);--docsearch-footer-height:52px;--docsearch-footer-background:#ffffffa6;--docsearch-footer-shadow:0 -1px 0 0 #e0e3e8,0 -3px 6px 0 rgba(69,98,155,.12);--fav-out-dur:.16s;--del-dur:.15s;--ease-smooth:cubic-bezier(.25,.8,.4,1);--ease-fast:cubic-bezier(.45,.15,.6,.9);--shadow-pop:0 4px 12px rgba(0,0,0,.06);--shimmer-bg:linear-gradient(90deg,#e0e3e8 0%,var(--docsearch-muted-color) 20%,var(--docsearch-muted-color) 60%,#e0e3e8 95%);--docsearch-dropdown-menu-background:var(--docsearch-hit-background);--docsearch-dropdown-menu-item-hover-background:var(--docsearch-modal-background)}html.dark{--docsearch-text-color:#c4c7dc;--docsearch-secondary-text-color:#b6b7d5;--docsearch-subtle-color:#212139;--docsearch-error-color:#ef5350;--docsearch-success-color:rgba(67,160,71,.2);--docsearch-highlight-color:#457aff;--docsearch-focus-color:#9ac8ff;--docsearch-background-color:#36395a;--docsearch-icon-color:#b6b7d5;--docsearch-container-background:rgba(9,10,17,.8);--docsearch-modal-background:#15172a;--docsearch-modal-shadow:inset 1px 1px 0 0 #2c2e40,0 3px 8px 0 #000309;--docsearch-searchbox-background:#000000a6;--docsearch-searchbox-focus-background:#000000a6;--docsearch-hit-color:#bec3c9;--docsearch-hit-shadow:none;--docsearch-hit-background:#090a11;--docsearch-key-background:#36395a;--docsearch-key-color:#b6b7d5;--docsearch-key-pressed-shadow:inset 0 2px 4px rgba(12,13,20,.4);--docsearch-footer-background:#000000a6;--docsearch-footer-shadow:inset 0 1px 0 0 rgba(73,76,106,.5),0 -4px 8px 0 rgba(0,0,0,.2);--docsearch-logo-color:#fff;--docsearch-muted-color:#7f8497;--shimmer-bg:linear-gradient(90deg,#e0e3e8 0%,var(--docsearch-muted-color) 20%,var(--docsearch-muted-color) 60%,#e0e3e8 95%);--docsearch-dropdown-menu-item-hover-background:#10121e}.DocSearch-Button{all:unset;align-items:center;background-color:var(--docsearch-searchbox-background);border:1px solid var(--docsearch-subtle-color);border-radius:4px;color:var(--docsearch-muted-color);cursor:pointer;display:flex;height:36px;justify-content:space-between;padding:0 8px;-webkit-user-select:none;user-select:none}.DocSearch-Button-Container{align-items:center;display:flex;height:100%}.DocSearch-Button-Container svg{color:var(--docsearch-muted-color)}.DocSearch-Back-Icon,.DocSearch-Search-Icon{color:var(--docsearch-highlight-color);stroke-width:1.6}.DocSearch-Button-Placeholder{color:var(--docsearch-muted-color);display:inline-block;font-size:1rem;line-height:normal;padding:0 12px 0 8px}.DocSearch-Button-Keys{display:flex;min-width:calc(40px + .8em)}.DocSearch-Button-Key{align-items:center;background:var(--docsearch-key-background);border:0;border:1px solid color-mix(in srgb,var(--docsearch-subtle-color) 20%,transparent);border-radius:4px;box-shadow:none!important;color:var(--docsearch-key-color);display:flex;font-size:14px;height:24px;justify-content:center;position:relative;transition-duration:.1s;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);width:24px}.DocSearch-Button-Key--ctrl{width:33px}.DocSearch-Button-Key:first-child{margin-right:.4em}@media(prefers-reduced-motion){.DocSearch-Button-Key{transition:none}}.DocSearch-Button-Key--pressed{box-shadow:var(--docsearch-key-pressed-shadow)!important;transform:translateY(1px)}@media(max-width:768px){.DocSearch-Button{width:auto}.DocSearch-Button-Keys,.DocSearch-Button-Placeholder{display:none}}.DocSearch--active{overflow:hidden!important}.DocSearch-Container,.DocSearch-Container *{box-sizing:border-box}.DocSearch-Container{-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);background-color:var(--docsearch-container-background);height:100vh;left:0;position:fixed;top:0;width:100vw;z-index:400}.DocSearch-Container a{text-decoration:none}.DocSearch-Link{appearance:none;background:none;border:0;color:var(--docsearch-highlight-color);cursor:pointer;font:inherit;margin:0;padding:0}.DocSearch-Modal{background:var(--docsearch-modal-background);border-radius:4px;box-shadow:var(--docsearch-modal-shadow);display:flex;flex-direction:column;margin:60px auto auto;max-width:var(--docsearch-modal-width);position:relative}.DocSearch-SearchBar{display:flex}.DocSearch-SearchBar-Magnifier{color:var(--docsearch-highlight-color)}.DocSearch-Form{align-items:center;background:var(--docsearch-searchbox-focus-background);border-bottom:1px solid var(--docsearch-subtle-color);border-radius:4px 4px 0 0;display:flex;height:var( --docsearch-searchbox-height,var(--docsearch-searchbox-initial-height) );margin:0;min-height:var(--docsearch-searchbox-initial-height);padding-block:var(--docsearch-spacing);padding-inline:16px;position:relative;width:100%}.DocSearch-Input,.DocSearch-Modal-heading{appearance:none;background:transparent;border:0;color:var(--docsearch-text-color);flex:1;font:inherit;font-size:1.2em;font-weight:300;height:100%;line-height:1.4;outline:none;overflow-y:hidden;padding-block-start:4px;padding-inline-start:8px;resize:none;width:80%}.DocSearch-Input::placeholder{color:var(--docsearch-muted-color);opacity:1}.DocSearch-Input::-webkit-search-cancel-button,.DocSearch-Input::-webkit-search-decoration,.DocSearch-Input::-webkit-search-results-button,.DocSearch-Input::-webkit-search-results-decoration{display:none}.DocSearch-Actions{align-items:center;display:flex;gap:8px;height:var(--docsearch-actions-height);justify-content:flex-end;padding:0 2px;width:var(--docsearch-actions-width)}.DocSearch-Divider{border-left:1px solid var(--docsearch-subtle-color);height:16px}.DocSearch-Action{align-items:center;color:var(--docsearch-highlight-color);display:flex;justify-content:center;min-height:24px;min-width:24px}.DocSearch-Action,.DocSearch-AskAi-Return,.DocSearch-LoadingIndicator,.DocSearch-MagnifierLabel{margin:0;padding:0}.DocSearch-AskAi-Return{cursor:pointer}.DocSearch-AskAi-Return,.DocSearch-LoadingIndicator,.DocSearch-MagnifierLabel{align-items:center;color:var(--docsearch-highlight-color);display:flex;justify-content:center}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Action{animation:none;appearance:none;background:none;border:0;border-radius:50%;color:var(--docsearch-icon-color);cursor:pointer;right:0;stroke-width:var(--docsearch-icon-stroke-width)}}.DocSearch-Action,.DocSearch-AskAi-Return{animation:fade-in .1s ease-in forwards;appearance:none;background:none;border:none;border-radius:var(--docsearch-border-radius);color:var(--docsearch-icon-color);cursor:pointer;padding:2px;right:0;stroke-width:var(--docsearch-icon-stroke-width)}.DocSearch-AskAi-Return[hidden],.DocSearch-Close[hidden],.DocSearch-Input[hidden],.DocSearch-StreamingIndicator[hidden]{display:none}.DocSearch-Action:hover,.DocSearch-AskAi-Return:hover{background:var(--docsearch-soft-primary-color);color:var(--docsearch-highlight-color)}.DocSearch-LoadingIndicator svg,.DocSearch-MagnifierLabel svg{color:var(--docsearch-icon-color);height:24px;width:24px}.DocSearch-Form:focus-within .DocSearch-MagnifierLabel svg{color:var(--docsearch-highlight-color)}.DocSearch-Clear{appearance:none;background:none;border:0;color:var(--docsearch-highlight-color);cursor:pointer;flex:none;font:inherit;font-size:.9em;font-weight:300;height:28px;margin-left:var(--docsearch-spacing);outline:none;overflow:hidden;padding:0;-webkit-user-select:none;user-select:none;white-space:nowrap}.DocSearch-Clear:focus-visible,.DocSearch-Close:focus-visible{border-radius:4px;outline:2px solid var(--docsearch-focus-color);outline-offset:1px}.DocSearch-Dropdown{height:var(--docsearch-modal-variable-height);max-height:calc(var(--docsearch-modal-height) - var(--docsearch-spacing) - var(--docsearch-footer-height));min-height:var(--docsearch-spacing);overflow-y:auto;overflow-y:overlay;padding:0 var(--docsearch-spacing);scrollbar-color:var(--docsearch-muted-color) var(--docsearch-modal-background);scrollbar-width:thin}.DocSearch-Dropdown::-webkit-scrollbar{width:12px}.DocSearch-Dropdown::-webkit-scrollbar-track{background:transparent}.DocSearch-Dropdown::-webkit-scrollbar-thumb{background-color:var(--docsearch-muted-color);border:3px solid var(--docsearch-modal-background);border-radius:20px}.DocSearch-Dropdown-Container ul{list-style:none;margin:0;padding:0}.DocSearch-Label{color:var(--docsearch-secondary-text-color);font-size:.875em;font-weight:400;line-height:1.6em}.DocSearch-Help,.DocSearch-NoResults-Help{color:var(--docsearch-secondary-text-color);font-size:.8em;font-weight:300;line-height:1.5em;margin:0;-webkit-user-select:none;user-select:none}.DocSearch-Title{color:var(--docsearch-text-color);font-size:1.1em;font-weight:300;line-height:.5em;vertical-align:middle}.DocSearch-Title strong{font-weight:500}.DocSearch-Logo a{display:flex}.DocSearch-Logo svg{color:var(--docsearch-logo-color);margin-left:8px}.DocSearch-Hits:last-of-type{margin-bottom:24px}.DocSearch-Hits mark{background:none;color:var(--docsearch-highlight-color)}.DocSearch-HitsFooter{color:var(--docsearch-muted-color);display:flex;font-size:.85em;justify-content:center;margin-bottom:var(--docsearch-spacing);padding:var(--docsearch-spacing)}.DocSearch-HitsFooter a{border-bottom:1px solid;color:inherit}.DocSearch-Hit{border-radius:4px;display:flex;padding-bottom:4px;position:relative;scroll-margin-top:40px}.DocSearch-Hit:first-of-type{margin-top:4px}.DocSearch-Hit a,.DocSearch-Hit--AskAI{background:var(--docsearch-hit-background);border-radius:4px;cursor:pointer;display:block;padding-left:var(--docsearch-spacing);width:100%}.DocSearch-Hit-source{background:var(--docsearch-modal-background);color:var(--docsearch-text-color);font-size:.9em;font-weight:600;line-height:32px;margin:0 -4px;padding:8px 4px 4px;position:sticky;top:0;z-index:10}.DocSearch-Hit-Tree{color:var(--docsearch-muted-color);height:var(--docsearch-hit-height);opacity:.5;stroke-width:var(--docsearch-icon-stroke-width);width:24px}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit--AskAI,.DocSearch-Hit[aria-selected=true] a{background-color:var(--docsearch-hit-highlight-color)}.DocSearch-Conversation-History .DocSearch-Hit[aria-selected=true] a{background-color:var(--docsearch-hit-background)}.DocSearch-Hit mark{color:var(--docsearch-highlight-color);text-decoration:underline;text-underline-offset:.3em}.DocSearch-Hit-Container{align-items:center;color:var(--docsearch-text-color);display:flex;flex-direction:row;height:var(--docsearch-hit-height);padding:0 var(--docsearch-spacing) 0 0}.DocSearch-Hit-icon{color:var(--docsearch-secondary-text-color);height:20px;width:20px}.DocSearch-Hit-action,.DocSearch-Hit-icon{stroke-width:var(--docsearch-icon-stroke-width)}.DocSearch-Hit-action{align-items:center;color:var(--docsearch-muted-color);display:flex;height:22px;width:22px}.DocSearch-Hit-action svg{display:block;height:18px;width:18px}.DocSearch-Hit-action+.DocSearch-Hit-action{margin-left:6px}.DocSearch-Hit-action-button{appearance:none;background:none;border:0;border-radius:50%;color:inherit;cursor:pointer;padding:2px}svg.DocSearch-Hit-Select-Icon{display:none}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-Select-Icon{display:block}.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{background:#0003;transition:background-color .1s ease-in}.DocSearch-Hit-action-button:focus path,.DocSearch-Hit-action-button:hover path{fill:#fff}.DocSearch-Hit-content-wrapper{display:flex;flex:1 1 auto;flex-direction:column;font-weight:400;gap:4px;justify-content:center;line-height:1.2em;margin:0 8px;overflow-x:hidden;position:relative;text-overflow:ellipsis;white-space:nowrap;width:80%}.DocSearch-Hit-title{font-size:.9em}.DocSearch-Hit-path{color:var(--docsearch-secondary-text-color);font-size:.75em}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-Tree,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-text,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-title{color:var(--docsearch-text-color)}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-action,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-icon,.DocSearch-Hit[aria-selected=true] mark{color:var(--docsearch-highlight-color)}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{background:#0003;transition:none}}.DocSearch-AskAiScreen,.DocSearch-ErrorScreen,.DocSearch-NoResults,.DocSearch-StartScreen{align-items:center;color:var(--docsearch-secondary-text-color);display:flex;flex-direction:column;font-size:1.25em;font-weight:400;justify-content:center;margin:0 auto;text-align:center;width:80%}.DocSearch-AskAiScreen,.DocSearch-ErrorScreen,.DocSearch-NoResults{max-height:80%}.DocSearch-StartScreen{height:100%}.DocSearch-NoResults{gap:.8em;margin-top:2em}.DocSearch-NoResults--withAskAi{justify-content:flex-start;margin-top:0}.DocSearch-AskAiScreen,.DocSearch-ErrorScreen,.DocSearch-StartScreen{gap:24px}.DocSearch-StartScreen-Icon{height:64px;stroke:var(--docsearch-icon-color);width:64px}.DocSearch-Screen-Icon{color:var(--docsearch-icon-color)}.DocSearch-NoResults-Prefill-List{display:flex;flex-direction:column;gap:12px;text-align:center}.DocSearch-NoResults-Prefill-List-Items{display:flex;flex-direction:column;gap:2px}.DocSearch-NoResults-Prefill-List-Items p{align-items:center;display:flex;margin:0;text-align:left}.DocSearch-Prefill{align-items:center;appearance:none;background:none;border:0;border-radius:1em;color:var(--docsearch-highlight-color);cursor:pointer;display:inline-flex;font-size:.8em;font-weight:300;gap:4px;height:40px;padding:0 4px}.DocSearch-Prefill:focus,.DocSearch-Prefill:hover{outline:none;text-decoration:underline}.DocSearch-Footer{align-items:center;background:var(--docsearch-footer-background);border-radius:0 0 4px 4px;border-top:1px solid var(--docsearch-subtle-color);display:flex;flex-direction:row-reverse;flex-shrink:0;height:var(--docsearch-footer-height);justify-content:space-between;padding:0 var(--docsearch-spacing);position:relative;-webkit-user-select:none;user-select:none;width:100%;z-index:300}.DocSearch-Commands{color:var(--docsearch-muted-color);display:flex;gap:16px;list-style:none;margin:0;padding:0}.DocSearch-Commands li,.DocSearch-Commands-Key{align-items:center;display:flex}.DocSearch-Commands-Key{background-color:var(--docsearch-background-color);border:0;border-radius:2px;box-shadow:none!important;color:var(--docsearch-icon-color);height:24px;justify-content:center;margin-right:4px;width:24px}.DocSearch-Commands-Key:last-of-type{margin-right:8px}.DocSearch-Escape-Key{font-size:10px;font-weight:300;letter-spacing:normal;line-height:16px;text-align:center;text-transform:uppercase}.DocSearch-VisuallyHiddenForAccessibility{clip:rect(0 0 0 0);clip-path:inset(50%);height:1px;overflow:hidden;position:absolute;white-space:nowrap;width:1px}.DocSearch-AskAi-Section{display:flex;flex-direction:column;gap:8px;padding:12px 0}.DocSearch-Hit-AskAIButton{align-items:center;color:var(--docsearch-text-color);display:flex;flex-direction:row}.DocSearch-Hit-AskAIButton-icon{color:var(--docsearch-icon-color);flex-shrink:0;margin-right:12px}.DocSearch-Hit-AskAIButton-title{color:var(--docsearch-hit-color);display:flex;flex:1 1 auto;font-weight:400;gap:4px;overflow-x:hidden;position:relative;text-overflow:ellipsis;white-space:nowrap;width:80%}.DocSearch-Hit-AskAIButton-title-query{background:none;margin-left:4px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.DocSearch-Hit-AskAIButton-title mark{text-decoration:none}@keyframes fade-in{0%{opacity:0}to{opacity:1}}.DocSearch-AskAiScreen-Container{display:flex;flex-direction:column;gap:0;height:100%;justify-content:flex-start;padding:0;text-align:left;width:100%}.DocSearch-AskAiScreen-Disclaimer{align-self:flex-start;display:flex;font-size:.6em;font-weight:300;margin:0;padding:1.5em 0 .5em;text-align:left}.DocSearch-AskAiScreen-Body{gap:24px;width:100%}.DocSearch-AskAiScreen-Body,.DocSearch-AskAiScreen-Response,.DocSearch-AskAiScreen-Response-Container{display:flex;flex-direction:column}.DocSearch-AskAiScreen-Response{align-self:flex-start;background:var(--docsearch-hit-background);border-radius:4px;color:var(--docsearch-text-color);font-size:.8em;gap:1em;margin-bottom:8px;padding:24px;width:100%}.DocSearch-AskAiScreen-Query{font-size:1.25em;font-weight:600;line-break:loose;line-height:1.4;margin:0}.DocSearch-AskAiScreen-Answer{line-height:1.5}.DocSearch-AskAiScreen-Answer,.DocSearch-AskAiScreen-ThinkingDots{color:var(--docsearch-secondary-text-color);font-weight:400;margin:0}.DocSearch-AskAiScreen-ThinkingDots{font-size:.8em}.DocSearch-AskAiScreen-Answer-Footer{align-items:center;display:flex;flex-direction:row;gap:8px;justify-content:space-between}.DocSearch-AskAiScreen-Actions{align-items:center;display:flex;flex-direction:row;gap:12px;margin-left:auto}.DocSearch-AskAiScreen-ActionButton{align-items:center;background:none;border:none;border-radius:4px;cursor:pointer;display:flex;justify-content:center;margin:0;padding:4px;transition:background-color .2s ease;width:24px}.DocSearch-AskAiScreen-ActionButton:hover{background:var(--docsearch-hit-highlight-color)}.DocSearch-AskAiScreen-ActionButton svg{color:var(--docsearch-icon-color);height:20px;stroke-width:1.5;width:20px}.DocSearch-AskAiScreen-CopyButton--copied{background-color:var(--docsearch-success-color);cursor:default}.DocSearch-AskAiScreen-Error{align-items:baseline;background-color:#ef53501a;border-radius:4px;color:var(--docsearch-error-color);display:flex;font-size:1em;font-weight:400;gap:8px;padding:1em}.DocSearch-AskAiScreen-MessageContent{display:flex;flex-direction:column;row-gap:1em}.DocSearch-AskAiScreen-Error svg,.DocSearch-AskAiScreen-MessageContent-Tool svg{flex-shrink:0;height:16px;width:16px}.DocSearch-AskAiScreen-Error p{margin:0}.DocSearch-AskAiScreen-Error .DocSearch-Markdown-Content{color:var(--docsearch-error-color)}.DocSearch-AskAiScreen-FeedbackText{color:var(--docsearch-muted-color);font-size:.7em;font-weight:400;margin:0}.DocSearch-AskAiScreen-FeedbackText--visible{animation:fade-in .3s ease-in forwards}.DocSearch-AskAiScreen-RelatedSources{display:flex;flex-direction:column;gap:4px;width:100%}.DocSearch-AskAiScreen-RelatedSources-List{display:flex;flex-direction:row;flex-wrap:wrap;gap:12px;width:100%}.DocSearch-AskAiScreen-RelatedSources-Title{color:var(--docsearch-secondary-color);font-size:.7em;font-weight:400;margin:0;padding:6px 0}.DocSearch-AskAiScreen-RelatedSources-NoResults{color:var(--docsearch-text-color);font-size:.8rem;font-weight:400;margin:0}.DocSearch-AskAiScreen-RelatedSources-Error{color:var(--docsearch-error-color);font-size:.8rem;font-weight:400;margin:0}.DocSearch-AskAiScreen-RelatedSources-Item-Link{align-items:center;background:var(--docsearch-hit-background);border-radius:4px;color:var(--docsearch-text-color);display:flex;font-size:.75em;gap:6px;max-width:70%;padding:12px 8px;text-decoration:none;transition:background-color .2s ease}.DocSearch-AskAiScreen-RelatedSources-Item-Link svg{color:var(--docsearch-icon-color);flex-shrink:0;stroke-width:1.2}.DocSearch-AskAiScreen-RelatedSources-Item-Link span{flex:1 1 0;font-weight:500;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.DocSearch-AskAiScreen-ExchangesList{display:flex;flex-direction:column;gap:24px;margin:8px 0}.DocSearch-AskAiScreen-RelatedSources-Item-Link:hover{background:var(--docsearch-hit-highlight-color)}.DocSearch-Markdown-Content{color:var(--docsearch-text-color);font-size:.9355em;line-height:1.6;word-wrap:break-word}.DocSearch-Markdown-Content--streaming{animation:fade-in .3s ease-in-out both}.DocSearch-Markdown-Content p{margin:1em 0}.DocSearch-Markdown-Content p:last-child{margin-bottom:0}.DocSearch-Markdown-Content p:first-child{margin-top:0}.DocSearch-Markdown-Content code{border-radius:3px;font-family:ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace;font-size:.9em;letter-spacing:normal;margin:0;padding:.2em 0}.DocSearch-Markdown-Content code,.DocSearch-Markdown-Content pre{background-color:var(--docsearch-key-background);color:var(--docsearch-text-color)}.DocSearch-Markdown-Content pre{border-radius:6px;margin:1.5em 0;overflow-x:auto;padding:1.2em}.DocSearch-Markdown-Content pre code{background-color:transparent;border-radius:0;color:inherit;font-size:.8em;margin:0;padding:0;white-space:pre-wrap;word-wrap:break-word;line-height:1.5}.DocSearch-Markdown-Content h1,.DocSearch-Markdown-Content h2,.DocSearch-Markdown-Content h3,.DocSearch-Markdown-Content h4,.DocSearch-Markdown-Content h5,.DocSearch-Markdown-Content h6{color:var(--docsearch-text-color);font-weight:600;letter-spacing:-.02em;line-height:1.3;margin:1em 0}.DocSearch-Markdown-Content h1{font-size:1.5em}.DocSearch-Markdown-Content h2{font-size:1.2em}.DocSearch-Markdown-Content h3{font-size:1em}.DocSearch-Markdown-Content h4{font-size:.9em}.DocSearch-Markdown-Content h5,.DocSearch-Markdown-Content h6{font-size:.8em}.DocSearch-Markdown-Content ol,.DocSearch-Markdown-Content ul{color:var(--docsearch-text-color);margin:1.2em 0;padding-left:1.5em}.DocSearch-Markdown-Content ul{list-style-type:disc}.DocSearch-Markdown-Content ol{list-style-type:decimal}.DocSearch-Markdown-Content li{color:var(--docsearch-text-color);line-height:1.6;margin:.8em 0;padding-left:.3em}.DocSearch-Markdown-Content li>ol,.DocSearch-Markdown-Content li>ul{margin:.5em}.DocSearch-Markdown-Content li::marker{color:var(--docsearch-muted-color)}.DocSearch-Markdown-Content a{color:var(--docsearch-highlight-color);text-decoration:none;transition:all .2s ease}.DocSearch-Markdown-Content a:hover{opacity:.9;text-decoration:underline}.DocSearch-Markdown-Content blockquote{border-left:4px solid var(--docsearch-hit-highlight-color);color:var(--docsearch-secondary-text-color);font-style:italic;margin:1.5em 0;padding:.5em 0 .5em 1em}.DocSearch-Markdown-Content hr{border:none;border-top:1px solid var(--docsearch-subtle-color);margin:1em 0}.DocSearch-Markdown-Content table{border-collapse:collapse;margin:1.5em 0;width:100%}.DocSearch-Markdown-Content td,.DocSearch-Markdown-Content th{border:1px solid var(--docsearch-subtle-color);padding:.75em;text-align:left}.DocSearch-Markdown-Content th{background-color:var(--docsearch-hit-background);font-weight:600}.DocSearch-AskAiScreen-MessageContent-Reasoning{align-items:center;color:var(--docsearch-muted-color);display:flex;font-size:1em;gap:4px}.DocSearch-AskAiScreen-MessageContent-Reasoning svg{color:var(--docsearch-icon-color)}.DocSearch-AskAiScreen-MessageContent-Tool{align-items:center;color:var(--docsearch-muted-color);display:flex;line-height:1.2;width:100%}.DocSearch-AskAiScreen-MessageContent-Tool.Tool--Result{padding-top:0}.DocSearch-AskAiScreen-MessageContent-Tool>svg{color:var(--docsearch-icon-color);margin-right:8px}.DocSearch-AskAiScreen-MessageContent-Tool-Query{color:var(--docsearch-muted-color);transition:box-shadow .2s ease}.DocSearch-AskAiScreen-MessageContent-Tool-Query svg{color:var(--docsearch-muted-color)}.DocSearch-AskAiScreen-MessageContent-Tool-Query:hover{box-shadow:0 1px 0 0 var(--docsearch-highlight-color);color:var(--docsearch-highlight-color);cursor:pointer}.DocSearch-AskAiScreen-MessageContent-Tool-Query:hover svg{color:var(--docsearch-highlight-color)}.DocSearck-AskAiScreen-MessageContent-Stopped{color:var(--docsearch-muted-color);font-style:italic;margin-top:1em}.DocSearch-AskAiScreen-SmallerLoadingIcon{height:16px;width:16px}.shimmer{background:var(--shimmer-bg);background-clip:text;-webkit-background-clip:text;background-size:200% auto;color:transparent;display:flex;-webkit-text-fill-color:transparent;animation:shimmerText 2.5s linear infinite;pointer-events:none}@keyframes shimmerText{0%{background-position:200% 0}to{background-position:-200% 0}}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes pulse{0%,to{opacity:.3}50%{opacity:.6}}@media(max-width:768px){:root{--docsearch-spacing:10px;--docsearch-footer-height:48px}.DocSearch-Input{font-size:1rem}.DocSearch-Hit-AskAIButton-icon{margin-right:8px}body:has(.DocSearch-Container){overflow:hidden;position:fixed}.DocSearch-Dropdown{height:100%}.DocSearch-Container{height:calc(var(--docsearch-vh, 1vh)*100);height:100dvh}.DocSearch-Footer{border-radius:0;bottom:0;position:static}.DocSearch-Hit-content-wrapper{display:flex;position:relative;width:80%}.DocSearch-Modal{border-radius:0;box-shadow:none;height:calc(var(--docsearch-vh, 1vh)*100);height:100dvh;margin:0;max-width:100%;width:100%}.DocSearch-Dropdown{max-height:none}.DocSearch-Commands,.DocSearch-Hit-Tree{display:none}.DocSearch-AskAiScreen-Response-Container{flex-direction:column}.DocSearch-AskAiScreen-RelatedSources,.DocSearch-AskAiScreen-Response{width:100%}}.DocSearch-CodeSnippet{position:relative}.DocSearch-CodeSnippet-CopyButton{align-items:center;background:var(--docsearch-key-background);border:none;border-radius:4px;color:var(--docsearch-text-color);cursor:pointer;display:flex;font-size:.75em;padding:.2em .6em;position:absolute;right:8px;top:8px;transition:opacity .2s ease}.DocSearch-CodeSnippet-CopyButton:hover{opacity:.8}.DocSearch-CodeSnippet-CopyButton:active{opacity:.6}.DocSearch-CodeSnippet-CopyButton svg{height:16px;margin-right:4px;width:16px}.DocSearch-CodeSnippet-CheckIcon,.DocSearch-CodeSnippet-CopyButton--copied .DocSearch-CodeSnippet-CopyIcon{display:none}.DocSearch-CodeSnippet-CopyButton--copied .DocSearch-CodeSnippet-CheckIcon{display:inline-block}.DocSearch-Markdown-Content--streaming .DocSearch-CodeSnippet-CopyButton{display:none}.DocSearch-NewConversationScreen{padding:3em var(--docsearch-spacing)}.DocSearch-NewConversationScreen-Title{color:var(--docsearch-text-color);font-size:26px;font-weight:600;margin-bottom:.15em}.DocSearch-NewConversationScreen-Description{color:var(--docsearch-muted-color);font-size:14px}.DocSearch-NewConversationScreen-SuggestedQuestions{align-items:start;display:flex;flex-direction:column;gap:var(--docsearch-spacing);margin-top:1.5em}.DocSearch-NewConversationScreen-SuggestedQuestion{align-items:center;background-color:var(--docsearch-searchbox-background);border:1px solid var(--docsearch-subtle-color);border-radius:var(--docsearch-border-radius);color:var(--docsearch-text-color);cursor:pointer;display:inline-flex;height:40px;justify-content:center;padding:12px}.DocSearch-Menu{position:relative}.DocSearch-Menu-content{background-color:var(--docsearch-dropdown-menu-background);border-radius:var(--docsearch-border-radius);box-shadow:0 0 0 1px #21243d0d,0 8px 16px -4px #21243d40;display:none;flex-direction:column;min-width:195px;padding:8px 0;position:absolute;right:0;top:calc(100% + 12px);z-index:422}.DocSearch-Menu-content.open{display:flex}.DocSearch-Menu-item{align-items:center;background-color:transparent;border:0;color:var(--docsearch-text-color);cursor:pointer;display:flex;font-size:14px;gap:8px;padding:10px 16px;white-space:nowrap}.DocSearch-Menu-item:hover{background-color:var(--docsearch-dropdown-menu-item-hover-background)}[class*=DocSearch]{--docsearch-actions-height: auto;--docsearch-actions-width: auto;--docsearch-background-color: var(--vp-c-bg-soft);--docsearch-container-background: var(--vp-backdrop-bg-color);--docsearch-focus-color: var(--vp-c-brand-1);--docsearch-footer-background: var(--vp-c-bg);--docsearch-highlight-color: var(--vp-c-brand-1);--docsearch-hit-background: var(--vp-c-default-soft);--docsearch-hit-color: var(--vp-c-text-1);--docsearch-hit-highlight-color: var(--vp-c-brand-soft);--docsearch-icon-color: var(--vp-c-text-2);--docsearch-key-background: transparent;--docsearch-key-color: var(--vp-c-text-2);--docsearch-modal-background: var(--vp-c-bg-soft);--docsearch-muted-color: var(--vp-c-text-2);--docsearch-primary-color: var(--vp-c-brand-1);--docsearch-searchbox-focus-background: transparent;--docsearch-secondary-text-color: var(--vp-c-text-2);--docsearch-soft-primary-color: var(--vp-c-brand-soft);--docsearch-subtle-color: var(--vp-c-divider);--docsearch-success-color: var(--vp-c-brand-soft);--docsearch-text-color: var(--vp-c-text-1)}.dark [class*=DocSearch]{--docsearch-modal-shadow: none}.DocSearch-Clear{padding:0 8px}.DocSearch-Commands-Key{padding:4px;border:1px solid var(--docsearch-subtle-color);border-radius:4px}.DocSearch-Hit a:focus-visible{outline:2px solid var(--docsearch-focus-color)}.DocSearch-Logo [class^=cls-]{fill:currentColor}.DocSearch-SearchBar+.DocSearch-Footer{border-top-color:transparent}.DocSearch-Title{font-size:revert;line-height:revert}.DocSearch-Button{--docsearch-muted-color: var(--docsearch-text-color);--docsearch-searchbox-background: transparent;width:auto;padding:2px 12px;border:none;border-radius:8px}.DocSearch-Search-Icon{color:inherit!important;width:20px;height:20px}@media(min-width:768px){.DocSearch-Button{--docsearch-muted-color: var(--docsearch-secondary-text-color);--docsearch-searchbox-background: var(--vp-c-bg-alt)}.DocSearch-Search-Icon{width:15px;height:15px}.DocSearch-Button-Placeholder{font-size:13px}}.DocSearch-Button-Keys{min-width:auto;margin:0;padding:4px 6px;background-color:var(--docsearch-key-background);border:1px solid var(--docsearch-subtle-color);border-radius:4px;font-size:12px;line-height:1;color:var(--docsearch-key-color)}.DocSearch-Button-Keys>*{display:none}.DocSearch-Button-Keys:after{direction:ltr;content:"Ctrl K"}.mac .DocSearch-Button-Keys:after{content:"⌘ K"}.VPNavBarSearch{display:flex;align-items:center}@media(min-width:768px){.VPNavBarSearch{flex-grow:1;padding-left:24px}}@media(min-width:960px){.VPNavBarSearch{padding-left:32px}}.VPNavBarSocialLinks[data-v-cd4c0ab6]{display:none}@media(min-width:1280px){.VPNavBarSocialLinks[data-v-cd4c0ab6]{display:flex;align-items:center}}.title[data-v-e5d5fdf8]{display:flex;align-items:center;border-bottom:1px solid transparent;width:100%;height:var(--vp-nav-height);font-size:16px;font-weight:600;color:var(--vp-c-text-1);transition:opacity .25s}@media(min-width:960px){.title[data-v-e5d5fdf8]{flex-shrink:0}.VPNavBarTitle.has-sidebar .title[data-v-e5d5fdf8]{border-bottom-color:var(--vp-c-divider)}}[data-v-e5d5fdf8] .logo{margin-right:8px;height:var(--vp-nav-logo-height)}.VPNavBarTranslations[data-v-1c347a57]{display:none}@media(min-width:1280px){.VPNavBarTranslations[data-v-1c347a57]{display:flex;align-items:center}}.title[data-v-1c347a57]{padding:0 24px 0 12px;line-height:32px;font-size:14px;font-weight:700;color:var(--vp-c-text-1)}.VPNavBar[data-v-a10c09a7]{position:relative;height:var(--vp-nav-height);pointer-events:none;white-space:nowrap;transition:background-color .25s}.VPNavBar.screen-open[data-v-a10c09a7]{transition:none;background-color:var(--vp-nav-bg-color);border-bottom:1px solid var(--vp-c-divider)}.VPNavBar[data-v-a10c09a7]:not(.home){background-color:var(--vp-nav-bg-color)}@media(min-width:960px){.VPNavBar[data-v-a10c09a7]:not(.home){background-color:transparent}.VPNavBar[data-v-a10c09a7]:not(.has-sidebar):not(.home.top){background-color:var(--vp-nav-bg-color)}}.wrapper[data-v-a10c09a7]{padding:0 8px 0 24px}@media(min-width:768px){.wrapper[data-v-a10c09a7]{padding:0 32px}}@media(min-width:960px){.VPNavBar.has-sidebar .wrapper[data-v-a10c09a7]{padding:0}}.container[data-v-a10c09a7]{display:flex;justify-content:space-between;margin:0 auto;max-width:calc(var(--vp-layout-max-width) - 64px);height:var(--vp-nav-height);pointer-events:none}.container>.title[data-v-a10c09a7],.container>.content[data-v-a10c09a7]{pointer-events:none}.container[data-v-a10c09a7] *{pointer-events:auto}@media(min-width:960px){.VPNavBar.has-sidebar .container[data-v-a10c09a7]{max-width:100%}}.title[data-v-a10c09a7]{flex-shrink:0;height:calc(var(--vp-nav-height) - 1px);transition:background-color .5s}@media(min-width:960px){.VPNavBar.has-sidebar .title[data-v-a10c09a7]{position:absolute;top:0;left:0;z-index:2;padding:0 32px;width:var(--vp-sidebar-width);height:var(--vp-nav-height);background-color:transparent}}@media(min-width:1440px){.VPNavBar.has-sidebar .title[data-v-a10c09a7]{padding-left:max(32px,calc((100% - (var(--vp-layout-max-width) - 64px)) / 2));width:calc((100% - (var(--vp-layout-max-width) - 64px)) / 2 + var(--vp-sidebar-width) - 32px)}}.content[data-v-a10c09a7]{flex-grow:1}@media(min-width:960px){.VPNavBar.has-sidebar .content[data-v-a10c09a7]{position:relative;z-index:1;padding-left:var(--vp-sidebar-width)}.VPNavBar.has-sidebar .content-body[data-v-a10c09a7]{padding-right:32px}}@media(min-width:1440px){.VPNavBar.has-sidebar .content[data-v-a10c09a7]{padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}.VPNavBar.has-sidebar .content-body[data-v-a10c09a7]{padding-right:calc((100vw - var(--vp-layout-max-width)) / 2 + 32px)}}.content-body[data-v-a10c09a7]{display:flex;justify-content:flex-end;align-items:center;height:var(--vp-nav-height);transition:background-color .5s}@media(min-width:960px){.VPNavBar:not(.home.top) .content-body[data-v-a10c09a7]{position:relative;background-color:var(--vp-nav-bg-color)}.VPNavBar:not(.has-sidebar):not(.home.top) .content-body[data-v-a10c09a7]{background-color:transparent}}@media(max-width:767px){.content-body[data-v-a10c09a7]{column-gap:.5rem}}.menu+.translations[data-v-a10c09a7]:before,.menu+.appearance[data-v-a10c09a7]:before,.menu+.social-links[data-v-a10c09a7]:before,.translations+.appearance[data-v-a10c09a7]:before,.appearance+.social-links[data-v-a10c09a7]:before{margin-right:8px;margin-left:8px;width:1px;height:24px;background-color:var(--vp-c-divider);content:""}.menu+.appearance[data-v-a10c09a7]:before,.translations+.appearance[data-v-a10c09a7]:before{margin-right:16px}.appearance+.social-links[data-v-a10c09a7]:before{margin-left:16px}.social-links[data-v-a10c09a7]{margin-right:-8px}.divider[data-v-a10c09a7]{width:100%;height:1px}@media(min-width:960px){.VPNavBar.has-sidebar .divider[data-v-a10c09a7]{padding-left:var(--vp-sidebar-width)}}@media(min-width:1440px){.VPNavBar.has-sidebar .divider[data-v-a10c09a7]{padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.divider-line[data-v-a10c09a7]{width:100%;height:1px;transition:background-color .5s}.VPNavBar:not(.home) .divider-line[data-v-a10c09a7]{background-color:var(--vp-c-gutter)}@media(min-width:960px){.VPNavBar:not(.home.top) .divider-line[data-v-a10c09a7]{background-color:var(--vp-c-gutter)}.VPNavBar:not(.has-sidebar):not(.home.top) .divider[data-v-a10c09a7]{background-color:var(--vp-c-gutter)}}.VPNavScreenAppearance[data-v-0c49eb9f]{display:flex;justify-content:space-between;align-items:center;border-radius:8px;padding:12px 14px 12px 16px;background-color:var(--vp-c-bg-soft)}.text[data-v-0c49eb9f]{line-height:24px;font-size:12px;font-weight:500;color:var(--vp-c-text-2)}.VPNavScreenMenuLink[data-v-f0c07abe]{display:block;border-bottom:1px solid var(--vp-c-divider);padding:12px 0 11px;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:border-color .25s,color .25s}.VPNavScreenMenuLink[data-v-f0c07abe]:hover{color:var(--vp-c-brand-1)}.VPNavScreenMenuGroupLink[data-v-1c460cf9]{display:block;margin-left:12px;line-height:32px;font-size:14px;font-weight:400;color:var(--vp-c-text-1);transition:color .25s}.VPNavScreenMenuGroupLink[data-v-1c460cf9]:hover{color:var(--vp-c-brand-1)}.VPNavScreenMenuGroupSection[data-v-b9d15d51]{display:block}.title[data-v-b9d15d51]{line-height:32px;font-size:13px;font-weight:700;color:var(--vp-c-text-2);transition:color .25s}.VPNavScreenMenuGroup[data-v-8ab0c53a]{border-bottom:1px solid var(--vp-c-divider);height:48px;overflow:hidden;transition:border-color .5s}.VPNavScreenMenuGroup .items[data-v-8ab0c53a]{visibility:hidden}.VPNavScreenMenuGroup.open .items[data-v-8ab0c53a]{visibility:visible}.VPNavScreenMenuGroup.open[data-v-8ab0c53a]{padding-bottom:10px;height:auto}.VPNavScreenMenuGroup.open .button[data-v-8ab0c53a]{padding-bottom:6px;color:var(--vp-c-brand-1)}.VPNavScreenMenuGroup.open .button-icon[data-v-8ab0c53a]{transform:rotate(45deg)}.button[data-v-8ab0c53a]{display:flex;justify-content:space-between;align-items:center;padding:12px 4px 11px 0;width:100%;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.button[data-v-8ab0c53a]:hover{color:var(--vp-c-brand-1)}.button-icon[data-v-8ab0c53a]{transition:transform .25s}.group[data-v-8ab0c53a]:first-child{padding-top:0}.group+.group[data-v-8ab0c53a],.group+.item[data-v-8ab0c53a]{padding-top:4px}.VPNavScreenTranslations[data-v-85de7b6f]{height:24px;overflow:hidden}.VPNavScreenTranslations.open[data-v-85de7b6f]{height:auto}.title[data-v-85de7b6f]{display:flex;align-items:center;font-size:14px;font-weight:500;color:var(--vp-c-text-1)}.icon[data-v-85de7b6f]{font-size:16px}.icon.lang[data-v-85de7b6f]{margin-right:8px}.icon.chevron[data-v-85de7b6f]{margin-left:4px}.list[data-v-85de7b6f]{padding:4px 0 0 24px}.link[data-v-85de7b6f]{line-height:32px;font-size:13px;color:var(--vp-c-text-1)}.VPNavScreen[data-v-e0c26501]{position:fixed;top:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px));right:0;bottom:0;left:0;padding:0 32px;width:100%;background-color:var(--vp-nav-screen-bg-color);overflow-y:auto;transition:background-color .25s;pointer-events:auto}.VPNavScreen.fade-enter-active[data-v-e0c26501],.VPNavScreen.fade-leave-active[data-v-e0c26501]{transition:opacity .25s}.VPNavScreen.fade-enter-active .container[data-v-e0c26501],.VPNavScreen.fade-leave-active .container[data-v-e0c26501]{transition:transform .25s ease}.VPNavScreen.fade-enter-from[data-v-e0c26501],.VPNavScreen.fade-leave-to[data-v-e0c26501]{opacity:0}.VPNavScreen.fade-enter-from .container[data-v-e0c26501],.VPNavScreen.fade-leave-to .container[data-v-e0c26501]{transform:translateY(-8px)}@media(min-width:768px){.VPNavScreen[data-v-e0c26501]{display:none}}.container[data-v-e0c26501]{margin:0 auto;padding:24px 0 96px;max-width:288px}.menu+.translations[data-v-e0c26501],.menu+.appearance[data-v-e0c26501],.translations+.appearance[data-v-e0c26501]{margin-top:24px}.menu+.social-links[data-v-e0c26501]{margin-top:16px}.appearance+.social-links[data-v-e0c26501]{margin-top:16px}.VPNav[data-v-d78ad477]{position:relative;top:var(--vp-layout-top-height, 0px);left:0;z-index:var(--vp-z-index-nav);width:100%;pointer-events:none;transition:background-color .5s}@media(min-width:960px){.VPNav[data-v-d78ad477]{position:fixed}}.VPSidebarItem.level-0[data-v-c0d2b08d]{padding-bottom:24px}.VPSidebarItem.collapsed.level-0[data-v-c0d2b08d]{padding-bottom:10px}.item[data-v-c0d2b08d]{position:relative;display:flex;width:100%}.VPSidebarItem.collapsible>.item[data-v-c0d2b08d]{cursor:pointer}.indicator[data-v-c0d2b08d]{position:absolute;top:6px;bottom:6px;left:-17px;width:2px;border-radius:2px;transition:background-color .25s}.VPSidebarItem.level-2.is-active>.item>.indicator[data-v-c0d2b08d],.VPSidebarItem.level-3.is-active>.item>.indicator[data-v-c0d2b08d],.VPSidebarItem.level-4.is-active>.item>.indicator[data-v-c0d2b08d],.VPSidebarItem.level-5.is-active>.item>.indicator[data-v-c0d2b08d]{background-color:var(--vp-c-brand-1)}.link[data-v-c0d2b08d]{display:flex;align-items:center;flex-grow:1}.text[data-v-c0d2b08d]{flex-grow:1;padding:4px 0;line-height:24px;font-size:14px;transition:color .25s}.VPSidebarItem.level-0 .text[data-v-c0d2b08d]{font-weight:700;color:var(--vp-c-text-1)}.VPSidebarItem.level-1 .text[data-v-c0d2b08d],.VPSidebarItem.level-2 .text[data-v-c0d2b08d],.VPSidebarItem.level-3 .text[data-v-c0d2b08d],.VPSidebarItem.level-4 .text[data-v-c0d2b08d],.VPSidebarItem.level-5 .text[data-v-c0d2b08d]{font-weight:500;color:var(--vp-c-text-2)}.VPSidebarItem.level-0.is-link>.item>.link:hover .text[data-v-c0d2b08d],.VPSidebarItem.level-1.is-link>.item>.link:hover .text[data-v-c0d2b08d],.VPSidebarItem.level-2.is-link>.item>.link:hover .text[data-v-c0d2b08d],.VPSidebarItem.level-3.is-link>.item>.link:hover .text[data-v-c0d2b08d],.VPSidebarItem.level-4.is-link>.item>.link:hover .text[data-v-c0d2b08d],.VPSidebarItem.level-5.is-link>.item>.link:hover .text[data-v-c0d2b08d]{color:var(--vp-c-brand-1)}.VPSidebarItem.level-0.has-active>.item>.text[data-v-c0d2b08d],.VPSidebarItem.level-1.has-active>.item>.text[data-v-c0d2b08d],.VPSidebarItem.level-2.has-active>.item>.text[data-v-c0d2b08d],.VPSidebarItem.level-3.has-active>.item>.text[data-v-c0d2b08d],.VPSidebarItem.level-4.has-active>.item>.text[data-v-c0d2b08d],.VPSidebarItem.level-5.has-active>.item>.text[data-v-c0d2b08d],.VPSidebarItem.level-0.has-active>.item>.link>.text[data-v-c0d2b08d],.VPSidebarItem.level-1.has-active>.item>.link>.text[data-v-c0d2b08d],.VPSidebarItem.level-2.has-active>.item>.link>.text[data-v-c0d2b08d],.VPSidebarItem.level-3.has-active>.item>.link>.text[data-v-c0d2b08d],.VPSidebarItem.level-4.has-active>.item>.link>.text[data-v-c0d2b08d],.VPSidebarItem.level-5.has-active>.item>.link>.text[data-v-c0d2b08d]{color:var(--vp-c-text-1)}.VPSidebarItem.level-0.is-active>.item .link>.text[data-v-c0d2b08d],.VPSidebarItem.level-1.is-active>.item .link>.text[data-v-c0d2b08d],.VPSidebarItem.level-2.is-active>.item .link>.text[data-v-c0d2b08d],.VPSidebarItem.level-3.is-active>.item .link>.text[data-v-c0d2b08d],.VPSidebarItem.level-4.is-active>.item .link>.text[data-v-c0d2b08d],.VPSidebarItem.level-5.is-active>.item .link>.text[data-v-c0d2b08d]{color:var(--vp-c-brand-1)}.caret[data-v-c0d2b08d]{display:flex;justify-content:center;align-items:center;margin-right:-7px;width:32px;height:32px;color:var(--vp-c-text-3);cursor:pointer;transition:color .25s;flex-shrink:0}.item:hover .caret[data-v-c0d2b08d]{color:var(--vp-c-text-2)}.item:hover .caret[data-v-c0d2b08d]:hover{color:var(--vp-c-text-1)}.caret-icon[data-v-c0d2b08d]{font-size:18px;transform:rotate(90deg);transition:transform .25s}.VPSidebarItem.collapsed .caret-icon[data-v-c0d2b08d]{transform:rotate(0)}.VPSidebarItem.level-1 .items[data-v-c0d2b08d],.VPSidebarItem.level-2 .items[data-v-c0d2b08d],.VPSidebarItem.level-3 .items[data-v-c0d2b08d],.VPSidebarItem.level-4 .items[data-v-c0d2b08d],.VPSidebarItem.level-5 .items[data-v-c0d2b08d]{border-left:1px solid var(--vp-c-divider);padding-left:16px}.VPSidebarItem.collapsed .items[data-v-c0d2b08d]{display:none}.no-transition[data-v-3423a55b] .caret-icon{transition:none}.group+.group[data-v-3423a55b]{border-top:1px solid var(--vp-c-divider);padding-top:10px}@media(min-width:960px){.group[data-v-3423a55b]{padding-top:10px;width:calc(var(--vp-sidebar-width) - 64px)}}.VPSidebar[data-v-3ad41a46]{position:fixed;top:var(--vp-layout-top-height, 0px);bottom:0;left:0;z-index:var(--vp-z-index-sidebar);padding:32px 32px 96px;width:calc(100vw - 64px);max-width:320px;background-color:var(--vp-sidebar-bg-color);opacity:0;box-shadow:var(--vp-c-shadow-3);overflow-x:hidden;overflow-y:auto;transform:translate(-100%);transition:opacity .5s,transform .25s ease;overscroll-behavior:contain}.VPSidebar.open[data-v-3ad41a46]{opacity:1;visibility:visible;transform:translate(0);transition:opacity .25s,transform .5s cubic-bezier(.19,1,.22,1)}.dark .VPSidebar[data-v-3ad41a46]{box-shadow:var(--vp-shadow-1)}@media(min-width:960px){.VPSidebar[data-v-3ad41a46]{padding-top:var(--vp-nav-height);width:var(--vp-sidebar-width);max-width:100%;background-color:var(--vp-sidebar-bg-color);opacity:1;visibility:visible;box-shadow:none;transform:translate(0)}}@media(min-width:1440px){.VPSidebar[data-v-3ad41a46]{padding-left:max(32px,calc((100vw - (var(--vp-layout-max-width) - 64px)) / 2));width:calc((100vw - (var(--vp-layout-max-width) - 64px)) / 2 + var(--vp-sidebar-width) - 32px)}}@media(min-width:960px){.curtain[data-v-3ad41a46]{position:sticky;top:calc(var(--vp-nav-height) * -1);left:0;z-index:1;margin-top:calc(var(--vp-nav-height) * -1);margin-right:-32px;margin-left:-32px;height:var(--vp-nav-height);background-color:var(--vp-sidebar-bg-color)}}.nav[data-v-3ad41a46]{outline:0}.VPSkipLink[data-v-84877a60]{position:fixed;top:8px;left:8px;padding:8px 16px;z-index:999;border-radius:8px;font-size:12px;font-weight:700;text-decoration:none;color:var(--vp-c-brand-1);box-shadow:var(--vp-shadow-3);background-color:var(--vp-c-bg)}.VPSkipLink[data-v-84877a60]:focus{height:auto;width:auto;clip:auto;clip-path:none}@media(min-width:1280px){.VPSkipLink[data-v-84877a60]{top:14px;left:16px}}.Layout[data-v-17498edd]{display:flex;flex-direction:column;min-height:100vh}.tk-copy-banner{background:var(--vp-c-brand-1);left:0;overflow:hidden;position:fixed;text-align:center;top:0;transform:translateY(-100%);transition:transform 1s ease,opacity 1s ease;width:100%;z-index:9999}.tk-copy-banner__content{-webkit-backdrop-filter:blur(5px);backdrop-filter:blur(5px);padding:16px;position:relative;z-index:2}@media(max-width:768px){.tk-copy-banner__content{padding:10px}}.tk-copy-banner__desc{color:#fff;font-size:19px;font-weight:700}@media(max-width:768px){.tk-copy-banner__desc{font-size:16px}}.tk-copy-banner__slide{animation:remove-corner 2s ease-in-out forwards;background-color:var(--vp-c-brand-2);border-bottom-right-radius:25px;border-top-right-radius:25px;height:100%;left:0;position:absolute;top:0;transition:width 2s ease-in-out;width:0;z-index:1}.tk-copy-banner.is-show{transform:translateY(0)}.tk-copy-banner.is-hide{opacity:0;transform:translateY(-100%)}.tk-copy-banner.is-hide .slide-block{border-radius:0;width:100%}@keyframes remove-corner{0%{border-bottom-right-radius:25px;border-top-right-radius:25px}80%{border-bottom-right-radius:15px;border-top-right-radius:15px}to{border-bottom-right-radius:0;border-top-right-radius:0}}.tk-article-page.tk-archives{width:1220px}.tk-archives .contribute__chart{width:100%;height:260px}.tk-archives .contribute__chart .chart__box{margin:auto;width:100%;height:100%}.error-page[data-v-9553caa6]{width:100%;height:calc(100vh - var(--vp-nav-height));gap:120px}.error-page__detail h2[data-v-9553caa6]{font-size:60px;color:var(--vp-c-text-1);line-height:1}.error-page__detail h4[data-v-9553caa6]{margin:10px 0 20px;font-size:19px;font-weight:400;color:var(--vp-c-text-2)}.error-page__detail button[data-v-9553caa6]{color:#fff;background-color:#395ae3;box-shadow:0 2px #0591ff1a;font-size:14px;width:100px;height:32px;padding:4px 15px;border-radius:6px;outline:none;position:relative;display:inline-block;font-weight:400;white-space:nowrap;text-align:center;background-image:none;border:1px solid transparent;cursor:pointer;transition:all .2s cubic-bezier(.645,.045,.355,1);-webkit-user-select:none;user-select:none;touch-action:manipulation;line-height:1.5714285714}.error-page__detail button[data-v-9553caa6]:hover{background-color:#5a79f4}@media(max-width:768px){.error-page[data-v-9553caa6]{flex-direction:column;gap:60px;transform:translateY(-10%)}.error-page__detail[data-v-9553caa6]{align-items:center}}.contact-card[data-v-4b99f778]{--link-bg: #f0f2f5;--link-bg-hover: #e8eaed;--text-primary: #333;--text-secondary: #666;--accent-color: var(--vp-c-brand-1)}html.dark .contact-card[data-v-4b99f778]{--link-bg: #2a2d31;--link-bg-hover: #36393f;--text-primary: #e5e7eb;--text-secondary: #9ca3af}.contact-description[data-v-4b99f778]{margin-bottom:16px;text-align:center}.contact-description p[data-v-4b99f778]{color:var(--text-secondary);font-size:14px;margin:0}.contact-links[data-v-4b99f778]{display:flex;flex-direction:column;gap:8px}.contact-link[data-v-4b99f778]{display:flex;align-items:center;padding:12px 16px;background-color:var(--link-bg);border-radius:8px;text-decoration:none;color:var(--text-primary);transition:all .2s ease;gap:12px}.contact-link[data-v-4b99f778]:hover{background-color:var(--link-bg-hover);transform:translate(4px)}.contact-icon[data-v-4b99f778]{display:flex;align-items:center;justify-content:center;width:24px;height:24px}.contact-icon[data-v-4b99f778] svg{width:20px;height:20px}.contact-name[data-v-4b99f778]{flex:1;font-size:15px;font-weight:500}.contact-arrow[data-v-4b99f778]{color:var(--accent-color);opacity:0;transform:translate(-8px);transition:all .2s ease;font-size:14px}.contact-link:hover .contact-arrow[data-v-4b99f778]{opacity:1;transform:translate(0)}.contact-footer[data-v-4b99f778]{margin-top:16px;text-align:center;padding-top:12px;border-top:1px dashed var(--link-bg-hover)}.contact-footer p[data-v-4b99f778]{color:var(--text-secondary);font-size:13px;margin:0}@media(max-width:768px){.contact-link[data-v-4b99f778]{padding:10px 14px}.contact-name[data-v-4b99f778]{font-size:14px}}.wechat-modal-overlay[data-v-4b99f778]{position:fixed;inset:0;background-color:#0009;display:flex;align-items:center;justify-content:center;z-index:9999;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.wechat-modal[data-v-4b99f778]{background-color:var(--vp-c-bg);border-radius:12px;max-width:320px;width:90%;box-shadow:0 20px 40px #0000004d;overflow:hidden;animation:modalSlideIn-4b99f778 .3s ease}@keyframes modalSlideIn-4b99f778{0%{opacity:0;transform:scale(.9) translateY(-20px)}to{opacity:1;transform:scale(1) translateY(0)}}.wechat-modal-header[data-v-4b99f778]{display:flex;align-items:center;justify-content:space-between;padding:16px 20px;border-bottom:1px solid var(--vp-c-divider);font-weight:600;font-size:16px}.wechat-modal-close[data-v-4b99f778]{background:none;border:none;font-size:24px;cursor:pointer;color:var(--vp-c-text-2);line-height:1;padding:0;transition:color .2s}.wechat-modal-close[data-v-4b99f778]:hover{color:var(--vp-c-text-1)}.wechat-modal-body[data-v-4b99f778]{padding:20px;text-align:center;display:flex;justify-content:center}.wechat-qrcode[data-v-4b99f778]{max-width:200px;border-radius:8px;border:1px solid var(--vp-c-divider)}.wechat-placeholder[data-v-4b99f778]{color:var(--vp-c-text-2);font-size:14px;margin:0}.tk-my.is-circle-bg{margin-bottom:20px}.tk-my.is-circle-bg .tk-my__avatar.circle-rotate{margin-top:200px}.tk-pointer{cursor:pointer}.tk-center{left:50%;position:absolute;top:50%;transform:translate(-50%,-50%)}.VPBadge.success{background-color:var(--tk-el-color-success-light-9);border-color:var(--tk-el-color-success-light-8);color:var(--tk-el-color-success)}.hover-color{cursor:pointer!important;transition:color var(--tk-transition-duration-fast)}.hover-color:hover{color:var(--tk-theme-color)}.scroll__animate{opacity:0;transform:translateY(20px)}.scroll__animate.visible{opacity:1;transform:translateY(0);transition:opacity .6s ease-out,transform .7s ease-out}.skeleton-image:has(:not(.loaded)){animation:skeleton-loading 1.4s ease infinite;background-image:linear-gradient(90deg,var(--tk-fill-color-dark) 25%,var(--tk-bg-color) 37%,var(--tk-fill-color-dark) 63%);background-size:400% 100%}.skeleton-image:has(:not(.loaded))>img{background-color:var(--tk-bg-color);filter:blur(10px);opacity:0;transition:filter .3s,opacity .3s}.skeleton-image:has(:not(.loaded))>img.loaded{filter:blur(0);opacity:1}@keyframes skeleton-loading{0%{background-position:100% 50%}to{background-position:0 50%}}.flx,.flx-column{display:flex}.flx-column{flex-direction:column}.flx-center,.flx-column-center{align-items:center;display:flex;justify-content:center}.flx-column-center{flex-direction:column}.flx-align-center{align-items:center;display:flex}.flx-justify-center{display:flex;justify-content:center}.flx-justify-between{align-items:center;display:flex;justify-content:space-between}.flx-justify-around{align-items:center;display:flex;justify-content:space-around}.flx-start-justify-center{align-items:flex-start;display:flex;justify-content:center}.flx-wrap-between{display:flex;flex-wrap:wrap;justify-content:space-between}.flx-wrap-justify-center{display:flex;flex-wrap:wrap;justify-content:center}.flx-1{flex:1}.flx-wrap{flex-wrap:wrap}.flx-space-y-20{display:flex;flex-direction:column;gap:20px}.sle{white-space:nowrap}.mle,.sle{overflow:hidden;text-overflow:ellipsis}.mle{display:-webkit-box;-webkit-box-orient:vertical;line-clamp:2;-webkit-line-clamp:2}.display-none{display:none!important}*{scrollbar-color:#f5f7fa}::-webkit-scrollbar{width:6px}::-webkit-scrollbar:horizontal{height:6px}::-webkit-scrollbar-track{border-radius:10px}::-webkit-scrollbar-thumb{background-color:#0003;border-radius:10px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}::-webkit-scrollbar-thumb:hover{background-color:#0000004d;cursor:pointer}.dark ::-webkit-scrollbar-thumb{background-color:#fff3}.dark ::-webkit-scrollbar-thumb:hover{background-color:#fff6}.tk-collapse-transition-enter-active,.tk-collapse-transition-leave-active{transition:max-height .3s ease-in-out,padding-top .3s ease-in-out,padding-bottom .3s ease-in-out}::view-transition-new(root),::view-transition-old(root){animation:none;mix-blend-mode:normal}html[view-transition=out-in].dark::view-transition-new(root),html[view-transition=out-in]::view-transition-old(root){z-index:1}html[view-transition=out-in].dark::view-transition-old(root),html[view-transition=out-in]::view-transition-new(root){z-index:9999}.tk-fade-scale-enter-active,.tk-fade-scale-leave-active{transition:opacity .3s cubic-bezier(.55,0,.1,1),transform .3s cubic-bezier(.55,0,.1,1)}.tk-fade-scale-enter-from,.tk-fade-scale-leave-to{opacity:0;transform:scale(.8)}.tk-fade-enter-active,.tk-fade-leave-active{transition:opacity .3s cubic-bezier(.55,0,.1,1)}.tk-fade-enter-from,.tk-fade-leave-to{opacity:0}.tk-fade-linear-enter-active,.tk-fade-linear-leave-active{transition:opacity .2s linear}.tk-fade-linear-enter-from,.tk-fade-linear-leave-to{opacity:0}.tk-slide-next-enter-active,.tk-slide-next-leave-active,.tk-slide-next-move{transition:opacity .5s ease,transform .5s ease}.tk-slide-next-enter-from{opacity:0;transform:translate(100%)}.tk-slide-next-leave-to{opacity:0;transform:translate(-100%)}.tk-slide-next-leave-active{position:absolute}.tk-slide-prev-enter-active,.tk-slide-prev-leave-active,.tk-slide-prev-move{transition:opacity .5s ease,transform .5s ease}.tk-slide-prev-enter-from{opacity:0;transform:translate(-100%)}.tk-slide-prev-leave-to{opacity:0;transform:translate(100%)}.tk-slide-prev-leave-active{position:absolute}.tk-slide-fade-enter-active,.tk-slide-fade-leave-active,.tk-slide-fade-move{transition:opacity .3s ease,transform .3s ease}.tk-slide-fade-enter-from{opacity:0;transform:translate(-20px)}.tk-slide-fade-leave-to{display:none;transform:translate(0)}.tk-scroll-enter-active,.tk-scroll-leave-active,.tk-scroll-move{transition:opacity .5s ease,transform .5s ease}.tk-scroll-enter-from{opacity:0;transform:translateY(70px)}.tk-scroll-leave-to{opacity:0;transform:translateY(-30px)}.tk-scroll-leave-active{position:absolute}:root{--tk-theme-color:var(--vp-c-brand-1);--tk-line-color:rgba(0,0,0,.12);--tk-text-color-regular:var(--vp-c-text-2);--tk-text-color-secondary:#86909c;--tk-text-color-placeholder:#a8abb2;--tk-text-color-disabled:#c0c4cc;--tk-bg-color:var(--vp-c-bg);--tk-bg-color-elm:var(--vp-c-bg-elv);--tk-bg-color-mute:#f4f4f4;--tk-fill-color:#f0f2f5;--tk-fill-color-blank:#fff;--tk-fill-color-light:#f5f7fa;--tk-fill-color-dark:#ebedf0;--tk-card-shadow:0 2px 10px 2px rgba(0,0,0,.1);--tk-hover-shadow:0 1px 16px 4px rgba(0,0,0,.2);--tk-home-bg-color:#fff;--tk-transition-duration:.3s;--tk-transition-duration-fast:.2s;--tk-transition-duration-slow:.5s;--tk-transition-duration-slow-plus:.6s}:root.dark{--tk-theme-color:var(--vp-c-brand-1);--tk-line-color:rgba(0,0,0,.12);--tk-text-color-regular:var(--vp-c-text-2);--tk-text-color-secondary:#9facba;--tk-text-color-placeholder:#8d9095;--tk-text-color-disabled:#6c6e72;--tk-bg-color:var(--vp-c-bg);--tk-bg-color-elm:var(--vp-c-bg-elv);--tk-bg-color-mute:#27272b;--tk-fill-color:#303030;--tk-fill-color-blank:transparent;--tk-fill-color-light:#262727;--tk-fill-color-dark:#2c2f35;--tk-card-shadow:0 2px 10px 2px hsla(0,0%,100%,.12);--tk-hover-shadow:0 3px 12px 3px hsla(0,0%,100%,.2);--tk-home-bg-color:#1b1b1f}:root{--tk-gap1:10px;--tk-gap2:20px;--tk-gap3:30px;--tk-el-color-primary:#409eff;--tk-el-color-primary-light-3:#79bbff;--tk-el-color-primary-light-5:#a0cfff;--tk-el-color-primary-light-7:#c6e2ff;--tk-el-color-primary-light-8:#d9ecff;--tk-el-color-primary-light-9:#ecf5ff;--tk-el-color-primary-dark-2:#337ecc;--tk-el-color-success:#67c23a;--tk-el-color-success-light-3:#95d475;--tk-el-color-success-light-5:#b3e19d;--tk-el-color-success-light-7:#d1edc4;--tk-el-color-success-light-8:#e1f3d8;--tk-el-color-success-light-9:#f0f9eb;--tk-el-color-success-dark-2:#529b2e;--tk-el-color-warning:#e6a23c;--tk-el-color-warning-light-3:#eebe77;--tk-el-color-warning-light-5:#f3d19e;--tk-el-color-warning-light-7:#f8e3c5;--tk-el-color-warning-light-8:#faecd8;--tk-el-color-warning-light-9:#fdf6ec;--tk-el-color-warning-dark-2:#b88230;--tk-el-color-danger:#f56c6c;--tk-el-color-danger-light-3:#f89898;--tk-el-color-danger-light-5:#fab6b6;--tk-el-color-danger-light-7:#fcd3d3;--tk-el-color-danger-light-8:#fde2e2;--tk-el-color-danger-light-9:#fef0f0;--tk-el-color-danger-dark-2:#c45656;--tk-el-color-error:#f56c6c;--tk-el-color-error-light-3:#f89898;--tk-el-color-error-light-5:#fab6b6;--tk-el-color-error-light-7:#fcd3d3;--tk-el-color-error-light-8:#fde2e2;--tk-el-color-error-light-9:#fef0f0;--tk-el-color-error-dark-2:#c45656;--tk-el-color-info:#909399;--tk-el-color-info-light-3:#b1b3b8;--tk-el-color-info-light-5:#c8c9cc;--tk-el-color-info-light-7:#dedfe0;--tk-el-color-info-light-8:#e9e9eb;--tk-el-color-info-light-9:#f4f4f5;--tk-el-color-info-dark-2:#73767a}:root.dark{--tk-el-color-primary:#409eff;--tk-el-color-primary-light-3:#3375b9;--tk-el-color-primary-light-5:#2a598a;--tk-el-color-primary-light-7:#213d5b;--tk-el-color-primary-light-8:#1d3043;--tk-el-color-primary-light-9:#18222c;--tk-el-color-primary-dark-2:#66b1ff;--tk-el-color-success:#67c23a;--tk-el-color-success-light-3:#4e8e2f;--tk-el-color-success-light-5:#3e6b27;--tk-el-color-success-light-7:#2d481f;--tk-el-color-success-light-8:#25371c;--tk-el-color-success-light-9:#1c2518;--tk-el-color-success-dark-2:#85ce61;--tk-el-color-warning:#e6a23c;--tk-el-color-warning-light-3:#a77730;--tk-el-color-warning-light-5:#7d5b28;--tk-el-color-warning-light-7:#533f20;--tk-el-color-warning-light-8:#3e301c;--tk-el-color-warning-light-9:#292218;--tk-el-color-warning-dark-2:#ebb563;--tk-el-color-danger:#f56c6c;--tk-el-color-danger-light-3:#b25252;--tk-el-color-danger-light-5:#854040;--tk-el-color-danger-light-7:#582e2e;--tk-el-color-danger-light-8:#412626;--tk-el-color-danger-light-9:#2b1d1d;--tk-el-color-danger-dark-2:#f78989;--tk-el-color-error:#f56c6c;--tk-el-color-error-light-3:#b25252;--tk-el-color-error-light-5:#854040;--tk-el-color-error-light-7:#582e2e;--tk-el-color-error-light-8:#412626;--tk-el-color-error-light-9:#2b1d1d;--tk-el-color-error-dark-2:#f78989;--tk-el-color-info:#909399;--tk-el-color-info-light-3:#6b6d71;--tk-el-color-info-light-5:#525457;--tk-el-color-info-light-7:#393a3c;--tk-el-color-info-light-8:#2d2d2f;--tk-el-color-info-light-9:#202121;--tk-el-color-info-dark-2:#a6a9ad}html[theme-color=vp-green]{--vp-c-brand-1:var(--vp-c-green-1);--vp-c-brand-2:var(--vp-c-green-2);--vp-c-brand-3:var(--vp-c-green-3);--vp-c-brand-soft:var(--vp-c-green-soft)}html[theme-color=vp-yellow]{--vp-c-brand-1:var(--vp-c-yellow-1);--vp-c-brand-2:var(--vp-c-yellow-2);--vp-c-brand-3:var(--vp-c-yellow-3);--vp-c-brand-soft:var(--vp-c-yellow-soft)}html[theme-color=vp-red]{--vp-c-brand-1:var(--vp-c-red-1);--vp-c-brand-2:var(--vp-c-red-2);--vp-c-brand-3:var(--vp-c-red-3);--vp-c-brand-soft:var(--vp-c-red-soft)}html[theme-color=ep-blue]{--vp-c-brand-1:var(--tk-el-color-primary);--vp-c-brand-2:var(--tk-el-color-primary-light-3);--vp-c-brand-3:var(--tk-el-color-primary-light-5);--vp-c-brand-soft:var(--tk-el-color-primary-light-8)}html[theme-color=ep-green]{--vp-c-brand-1:var(--tk-el-color-success);--vp-c-brand-2:var(--tk-el-color-success-light-3);--vp-c-brand-3:var(--tk-el-color-success-light-5);--vp-c-brand-soft:var(--tk-el-color-success-light-8)}html[theme-color=ep-yellow]{--vp-c-brand-1:var(--tk-el-color-warning);--vp-c-brand-2:var(--tk-el-color-warning-light-3);--vp-c-brand-3:var(--tk-el-color-warning-light-5);--vp-c-brand-soft:var(--tk-el-color-warning-light-8)}html[theme-color=ep-red]{--vp-c-brand-1:var(--tk-el-color-danger);--vp-c-brand-2:var(--tk-el-color-danger-light-3);--vp-c-brand-3:var(--tk-el-color-danger-light-5);--vp-c-brand-soft:var(--tk-el-color-danger-light-8)}html[tk-theme-size=wide]{--tk-home-max-width:1420px;--tk-home-gap:var(--tk-gap3);--tk-home-post-simple-img-width:160px;--tk-home-post-full-img-width:480px;--tk-home-post-full-img-height:100%;--tk-home-post-line-clamp:4;--tk-home-card-padding:15px;--tk-home-card-width:350px;--tk-home-card-svg-margin-left:10px;--tk-home-font-size-large:19px;--tk-home-font-size-base:17px;--tk-home-font-size-middle:15px;--tk-home-font-size-sm:14px;--tk-home-font-size-small:13px;--tk-home-page-width:1100px;--tk-home-footer-group-width:100%}html[tk-theme-size=large]{--tk-home-max-width:1330px;--tk-home-gap:var(--tk-gap3);--tk-home-post-simple-img-width:160px;--tk-home-post-full-img-width:420px;--tk-home-post-full-img-height:100%;--tk-home-post-line-clamp:4;--tk-home-card-padding:15px;--tk-home-card-width:350px;--tk-home-card-svg-margin-left:10px;--tk-home-font-size-large:19px;--tk-home-font-size-base:17px;--tk-home-font-size-middle:15px;--tk-home-font-size-sm:14px;--tk-home-font-size-small:13px;--tk-home-page-width:1000px;--tk-home-footer-group-width:90%}:root,html[tk-theme-size=default]{--tk-home-max-width:1140px;--tk-home-gap:var(--tk-gap2);--tk-home-post-simple-img-width:120px;--tk-home-post-simple-img-height:80px;--tk-home-post-full-img-width:360px;--tk-home-post-full-img-height:100%;--tk-home-post-line-clamp:3;--tk-home-card-padding:10px;--tk-home-card-width:280px;--tk-home-card-svg-margin-left:5px;--tk-home-card-border-radius:4px;--tk-home-font-size-large:18px;--tk-home-font-size-base:16px;--tk-home-font-size-middle:14px;--tk-home-font-size-sm:13px;--tk-home-font-size-small:12px;--tk-page-width:900px;--tk-home-footer-group-width:80%}html[tk-theme-size=small]{--tk-home-max-width:1000px;--tk-home-gap:var(--tk-gap2);--tk-home-post-simple-img-width:100px;--tk-home-post-simple-img-height:80px;--tk-home-post-full-img-width:240px;--tk-home-post-full-img-height:100%;--tk-home-post-line-clamp:2;--tk-home-card-padding:8px;--tk-home-card-width:260px;--tk-home-card-svg-margin-left:4px;--tk-home-font-size-large:17px;--tk-home-font-size-base:15px;--tk-home-font-size-middle:13px;--tk-home-font-size-sm:13px;--tk-home-font-size-small:12px;--tk-page-width:800px;--tk-home-footer-group-width:70%}@media(min-width:768px){:root,html[tk-theme-size=default],html[tk-theme-size=large],html[tk-theme-size=small]{--tk-home-card-width:280px}}@media(max-width:768px){:root,html[tk-theme-size=default],html[tk-theme-size=large],html[tk-theme-size=small]{--tk-home-card-width:100%}}.todo{list-style:none}.todo .todo-checkbox{-webkit-appearance:none;-moz-appearance:none;appearance:none;border:2px solid var(--tk-theme-color);border-radius:4px;cursor:pointer;height:16px;margin-right:8px;position:relative;vertical-align:middle;width:16px}.todo .todo-checkbox:checked{background-color:var(--tk-theme-color);border-color:var(--tk-theme-color)}.todo .todo-checkbox:checked:after{color:#fff;content:"✓";font-size:12px;left:53%;position:absolute;top:53%;transform:translate(-50%,-50%)}.todo .todo-checkbox:disabled{cursor:not-allowed;opacity:.9}.tk-center-container{text-align:center}.tk-right-container{text-align:right}.custom-block .tk-right-container{font-size:14px;margin:-8px 0 0}:root{--tk-custom-block-note-bg:#e8f5fa}:root.dark{--tk-custom-block-note-bg:#003a4d}.custom-block.note{background-color:var(--tk-custom-block-note-bg)}.container.share-card-container{margin:11px 0}.container.share-card-container .share-card{-moz-column-gap:var(--column-gap);column-gap:var(--column-gap);display:grid;grid-auto-flow:row dense;grid-template-columns:repeat(auto-fill,minmax(var(--column-min-width),1fr));row-gap:var(--row-gap)}.container.share-card-container .share-card__item{background-color:var(--item-bg-color);border-radius:6px;color:var(--item-text-color);cursor:pointer;display:flex;overflow:hidden;text-decoration:none;transition:all .3s}.container.share-card-container .share-card__item:hover{box-shadow:0 10px 20px -10px var(--item-bg-color,rgba(0,0,0,.15));color:var(--item-text-color);transform:translateY(-3px) scale(1.01)}.container.share-card-container .share-card__item:hover img{box-shadow:3px 2px 7px #00000026}.container.share-card-container .share-card__item:hover div p{text-shadow:3px 2px 5px rgba(0,0,0,.15)}.container.share-card-container .share-card__item__img{border:2px solid var(--vp-c-bg);border-radius:50%;box-shadow:3px 2px 5px #00000014;height:60px;margin:16px 0 16px 16px;max-width:60px;overflow:hidden;transition:all .4s;width:60px}.container.share-card-container .share-card__item__img img{height:100%;width:100%}.container.share-card-container .share-card__item__content{flex:1;padding:16px 0}.container.share-card-container .share-card__item__content p{margin:0;padding:0 16px;text-align:center;transition:text-shadow .4s}.container.share-card-container .share-card__item__content .name{margin:3px 0 5px}.container.share-card-container .share-card__item__content .desc{font-size:13px;line-height:17px;margin-bottom:3px;opacity:.8}.container.share-card-container .share-card.index-auto{grid-template-columns:repeat(auto-fill,minmax(240px,1fr))}@media(max-width:1440px){.container.share-card-container .share-card.index-4{grid-template-columns:repeat(auto-fill,minmax(calc(33.33333% - var(--column-gap)*2),1fr))}}@media(max-width:768px){.container.share-card-container .share-card.index-3,.container.share-card-container .share-card.index-4{grid-template-columns:repeat(auto-fill,minmax(calc(50% - var(--column-gap)),1fr))}}@media(max-width:640px){.container.share-card-container .share-card.index-2,.container.share-card-container .share-card.index-3,.container.share-card-container .share-card.index-4{grid-template-columns:repeat(auto-fill,minmax(100%,1fr))}}.container.img-card-container{margin:11px 0}.container.img-card-container .img-card{-moz-column-gap:var(--column-gap);column-gap:var(--column-gap);display:grid;grid-auto-flow:row dense;grid-template-columns:repeat(auto-fill,minmax(var(--column-min-width),1fr));row-gap:var(--row-gap)}.container.img-card-container .img-card__item{background-color:var(--vp-c-bg);border:1px solid var(--vp-c-divider);border-radius:6px;color:var(--vp-c-text-1);cursor:pointer;display:block;overflow:hidden;text-decoration:none;transition:all .3s}.container.img-card-container .img-card__item:hover{box-shadow:var(--vp-shadow-2);color:var(--vp-c-text-1);transform:translateY(-3px)}.container.img-card-container .img-card__item__img{background-color:#eee;height:var(--img-height);overflow:hidden;position:relative;transition:all .3s}.container.img-card-container .img-card__item__img img{display:block;height:100%;-o-object-fit:var(--img-object-fit);object-fit:var(--img-object-fit);width:100%}.container.img-card-container .img-card__item__info{padding:13px 16px}.container.img-card-container .img-card__item__info p{margin:0}.container.img-card-container .img-card__item__info .desc{display:-webkit-box;font-size:14.4px;line-height:17.6px;margin-top:5px;opacity:.8;overflow:hidden;text-overflow:ellipsis;white-space:normal;-webkit-box-orient:vertical;line-clamp:var(--desc-line-clamp);-webkit-line-clamp:var(--desc-line-clamp)}.container.img-card-container .img-card__item__footer{border-top:1px solid var(--vp-c-divider);display:flex;overflow:hidden;padding:13px 16px}.container.img-card-container .img-card__item__footer img{border-radius:50%;height:29px;width:29px}.container.img-card-container .img-card__item__footer span{font-size:12.8px;line-height:29px;margin-left:10px}.container.img-card-container .img-card.index-auto{grid-template-columns:repeat(auto-fill,minmax(240px,1fr))}@media(max-width:960px){.container.img-card-container .img-card.index-4{grid-template-columns:repeat(auto-fill,minmax(calc(33.33333% - var(--column-gap)*2),1fr))}}@media(max-width:768px){.container.img-card-container .img-card.index-3,.container.img-card-container .img-card.index-4{grid-template-columns:repeat(auto-fill,minmax(calc(50% - var(--column-gap)),1fr))}}@media(max-width:640px){.container.img-card-container .img-card.index-2,.container.img-card-container .img-card.index-3,.container.img-card-container .img-card.index-4{grid-template-columns:repeat(auto-fill,minmax(100%,1fr))}}html[theme-size=wide] .img-card-container .index-auto{grid-template-columns:repeat(auto-fill,minmax(calc(25% - var(--column-gap)*2),1fr))}html[theme-size=large] .img-card-container .index-auto{grid-template-columns:repeat(auto-fill,minmax(calc(33.33333% - var(--column-gap)*2),1fr))}html[theme-size=default] .img-card-container .index-auto,html[theme-size=small] .img-card-container .index-auto{grid-template-columns:repeat(auto-fill,minmax(calc(50% - var(--column-gap)*2),1fr))}.container.nav-card-container{margin:11px 0}.container.nav-card-container .nav-card{-moz-column-gap:var(--column-gap);column-gap:var(--column-gap);display:grid;grid-auto-flow:row dense;grid-template-columns:repeat(auto-fill,minmax(var(--column-min-width),1fr));row-gap:var(--row-gap)}.container.nav-card-container .nav-card__item{background-color:var(--vp-c-bg-soft);border:1px solid var(--vp-c-bg-soft);border-radius:6px;color:var(--vp-c-text-1);cursor:pointer;display:block;overflow:hidden;padding:10px;position:relative;text-decoration:none;transition:all .3s}.container.nav-card-container .nav-card__item:hover{background-color:var(--vp-c-bg-soft-up);border-color:var(--vp-c-brand);box-shadow:var(--vp-shadow-2);color:var(--vp-c-text-1);transform:translateY(-4px)}.container.nav-card-container .nav-card__item__img{border-radius:6px;height:40px;margin-right:10px;min-width:40px;overflow:hidden}.container.nav-card-container .nav-card__item__img img{height:100%;width:100%}.container.nav-card-container .nav-card__item__info{align-items:center;display:flex}.container.nav-card-container .nav-card__item__info .name{flex:1;font-size:16px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.container.nav-card-container .nav-card__item .desc{color:var(--vp-c-text-2);display:-webkit-box;font-size:12px;line-height:1.5;margin:12px 0 0;overflow:hidden;text-overflow:ellipsis;white-space:normal;-webkit-box-orient:vertical;line-clamp:var(--desc-line-clamp);-webkit-line-clamp:var(--desc-line-clamp)}.container.nav-card-container .nav-card__item .badge{position:absolute;right:3px;top:6px}.container.nav-card-container .nav-card.index-auto{grid-template-columns:repeat(auto-fill,minmax(240px,1fr))}@media(max-width:960px){.container.nav-card-container .nav-card.index-4{grid-template-columns:repeat(auto-fill,minmax(calc(33.33333% - var(--column-gap)*2),1fr))}}@media(max-width:768px){.container.nav-card-container .nav-card.index-3,.container.nav-card-container .nav-card.index-4{grid-template-columns:repeat(auto-fill,minmax(calc(50% - var(--column-gap)),1fr))}}@media(max-width:640px){.container.nav-card-container .nav-card.index-2,.container.nav-card-container .nav-card.index-3,.container.nav-card-container .nav-card.index-4{grid-template-columns:repeat(auto-fill,minmax(100%,1fr))}}.video-container{align-items:center;display:flex;justify-content:center;padding:.5em}.video-container .video-iframe{aspect-ratio:16/9;border:none;border-radius:.5em;box-shadow:0 4px 6px #0000001a;height:auto;max-width:100%;width:100%}.tk-article-page{margin:25px auto;width:100%}@media(min-width:1280px){.tk-article-page{width:var(--tk-page-width)}}@media(max-width:1280px){.tk-article-page{padding:0 10px}}.tk-article-page.is-aside{display:flex}@media(min-width:1280px){.tk-article-page.is-aside{width:calc(var(--tk-page-width) + 360px)}.tk-article-page.is-aside .tk-doc{transform:translate(80px)}}.tk-article-page .tk-doc{background-color:var(--tk-bg-color);border-radius:10px;box-shadow:var(--vp-shadow-3);flex:1;overflow-y:auto;padding:20px 30px}.tk-article-page__aside{display:none;flex-grow:1;max-width:256px;order:2;padding-left:112px;position:relative}@media(min-width:1280px){.tk-article-page__aside{display:block}}.tk-article-page__aside__container{height:100vh;overflow-x:hidden;overflow-y:auto;padding-top:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + var(--vp-doc-top-height, 0px) + 48px);position:fixed;scrollbar-width:none;top:0;width:224px}.tk-article-page~div{display:none}.tk-article-page h1{font-size:32px;font-weight:600;line-height:32px}.tk-article-page h2{font-size:27px;font-weight:600;line-height:27px}.tk-article-page h3{font-size:22px;font-weight:500;line-height:22px}.tk-aside-outline{display:none}.tk-aside-outline.has-outline{display:block}.tk-aside-outline__content{border-left:1px solid var(--vp-c-divider);font-size:13px;font-weight:500;padding-left:16px;position:relative}.tk-aside-outline--marker{background-color:var(--vp-c-brand-1);border-radius:2px;height:18px;left:-1px;opacity:0;position:absolute;top:32px;transition:top .25s cubic-bezier(0,1,.5,1),background-color .5s,opacity .25s;width:2px;z-index:0}.tk-aside-outline--title{font-size:14px;font-weight:600;line-height:32px}.tk-aside-outline-item.is-root{position:relative;z-index:1}.tk-aside-outline-item.is-nested{padding-left:16px;padding-right:16px}.tk-aside-outline-item--link{color:var(--vp-c-text-2);display:block;font-size:14px;font-weight:400;line-height:32px;overflow:hidden;text-overflow:ellipsis;transition:color .3s;white-space:nowrap}.tk-aside-outline-item--link:hover{font-weight:700}.tk-aside-outline-item--link.active{color:var(--tk-theme-color)}:root{--tk-avatar-bg-color:var(--tk-text-color-disabled);--tk-avatar-text-color:var(--vp-c-white);--tk-avatar-text-size:14px;--tk-avatar-icon-size:18px;--tk-avatar-border-radius:4px;--tk-avatar-size-small:24px;--tk-avatar-size:40px;--tk-avatar-size-large:56px}.tk-avatar{align-items:center;background:var(--tk-avatar-bg-color);box-sizing:border-box;color:var(--tk-avatar-text-color);display:inline-flex;font-size:var(--tk-avatar-text-size);height:var(--tk-avatar-size);justify-content:center;outline:none;overflow:hidden;text-align:center;width:var(--tk-avatar-size)}.tk-avatar>img{display:block;height:100%;width:100%}.tk-avatar--circle{border-radius:50%}.tk-avatar--square{border-radius:var(--tk-avatar-border-radius)}.tk-avatar--icon{font-size:var(--tk-avatar-icon-size)}.tk-avatar--small{height:var(--tk-avatar-size-small);width:var(--tk-avatar-size-small)}.tk-avatar--large{height:var(--tk-avatar-size-large);width:var(--tk-avatar-size-large)}.tk-breadcrumb{font-size:14px;line-height:1}.tk-breadcrumb__separator{color:var(--vp-c-border);margin:0 7px}.tk-breadcrumb__item{align-items:center;display:inline-flex;float:left}.tk-breadcrumb__inner{color:var(--vp-c-text-1)}.tk-breadcrumb__inner a{font-weight:700;text-decoration:none;transition:color var(--tk-transition-duration-fast) cubic-bezier(.645,.045,.355,1)}.tk-breadcrumb__inner a:hover{color:var(--tk-theme-color);cursor:pointer}.tk-breadcrumb__item:last-child .tk-breadcrumb__inner,.tk-breadcrumb__item:last-child .tk-breadcrumb__inner a,.tk-breadcrumb__item:last-child .tk-breadcrumb__inner a:hover,.tk-breadcrumb__item:last-child .tk-breadcrumb__inner:hover{color:var(--vp-c-text-1);cursor:text;font-weight:400}.tk-breadcrumb__item:last-child .tk-breadcrumb__separator{display:none}.tk-icon{align-items:center;color:var(--icon-color,inherit);display:inline-flex;font-size:var(--icon-size,inherit);justify-content:center;line-height:1em;position:relative;fill:var(--icon-color,currentColor);transition:color var(--tk-transition-duration)}.tk-icon,.tk-icon svg{height:var(--icon-size,1em);width:var(--icon-size,1em)}.tk-icon svg{vertical-align:middle;fill:currentcolor}.tk-icon svg:focus{outline:none}.tk-icon .iconfont{color:var(--icon-color,inherit);font-size:var(--icon-size,1em)}.tk-icon.is-hover:hover i,.tk-icon.is-hover:hover svg,i.tk-icon.is-hover:hover{color:var(--icon-color-hover,inherit)}.tk-image-viewer__wrapper{inset:0;position:fixed}.tk-image-viewer__wrapper:focus{outline:none!important}.tk-image-viewer__btn{align-items:center;border-radius:50%;box-sizing:border-box;cursor:pointer;display:flex;justify-content:center;opacity:.8;position:absolute;-webkit-user-select:none;-moz-user-select:none;user-select:none;z-index:1}.tk-image-viewer__btn .tk-icon{cursor:pointer}.tk-image-viewer__close{font-size:40px;height:40px;right:40px;top:40px;width:40px}.tk-image-viewer__canvas{align-items:center;display:flex;height:100%;justify-content:center;position:static;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:100%}.tk-image-viewer__actions{background-color:var(--vp-c-text-1);border-color:#fff;border-radius:22px;bottom:30px;height:44px;left:50%;padding:0 23px;transform:translate(-50%)}.tk-image-viewer__actions__inner{align-items:center;color:#fff;cursor:default;display:flex;font-size:23px;gap:22px;height:100%;justify-content:space-around;padding:0 6px;width:100%}.tk-image-viewer__actions__divider{margin:0 -6px}.tk-image-viewer__progress{bottom:90px;color:#fff;cursor:default;left:50%;transform:translate(-50%)}.tk-image-viewer__prev{left:40px}.tk-image-viewer__next,.tk-image-viewer__prev{background-color:var(--vp-c-text-1);border-color:#fff;color:#fff;font-size:24px;height:44px;top:50%;transform:translateY(-50%);width:44px}.tk-image-viewer__next{right:40px;text-indent:2px}.tk-image-viewer__close{background-color:var(--vp-c-text-1);border-color:#fff;color:#fff;font-size:24px;height:44px;width:44px}.tk-image-viewer__mask{background:#000;height:100%;left:0;opacity:.5;position:absolute;top:0;width:100%}.viewer-fade-enter-active{animation:viewer-fade-in .3s}.viewer-fade-leave-active{animation:viewer-fade-out .3s}@keyframes viewer-fade-in{0%{opacity:0;transform:translate3d(0,-20px,0)}to{opacity:1;transform:translateZ(0)}}@keyframes viewer-fade-out{0%{opacity:1;transform:translateZ(0)}to{opacity:0;transform:translate3d(0,-20px,0)}}:root{--tk-slider-height:32px;--tk-slider-shadow-color:var(--tk-text-color-disabled);--tk-slider-thumb-height:32px;--tk-slider-thumb-width:32px;--tk-slider-thumb-border-radius:6px;--tk-slider-thumb-color:#fff;--tk-slider-track-height:calc(var(--tk-slider-height) - var(--tk-slider-track-progress-padding)*2);--tk-slider-track-border-radius:6px;--tk-slider-track-color:#fff;--tk-slider-track-progress-color:#fff;--tk-slider-track-progress-padding:0px;--tk-slider-transition-duration:var(--tk-transition-duration-fast)}:root.dark{--tk-slider-thumb-color:#e1e2da;--tk-slider-track-color:#e1e2da;--tk-slider-track-progress-color:#e1e2da}.tk-input-slide{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#e1e4e880;border:none;border-radius:8px;color:#d1d5db;display:flex;flex-direction:row;font-size:14px;padding:4px;width:100%}.tk-input-slide__label{position:relative;-webkit-user-select:none;-moz-user-select:none;user-select:none}.tk-input-slide__label,.tk-input-slide__label__input{cursor:col-resize;height:var(--tk-slider-height);width:100%}.tk-input-slide__label__input{-moz-appearance:none;appearance:none;-webkit-appearance:none;margin:0;transition:background-color var(--tk-slider-transition-duration) ease}.tk-input-slide__label__input:focus{outline:none}.tk-input-slide__label__input::-webkit-slider-thumb{-webkit-appearance:none;background:var(--tk-slider-thumb-color);border:none;border-radius:var(--tk-slider-thumb-border-radius);box-shadow:0 2px 4px 0 var(--tk-slider-shadow-color);cursor:col-resize;height:var(--tk-slider-thumb-height);margin-left:calc(0 - var(--tk-slider-track-progress-padding));margin-top:calc(var(--tk-slider-track-height)*.5 - var(--tk-slider-thumb-height)*.5);width:var(--tk-slider-thumb-width)}.tk-input-slide__label__input::-webkit-slider-runnable-track{background:#f2f2f200;border:none;border-radius:var(--tk-slider-track-border-radius);box-shadow:none;cursor:col-resize;height:var(--tk-slider-track-height)}.tk-input-slide__label__input::-moz-range-thumb{background:var(--tk-slider-thumb-color);border:none;border-radius:var(--tk-slider-thumb-border-radius);box-shadow:0 2px 4px 0 var(--tk-slider-shadow-color);cursor:col-resize;height:var(--tk-slider-thumb-height);margin-left:calc(0 - var(--tk-slider-track-progress-padding));width:var(--tk-slider-thumb-width)}.tk-input-slide__label__input::-moz-range-track{background:#f2f2f200;border:none;border-radius:var(--tk-slider-track-border-radius);box-shadow:none;cursor:col-resize;height:var(--tk-slider-track-height)}.tk-input-slide__label__input::-ms-fill-lower,.tk-input-slide__label__input::-ms-fill-upper{background:transparent;border-color:transparent}.tk-input-slide__label__input::-ms-thumb{background:var(--tk-slider-thumb-color);border:none;border-radius:var(--tk-slider-thumb-border-radius);box-shadow:0 2px 4px 0 var(--tk-slider-shadow-color);cursor:col-resize;height:var(--tk-slider-thumb-height);margin-left:calc(0 - var(--tk-slider-track-progress-padding));margin-top:0;width:var(--tk-slider-thumb-width)}.tk-input-slide__label__input::-ms-track{background:#f2f2f200;border:none;border-radius:var(--tk-slider-track-border-radius);box-shadow:none;cursor:col-resize;height:var(--tk-slider-track-height)}.tk-input-slide__label__input-progress{--tk-slider-range:calc(var(--tk-slider-max) - var(--tk-slider-min));--tk-slider-ratio:calc((var(--tk-slider-value) - var(--tk-slider-min))/var(--tk-slider-range));--tk-slider-sx:calc(var(--tk-slider-thumb-width)*.5 + var(--tk-slider-ratio)*(100% - var(--tk-slider-thumb-width)))}.tk-input-slide__label__input-progress::-webkit-slider-runnable-track{background:linear-gradient(var(--tk-slider-track-progress-color),var(--tk-slider-track-progress-color)) 0/var(--tk-slider-sx) 100% no-repeat,#fff0;cursor:col-resize;margin-left:var(--tk-slider-track-progress-padding);margin-right:calc(0 - var(--tk-slider-track-progress-padding))}.tk-input-slide__label__input-progress::-moz-range-track{background:linear-gradient(var(--tk-slider-track-progress-color),var(--tk-slider-track-progress-color)) 0/var(--tk-slider-sx) 100% no-repeat,#fff0;cursor:col-resize;display:block;width:calc(100% - var(--tk-slider-track-progress-padding) - var(--tk-slider-track-progress-padding))}.tk-input-slide__label__input-progress::-ms-fill-lower{background:var(--tk-slider-track-progress-color);border:none;border-radius:var(--tk-slider-track-border-radius) 0 0 var(--tk-slider-track-border-radius);border-right:0;cursor:col-resize;height:var(--tk-slider-track-height);margin-bottom:0;margin-left:calc(var(--tk-slider-track-progress-padding));margin-right:calc(0 - var(--tk-slider-track-progress-padding));margin-top:0}.tk-input-slide__label__tooltip{background-color:#000;border-radius:8px;color:#fff;min-width:48px;padding:8px;position:absolute;text-align:center;top:calc(-16px - var(--tk-slider-height))}:root{--tk-message-bg-color:var(--tk-el-color-info-light-9);--tk-message-border-color:var(--vp-c-border);--tk-message-border-width:1px;--tk-message-border-radius:4px;--tk-message-border-style:solid;--tk-message-padding:11px 15px;--tk-message-close-size:16px;--tk-message-close-icon-color:var(--tk-text-color-placeholder);--tk-message-close-hover-color:var(--vp-c-brand-3);--tk-message-bg-color-overlay:#fff}:root.dark{--tk-message-bg-color-overlay:#1d1e1f}.tk-message{align-items:center;background-color:var(--tk-message-bg-color);border-color:var(--tk-message-border-color);border-radius:var(--tk-message-border-radius);border-style:var(--tk-message-border-style);border-width:var(--tk-message-border-width);box-sizing:border-box;display:flex;gap:8px;left:50%;max-width:calc(100% - 32px);padding:var(--tk-message-padding);position:fixed;top:20px;transform:translate(-50%);transition:opacity .2s,transform .4s,top .4s;width:-moz-fit-content;width:fit-content}.tk-message.is-center{justify-content:center}.tk-message.is-plain{background-color:var(--tk-message-bg-color-overlay);border-color:var(--tk-message-bg-color-overlay);box-shadow:var(--tk-card-shadow)}.tk-message p{margin:0}.tk-message--primary{--tk-message-bg-color:var(--tk-el-color-primary-light-9);--tk-message-border-color:var(--tk-el-color-primary-light-8);--tk-message-text-color:var(--tk-el-color-primary)}.tk-message--primary .tk-message__content{color:var(--tk-message-text-color);overflow-wrap:break-word}.tk-message .tk-message-icon--primary{color:var(--tk-message-text-color)}.tk-message--success{--tk-message-bg-color:var(--tk-el-color-success-light-9);--tk-message-border-color:var(--tk-el-color-success-light-8);--tk-message-text-color:var(--tk-el-color-success)}.tk-message--success .tk-message__content{color:var(--tk-message-text-color);overflow-wrap:break-word}.tk-message .tk-message-icon--success{color:var(--tk-message-text-color)}.tk-message--info{--tk-message-bg-color:var(--tk-el-color-info-light-9);--tk-message-border-color:var(--tk-el-color-info-light-8);--tk-message-text-color:var(--tk-el-color-info)}.tk-message--info .tk-message__content{color:var(--tk-message-text-color);overflow-wrap:break-word}.tk-message .tk-message-icon--info{color:var(--tk-message-text-color)}.tk-message--warning{--tk-message-bg-color:var(--tk-el-color-warning-light-9);--tk-message-border-color:var(--tk-el-color-warning-light-8);--tk-message-text-color:var(--tk-el-color-warning)}.tk-message--warning .tk-message__content{color:var(--tk-message-text-color);overflow-wrap:break-word}.tk-message .tk-message-icon--warning{color:var(--tk-message-text-color)}.tk-message--error{--tk-message-bg-color:var(--tk-el-color-error-light-9);--tk-message-border-color:var(--tk-el-color-error-light-8);--tk-message-text-color:var(--tk-el-color-error)}.tk-message--error .tk-message__content{color:var(--tk-message-text-color);overflow-wrap:break-word}.tk-message .tk-message-icon--error{color:var(--tk-message-text-color)}.tk-message .tk-message__badge{position:absolute;right:-8px;top:-8px}.tk-message__content{font-size:14px;line-height:1;padding:0}.tk-message__content:focus{outline-width:0}.tk-message .tk-message__closeBtn{color:var(--tk-message-close-icon-color);cursor:pointer;font-size:var(--tk-message-close-size)}.tk-message .tk-message__closeBtn:focus{outline-width:0}.tk-message .tk-message__closeBtn:hover{color:var(--tk-message-close-hover-color)}.tk-message.antd{background:#fff!important;border-width:0!important;box-shadow:0 3px 6px -4px #0000001f,0 6px 16px #00000014,0 9px 28px 8px #0000000d!important;padding:10px 13px!important}.tk-message.antd.tk-message.is-closable .tk-message__content{padding-right:17px!important}.tk-message.antd .tk-message__content{background-image:none!important;color:#000000d9!important;pointer-events:all!important}.tk-message.antd .tk-message__closeBtn{border-radius:4px;outline:none;right:9px!important;transition:background-color .2s,color .2s}.tk-message.antd .tk-message__closeBtn:hover{background-color:#0000000f}.tk-message-fade-enter-from,.tk-message-fade-leave-to{opacity:0;transform:translate(-50%,-100%)}.tk-page-card{background-color:var(--tk-bg-color-elm);border-radius:var(--tk-home-card-border-radius);box-shadow:var(--tk-card-shadow);overflow:hidden;padding:var(--tk-home-card-padding);transition:box-shadow var(--tk-transition-duration-slow),transform var(--tk-transition-duration-slow);width:var(--tk-home-card-width)}.tk-page-card:hover{box-shadow:var(--tk-hover-shadow);transform:scale(1.01)}.tk-page-card__header{margin-bottom:10px}.tk-page-card__header .title{font-size:var(--tk-home-font-size-large)}.tk-page-card__header .title svg{height:16px;margin-right:var(--tk-home-card-svg-margin-left);width:16px}.tk-page-card__header .page-button{padding:0 3px;-webkit-user-select:none;-moz-user-select:none;user-select:none}.tk-page-card__header .page-button:hover{color:var(--tk-theme-color)}.tk-page-card__header .page-button.pointer{cursor:pointer}.tk-page-card__header .page-button.disabled{cursor:not-allowed;opacity:.5}:root{--tk-pagination-font-size:14px;--tk-pagination-bg-color:var(--tk-fill-color-blank);--tk-pagination-text-color:var(--vp-c-text-1);--tk-pagination-border-radius:2px;--tk-pagination-button-color:var(--vp-c-text-1);--tk-pagination-button-width:32px;--tk-pagination-button-height:32px;--tk-pagination-button-disabled-color:var(--tk-text-color-placeholder);--tk-pagination-button-disabled-bg-color:var(--tk-fill-color-blank);--tk-pagination-button-bg-color:var(--tk-fill-color);--tk-pagination-hover-color:var(--tk-theme-color);--tk-pagination-font-size-small:12px;--tk-pagination-button-width-small:24px;--tk-pagination-button-height-small:24px;--tk-pagination-button-width-large:40px;--tk-pagination-button-height-large:40px;--tk-pagination-item-gap:16px;--tk-pagination-transition-duration:var(--tk-transition-duration-fast)}.tk-pagination{align-items:center;color:var(--tk-pagination-text-color);display:flex;font-size:var(--tk-pagination-font-size);font-weight:400;white-space:nowrap}.tk-pagination .tk-input__inner{-webkit-appearance:textfield;-moz-appearance:textfield;appearance:textfield;text-align:center}.tk-pagination button{align-items:center;background:var(--tk-pagination-bg-color);border:none;border-radius:var(--tk-pagination-border-radius);box-sizing:border-box;color:var(--tk-pagination-button-color);cursor:pointer;display:flex;font-size:var(--tk-pagination-font-size);height:var(--tk-pagination-button-height);justify-content:center;line-height:var(--tk-pagination-button-height);min-width:var(--tk-pagination-button-width);padding:0 4px;text-align:center}.tk-pagination button *{pointer-events:none}.tk-pagination button:focus{outline:none}.tk-pagination button.is-active,.tk-pagination button:hover{color:var(--tk-pagination-hover-color)}.tk-pagination button.is-active{cursor:default;font-weight:700}.tk-pagination button.is-active.is-disabled{color:var(--vp-c-text-3);font-weight:700}.tk-pagination button.is-disabled,.tk-pagination button:disabled{background-color:var(--tk-pagination-button-disabled-bg-color);color:var(--tk-pagination-button-disabled-color);cursor:not-allowed}.tk-pagination button:focus-visible{outline:1px solid var(--tk-pagination-hover-color);outline-offset:-1px}.tk-pagination .btn-next .tk-icon,.tk-pagination .btn-prev .tk-icon{display:block;font-size:12px;font-weight:700;width:inherit}.tk-pagination>.is-first{margin-left:0!important}.tk-pagination>.is-last{margin-right:0!important}.tk-pagination .btn-prev,.tk-pagination__total{margin-left:var(--tk-pagination-item-gap)}.tk-pagination__total{color:var(--vp-c-text-2);font-weight:400}.tk-pagination__total[disabled=true]{color:var(--tk-text-color-placeholder)}.tk-pagination__jump{align-items:center;color:var(--vp-c-text-2);display:flex;font-weight:400;margin-left:var(--tk-pagination-item-gap)}.tk-pagination__jump[disabled=true]{color:var(--tk-text-color-placeholder)}.tk-pagination__goto{margin-right:8px}.tk-pagination__input{align-items:center;background-image:none;border-radius:4px;box-shadow:0 0 0 1px var(--vp-c-divider) inset;box-sizing:border-box;cursor:text;display:inline-flex;flex-grow:1;justify-content:center;padding:1px 11px;text-align:center;transform:translateZ(0);transition:box-shadow var(--tk-pagination-transition-duration) cubic-bezier(.645,.045,.355,1);width:56px}.tk-pagination__input:hover{box-shadow:0 0 0 1px var(--vp-c-border) inset}.tk-pagination__input:focus{box-shadow:0 0 0 1px var(--vp-c-brand-2) inset}.tk-pagination__input--small{font-size:12px;height:22px;padding:1px 7px}.tk-pagination__input--large{height:38px}.tk-pagination__classifier{margin-left:8px}.tk-pagination__right-wrapper{align-items:center;display:flex;flex:1;justify-content:flex-end}.tk-pagination.is-background .btn-next,.tk-pagination.is-background .btn-prev,.tk-pagination.is-background .tk-pager li{background-color:var(--tk-pagination-button-bg-color);margin:0 4px}.tk-pagination.is-background .btn-next.is-active,.tk-pagination.is-background .btn-prev.is-active,.tk-pagination.is-background .tk-pager li.is-active{background-color:var(--tk-theme-color);color:#fff}.tk-pagination.is-background .btn-next.is-disabled,.tk-pagination.is-background .btn-next:disabled,.tk-pagination.is-background .btn-prev.is-disabled,.tk-pagination.is-background .btn-prev:disabled,.tk-pagination.is-background .tk-pager li.is-disabled,.tk-pagination.is-background .tk-pager li:disabled{background-color:var(--tk-fill-color-light);color:var(--tk-text-color-placeholder)}.tk-pagination.is-background .btn-next.is-disabled.is-active,.tk-pagination.is-background .btn-next:disabled.is-active,.tk-pagination.is-background .btn-prev.is-disabled.is-active,.tk-pagination.is-background .btn-prev:disabled.is-active,.tk-pagination.is-background .tk-pager li.is-disabled.is-active,.tk-pagination.is-background .tk-pager li:disabled.is-active{background-color:var(--tk-fill-color-dark);color:var(--vp-c-text-3)}.tk-pagination.is-background .btn-prev{margin-left:var(--tk-pagination-item-gap)}.tk-pagination--small .btn-next,.tk-pagination--small .btn-prev,.tk-pagination--small .tk-pager li{font-size:var(--tk-pagination-font-size-small);height:var(--tk-pagination-button-height-small);line-height:var(--tk-pagination-button-height-small);min-width:var(--tk-pagination-button-width-small)}.tk-pagination--small button,.tk-pagination--small span:not([class*=suffix]){font-size:var(--tk-pagination-font-size-small)}.tk-pagination--small .tk-select{width:100px}.tk-pagination--large .btn-next,.tk-pagination--large .btn-prev,.tk-pagination--large .tk-pager li{height:var(--tk-pagination-button-height-large);line-height:var(--tk-pagination-button-height-large);min-width:var(--tk-pagination-button-width-large)}.tk-pagination--large .tk-select .tk-input{width:160px}.tk-pager{font-size:0;list-style:none;margin:0;padding:0;-webkit-user-select:none;-moz-user-select:none;user-select:none}.tk-pager,.tk-pager li{align-items:center;display:flex}.tk-pager li{background:var(--tk-pagination-bg-color);border:none;border-radius:var(--tk-pagination-border-radius);box-sizing:border-box;color:var(--tk-pagination-button-color);cursor:pointer;font-size:var(--tk-pagination-font-size);height:var(--tk-pagination-button-height);justify-content:center;line-height:var(--tk-pagination-button-height);min-width:var(--tk-pagination-button-width);padding:0 4px;text-align:center}.tk-pager li *{pointer-events:none}.tk-pager li:focus{outline:none}.tk-pager li.is-active,.tk-pager li:hover{color:var(--tk-pagination-hover-color)}.tk-pager li.is-active{cursor:default;font-weight:700}.tk-pager li.is-active.is-disabled{color:var(--vp-c-text-3);font-weight:700}.tk-pager li.is-disabled,.tk-pager li:disabled{background-color:var(--tk-pagination-button-disabled-bg-color);color:var(--tk-pagination-button-disabled-color);cursor:not-allowed}.tk-pager li:focus-visible{outline:1px solid var(--tk-pagination-hover-color);outline-offset:-1px}:root{--tk-popover-color:var(--vp-c-text-1);--tk-popover-bg-color:var(--tk-bg-color-elm);--tk-popover-padding:10px;--tk-popover-font-size:14px;--tk-popover-shadow:var(--vp-shadow-3);--tk-popover-border-color:var(--vp-c-divider);--tk-popover-border-radius:4px}.tk-popover{background-color:var(--tk-popover-bg-color);border:1px solid var(--tk-popover-border-color);border-radius:var(--tk-popover-border-radius);box-shadow:var(--tk-popover-shadow);box-sizing:border-box;color:var(--tk-popover-color);font-size:var(--tk-popover-font-size);max-height:calc(100vh - 100px);max-width:100vw;outline:none;overflow:auto;overflow-wrap:break-word;padding:var(--tk-popover-padding);position:absolute}:root{--tk-segmented-item-text:var(--vp-c-text-1);--tk-segmented-item-active-text:var(--vp-c-text-1);--tk-segmented-item-active-bg:var(--tk-bg-color-elm);--tk-segmented-item-shadow-color:var(--tk-text-color-disabled)}:root.dark{--tk-segmented-item-active-text:var(--tk-bg-color-elm);--tk-segmented-item-active-bg:var(--vp-c-text-1)}.tk-segmented-item{align-items:center;border-radius:6px;color:var(--tk-segmented-item-text);cursor:pointer;display:flex;flex:1;font-size:14px;font-weight:500;justify-content:center;padding:8px 12px;transition:background-color .25s,color .25s,box-shadow .25s;width:100%}.tk-segmented-item.is-active{background-color:var(--tk-segmented-item-active-bg);box-shadow:0 2px 4px 0 var(--tk-segmented-item-shadow-color);color:var(--tk-segmented-item-active-text);font-weight:700}.tk-segmented-item.is-disabled{color:var(--tk-segmented-item-active-text);cursor:not-allowed;opacity:.5}.tk-segmented-item:not(.is-disabled):hover{background-color:var(--tk-segmented-item-active-bg);box-shadow:0 2px 4px 0 var(--tk-segmented-item-shadow-color);color:var(--tk-segmented-item-active-text)}.tk-segmented-item__content{align-items:center;display:inline-flex;gap:4px;justify-content:center;vertical-align:middle}:root{--tk-segmented-padding:4px;--tk-segmented-gap:8px;--tk-segmented-line-height:20px;--tk-segmented-border-radius:6px}.tk-segmented{align-items:stretch;-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:var(--tk-segmented-border-radius);border-style:none;display:inline-flex;flex-wrap:wrap;gap:var(--tk-segmented-gap);line-height:var(--tk-segmented-line-height);padding:var(--tk-segmented-padding);width:100%}.tk-title-tag{border:1px solid var(--tk-theme-color);border-radius:3px;color:var(--tk-theme-color);display:inline-block;font-size:14px;font-weight:500;height:22px;line-height:18px;padding:2px 6px}.tk-title-tag--vp-primary{border:1px solid var(--vp-c-brand-1);color:var(--vp-c-brand-1)}.tk-title-tag--vp-info{border:1px solid var(--vp-c-gray-1);color:var(--vp-c-gray-1)}.tk-title-tag--vp-success{border:1px solid var(--vp-c-green-1);color:var(--vp-c-green-1)}.tk-title-tag--vp-warning{border:1px solid var(--vp-c-yellow-1);color:var(--vp-c-yellow-1)}.tk-title-tag--vp-danger{border:1px solid var(--vp-c-red-1);color:var(--vp-c-red-1)}.tk-title-tag--vp-important{border:1px solid var(--vp-c-purple-1);color:var(--vp-c-purple-1)}.tk-title-tag--ep-primary{border:1px solid var(--tk-el-color-primary);color:var(--tk-el-color-primary)}.tk-title-tag--ep-info{border:1px solid var(--tk-el-color-info);color:var(--tk-el-color-info)}.tk-title-tag--ep-success{border:1px solid var(--tk-el-color-success);color:var(--tk-el-color-success)}.tk-title-tag--ep-warning{border:1px solid var(--tk-el-color-warning);color:var(--tk-el-color-warning)}.tk-title-tag--ep-danger{border:1px solid var(--tk-el-color-danger);color:var(--tk-el-color-danger)}.tk-title-tag--right{margin-left:4px}.tk-title-tag--left{margin-right:4px}.tk-title-tag--large{font-size:16px;font-weight:600;height:24px;line-height:18px}.tk-title-tag--small{font-size:13px;height:19px;line-height:15px}.tk-title-tag--mini{font-size:12px;height:18px;line-height:14px}h1 .tk-title-tag{transform:translateY(-4px)}.tk-vp-container .custom-block.no-title{padding:10px 16px}.tk-archives .count{font-size:13.6px;font-style:oblique;font-weight:300;opacity:.8}.tk-archives__header .count{font-style:normal}.tk-archives__timeline{margin:32px 0}.tk-archives__timeline--year{background-color:var(--tk-bg-color);border-bottom:1px solid var(--tk-line-color);margin-top:32px;position:sticky;top:var(--vp-nav-height);z-index:1}.tk-archives__timeline--year .year{font-size:24px;font-weight:500;padding:8px 0}.tk-archives__timeline__m{margin-top:16px}.tk-archives__timeline__m--month{border-bottom:1px solid var(--tk-line-color);margin-top:16px}.tk-archives__timeline__m--month .month{font-size:19px;padding-bottom:8px}.tk-archives__timeline__m ul{padding:8px 16px}.tk-archives__timeline__m ul li{line-height:2}.tk-archives__timeline__m ul li a{display:block;transition:padding var(--tk-transition-duration)}.tk-archives__timeline__m ul li a:hover{background:var(--tk-fill-color-light);color:var(--tk-theme-color);padding-left:16px}.tk-archives__timeline__m ul li a .date{font-size:13.6px;margin-right:8px;opacity:.6}:root{--tk-home-article-analyze-gap:var(--tk-gap1)}.tk-article-analyze{flex-wrap:wrap;font-size:var(--tk-home-font-size-sm);gap:var(--tk-home-article-analyze-gap);margin-bottom:24px}.tk-article-analyze__wrapper{flex-wrap:wrap;font-size:14px}.tk-article-analyze__wrapper.teleport{margin-bottom:10px;margin-top:10px}.tk-article-analyze__wrapper .tk-icon{margin-right:3px}.tk-article-analyze__wrapper>div:not(:last-child){margin-right:14px}.tk-article-analyze__wrapper a{font-size:14px;font-weight:400;text-decoration:none}.tk-article-analyze__wrapper i{margin-right:3px}:root{--tk-appreciation-gap:var(--tk-gap1)}.tk-article-appreciation{font-size:14px;padding:20px;text-align:center}.tk-article-appreciation__button{align-items:center;-webkit-appearance:none;background-color:var(--tk-theme-color);border:1px solid var(--tk-theme-color);border-radius:4px;color:var(--vp-c-white);cursor:pointer;display:inline-flex;font-size:14px;font-weight:500;height:32px;justify-content:center;line-height:1;outline:none;padding:8px 15px;text-align:center;transition-duration:var(--tk-transition-duration-fast);-webkit-user-select:none;-moz-user-select:none;user-select:none;vertical-align:middle;white-space:nowrap}.tk-article-appreciation__button:hover{background-color:var(--vp-c-brand-3);border-color:var(--vp-c-brand-3)}.tk-article-appreciation__button__icon{margin-right:8px}.tk-article-appreciation__content{align-items:center;display:flex;flex-wrap:wrap;gap:var(--tk-appreciation-gap);justify-content:center;margin-top:10px;position:relative}.tk-article-appreciation--doc-after img{max-width:240px}.tk-article-appreciation--doc-after-popper{margin-top:0}.tk-article-appreciation--doc-after-popper img{max-width:160px}.tk-article-appreciation--aside-bottom img{max-width:100%}:root{--tk-article-banner-height:500px;--tk-article-banner-info-mr:16px;--tk-article-banner-text-color:#fff;--tk-article-banner-text-size:16px}@media(max-width:768px){:root{--tk-article-banner-text-size:15px}}.tk-article-banner{height:var(--tk-article-banner-height);position:relative;width:100%;z-index:1}@media(max-width:768px){.tk-article-banner{height:100vh}}.tk-article-banner__wrapper{background-position:50%;background-repeat:no-repeat;background-size:cover;height:100%;overflow:hidden;position:relative;transition:var(--tk-transition-duration-slow-plus);width:100%}.tk-article-banner__wrapper:before{background-color:var(--tk-article-banner-bg-color,var(--tk-theme-color));content:"";display:block;height:100%;left:0;position:absolute;top:0;transition:var(--tk-transition-duration);width:100%}.tk-article-banner__cover{animation:showCover 1s .3s backwards;display:block;filter:blur(10px);height:100%;margin-bottom:0;opacity:.5;overflow:hidden;position:absolute;top:0;transform:scale(1.3);width:100%}.tk-article-banner__cover img{height:100%;-o-object-fit:cover;object-fit:cover;opacity:.8;transition:all var(--tk-transition-duration-fast) ease 0s;width:100%}@keyframes showCover{0%{opacity:0;transform:scale(1)}}.tk-article-banner__info{align-items:flex-start;color:var(--tk-article-banner-text-color);display:flex;flex-direction:column;height:100%;justify-content:center;margin:0 auto;max-width:1400px;padding:0 60px;width:100%;z-index:10}@media(max-width:768px){.tk-article-banner__info{align-items:center;padding:22rem 6% 0;text-align:left}}.tk-article-banner__info h1{font-size:46px;font-weight:700;line-height:1.2;margin:20px 0;text-align:left;-webkit-line-clamp:2;overflow:hidden;padding:0}@media(max-width:768px){.tk-article-banner__info h1{font-size:30px;margin:10px auto;text-align:center;width:100%;-webkit-line-clamp:3}}.tk-article-banner__info .tk-breadcrumb{font-size:var(--tk-article-banner-text-size);margin-bottom:35px}.tk-article-banner__info .tk-breadcrumb__separator{color:#c2c2c4}.tk-article-banner__info .tk-breadcrumb__inner,.tk-article-banner__info .tk-breadcrumb__item:last-child .tk-breadcrumb__inner,.tk-article-banner__info .tk-breadcrumb__item:last-child .tk-breadcrumb__inner a,.tk-article-banner__info .tk-breadcrumb__item:last-child .tk-breadcrumb__inner a:hover,.tk-article-banner__info .tk-breadcrumb__item:last-child .tk-breadcrumb__inner:hover{color:var(--tk-article-banner-text-color)}@media(max-width:768px){.tk-article-banner__info .tk-article-analyze__wrapper{justify-content:center}}.tk-article-banner__info .tk-article-analyze__wrapper>div:not(:last-child){margin-right:var(--tk-article-banner-info-mr)}.tk-article-banner__info .tk-article-analyze__wrapper .tk-article-info{color:var(--tk-article-banner-text-color)}.tk-article-banner__info .tk-article-analyze__wrapper .tk-article-info>span:not(:last-child){margin-right:var(--tk-article-banner-info-mr)}.tk-article-banner__info .tk-article-analyze__wrapper a,.tk-article-banner__info .tk-article-analyze__wrapper i{font-size:var(--tk-article-banner-text-size);opacity:.85}.tk-article-banner__info .tk-article-analyze__wrapper a:hover,.tk-article-banner__info .tk-article-analyze__wrapper i:hover{color:inherit;opacity:1}.tk-article-banner__meta{font-size:var(--tk-article-banner-text-size);gap:10px}.tk-article-banner__meta a{font-weight:800}.tk-article-banner__meta .meta-info{align-items:center;border-radius:12px;display:flex;flex-direction:row;height:32px;line-height:32px;padding:0 10px;transition:var(--tk-transition-duration) ease-out}.tk-article-banner__meta .categories{gap:8px}.tk-article-banner__meta .categories .category{background-color:#fff3}.tk-article-banner__meta .categories .category:hover{background-color:var(--tk-article-banner-text-color);color:var(--tk-article-banner-bg-color,var(--tk-theme-color))}.tk-article-banner__meta .tags{gap:8px}.tk-article-banner__meta .tags .tag{color:var(--tk-article-banner-text-color);gap:2px}.tk-article-banner__meta .tags .tag:hover{background:#fff3}.tk-article-banner .tk-banner-waves{height:8vh;margin-top:-7vh}.tk-article-banner~.VPNav .VPNavBar:not(.home).top{background-color:transparent;color:var(--tk-article-banner-text-color)}.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPNavBarMenuGroup .text,.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPNavBarMenuLink,.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPNavBarTitle .title,.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPSocialLink{color:var(--tk-article-banner-text-color)}.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPNavBarMenuGroup .text.active,.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPNavBarMenuGroup .text:hover,.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPNavBarMenuLink.active,.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPNavBarMenuLink:hover,.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPNavBarTitle .title.active,.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPNavBarTitle .title:hover,.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPSocialLink.active,.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPSocialLink:hover{color:var(--tk-theme-color)}.tk-article-banner~.VPNav .VPNavBar:not(.home).top .divider{display:none}.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPNavBarSearch .DocSearch-Button{background-color:transparent}.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPNavBarSearch .DocSearch-Button .DocSearch-Button-Placeholder,.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPNavBarSearch .DocSearch-Button .tk-icon,.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPNavBarSearch .DocSearch-Button .vp-icon{color:var(--tk-article-banner-text-color)}.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPNavBarSearch .DocSearch-Button .DocSearch-Button-Key{border:none;color:var(--tk-article-banner-text-color)}.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPNavBarSearch .DocSearch-Button .DocSearch-Button-Key:after,.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPNavBarTranslations .text{color:var(--tk-article-banner-text-color)}.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPNavBarHamburger .bottom,.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPNavBarHamburger .middle,.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPNavBarHamburger .top{background-color:var(--tk-article-banner-text-color)}.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPNavBarExtra .button{color:var(--tk-article-banner-text-color)}.tk-article-banner~.VPNav .VPNavBar:not(.home).top.screen-open{--tk-article-banner-text-color:var(--vp-c-text-1);background-color:var(--vp-nav-bg-color)}@media(max-width:768px){.tk-article-banner~.VPNav{position:absolute}}.tk-article-breadcrumb .home:hover{color:var(--tk-theme-color)!important;cursor:pointer!important}:root{--tk-heading-highlight-color:var(--vp-c-text-1);--tk-heading-highlight-bg-color:var(--vp-c-brand-soft)}.tk-article-heading-highlight{animation:heading-highlight-animation 1.5s ease-in-out}@keyframes heading-highlight-animation{0%{background-color:transparent;box-shadow:0 0 0 8px transparent}10%,35%{background-color:var(--tk-heading-highlight-bg-color);border-color:transparent;border-radius:4px;box-shadow:0 0 0 8px var(--tk-heading-highlight-bg-color);color:var(--tk-heading-highlight-color)}99%{background-color:transparent;border-radius:4px;box-shadow:0 0 0 8px transparent}to{background-color:transparent;border-radius:0;box-shadow:none}}.tk-article-info{color:var(--tk-text-color-regular);font-size:var(--tk-home-font-size-sm)}.tk-article-info.article>span:not(:last-child){margin-right:14px}.tk-article-info__item:not(.split):not(:last-child){margin-right:16px}.tk-article-info__icon{margin-right:3px;vertical-align:-1px}.tk-article-info .split:not(:last-child):after{background-color:var(--tk-text-color-regular);content:"";display:inline-block;height:8px;margin:0 10px;width:.8px}.tk-article-info .or:not(:last-child):after{background-color:var(--tk-text-color-regular);content:"/";display:inline-block;height:0;width:5.6px}.tk-article-overview h2{border-bottom:1px solid var(--vp-c-divider);border-top:none;padding-bottom:16px;padding-top:0}.tk-article-overview h2 .header-anchor{top:0}:root{--tk-nav-color-dilute:hsla(0,0%,100%,.9);--tk-sidebar-color-dilute:hsla(0,0%,100%,.85)}:root.dark{--tk-nav-color-dilute:rgba(27,27,31,.9);--tk-sidebar-color-dilute:rgba(27,27,31,.85)}html[layout-mode=original] body:not(:has(.is-home)):has(.tk-card,.tk-card-nav,.tk-segment,.tk-segment-nav){background-color:var(--tk-bg-color-mute)}html[layout-mode=original] body:not(:has(.is-home)):has(.tk-card,.tk-card-nav,.tk-segment,.tk-segment-nav) .tk-spotlight-hover__under{z-index:0}html[layout-mode=original] .tk-card .VPContent:not(.is-home) .VPDoc.has-sidebar,html[layout-mode=original] .tk-card-nav .VPContent:not(.is-home) .VPDoc.has-sidebar{background-color:var(--tk-bg-color);padding-left:10px;padding-top:0}html[layout-mode=original] .tk-card .VPContent:not(.is-home) .VPDoc:not(.has-sidebar),html[layout-mode=original] .tk-card-nav .VPContent:not(.is-home) .VPDoc:not(.has-sidebar){padding-top:0}html[layout-mode=original] .tk-card .VPContent:not(.is-home) .VPDoc:not(.has-sidebar) .container,html[layout-mode=original] .tk-card-nav .VPContent:not(.is-home) .VPDoc:not(.has-sidebar) .container{background-color:var(--tk-bg-color)}html[layout-mode=original] .tk-card .VPContent:not(.is-home) .VPDoc:not(.has-sidebar) .container>.content,html[layout-mode=original] .tk-card-nav .VPContent:not(.is-home) .VPDoc:not(.has-sidebar) .container>.content{padding-left:0;padding-right:10px}html[layout-mode=original] .tk-segment .VPContent:not(.is-home) .VPDoc,html[layout-mode=original] .tk-segment-nav .VPContent:not(.is-home) .VPDoc{padding:0}html[layout-mode=original] .tk-segment .VPContent:not(.is-home) .VPDoc:not(.has-sidebar) .container>.content,html[layout-mode=original] .tk-segment-nav .VPContent:not(.is-home) .VPDoc:not(.has-sidebar) .container>.content{max-width:845px}html[layout-mode=original] .tk-segment .VPContent:not(.is-home) .VPDoc .container>.content,html[layout-mode=original] .tk-segment-nav .VPContent:not(.is-home) .VPDoc .container>.content{background-color:var(--tk-bg-color)}@media(max-width:1280px){html[layout-mode=original] .tk-segment .VPContent:not(.is-home) .VPDoc .container>.content,html[layout-mode=original] .tk-segment-nav .VPContent:not(.is-home) .VPDoc .container>.content{padding:32px 24px 96px}}html[layout-mode=original] .tk-segment .VPContent:not(.is-home) .VPDoc .aside .aside-container .aside-content,html[layout-mode=original] .tk-segment-nav .VPContent:not(.is-home) .VPDoc .aside .aside-container .aside-content{padding-bottom:20px}html[layout-mode=original] .tk-segment .VPContent:not(.is-home) .VPDoc .aside .aside-container .aside-content .content,html[layout-mode=original] .tk-segment-nav .VPContent:not(.is-home) .VPDoc .aside .aside-container .aside-content .content{background-color:var(--tk-bg-color);border-left:none;border-radius:4px;padding-bottom:10px;padding-right:15px}html[layout-mode=original] .tk-segment .VPContent:not(.is-home) .VPDoc .aside .aside-curtain,html[layout-mode=original] .tk-segment-nav .VPContent:not(.is-home) .VPDoc .aside .aside-curtain{display:none}html[layout-mode=original] .tk-segment .tk-article-share__button,html[layout-mode=original] .tk-segment-nav .tk-article-share__button{background-color:var(--tk-bg-color)}@media(min-width:1440px){html[layout-mode=original] .tk-card-nav .VPNav .VPNavBar.has-sidebar:not(.home) .container>.title,html[layout-mode=original] .tk-segment-nav .VPNav .VPNavBar.has-sidebar:not(.home) .container>.title{padding-left:20px}html[layout-mode=original] .tk-card-nav .VPNav .VPNavBar.has-sidebar:not(.home) .container>.content,html[layout-mode=original] .tk-segment-nav .VPNav .VPNavBar.has-sidebar:not(.home) .container>.content{padding-left:var(--vp-sidebar-width);padding-right:32px}html[layout-mode=original] .tk-card-nav .VPNav .VPNavBar.has-sidebar:not(.home) .container>.content .content-body,html[layout-mode=original] .tk-segment-nav .VPNav .VPNavBar.has-sidebar:not(.home) .container>.content .content-body{background:transparent}html[layout-mode=original] .tk-card-nav .VPNav .VPNavBar.has-sidebar:not(.home) .container>.content .content-body .VPNavBarSearch,html[layout-mode=original] .tk-segment-nav .VPNav .VPNavBar.has-sidebar:not(.home) .container>.content .content-body .VPNavBarSearch{padding-left:0}html[layout-mode=original] .tk-card-nav .VPNav .VPNavBar:not(.has-sidebar) .container,html[layout-mode=original] .tk-segment-nav .VPNav .VPNavBar:not(.has-sidebar) .container{margin:0;max-width:100%}}html[layout-mode=original] .tk-card-nav.Layout .VPNav .VPNavBar:not(.home),html[layout-mode=original] .tk-card.Layout .VPNav .VPNavBar:not(.home),html[layout-mode=original] .tk-segment-nav.Layout .VPNav .VPNavBar:not(.home),html[layout-mode=original] .tk-segment.Layout .VPNav .VPNavBar:not(.home){background-color:var(--tk-bg-color)}@media(min-width:1440px){html[layout-mode=original] .tk-card-nav.Layout .VPNav .VPNavBar:not(.home),html[layout-mode=original] .tk-card.Layout .VPNav .VPNavBar:not(.home),html[layout-mode=original] .tk-segment-nav.Layout .VPNav .VPNavBar:not(.home),html[layout-mode=original] .tk-segment.Layout .VPNav .VPNavBar:not(.home){background-color:var(--tk-nav-color-dilute)}}html[layout-mode=original] .tk-card .VPContent:not(.is-home) .VPDoc,html[layout-mode=original] .tk-card-nav .VPContent:not(.is-home) .VPDoc,html[layout-mode=original] .tk-segment .VPContent:not(.is-home) .VPDoc,html[layout-mode=original] .tk-segment-nav .VPContent:not(.is-home) .VPDoc{position:relative}html[layout-mode=original] .tk-card .VPContent:not(.is-home) .VPDoc .container>.content,html[layout-mode=original] .tk-card-nav .VPContent:not(.is-home) .VPDoc .container>.content,html[layout-mode=original] .tk-segment .VPContent:not(.is-home) .VPDoc .container>.content,html[layout-mode=original] .tk-segment-nav .VPContent:not(.is-home) .VPDoc .container>.content{border-radius:4px;padding-top:20px}html[layout-mode=original] .tk-card .VPContent:not(.is-home) .VPDoc .container>.content main>div,html[layout-mode=original] .tk-card-nav .VPContent:not(.is-home) .VPDoc .container>.content main>div,html[layout-mode=original] .tk-segment .VPContent:not(.is-home) .VPDoc .container>.content main>div,html[layout-mode=original] .tk-segment-nav .VPContent:not(.is-home) .VPDoc .container>.content main>div{z-index:1}html[layout-mode=original] .tk-card .VPNav .VPNavBar.has-sidebar .divider,html[layout-mode=original] .tk-card-nav .VPNav .VPNavBar.has-sidebar .divider,html[layout-mode=original] .tk-segment .VPNav .VPNavBar.has-sidebar .divider,html[layout-mode=original] .tk-segment-nav .VPNav .VPNavBar.has-sidebar .divider{padding:0}html[layout-mode=original] .tk-card .VPNav .VPNavBar.has-sidebar .VPNavBarTitle.has-sidebar .title,html[layout-mode=original] .tk-card-nav .VPNav .VPNavBar.has-sidebar .VPNavBarTitle.has-sidebar .title,html[layout-mode=original] .tk-segment .VPNav .VPNavBar.has-sidebar .VPNavBarTitle.has-sidebar .title,html[layout-mode=original] .tk-segment-nav .VPNav .VPNavBar.has-sidebar .VPNavBarTitle.has-sidebar .title{border:none}@media(min-width:1440px){html[layout-mode=original] .tk-card .VPSidebar,html[layout-mode=original] .tk-card-nav .VPSidebar,html[layout-mode=original] .tk-segment .VPSidebar,html[layout-mode=original] .tk-segment-nav .VPSidebar{background-color:var(--tk-sidebar-color-dilute);padding:0;top:var(--vp-nav-height);width:var(--vp-sidebar-width)}html[layout-mode=original] .tk-card .VPSidebar .nav,html[layout-mode=original] .tk-card-nav .VPSidebar .nav,html[layout-mode=original] .tk-segment .VPSidebar .nav,html[layout-mode=original] .tk-segment-nav .VPSidebar .nav{margin-top:10px}html[layout-mode=original] .tk-card .VPSidebar .nav .group,html[layout-mode=original] .tk-card-nav .VPSidebar .nav .group,html[layout-mode=original] .tk-segment .VPSidebar .nav .group,html[layout-mode=original] .tk-segment-nav .VPSidebar .nav .group{width:245px}html[layout-mode=original] .tk-card .VPSidebar .nav .VPSidebarItem.level-0,html[layout-mode=original] .tk-card-nav .VPSidebar .nav .VPSidebarItem.level-0,html[layout-mode=original] .tk-segment .VPSidebar .nav .VPSidebarItem.level-0,html[layout-mode=original] .tk-segment-nav .VPSidebar .nav .VPSidebarItem.level-0{padding-left:18px}html[layout-mode=original] .tk-card .VPSidebar .nav .VPSidebarItem.level-0 .items,html[layout-mode=original] .tk-card-nav .VPSidebar .nav .VPSidebarItem.level-0 .items,html[layout-mode=original] .tk-segment .VPSidebar .nav .VPSidebarItem.level-0 .items,html[layout-mode=original] .tk-segment-nav .VPSidebar .nav .VPSidebarItem.level-0 .items{padding-left:16px}}@media(min-width:1280px){html[layout-mode=original] .tk-card .VPContent:not(.is-home) .VPDoc,html[layout-mode=original] .tk-card-nav .VPContent:not(.is-home) .VPDoc,html[layout-mode=original] .tk-segment .VPContent:not(.is-home) .VPDoc,html[layout-mode=original] .tk-segment-nav .VPContent:not(.is-home) .VPDoc{margin:20px}html[layout-mode=original] .tk-card .VPContent:not(.is-home) .VPDoc .container>.content .content-container,html[layout-mode=original] .tk-card-nav .VPContent:not(.is-home) .VPDoc .container>.content .content-container,html[layout-mode=original] .tk-segment .VPContent:not(.is-home) .VPDoc .container>.content .content-container,html[layout-mode=original] .tk-segment-nav .VPContent:not(.is-home) .VPDoc .container>.content .content-container{max-width:100%}}.tk-article-share{padding:14px 0}.tk-article-share__button{background-color:var(--vp-c-bg-alt);border:1px solid transparent;border-radius:14px;color:var(--tk-theme-color);cursor:pointer;font-size:14px;font-weight:500;overflow:hidden;padding:7px 14px;position:relative;transition:all var(--tk-transition-duration-slow) cubic-bezier(.25,.8,.25,1);width:100%;z-index:1}.tk-article-share__button:before{background-color:var(--vp-c-brand-soft);content:"";height:100%;left:-100%;position:absolute;top:0;transition:left var(--tk-transition-duration-slow-plus) ease;width:100%;z-index:-1}.tk-article-share__button:hover{background-color:var(--vp-c-brand-soft);border-color:var(--vp-c-brand-soft);transform:translateY(-1px)}.tk-article-share__button:active{transform:scale(.9)}.tk-article-share__button.copied{background-color:var(--vp-c-brand-soft);color:var(--tk-theme-color)}.tk-article-share__button.copied:before{background-color:var(--vp-c-brand-soft);left:0}.tk-article-title .VPBadge.left{margin-right:5px}.tk-article-title .VPBadge.right{margin-left:5px}:root{--tk-article-update-num-color:var(--tk-theme-color);--tk-article-update-more-color:var(--vp-c-brand-2)}.tk-article-update{border:1px solid var(--vp-c-divider);border-radius:8px;margin:16px 0}.tk-article-update__title{border-bottom:1px solid var(--vp-c-divider);font-size:18px;padding:16px}.tk-article-update__title .edit-icon{margin-right:5px}.tk-article-update>ul{overflow:hidden}.tk-article-update>ul>li{border-bottom:1px dotted var(--vp-c-divider);height:50px;padding:8px 0;width:100%}.tk-article-update>ul>li:last-child{color:var(--tk-article-update-more-color)}.tk-article-update>ul>li:last-child:hover{color:var(--tk-theme-color)}.tk-article-update--num{color:var(--tk-article-update-num-color);font-size:17px;margin:0;text-align:center;width:50px}.tk-article-update__content{display:flex;flex:1}.tk-article-update__content a{padding-right:10px;width:180px}.tk-article-update__content a:hover{text-decoration:underline;text-decoration-color:var(--tk-theme-color)}.tk-article-update__content--date{color:var(--vp-c-text-3);font-size:14px;margin-right:15px;max-width:160px}:root{--tk-body-bg-img-nav-color:hsla(0,0%,100%,.9);--tk-body-bg-img-sidebar-color:hsla(0,0%,100%,.85)}:root.dark{--tk-body-bg-img-nav-color:rgba(27,27,31,.9);--tk-body-bg-img-sidebar-color:rgba(27,27,31,.85)}.tk-body-bg-image{background:var(--tk-body-bg-img);height:100vh;left:0;opacity:var(--tk-body-bg-img-opacity);position:fixed;top:0;transition:background-image 1s;width:100vw;z-index:-999999}.tk-body-bg-image .mask{background-color:var(--tk-body-mask-bg-color);height:100%;width:100%}.tk-body-bg-image~.tk-layout.Layout .VPContent:not(.is-home){background-color:var(--tk-bg-color)}@media(min-width:1280px){.tk-body-bg-image~.tk-layout.Layout header.VPNav .VPNavBar:not(.full-img-nav-bar).home,.tk-body-bg-image~.tk-layout.Layout header.VPNav .VPNavBar:not(.full-img-nav-bar):not(.home){background-color:var(--tk-body-bg-img-nav-color)}.tk-body-bg-image~.tk-layout.Layout.tk-card .VPNav .VPNavBar:not(.home) .content-body,.tk-body-bg-image~.tk-layout.Layout.tk-card-nav .VPNav .VPNavBar:not(.home) .content-body,.tk-body-bg-image~.tk-layout.Layout.tk-segment .VPNav .VPNavBar:not(.home) .content-body,.tk-body-bg-image~.tk-layout.Layout.tk-segment-nav .VPNav .VPNavBar:not(.home) .content-body{background-color:transparent}.tk-body-bg-image~.tk-layout.Layout.tk-card .VPSidebar,.tk-body-bg-image~.tk-layout.Layout.tk-card-nav .VPSidebar,.tk-body-bg-image~.tk-layout.Layout.tk-segment .VPSidebar,.tk-body-bg-image~.tk-layout.Layout.tk-segment-nav .VPSidebar{background-color:var(--tk-body-bg-img-sidebar-color)}.tk-body-bg-image~.tk-layout.Layout.tk-card .VPSidebar .curtain,.tk-body-bg-image~.tk-layout.Layout.tk-card-nav .VPSidebar .curtain,.tk-body-bg-image~.tk-layout.Layout.tk-segment .VPSidebar .curtain,.tk-body-bg-image~.tk-layout.Layout.tk-segment-nav .VPSidebar .curtain{background-color:transparent}}.tk-body-bg-image~.tk-layout.Layout .VPContent.is-home .vp-doc>div{background-color:var(--tk-bg-color);border-radius:4px;padding:0 32px 1px;width:calc(var(--tk-home-max-width) - var(--tk-home-card-width))}.tk-body-bg-image~.tk-layout.Layout .VPNavBar.home .divider{display:none}html[layout-mode=original] .tk-body-bg-image~.tk-layout.Layout.tk-card .VPContent:not(.is-home),html[layout-mode=original] .tk-body-bg-image~.tk-layout.Layout.tk-card-nav .VPContent:not(.is-home),html[layout-mode=original] .tk-body-bg-image~.tk-layout.Layout.tk-segment .VPContent:not(.is-home),html[layout-mode=original] .tk-body-bg-image~.tk-layout.Layout.tk-segment-nav .VPContent:not(.is-home){background-color:transparent}.tk-border-highlight{border-radius:6px;outline-color:transparent;outline-offset:4px;outline-style:dashed;outline-width:2px;transition:outline var(--tk-transition-duration-fast) cubic-bezier(.4,0,.2,1)}.tk-border-highlight.is-active{outline-color:var(--vp-c-brand-1)}.tk-sub-catalogue{margin-bottom:28px;margin-top:16px;width:100%}.tk-sub-catalogue__title .anchor{color:var(--tk-theme-color);font-size:.85em;margin-left:-1em;opacity:0;padding-right:.38em}.tk-sub-catalogue__title .anchor:hover{text-decoration:underline}.tk-sub-catalogue__title span{font-size:17.6px}.tk-sub-catalogue__title:hover .anchor{opacity:1}.tk-sub-catalogue__inline{margin-left:16px;margin-top:11px}.tk-sub-catalogue__inline .tk-sub-catalogue{margin-bottom:0}.tk-catalogue-item{margin-bottom:8px;width:48%}.tk-catalogue-item a,.tk-catalogue-item a:hover{color:var(--tk-theme-color)}@media(max-width:768px){.tk-catalogue-item{width:100%}}.tk-catalogue__header{border-bottom:1px solid var(--tk-line-color);margin-top:16px;padding-bottom:19px}.tk-catalogue__header .description{margin-top:10px}.tk-catalogue__wrapper .title{font-size:23px;margin:32px 0 16px}.tk-catalogue__wrapper .post{display:inline-block;margin-bottom:16px;width:50%}:root{--tk-code-block-fold-height:40px;--tk-code-block-lang-transform:uppercase}html[code-block=tk]:root{--vp-icon-copy:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='rgba(60,60,67,1)' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Crect width='8' height='4' x='8' y='2' rx='1' ry='1'/%3E%3Cpath d='M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2'/%3E%3C/svg%3E");--vp-icon-copied:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='rgba(60,60,67,1)' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Crect width='8' height='4' x='8' y='2' rx='1' ry='1'/%3E%3Cpath d='M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2'/%3E%3Cpath d='m9 14 2 2 4-4'/%3E%3C/svg%3E")}html[code-block=tk]:root.dark{--vp-icon-copy:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='rgba(223,223,214,1)' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Crect width='8' height='4' x='8' y='2' rx='1' ry='1'/%3E%3Cpath d='M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2'/%3E%3C/svg%3E");--vp-icon-copied:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='rgba(223,223,214,1)' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Crect width='8' height='4' x='8' y='2' rx='1' ry='1'/%3E%3Cpath d='M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2'/%3E%3Cpath d='m9 14 2 2 4-4'/%3E%3C/svg%3E")}html[code-block=tk] .tk-postItem__info__left__excerpt div[class*=language-],html[code-block=tk] .vp-doc :not(.tk-vp-code)>div[class*=language-]{overflow:hidden;transition:height var(--tk-transition-duration) ease-in-out}html[code-block=tk] .tk-postItem__info__left__excerpt div[class*=language-] .vp-code,html[code-block=tk] .vp-doc :not(.tk-vp-code)>div[class*=language-] .vp-code{padding-top:var(--tk-code-block-fold-height)}html[code-block=tk] .tk-postItem__info__left__excerpt div[class*=language-] .line-numbers-wrapper,html[code-block=tk] .vp-doc :not(.tk-vp-code)>div[class*=language-] .line-numbers-wrapper{margin-top:var(--tk-code-block-fold-height);padding-top:0}html[code-block=tk] .tk-postItem__info__left__excerpt div[class*=language-]:before,html[code-block=tk] .vp-doc :not(.tk-vp-code)>div[class*=language-]:before{background:#fc625d;border-radius:50%;box-shadow:20px 0 #fdbc40,40px 0 #35cd4b;content:"";display:block;height:12px;left:14px;position:absolute;top:calc(var(--tk-code-block-fold-height)/2);transform:translateY(-50%);width:12px}html[code-block=tk] .tk-postItem__info__left__excerpt div[class*=language-] span.lang,html[code-block=tk] .vp-doc :not(.tk-vp-code)>div[class*=language-] span.lang{color:var(--vp-c-text-1);font-size:18px;font-weight:700;left:75px;position:absolute;text-transform:var(--tk-code-block-lang-transform);top:calc(var(--tk-code-block-fold-height)/2);transform:translateY(-50%);width:-moz-fit-content;width:fit-content;z-index:3}html[code-block=tk] .tk-postItem__info__left__excerpt div[class*=language-] button.copy,html[code-block=tk] .vp-doc :not(.tk-vp-code)>div[class*=language-] button.copy{background-color:transparent;background-size:14px;border:none;height:18px;opacity:1;position:absolute;right:36px;top:calc(var(--tk-code-block-fold-height)/2);transform:translateY(-50%);width:18px}html[code-block=tk] .tk-postItem__info__left__excerpt div[class*=language-] button.copy:focus,html[code-block=tk] .tk-postItem__info__left__excerpt div[class*=language-] button.copy:focus+span.lang,html[code-block=tk] .tk-postItem__info__left__excerpt div[class*=language-]:hover button.copy+span.lang,html[code-block=tk] .tk-postItem__info__left__excerpt div[class*=language-]:hover>button.copy,html[code-block=tk] .vp-doc :not(.tk-vp-code)>div[class*=language-] button.copy:focus,html[code-block=tk] .vp-doc :not(.tk-vp-code)>div[class*=language-] button.copy:focus+span.lang,html[code-block=tk] .vp-doc :not(.tk-vp-code)>div[class*=language-]:hover button.copy+span.lang,html[code-block=tk] .vp-doc :not(.tk-vp-code)>div[class*=language-]:hover>button.copy{opacity:1}html[code-block=tk] .tk-postItem__info__left__excerpt div[class*=language-] .code-arrow,html[code-block=tk] .vp-doc :not(.tk-vp-code)>div[class*=language-] .code-arrow{color:var(--vp-c-text-2);cursor:pointer;position:absolute;right:14px;top:calc(var(--tk-code-block-fold-height)/2);transform:translateY(-50%);transition:all var(--tk-transition-duration);-webkit-user-select:none;-moz-user-select:none;user-select:none;z-index:3}html[code-block=tk] .tk-postItem__info__left__excerpt div[class*=language-] .code-arrow:hover,html[code-block=tk] .vp-doc :not(.tk-vp-code)>div[class*=language-] .code-arrow:hover{color:var(--vp-c-text-1)}html[code-block=tk] .tk-postItem__info__left__excerpt div[class*=language-] .code-arrow svg,html[code-block=tk] .vp-doc :not(.tk-vp-code)>div[class*=language-] .code-arrow svg{height:16px;width:16px;fill:var(--vp-c-text-1)}html[code-block=tk] .tk-postItem__info__left__excerpt div[class*=language-] .code-arrow.fold,html[code-block=tk] .vp-doc :not(.tk-vp-code)>div[class*=language-] .code-arrow.fold{transform:rotate(90deg) translate(-50%)}html[code-block=tk] .tk-postItem__info__left__excerpt div[class*=language-] .code-block-overlay,html[code-block=tk] .vp-doc :not(.tk-vp-code)>div[class*=language-] .code-block-overlay{align-items:center;background:linear-gradient(#0a0a0a00,#0a0a0af2);bottom:0;color:#ffffffe6;cursor:pointer;display:flex;font-size:20px;height:70px;justify-content:center;left:0;padding:0 24px;position:absolute;right:0;transition:opacity var(--tk-transition-duration) ease,color var(--tk-transition-duration) ease;z-index:10}html[code-block=tk] .tk-postItem__info__left__excerpt div[class*=language-] .code-block-overlay:hover,html[code-block=tk] .vp-doc :not(.tk-vp-code)>div[class*=language-] .code-block-overlay:hover{color:#fff;opacity:.8}html[code-block=tk] .tk-postItem__info__left__excerpt div[class*=language-] .code-block-overlay .overlay-icon,html[code-block=tk] .vp-doc :not(.tk-vp-code)>div[class*=language-] .code-block-overlay .overlay-icon{font-size:18px;margin-left:6px}.tk-artalk{--at-color-main:var(--vp-c-brand-2)}.tk-demo-code-description{font-size:14px;line-height:20px;margin-bottom:16px;margin-top:16px}.tk-demo-code{border:1px solid var(--vp-c-divider);border-radius:4px 4px 0 0}.tk-demo-code__effect{margin:.5px;overflow-y:auto;padding:24px}.tk-demo-code__button-group{align-items:center;border-top:1px solid var(--vp-c-divider);display:flex;height:40px;justify-content:flex-end;padding:8px}.tk-demo-code__button-group .tk-icon{color:var(--vp-c-text-1);cursor:pointer;margin:0 8px;opacity:.5;transition:opacity var(--tk-transition-duration);-webkit-user-select:none;-moz-user-select:none;user-select:none}.tk-demo-code__button-group .tk-icon:hover{opacity:1}.tk-demo-code .language-vue{border-radius:0!important;margin:0!important}.tk-demo-code__float-control{align-items:center;background-color:var(--tk-bg-color);border-bottom-left-radius:4px;border-bottom-right-radius:4px;border-left:1px solid var(--vp-c-divider);border-top:1px solid var(--vp-c-divider);bottom:0;color:var(--vp-c-text-1);cursor:pointer;display:flex;height:40px;justify-content:center;left:0;margin-top:-1px;position:sticky;right:0;z-index:10}.tk-demo-code__float-control span{font-size:14px;margin-left:10px}.tk-demo-code__float-control:hover{color:var(--tk-theme-color)}.tk-footer-group{display:grid;gap:20px 16px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));margin:20px auto;max-width:var(--tk-home-footer-group-width);padding-bottom:20px;width:100%}.tk-footer-group>div{padding-left:25%}.tk-footer-group__title{display:inline-flex;font-size:16px;font-weight:700;margin-bottom:14px;opacity:.9}.tk-footer-group__link{color:var(--vp-c-text-1);font-size:14px}.tk-footer-group__link a{align-items:center;border-radius:12px;display:inline-flex;margin-left:-10px;max-width:120px;padding:8px 10px;transition:color var(--tk-transition-duration) ease,background-color var(--tk-transition-duration) ease;width:-moz-max-content;width:max-content}.tk-footer-group__link a:hover{background-color:var(--tk-fill-color-light)}.tk-footer-group__link__external-icon{margin-left:4px}@media(max-width:640px){.tk-footer-group{grid-template-columns:repeat(2,1fr)}}:root{--tk-footer-gap:var(--tk-gap2)}.tk-footer-info{padding:0 20px 12px;text-align:center;width:100%}.tk-footer-info__icons{gap:var(--tk-footer-gap)}.tk-footer-info p{color:var(--vp-c-text-2);font-size:14px;font-weight:500;line-height:24px}.tk-footer-info__list{color:var(--vp-c-text-2);font-size:14px;gap:15px}.tk-footer-info__list__item{gap:5px}.tk-footer-info__list__item a:hover{color:var(--tk-theme-color);text-decoration:underline;text-decoration-color:var(--tk-theme-color);text-decoration-style:dashed}@media(max-width:719px){.tk-footer-info__list{align-items:center;flex-direction:column;gap:0}}.tk-banner-content{color:var(--tk-banner-text-color);padding-top:48px;text-align:center;width:100%}.tk-banner-content__title{font-size:var(--tk-banner-title-text);font-weight:600;line-height:1.25}.tk-banner-content__desc{font-size:var(--tk-banner-desc-text);line-height:1.3;margin:24px auto;max-width:800px;min-height:32px}@media(max-width:640px){.tk-banner-content__desc{margin:24px 10px}}.tk-banner-content__desc .switch{cursor:pointer}.tk-banner-content__desc .typed{opacity:1}.tk-banner-content__desc .typed.is-animation{animation:fade-out 1s infinite}@keyframes fade-out{0%{opacity:1}to{opacity:0}}:root{--tk-home-banner-feature-row-gap:var(--tk-gap2)}.tk-banner-feature{margin:40px auto 0;max-width:1100px;overflow:hidden;padding:32px 0;position:relative;row-gap:var(--tk-home-banner-feature-row-gap);width:100%}.tk-banner-feature__feature__item{color:var(--tk-banner-text-color);text-align:center;width:30%}.tk-banner-feature__feature__item .feature-img{animation:heart 1.2s ease-in-out 0s infinite alternate;animation-play-state:paused;height:160px;width:160px}.tk-banner-feature__feature__item .feature-img:hover{animation-play-state:running}.tk-banner-feature__feature__item .feature-title{font-size:21px;font-weight:500;margin-top:16px}.tk-banner-feature__feature__item .feature-details{margin:16px;opacity:.8}.tk-banner-feature__feature__item.tk-slide-next-enter-from{opacity:0!important;transform:translate(100%)!important}@media(max-width:719px){.tk-banner-feature__feature__item{width:100%}}@keyframes heart{0%{transform:translate(0)}to{transform:translateY(8px)}}.tk-banner-bg-image.part{min-height:var(--tk-home-banner-part-min-height)}.tk-banner-bg-image.full{height:100vh;left:0;position:absolute;top:0;width:100%}.tk-banner-bg-image.full,.tk-banner-bg-image.part{background:var(--tk-banner-img-bg) fixed;transition:background 1s}.tk-banner-bg-image.full .mask,.tk-banner-bg-image.part .mask{background-color:var(--tk-banner-mask-bg-color);height:100%;position:absolute;width:100%}.tk-banner-bg-pure{min-height:var(--tk-home-banner-part-min-height)}:root{--tk-waves-fill-color-1:hsla(0,0%,99%,.7);--tk-waves-fill-color-2:hsla(0,0%,99%,.5);--tk-waves-fill-color-3:hsla(0,0%,99%,.3);--tk-waves-fill-color-4:var(--tk-bg-color-elm)}:root.dark{--tk-waves-fill-color-1:rgba(34,34,34,.7);--tk-waves-fill-color-2:rgba(34,34,34,.5);--tk-waves-fill-color-3:rgba(34,34,34,.3)}.tk-banner-waves{height:12vh;margin-top:-11vh;max-height:150px;min-height:50px;position:relative;width:100%;z-index:10}.tk-banner-waves .parallax .use{animation:move-forever 25s cubic-bezier(.55,.5,.45,.5) infinite}.tk-banner-waves .parallax .use:first-child{animation-delay:-2s;animation-duration:7s;fill:var(--tk-waves-fill-color-1)}.tk-banner-waves .parallax .use:first-child :is(.dark .dark\:fill-black){fill:#000!important}.tk-banner-waves .parallax .use:nth-child(2){animation-delay:-3s;animation-duration:10s;fill:var(--tk-waves-fill-color-2)}.tk-banner-waves .parallax .use:nth-child(2) :is(.dark .dark\:fill-black){fill:#000}.tk-banner-waves .parallax .use:nth-child(3){animation-delay:-4s;animation-duration:13s;fill:var(--tk-waves-fill-color-3)}.tk-banner-waves .parallax .use:nth-child(4){animation-delay:-5s;animation-duration:20s;fill:var(--tk-waves-fill-color-4)}@keyframes move-forever{0%{transform:translate3d(-90px,0,0)}to{transform:translate3d(85px,0,0)}}:root{--tk-home-banner-part-min-height:450px;--tk-bg-img-default:#28282d url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACMAAAAjCAYAAAAe2bNZAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAABOSURBVFhH7c6xCQAgDAVRR9A6E4hLu4uLiWJ7tSnuQcIvr2TRYsw3/zOGGEOMIcYQY4gxxBhiDDGGGEOMIcYQY4gxxBhiDLkx52W4Gn1tuslCtHJvL54AAAAASUVORK5CYII=)}.tk-banner{position:relative}.tk-banner.is-full-img{margin-top:calc(var(--vp-nav-height)*-1)}.tk-banner.is-full-img .tk-banner__content{height:100vh}.tk-banner.is-full-img .tk-banner__content.no-feature{padding-bottom:15vh}.tk-banner__content{display:flex;flex-direction:column;justify-content:center;min-height:var(--tk-home-banner-part-min-height);position:relative}.tk-banner__content.no-feature{padding-bottom:10vh}.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open){background-color:transparent;color:var(--vp-c-white)}.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPNavBarMenuGroup .text,.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPNavBarMenuLink,.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPNavBarTitle .title,.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPSocialLink{color:var(--vp-c-white)}.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPNavBarMenuGroup .text.active,.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPNavBarMenuGroup .text:hover,.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPNavBarMenuLink.active,.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPNavBarMenuLink:hover,.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPNavBarTitle .title.active,.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPNavBarTitle .title:hover,.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPSocialLink.active,.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPSocialLink:hover{color:var(--tk-theme-color)}.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .divider{display:none}.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPNavBarSearch .DocSearch-Button{background-color:transparent}.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPNavBarSearch .DocSearch-Button .DocSearch-Button-Placeholder,.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPNavBarSearch .DocSearch-Button .tk-icon,.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPNavBarSearch .DocSearch-Button .vp-icon{color:var(--vp-c-white)}.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPNavBarSearch .DocSearch-Button .DocSearch-Button-Key{border:none;color:var(--vp-c-white)}.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPNavBarSearch .DocSearch-Button .DocSearch-Button-Key:after,.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPNavBarTranslations .text{color:var(--vp-c-white)}.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPNavBarHamburger .bottom,.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPNavBarHamburger .middle,.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPNavBarHamburger .top{background-color:var(--vp-c-white)}.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPNavBarExtra .button{color:var(--vp-c-white)}:root{--tk-home-info-gap:var(--tk-gap1)}.tk-home-card-list{gap:var(--tk-home-info-gap)}.tk-category.is-page{max-height:calc(100vh - 160px);min-height:67px;overflow-y:auto;position:sticky;top:72px}.tk-category__list{margin-top:5px;position:relative}.tk-category__list a{border-left:2px solid transparent;display:flex;font-size:var(--tk-home-font-size-middle);justify-content:space-between;margin-top:-1px;padding:2px 5px;transition:background-color var(--tk-transition-duration-fast),border-color var(--tk-transition-duration-fast),color var(--tk-transition-duration-fast),opacity var(--tk-transition-duration-slow) ease,transform var(--tk-transition-duration-slow) ease;width:100%}.tk-category__list a:hover{background-color:var(--tk-fill-color-light);border-color:var(--tk-theme-color)}.tk-category__list a.active{background:var(--tk-theme-color);border-color:transparent;border-radius:1px;color:var(--tk-bg-color);padding-left:13px}.tk-category--empty{font-size:var(--tk-home-font-size-middle);padding:6px;text-align:center}.tk-doc-analysis__item{display:flex;font-size:var(--tk-home-font-size-middle);justify-content:space-between;padding:1px 2px}.tk-home-features{margin:auto;max-width:1280px}@media(min-width:960px){.tk-home-features{padding:0 64px;width:100%}}@media(min-width:640px){.tk-home-features{padding:0 48px}}.tk-home-features .header h2{border-top:none;font-size:48px;font-weight:400;letter-spacing:0;line-height:48px;margin-bottom:32px;padding-top:12px}.tk-home-features .header p{font-size:18px;margin:18px 0}.tk-home-features .item{border-radius:8px;overflow:hidden;padding:16px;transition:background .3s cubic-bezier(.4,0,.2,1),box-shadow .3s cubic-bezier(.4,0,.2,1),transform .3s cubic-bezier(.4,0,.2,1);width:100%}.tk-home-features .item:hover{background-color:transparent;box-shadow:var(--tk-hover-shadow);transform:scale(1.05)}.tk-home-features .item .feature-icon{font-size:inherit;margin-right:6px}.tk-home-features a{color:inherit;text-decoration:none}.tk-home-features a:hover{color:inherit}.tk-home-features__feature-wrapper{padding-top:24px;position:relative;text-align:center}.tk-home-features__feature__content .image{height:160px;margin:0 auto}.tk-home-features__feature__content .features{align-content:stretch;align-items:stretch;display:flex;flex-wrap:wrap;justify-content:space-around;margin-top:16px;text-align:start}@media(max-width:719px){.tk-home-features__feature__content .features{gap:10px}}@media(max-width:640px){.tk-home-features__feature__content .features{padding-inline-end:24px;padding-inline-start:24px}}.tk-home-features__feature__content .features__item{flex-basis:calc(33% - 48px);margin:8px}.tk-home-features__feature__content .features__item:first-child:nth-last-child(2),.tk-home-features__feature__content .features__item:nth-child(2):last-child{flex-basis:calc(50% - 3rem)}@media(min-width:1440px){.tk-home-features__feature__content .features__item{flex-basis:calc(25% - 48px)}}@media(max-width:719px){.tk-home-features__feature__content .features__item{flex-basis:100%;font-size:15.2px;padding:0 16px}}.tk-home-features__feature__content .features__item h3{font-size:20.8px;font-weight:700;margin:4px 0 8px}.tk-home-features__feature__content .features__item p{margin:0}.tk-home-features__highlight-wrapper{position:relative}.tk-home-features__highlight-wrapper:nth-child(2n) .tk-home-features__highlight{flex-flow:row-reverse}.tk-home-features__highlight{align-items:center;display:flex;flex:1;justify-content:flex-end;padding:40px}@media(max-width:719px){.tk-home-features__highlight{display:block;padding-inline-end:24px;padding-inline-start:24px}}.tk-home-features__highlight .image{margin:32px 64px;width:192px}@media(max-width:959px){.tk-home-features__highlight .image{width:160px}}@media(max-width:719px){.tk-home-features__highlight .image{margin:0 auto;width:128px}}.tk-home-features__highlight__content{display:flex;flex:1;flex-direction:column;gap:5px;text-align:start}.tk-home-features__highlight__content .highlights__item{display:block}.tk-home-features__highlight__content .highlights__item.no-details:hover{box-shadow:none;transform:none}.tk-home-features__highlight__content .highlights__item h3{font-size:18px;font-weight:600;margin-top:0}.tk-home-features__highlight__content .highlights__item p{margin:0}.tk-home-features__highlight__header{padding-left:3ch}:root{--tk-home-friend-link-gap:var(--tk-gap2)}.tk-friend-link__list{gap:var(--tk-home-friend-link-gap);padding-right:5px;position:relative}.tk-friend-link__list__item{padding:0 5px}.tk-friend-link__list__item a{gap:15px}.tk-friend-link__list__item a .friend-avatar{border-radius:50%;height:50px;min-width:50px;overflow:hidden;transition:all .6s;width:50px}.tk-friend-link__list__item a .friend-avatar .avatar{height:100%;width:100%}.tk-friend-link__list__item__info{min-width:0}.tk-friend-link__list__item__info .friend-name{font-size:var(--tk-home-font-size-middle);font-weight:450}.tk-friend-link__list__item__info .friend-desc{color:var(--vp-c-text-2);font-size:var(--tk-home-font-size-middle)}.tk-friend-link--empty{font-size:var(--tk-"" home-font-size-middle);padding:6px;text-align:center}html.tk-fullscreen-wallpaper{overflow:hidden}html.tk-fullscreen-wallpaper .VPNav,html.tk-fullscreen-wallpaper .tk-wallpaper-outside{display:none}.tk-my-screen{border-bottom:1px solid var(--vp-c-divider);display:flex;gap:16px;margin-bottom:15px;padding-bottom:10px}.tk-my-screen__avatar{border-radius:5px;height:60px;width:60px}.tk-my-screen__blogger{flex:1}.tk-my-screen__blogger .name{font-size:18px;font-weight:600;margin-bottom:6px}.tk-my-screen__blogger .slogan{font-size:15px}.tk-my{position:relative}.tk-my.is-circle-bg{background-color:transparent}.tk-my__avatar{margin-bottom:10px;width:100%}.tk-my__avatar.circle-rotate img{transition:var(--tk-transition-duration-slow-plus) ease}.tk-my__avatar.circle-rotate img:hover{transform:rotate(1turn) scale(1.1)}.tk-my__avatar.circle-rotate-last img:hover{transform:rotate(666turn);transition-duration:59s;transition-timing-function:cubic-bezier(.34,0,.84,1)}.tk-my__avatar.square{margin:calc(var(--tk-home-card-padding)*-1) calc(var(--tk-home-card-padding)*-1) 10px;width:var(--tk-home-card-width)}@media(max-width:768px){.tk-my__avatar.square>span img{width:240px}}.tk-my__avatar>div{position:relative}.tk-my__avatar>div .avatar-sticker{align-items:center;border-radius:50%;bottom:3px;display:flex;justify-content:center;position:absolute;right:3px;transform:scale(1);transition:.3s ease-out .2s;z-index:0}.tk-my__avatar__circle--bg{background-position:50%;background-repeat:no-repeat;background-size:cover;height:100%;left:0;position:absolute;right:0;top:0;z-index:-1}.tk-my__avatar__circle--bg.is-mask:after{background:linear-gradient(to bottom,rgba(0,0,0,.3) 0,var(--tk-bg-color-elm) 100%);bottom:0;content:"";height:100%;left:0;opacity:.5;position:absolute;right:0}.tk-my__icons{margin-bottom:5px}.tk-my__blogger{padding:5px 5px 0;text-align:left}.tk-my__blogger .name{display:block;font-size:21px;margin-bottom:6px;text-align:center}.tk-my__blogger .slogan{display:-webkit-box;overflow:hidden;text-overflow:ellipsis;-webkit-box-orient:vertical;line-clamp:3;-webkit-line-clamp:3}@media(max-width:768px){.tk-my{text-align:center}}.tk-post-item{background-color:var(--tk-bg-color-elm);border-radius:8px;box-shadow:var(--tk-card-shadow);margin-bottom:14px;overflow:hidden;position:relative;transition:box-shadow var(--tk-transition-duration-slow) cubic-bezier(.4,0,.2,1),transform var(--tk-transition-duration-slow) cubic-bezier(.4,0,.2,1);width:100%}.tk-post-item:hover{box-shadow:var(--tk-hover-shadow);transform:scale(1.01)}.tk-post-item .pin{height:30px;left:-4px;opacity:.5;overflow:hidden;position:absolute;top:-4px;width:30px;z-index:9}.tk-post-item .pin:before{background-image:linear-gradient(45deg,var(--tk-theme-color),var(--tk-theme-color));box-shadow:0 5px 10px #0000003b;content:"";height:30px;position:absolute;transform:rotate(-45deg) translateY(-20px);width:120%}.tk-post-item__left{flex:1;padding:16px 24px;width:100%}.tk-post-item__left__title{cursor:pointer;display:block;font-size:20px;font-weight:600}.tk-post-item__left__footer{margin-top:8px}.tk-post-item__left__excerpt{margin:8px 0}.tk-post-item__left__excerpt.bottom{border-top:1px solid var(--tk-line-color)}.tk-post-item__left__excerpt.bottom .excerpt{display:-webkit-box;margin:8px 0;overflow:hidden;text-overflow:ellipsis;-webkit-box-orient:vertical;line-clamp:var(--tk-home-post-line-clamp);-webkit-line-clamp:var(--tk-home-post-line-clamp)}.tk-post-item__left__excerpt .excerpt{color:var(--tk-text-color-secondary);font-size:14px}.tk-post-item__left__excerpt .excerpt h1,.tk-post-item__left__excerpt .excerpt h2,.tk-post-item__left__excerpt .excerpt h3{display:none}.tk-post-item__left__excerpt .excerpt img{margin:0 auto;max-height:280px;max-width:100%}.tk-post-item__left__excerpt .more{color:var(--vp-c-brand-2);float:right;line-height:16px;margin-right:16px}.tk-post-item__left__excerpt .more:hover{color:var(--tk-theme-color)}.tk-post-item__right .cover{cursor:pointer}.tk-post-item__right .cover.default .cover-img{background-position:50%;background-repeat:no-repeat;background-size:contain;border-radius:2px;height:var(--tk-home-post-simple-img-height);margin-right:24px;width:var(--tk-home-post-simple-img-width)}.tk-post-item__right .cover.full{height:100%}.tk-post-item__right .cover.full .cover-img{clip-path:polygon(0 0,100% 0,100% 100%,8% 100%);height:var(--tk-home-post-full-img-height);max-width:var(--tk-home-post-full-img-width);transition:transform var(--tk-transition-duration) linear}.tk-post-item__right .cover.full .cover-img:hover{transform:scale(1.1)}@media(max-width:640px){.tk-post-item__right{display:none}}.tk-post-item-card{background-color:var(--tk-bg-color-elm);border-radius:8px;box-shadow:var(--tk-card-shadow);height:100%;overflow:hidden;position:relative;transition:box-shadow var(--tk-transition-duration-slow) cubic-bezier(.4,0,.2,1),transform var(--tk-transition-duration-slow) cubic-bezier(.4,0,.2,1)}.tk-post-item-card:hover{box-shadow:var(--tk-hover-shadow);transform:scale(1.01)}.tk-post-item-card .top{color:var(--tk-top-color,var(--tk-theme-color));opacity:.8;position:absolute;right:-4px;top:-5px;z-index:9}.tk-post-item-card__cover-img{overflow:hidden}.tk-post-item-card__cover-img .cover-img{cursor:pointer;height:100%;-o-object-fit:cover;object-fit:cover;transition:transform var(--tk-transition-duration) linear;width:100%}.tk-post-item-card__cover-img .cover-img:hover{transform:scale(1.2)}.tk-post-item-card__info{margin-bottom:10px;padding:10px 15px}.tk-post-item-card__info .title{cursor:pointer;display:block;font-size:18px;font-weight:600;margin-bottom:10px}.tk-post-item-card__info .excerpt{color:var(--tk-text-color-secondary);font-size:12px;margin-bottom:10px}.tk-post-item-card__info .tk-article-info__item:not(.split):not(:last-child){margin-right:10px}.tk-post-list.is-card>ul{-moz-column-gap:1.1rem;column-gap:1.1rem;display:grid;grid-auto-flow:row dense;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));row-gap:1.1rem}.tk-post-list__empty{margin:.5px;padding:24px}.tk-post-list__empty__title{margin-top:20px}.tk-post-list .tk-pagination{padding:15px 2px 0}.tk-post-list li.full-img:nth-child(2n) .list{flex-direction:row-reverse}.tk-post-list li.full-img:nth-child(2n) .list .full .cover-img{clip-path:polygon(0 0,92% 0,100% 100%,0 100%)}.tk-tag.is-page{max-height:calc(100vh - 160px);min-height:67px;overflow-y:auto;position:sticky;top:72px}.tk-tag__list{margin-top:5px;position:relative}.tk-tag__list a{border-radius:3px;display:inline-block;font-size:var(--tk-home-font-size-small);height:24px;line-height:24px;margin:0 5px 6px;padding:0 7px;text-align:center;transition:transform var(--tk-transition-duration) cubic-bezier(.4,0,.2,1)}.tk-tag__list a:hover{transform:translateY(-2px) scale(1.05)}.tk-tag__list a.active{box-shadow:0 5px 10px -5px var(--tk-home-tag-bg-color);transform:scale(1.15)}.tk-tag__list a.active:hover{text-decoration:none}.tk-tag__list a .num{font-size:12px;position:relative;right:-3px;top:-8px}.tk-tag__list .more{color:var(--vp-c-text-1);font-size:var(--tk-home-font-size-middle);line-height:var(--tk-home-font-size-middle)}.tk-tag__list .more:hover{color:var(--tk-theme-color);transform:none}.tk-tag--empty{font-size:var(--tk-home-font-size-middle);padding:6px;text-align:center}:root{--tk-home-top-article-gap:var(--tk-gap1)}.tk-top-article__list{gap:var(--tk-home-top-article-gap);padding-right:5px;position:relative}.tk-top-article__list__item{display:flex;gap:10px}.tk-top-article__list__item .num{border-radius:8px 0;color:var(--tk-text-color-secondary);font-size:var(--tk-home-font-size-middle);font-style:italic;font-weight:600;height:18px;line-height:18px;margin-top:4px;padding:0 6px}.tk-top-article__list__item .num.sticky{background-color:var(--tk-num-bg-color);border-radius:8px 0;color:var(--vp-c-white);font-size:var(--tk-home-font-size-small)}.tk-top-article__list__item__info{min-width:0}.tk-top-article__list__item__info .title{font-size:var(--tk-home-font-size-middle);font-weight:450}.tk-top-article__list__item__info .date{color:var(--vp-c-text-2);font-size:var(--tk-home-font-size-small)}.tk-top-article--empty{font-size:var(--tk-home-font-size-middle);padding:6px;text-align:center}.tk-home__content{gap:var(--tk-home-gap);margin:48px auto 0;max-width:var(--tk-home-max-width)}.tk-home__content__post{flex:1;min-width:400px}.tk-home__content__info{position:sticky;top:calc(var(--vp-nav-height) + 10px)}.tk-home__content__info.is-left{order:-1}@media(max-width:768px){.tk-home__content__info.is-left{order:1}}@media(max-width:1280px){.tk-home__content{padding:0 10px}}@media(max-width:768px){.tk-home__content{flex-wrap:wrap}.tk-home__content__post{min-width:100%;width:100%}.tk-home__content__info{flex:1;width:100%}}:root{--tk-full-width-max-width:100%;--tk-page-max-width:100%;--tk-doc-max-width:100%}@media(min-width:1280px){html[layout-mode=fullWidth] .VPNavBar.has-sidebar>.wrapper>.container>.title{padding-left:max(32px,(100% - (var(--tk-full-width-max-width) - 64px))/2)!important;width:calc(50% - var(--tk-full-width-max-width)/2 + var(--vp-sidebar-width))!important}html[layout-mode=fullWidth] .VPNavBar.has-sidebar>.wrapper>.container,html[layout-mode=fullWidth] .VPNavBar>.wrapper>.container{max-width:var(--tk-full-width-max-width)!important}html[layout-mode=fullWidth] .VPNavBar.has-sidebar>.wrapper>.container>.content{padding-left:max(32px,var(--vp-sidebar-width))!important;padding-right:32px!important;width:100%!important}html[layout-mode=fullWidth] .VPSidebar{padding-left:max(32px,(100% - (var(--tk-full-width-max-width) - 64px))/2)!important;width:calc(50% - var(--tk-full-width-max-width)/2 + var(--vp-sidebar-width))!important}html[layout-mode=fullWidth] .VPContent.has-sidebar{padding-left:calc((100vw - var(--tk-full-width-max-width))/2 + var(--vp-sidebar-width) - var(--tk-sidebar-trigger-doc-offset, 0px))!important;padding-right:calc((100vw - var(--tk-full-width-max-width))/2)!important}html[layout-mode=fullWidth] .VPDoc.has-aside div.content-container,html[layout-mode=fullWidth] .VPDoc:not(.has-sidebar) .container,html[layout-mode=fullWidth] .VPDoc:not(.has-sidebar) .container>.content{max-width:var(--tk-full-width-max-width)}}@media(min-width:1440px){html[layout-mode=fullWidth] .VPNavBar>.wrapper>.container{max-width:var(--tk-full-width-max-width)}html[layout-mode=fullWidth] .VPNavBar.has-sidebar>.divider{padding-left:calc((100vw - var(--tk-full-width-max-width))/2 + var(--vp-sidebar-width))!important}}@media(min-width:1536px){html[layout-mode=fullWidth] .VPDoc .container,html[layout-mode=fullWidth] .VPNavBar>.wrapper>.container{max-width:var(--tk-full-width-max-width)}}@media(min-width:1280px){html[layout-mode=sidebarWidthAdjustableOnly] .VPNavBar.has-sidebar>.wrapper>.container>.title{padding-left:max(32px,(100% - (var(--tk-page-max-width) - 64px))/2)!important;width:calc(50% - var(--tk-page-max-width)/2 + var(--vp-sidebar-width))!important}html[layout-mode=sidebarWidthAdjustableOnly] .VPNavBar.has-sidebar>.wrapper>.container,html[layout-mode=sidebarWidthAdjustableOnly] .VPNavBar>.wrapper>.container{max-width:var(--tk-page-max-width)!important}html[layout-mode=sidebarWidthAdjustableOnly] .VPNavBar.has-sidebar>.wrapper>.container>.content{padding-left:max(32px,(var(--vp-sidebar-width)))!important;padding-right:32px!important;width:100%!important}html[layout-mode=sidebarWidthAdjustableOnly] .VPSidebar{padding-left:max(32px,(100% - (var(--tk-page-max-width) - 64px))/2)!important;width:calc(50% - var(--tk-page-max-width)/2 + var(--vp-sidebar-width))!important}}@media(min-width:1440px){html[layout-mode=sidebarWidthAdjustableOnly] .VPNavBar.has-sidebar>.wrapper>.container,html[layout-mode=sidebarWidthAdjustableOnly] .VPNavBar>.wrapper>.container{max-width:var(--tk-page-max-width)!important}html[layout-mode=sidebarWidthAdjustableOnly] .VPNavBar.has-sidebar>.divider{padding-left:calc((100vw - var(--tk-page-max-width))/2 + var(--vp-sidebar-width))!important}html[layout-mode=sidebarWidthAdjustableOnly] .VPContent.has-sidebar{padding-left:calc((100vw - var(--tk-doc-max-width))/2 + var(--vp-sidebar-width) - var(--tk-sidebar-trigger-doc-offset, 0px))!important;padding-right:calc((100vw - var(--tk-doc-max-width))/2)!important}}@media(min-width:1280px){html[layout-mode=bothWidthAdjustable] .VPNavBar.has-sidebar>.wrapper>.container>.title{padding-left:max(32px,(100% - (var(--tk-page-max-width) - 64px))/2)!important;width:calc(50% - var(--tk-page-max-width)/2 + var(--vp-sidebar-width))!important}html[layout-mode=bothWidthAdjustable] .VPNavBar.has-sidebar>.wrapper>.container,html[layout-mode=bothWidthAdjustable] .VPNavBar>.wrapper>.container{max-width:var(--tk-page-max-width)!important}html[layout-mode=bothWidthAdjustable] .VPNavBar.has-sidebar>.wrapper>.container>.content{padding-left:max(32px,var(--vp-sidebar-width))!important;padding-right:32px!important;width:100%!important}html[layout-mode=bothWidthAdjustable] .VPSidebar{padding-left:max(32px,(100% - (var(--tk-page-max-width) - 64px))/2)!important;width:calc(50% - var(--tk-page-max-width)/2 + var(--vp-sidebar-width))!important}html[layout-mode=bothWidthAdjustable] .VPDoc.has-aside .content-container,html[layout-mode=bothWidthAdjustable] .VPDoc:not(.has-sidebar) .container,html[layout-mode=bothWidthAdjustable] .VPDoc:not(.has-sidebar) .container>.content{max-width:var(--tk-doc-max-width)}}@media(min-width:1440px){html[layout-mode=bothWidthAdjustable] .VPNavBar.has-sidebar>.wrapper>.container,html[layout-mode=bothWidthAdjustable] .VPNavBar>.wrapper>.container{max-width:var(--tk-page-max-width)!important}html[layout-mode=bothWidthAdjustable] .VPNavBar.has-sidebar>.divider{padding-left:calc((100vw - var(--tk-page-max-width))/2 + var(--vp-sidebar-width))!important}html[layout-mode=bothWidthAdjustable] .VPContent.has-sidebar{padding-left:calc((100vw - var(--tk-doc-max-width))/2 + var(--vp-sidebar-width) - var(--tk-sidebar-trigger-doc-offset, 0px))!important;padding-right:calc((100vw - var(--tk-doc-max-width))/2)!important}}@media(min-width:1536px){html[layout-mode=bothWidthAdjustable] .VPNavBar.has-sidebar>.wrapper>.container,html[layout-mode=bothWidthAdjustable] .VPNavBar>.wrapper>.container{max-width:var(--tk-page-max-width)!important}html[layout-mode=bothWidthAdjustable] .VPDoc .container{max-width:var(--tk-doc-max-width)}}html[layout-mode-animated=true] .VPNavBar.has-sidebar>.wrapper>.container>.title,html[layout-mode-animated=true] .VPNavBar>.wrapper>.container>.title{transition:width var(--tk-transition-duration-slow) ease-in-out,padding-left var(--tk-transition-duration-slow) ease-in-out}html[layout-mode-animated=true] .VPNavBar>.wrapper>.container{transition:width var(--tk-transition-duration-slow) ease-in-out,max-width var(--tk-transition-duration-slow) ease-in-out}html[layout-mode-animated=true] .VPNavBar.has-sidebar>.wrapper>.container>.content,html[layout-mode-animated=true] .VPNavBar>.wrapper>.container>.content{transition:padding-right var(--tk-transition-duration-slow) ease-in-out,padding-left var(--tk-transition-duration-slow) ease-in-out}html[layout-mode-animated=true] .VPNavBar.has-sidebar>.divider{transition:padding-left var(--tk-transition-duration-slow) ease-in-out,width var(--tk-transition-duration-slow) ease-in-out}html[layout-mode-animated=true] .VPSidebar{transition:width var(--tk-transition-duration-slow) ease-in-out,padding-left var(--tk-transition-duration-slow) ease-in-out}html[layout-mode-animated=true] .VPContent.has-sidebar{transition:width var(--tk-transition-duration-slow) ease-in-out,padding-left var(--tk-transition-duration-slow) ease-in-out,padding-right var(--tk-transition-duration-slow) ease-in-out}html[layout-mode-animated=true] .VPDoc .container,html[layout-mode-animated=true] .VPDoc.has-aside .content-container,html[layout-mode-animated=true] .VPDoc:not(.has-sidebar) .container,html[layout-mode-animated=true] .VPDoc:not(.has-sidebar) .container>.content{transition:width var(--tk-transition-duration-slow) ease-in-out,max-width var(--tk-transition-duration-slow) ease-in-out}.tk-layout--hide-vp-home .VPHomeFeatures,.tk-layout--hide-vp-home .VPHomeHero{display:none}.tk-layout__comment{margin-top:20px}:root{--tk-login-bg-color:#eee;--tk-login-mask-bg-color:hsla(0,0%,100%,.8);--tk-login-bg-img:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' baseProfile='full' viewBox='0 0 1400 800'%3E%3Crect width='150' height='150' x='1300' y='400' fill='%2381C995' stroke='%2381C995' rx='40' ry='40'%3E%3CanimateTransform attributeName='transform' attributeType='XML' begin='0s' dur='35s' from='0 1450 550' repeatCount='indefinite' to='360 1450 550' type='rotate'/%3E%3C/rect%3E%3Cpath fill='%23a2b3ff' d='M100 350a150 150 0 1 1 300 0q0 20-20 20H120q-20 0-20-20'%3E%3CanimateMotion begin='0s' dur='20s' path='M 800 -200 L 800 -300 L 800 -200' repeatCount='indefinite'/%3E%3CanimateTransform attributeName='transform' attributeType='XML' begin='0s' dur='30s' keyTimes='0 ; 0.5 ; 1' repeatCount='indefinite' type='rotate' values='0 210 530 ; -30 210 530 ; 0 210 530'/%3E%3C/path%3E%3Ccircle cx='150' cy='150' r='180' fill='%2385FFBD' stroke='%2385FFBD'%3E%3CanimateMotion dur='5s' path='M 0 0 L 40 20 Z' repeatCount='indefinite'/%3E%3C/circle%3E%3Cpath fill='%23a2b3ff' d='M165 580h105q5-2 0-10l-47-87q-3-3-6 0l-52 87q-5 8 0 10'%3E%3CanimateTransform attributeName='transform' attributeType='XML' begin='0s' dur='35s' from='0 210 530' repeatCount='indefinite' to='360 210 530' type='rotate'/%3E%3C/path%3E%3Cpath fill='%233054EB' d='M100 350a40 40 0 1 1 80 0v80a40 40 0 1 1-80 0Z'%3E%3CanimateMotion begin='0s' dur='20s' path='M 140 390 L 180 360 L 140 390' repeatCount='indefinite'/%3E%3CanimateTransform attributeName='transform' attributeType='XML' begin='0s' dur='30s' keyTimes='0 ; 0.5 ; 1' repeatCount='indefinite' type='rotate' values='0 140 390; -60 140 390; 0 140 390'/%3E%3C/path%3E%3Crect width='100' height='100' x='400' y='600' fill='%233054EB' stroke='%2381C995' rx='40' ry='40'%3E%3CanimateTransform attributeName='transform' attributeType='XML' begin='0s' dur='35s' from='-30 550 750' repeatCount='indefinite' to='330 550 750' type='rotate'/%3E%3C/rect%3E%3C/svg%3E")}:root.dark{--tk-login-bg-color:#191919;--tk-login-mask-bg-color:rgba(0,0,0,.8)}.tk-login{background-color:var(--tk-login-bg-color);background-image:var(--tk-login-bg-img);background-size:cover;height:100vh;min-height:550px;padding:30px;position:relative}.tk-login__wrapper{align-items:center;background-color:var(--tk-login-mask-bg-color);border-radius:10px;display:flex;height:100%;justify-content:space-around;padding:0 50px;width:100%}@media(max-width:640px){.tk-login__wrapper{background-color:transparent;padding:0}}.tk-login__left{width:900px}.tk-login__left img{height:100%;width:100%}.tk-login__right{background-color:var(--tk-bg-color);border-radius:10px;box-shadow:var(--tk-card-shadow);min-width:450px;overflow:hidden;padding:50px 40px 45px}.tk-login__right .cursor-pointer{width:30%}@media(max-width:640px){.tk-login__right{min-width:100%}}.tk-login__right__header{flex-wrap:wrap;gap:15px;margin-bottom:45px}.tk-login__right__header img{width:60px}.tk-login__right__header .title{color:var(--vp-c-text-1);font-size:42px;font-weight:700;line-height:1;margin:0;white-space:wrap}@media(max-width:640px){.tk-login__right__header .title{font-size:24px;text-align:center}}.tk-login__right__form{align-items:center;border:1px solid var(--vp-c-divider);border-radius:4px;display:inline-flex;flex-grow:1;justify-content:center;padding:1px 15px;transition:border .2s ease;transition:border-color .3s;width:100%}.tk-login__right__form .sr-only{height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;clip:rect(0,0,0,0);border-width:0;white-space:nowrap}.tk-login__right__form:hover{border-color:var(--vp-c-border)}.tk-login__right__form .tk-icon{color:var(--vp-c-text-3);margin-right:8px;pointer-events:none}.tk-login__right__form.is-focus{border-color:var(--tk-theme-color)}.tk-login__right__form.is-error{border-color:var(--vp-c-danger-1)}.tk-login__right__form.is-error input::-moz-placeholder{color:var(--vp-c-danger-1)}.tk-login__right__form.is-error .tk-icon,.tk-login__right__form.is-error input::placeholder{color:var(--vp-c-danger-1)}.tk-login__right__form--control{height:36px;outline:none;width:100%}.tk-login__right__form__btn{display:flex;flex-wrap:wrap;gap:20px;justify-content:space-between;width:100%}@media(max-width:640px){.tk-login__right__form__btn{justify-content:center}}.tk-login__right__form__btn button{border:1px solid var(--vp-c-divider);border-radius:20px;font-size:14px;height:40px;padding:12px 19px;width:185px}@media(max-width:640px){.tk-login__right__form__btn button{width:100%}}.tk-login__right__form__btn button .tk-icon{margin-right:8px;pointer-events:none}.tk-login__right__form__btn button:hover{background-color:var(--tk-fill-color-light)}.tk-login__right__form__btn button.primary{background-color:var(--tk-theme-color);border:none;color:var(--vp-c-white)}.tk-login__right__form__btn button.primary .tk-icon{color:var(--vp-c-white)}.tk-login__right__form__btn button.primary:hover{background-color:var(--vp-c-brand-3)}.tk-login~div{display:none}.VPContent .tk-login{height:calc(100vh - var(--vp-nav-height))}.tk-notice__icon{background-color:var(--vp-c-brand-3);border-radius:50%;cursor:pointer;font-size:12px;opacity:.6;padding:8px;position:fixed;right:10px;top:80px;z-index:20}.tk-notice__icon.twinkle{animation:twinkle 1.5s ease-in-out infinite}@media(max-width:1280px){.tk-notice__icon{top:115px}}.tk-notice__popover{background-color:var(--tk-bg-color);border:1px solid var(--vp-c-brand-3);border-radius:6px;box-shadow:var(--vp-shadow-2);max-width:400px;min-width:260px;position:fixed;right:20px;top:80px;z-index:110}.tk-notice__popover.is-top{right:20px;top:80px}.tk-notice__popover.is-center{left:50%;top:50%;transform:translate(-50%,-50%)}.tk-notice__popover__header{background-color:var(--vp-c-brand-3);color:var(--vp-c-white);padding:6px 4px}.tk-notice__popover__header>div{overflow:hidden}.tk-notice__popover__header .title{font-size:14px;padding-left:6px}.tk-notice__popover__content{padding:10px}.tk-notice__mask{background-color:#00000080;bottom:0;height:100%;left:0;overflow:auto;position:fixed;top:0;width:100%;z-index:109}@keyframes twinkle{0%{opacity:.5}50%{opacity:0}to{opacity:.5}}html.disable-scroll{overflow:hidden}.tk-right-bottom-button{bottom:40px;gap:16px;position:fixed;right:32px;z-index:99}.tk-right-bottom-button__button{align-items:center;background:var(--tk-bg-color);border-radius:50%;box-shadow:var(--tk-card-shadow);cursor:pointer;display:flex;height:37px;justify-content:center;position:relative;text-align:center;transition:all var(--tk-transition-duration) ease;width:37px}.tk-right-bottom-button__button .content{-webkit-user-select:none;-moz-user-select:none;user-select:none}.tk-right-bottom-button__button:hover{background-color:var(--tk-theme-color);box-shadow:0 0 15px var(--tk-theme-color)}.tk-right-bottom-button__button:hover .content,.tk-right-bottom-button__button:hover .tk-icon{color:var(--vp-c-white)}.tk-right-bottom-button__button.back-top:before{background:radial-gradient(farthest-side,var(--tk-theme-color) 98%,transparent) top/3.7px 3.7px no-repeat,conic-gradient(var(--tk-theme-color) calc(var(--tk-progress)*1%),transparent 0);border-radius:50%;content:"";inset:0;-webkit-mask:radial-gradient(farthest-side,transparent calc(99% - 3.7px),#000 calc(100% - 3.7px));mask:radial-gradient(farthest-side,transparent calc(99% - 3.7px),#000 calc(100% - 3.7px));position:absolute}.tk-right-bottom-button__button.back-top:after{background-color:var(--tk-theme-color);border-radius:50%;content:"";inset:calc(50% - 1.85px);position:absolute;transform:rotate(calc(var(--tk-progress)*3.6deg - 90deg)) translate(calc(18.5px - 50%))}.tk-right-bottom-button__dropdown{border-radius:6px;line-height:25.6px;padding:6px 0 8px;text-align:left}.tk-right-bottom-button__dropdown .dropdown-item{cursor:pointer;font-size:14px;padding:0 10px 0 15px}.tk-right-bottom-button__dropdown .dropdown-item:hover{background-color:var(--tk-fill-color-light);color:var(--tk-theme-color)}.tk-right-bottom-button__dropdown .dropdown-item.active{background-color:var(--tk-theme-color);color:var(--tk-bg-color)}.tk-right-bottom-button__dropdown__title{color:var(--tk-el-color-info);font-size:12px;padding:0 10px}@media(max-width:719px){.tk-right-bottom-button{bottom:24px;right:16px}}@media(max-width:960px){.tk-right-bottom-button .size-change{display:none}}.tk-risk-link{background-color:var(--tk-bg-color-elm);border-radius:10px;box-shadow:var(--tk-card-shadow);max-width:620px;min-width:350px;padding:20px;top:40%}@media(max-width:640px){.tk-risk-link{width:calc(100% - 60px)}}.tk-risk-link__header{flex-wrap:wrap;gap:15px}.tk-risk-link__header img{width:40px}.tk-risk-link__title{font-size:18px;font-weight:600;line-height:24px}.tk-risk-link__link{color:var(--vp-c-text-3);font-size:16px}.tk-risk-link button{background-color:var(--tk-theme-color);background-image:none;border:1px solid transparent;border-radius:6px;color:#fff;cursor:pointer;display:inline-block;font-size:14px;font-weight:400;height:32px;line-height:1.5;outline:none;padding:4px 15px;position:relative;text-align:center;touch-action:manipulation;transition:all var(--tk-transition-duration-fast) cubic-bezier(.645,.045,.355,1);-webkit-user-select:none;-moz-user-select:none;user-select:none;white-space:nowrap}.tk-risk-link button:hover{background-color:var(--vp-c-brand-3)}.tk-risk-link button.btn{float:right}.tk-risk-link~div{display:none}.tk-route-loading__mask{background:var(--vp-c-bg);left:0;position:fixed;top:0;width:100%;z-index:9999}.tk-route-loading__loader,.tk-route-loading__mask{align-items:center;display:flex;height:100%;justify-content:center}.tk-route-loading__loader{flex-direction:column}.tk-route-loading__spinner{animation:spin 1s linear infinite;border:4px solid #f1f1f1;border-radius:50%;border-top:4px solid var(--vp-c-brand-1);height:40px;margin:0 auto 10px;width:40px}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(1turn)}}:root{--tk-sidebar-trigger-top-offset:10px;--tk-sidebar-trigger-left-offset:10px;--tk-sidebar-trigger-collapse-doc-offset:160px}.tk-layout.has-sidebar-trigger .VPSidebar{transition:width var(--tk-transition-duration-slow) ease-in-out,padding-left var(--tk-transition-duration-slow) ease-in-out,padding-right var(--tk-transition-duration-slow) ease-in-out,opacity var(--tk-transition-duration-slow),transform var(--tk-transition-duration)}.tk-layout.has-sidebar-trigger .VPContent.has-sidebar.sidebar-trigger-transition{transition:padding-left var(--tk-transition-duration-slow) ease-in-out}.tk-layout.has-sidebar-trigger .VPDoc:not(.has-sidebar) .tk-sidebar-trigger{display:none}.tk-layout.has-sidebar-trigger.is-sidebar-collapse{--tk-sidebar-trigger-doc-offset:var(--tk-sidebar-trigger-collapse-doc-offset)}.tk-layout.has-sidebar-trigger.is-sidebar-collapse .VPSidebar{padding-left:0!important;padding-right:0!important;width:0!important}.tk-layout.has-sidebar-trigger.is-sidebar-collapse .VPNav{border:1px solid var(--vp-c-divider)}.tk-layout.has-sidebar-trigger.is-sidebar-collapse .VPNav .VPNavBar.has-sidebar{background-color:var(--vp-nav-bg-color)}.tk-layout.has-sidebar-trigger.is-sidebar-collapse .VPNav .VPNavBar.has-sidebar .divider{display:none}.tk-layout.has-sidebar-trigger.is-sidebar-collapse .VPNavBarTitle.has-sidebar>.title{border:none}.tk-layout.has-sidebar-trigger.is-sidebar-collapse .VPContent.has-sidebar{padding-left:calc((100vw - var(--vp-layout-max-width))/2 + var(--vp-sidebar-width) - var(--tk-sidebar-trigger-doc-offset, 0px))}.tk-layout.has-sidebar-trigger.is-sidebar-collapse .tk-sidebar-trigger{left:var(--tk-sidebar-trigger-left-offset)!important}.tk-layout.has-sidebar-trigger .tk-sidebar-trigger{left:calc(50% - var(--vp-layout-max-width)/2 + var(--vp-sidebar-width) + var(--tk-sidebar-trigger-left-offset));position:fixed;top:calc(var(--vp-nav-height) + var(--tk-sidebar-trigger-top-offset));transition:left var(--tk-transition-duration-slow) ease-in-out;z-index:20px}.tk-layout.has-sidebar-trigger .tk-sidebar-trigger>div{box-shadow:none}.tk-layout.has-sidebar-trigger .tk-sidebar-trigger.is-active{transition-duration:var(--tk-transition-duration-slow)}@media(max-width:1440px){.tk-layout.has-sidebar-trigger .tk-sidebar-trigger{left:calc(var(--vp-sidebar-width) + var(--tk-sidebar-trigger-left-offset))!important}}@media(max-width:1280px){.tk-layout.has-sidebar-trigger .tk-sidebar-trigger{top:calc(var(--vp-nav-height) + var(--tk-sidebar-trigger-top-offset) + 47px)}}.tk-card-nav.Layout.has-sidebar-trigger .tk-sidebar-trigger,.tk-card.Layout.has-sidebar-trigger .tk-sidebar-trigger,.tk-segment-nav.Layout.has-sidebar-trigger .tk-sidebar-trigger,.tk-segment.Layout.has-sidebar-trigger .tk-sidebar-trigger{left:calc(var(--vp-sidebar-width) + var(--tk-sidebar-trigger-left-offset))}.tk-card-nav.Layout.has-sidebar-trigger.is-sidebar-collapse .tk-sidebar-trigger,.tk-card.Layout.has-sidebar-trigger.is-sidebar-collapse .tk-sidebar-trigger,.tk-segment-nav.Layout.has-sidebar-trigger.is-sidebar-collapse .tk-sidebar-trigger,.tk-segment.Layout.has-sidebar-trigger.is-sidebar-collapse .tk-sidebar-trigger{left:var(--tk-sidebar-trigger-left-offset)}html[layout-mode=original] .tk-layout .tk-sidebar-trigger{left:calc(50% - var(--vp-layout-max-width)/2 + var(--vp-sidebar-width) + var(--tk-sidebar-trigger-left-offset));transition-duration:var(--tk-transition-duration-slow)}html[layout-mode=bothWidthAdjustable] .tk-layout .tk-sidebar-trigger,html[layout-mode=sidebarWidthAdjustableOnly] .tk-layout .tk-sidebar-trigger{left:calc(50% - var(--tk-page-max-width)/2 + var(--vp-sidebar-width) + var(--tk-sidebar-trigger-left-offset));transition-duration:var(--tk-transition-duration-slow)}html[layout-mode=fullWidth] .tk-layout .tk-sidebar-trigger{left:calc(50% - var(--tk-full-width-max-width)/2 + var(--vp-sidebar-width) + var(--tk-sidebar-trigger-left-offset));transition-duration:var(--tk-transition-duration-slow)}:root{--tk-spotlight-under-bg-color:var(--vp-c-brand-soft)}.tk-spotlight-hover{pointer-events:none;position:fixed}.tk-spotlight-hover__aside:before{background-color:var(--vp-c-brand);border-radius:4px;content:"";display:block;height:100%;left:-24px;position:absolute;width:4px}.tk-spotlight-hover__under{background-color:var(--tk-spotlight-under-bg-color);z-index:-1}:root{--tk-theme-enhance-text-color:var(--vp-c-text-1);--tk-theme-enhance-inner-bg-color:var(--tk-fill-color-dark)}.tk-segmented{background-color:var(--tk-theme-enhance-inner-bg-color);color:var(--tk-theme-enhance-text-color)}.tk-theme-enhance{height:100%}.tk-theme-enhance:before{background-color:var(--vp-c-divider);content:"";height:24px;margin-left:16px;margin-right:16px;width:1px}.tk-theme-enhance .tk-icon{cursor:pointer}@media(max-width:768px){.tk-theme-enhance{display:none!important}}.tk-theme-enhance__popover{border-radius:12px;padding:20px;width:340px}.tk-theme-enhance__content>*{margin-bottom:10px}.tk-theme-enhance__content>:last-child{margin-bottom:0}.tk-theme-enhance__theme-color .label{margin-right:10px}.tk-theme-enhance__theme-color h3{display:inline-block;font-size:12px;margin-bottom:6px;opacity:.8}.tk-theme-enhance__theme-color .color-list{gap:10px}.tk-theme-enhance__theme-color .color-wrapper{border-radius:6px;cursor:pointer;outline:1px solid var(--vp-c-divider);padding:4px;transition:outline-color .2s ease-in-out}.tk-theme-enhance__theme-color .color-wrapper.is-active,.tk-theme-enhance__theme-color .color-wrapper:hover{outline:2px solid var(--tk-theme-color)}.tk-theme-enhance__theme-color .color-wrapper .color-bg{border-radius:6px;height:24px;margin:6px 12px;width:24px}.tk-theme-enhance__title{align-items:center;color:var(--tk-theme-enhance-text-color);display:inline-flex;flex:1 1 0%;font-size:14px;font-weight:500;gap:4px;padding-right:16px;-webkit-user-select:none;-moz-user-select:none;user-select:none}.tk-theme-enhance__title.is-disabled{opacity:.5}.tk-theme-enhance__helper{color:var(--tk-theme-enhance-text-color);cursor:help;opacity:.5;transition:all var(--tk-transition-duration-fast) cubic-bezier(.4,0,.2,1)}.tk-theme-enhance__helper:hover{opacity:1}.tk-theme-enhance__helper--title{font-weight:600;margin-bottom:4px}.tk-theme-enhance__helper--desc{font-size:14px;line-height:20px;margin-bottom:8px}.tk-theme-enhance__helper__popup{color:var(--tk-theme-enhance-text-color)}.tk-theme-enhance__helper__body{max-width:400px}.tk-theme-enhance__helper__body__tip{background-color:var(--tk-theme-enhance-inner-bg-color);border-radius:12px;font-size:14px;line-height:20px;margin-bottom:10px;padding:12px}.tk-theme-enhance__helper__body__tip:last-child{margin-bottom:0}.tk-theme-enhance__slide{background-color:var(--tk-theme-enhance-inner-bg-color);color:var(--tk-theme-enhance-text-color)}.tk-theme-enhance__switch{align-items:center;background:#dcdfe6;border:1px solid #dcdfe6;border-radius:10px;box-sizing:border-box;cursor:pointer;display:inline-flex;height:20px;min-width:40px;outline:none;position:relative;transition:border-color var(--tk-transition-duration),background-color var(--tk-transition-duration)}.tk-theme-enhance__switch .action{align-items:center;background-color:var(--vp-c-white);border-radius:100%;color:#dcdfe6;display:flex;height:16px;justify-content:center;left:1px;position:absolute;transition:all var(--tk-transition-duration);width:16px}.tk-theme-enhance__switch.is-checked{background-color:var(--vp-c-brand-1);border-color:var(--vp-c-brand-1)}.tk-theme-enhance__switch.is-checked .action{color:var(--vp-c-brand-1);left:calc(100% - 17px)}.tk-theme-enhance .tk-theme-enhance-slide-enter-active,.tk-theme-enhance .tk-theme-enhance-slide-leave-active,.tk-theme-enhance .tk-theme-enhance-slide-move{transition:all var(--tk-transition-duration-fast) ease-in-out}.tk-theme-enhance .tk-theme-enhance-slide-enter-from,.tk-theme-enhance .tk-theme-enhance-slide-leave-to{opacity:0;transform:translateY(-15px)}@font-face{font-family:iconfont;src:url(iconfont.woff2?t=1755181778742) format("woff2"),url(iconfont.woff?t=1755181778742) format("woff"),url(iconfont.ttf?t=1755181778742) format("truetype")}.iconfont{font-family:iconfont!important;font-size:16px;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon-douban:before{content:""}.icon-xiangce:before{content:""}.icon-telegram:before{content:""}.icon-rss:before{content:""}.icon-weixin:before{content:""}.icon-Youtube:before{content:""}.icon-QQ:before{content:""}.icon-weibo:before{content:""}.icon-yuque:before{content:""}.icon-vex:before{content:""}.icon-csdn:before{content:""}.icon-facebook:before{content:""}.icon-youjian:before{content:""}.icon-sf:before{content:""}.icon-juejin:before{content:""}.icon-douyin:before{content:""}.icon-cnblogs-grey:before{content:""}.icon-github:before{content:""}.icon-jianshu:before{content:""}.icon-npm:before{content:""}.icon-bilibili:before{content:""}.icon-zhihu:before{content:""}.icon-tuite:before{content:""}.icon-gitee:before{content:""}.vp-code{outline:none}@media(max-width:640px){.vp-block,.vp-code-group .tabs,.vp-doc div[class*=language-]{margin-left:0;margin-right:0}}.VPSidebar .nav .item h2.text{font-size:18px}.VPSidebar .nav .item p.text{font-size:15px;transition:transform var(--tk-transition-duration) ease-in-out}.VPSidebar .nav .item p.text:hover{transform:translate(4px)}.VPSidebar .nav .VPSidebarItem.level-0>.items{padding-left:10px}.DocSearch-Button{background-color:transparent}.Layout .VPNavBar .VPSwitchAppearance{width:22px!important}.Layout .VPNavBar .VPSwitchAppearance .check{transform:none}.VPNav .VPNavBarTranslations .VPMenu .title{color:var(--tk-theme-color)}.VPDoc .aside .aside-container .outline-link{transition:color var(--tk-transition-duration),transform var(--tk-transition-duration)}.VPDoc .aside .aside-container .outline-link:hover{transform:translate(4px)}.VPDoc .aside .aside-container .outline-link.active{color:var(--tk-theme-color)}.VPDoc h1{background:-webkit-linear-gradient(10deg,#bd34fe 5%,#e43498 15%);-webkit-background-clip:text;background-clip:text;color:transparent}.vp-doc table{display:table;width:100%}.vp-doc td,.vp-doc th{border:0;min-width:92px}.vp-doc tr:nth-child(2n){background-color:unset}.vp-doc tr:last-child{border-bottom:1px solid var(--vp-c-divider)}:root{--tk-mark-color:#d63200}:root.dark{--tk-mark-color:#b160ea}.vp-doc mark{background-color:transparent;border:1px solid var(--tk-mark-color);border-radius:32px;color:var(--tk-mark-color);font-size:15px;margin:0 3px;padding:1px 8px}.vp-doc blockquote{background-color:var(--vp-c-gray-soft);border-radius:10px;opacity:.9;padding:10px 16px}@keyframes rainbow{0%{--rainbow-prev:#009ff7;--rainbow-next:#c76dd1}1.25%{--rainbow-prev:#009dfa;--rainbow-next:#cf69c9}2.5%{--rainbow-prev:#009bfc;--rainbow-next:#d566c2}3.75%{--rainbow-prev:#0098fd;--rainbow-next:#dc63ba}5%{--rainbow-prev:#0096fd;--rainbow-next:#e160b3}6.25%{--rainbow-prev:#0093fd;--rainbow-next:#e65eab}7.5%{--rainbow-prev:#2e90fc;--rainbow-next:#e95ca2}8.75%{--rainbow-prev:#4d8dfa;--rainbow-next:#ed5a9a}10%{--rainbow-prev:#638af8;--rainbow-next:#ef5992}11.25%{--rainbow-prev:#7587f5;--rainbow-next:#f15989}12.5%{--rainbow-prev:#8583f1;--rainbow-next:#f25981}13.75%{--rainbow-prev:#9280ed;--rainbow-next:#f25a79}15%{--rainbow-prev:#9f7ce9;--rainbow-next:#f25c71}16.25%{--rainbow-prev:#aa78e3;--rainbow-next:#f15e69}17.5%{--rainbow-prev:#b574dd;--rainbow-next:#ef6061}18.75%{--rainbow-prev:#be71d7;--rainbow-next:#ed635a}20%{--rainbow-prev:#c76dd1;--rainbow-next:#eb6552}21.25%{--rainbow-prev:#cf69c9;--rainbow-next:#e8694b}22.5%{--rainbow-prev:#d566c2;--rainbow-next:#e46c44}23.75%{--rainbow-prev:#dc63ba;--rainbow-next:#e06f3d}25%{--rainbow-prev:#e160b3;--rainbow-next:#db7336}26.25%{--rainbow-prev:#e65eab;--rainbow-next:#d77630}27.5%{--rainbow-prev:#e95ca2;--rainbow-next:#d17a2a}28.75%{--rainbow-prev:#ed5a9a;--rainbow-next:#cc7d24}30%{--rainbow-prev:#ef5992;--rainbow-next:#c6811e}31.25%{--rainbow-prev:#f15989;--rainbow-next:#bf8418}32.5%{--rainbow-prev:#f25981;--rainbow-next:#b98713}33.75%{--rainbow-prev:#f25a79;--rainbow-next:#b28a0f}35%{--rainbow-prev:#f25c71;--rainbow-next:#ab8d0c}36.25%{--rainbow-prev:#f15e69;--rainbow-next:#a3900b}37.5%{--rainbow-prev:#ef6061;--rainbow-next:#9c920d}38.75%{--rainbow-prev:#ed635a;--rainbow-next:#949510}40%{--rainbow-prev:#eb6552;--rainbow-next:#8b9715}41.25%{--rainbow-prev:#e8694b;--rainbow-next:#83991b}42.5%{--rainbow-prev:#e46c44;--rainbow-next:#7a9b21}43.75%{--rainbow-prev:#e06f3d;--rainbow-next:#719d27}45%{--rainbow-prev:#db7336;--rainbow-next:#679e2e}46.25%{--rainbow-prev:#d77630;--rainbow-next:#5da035}47.5%{--rainbow-prev:#d17a2a;--rainbow-next:#51a13c}48.75%{--rainbow-prev:#cc7d24;--rainbow-next:#44a244}50%{--rainbow-prev:#c6811e;--rainbow-next:#34a44b}51.25%{--rainbow-prev:#bf8418;--rainbow-next:#1ba553}52.5%{--rainbow-prev:#b98713;--rainbow-next:#00a65b}53.75%{--rainbow-prev:#b28a0f;--rainbow-next:#00a663}55%{--rainbow-prev:#ab8d0c;--rainbow-next:#00a76c}56.25%{--rainbow-prev:#a3900b;--rainbow-next:#00a874}57.5%{--rainbow-prev:#9c920d;--rainbow-next:#00a87d}58.75%{--rainbow-prev:#949510;--rainbow-next:#00a985}60%{--rainbow-prev:#8b9715;--rainbow-next:#00a98e}61.25%{--rainbow-prev:#83991b;--rainbow-next:#00a996}62.5%{--rainbow-prev:#7a9b21;--rainbow-next:#00a99f}63.75%{--rainbow-prev:#719d27;--rainbow-next:#00a9a7}65%{--rainbow-prev:#679e2e;--rainbow-next:#00a9b0}66.25%{--rainbow-prev:#5da035;--rainbow-next:#00a9b8}67.5%{--rainbow-prev:#51a13c;--rainbow-next:#00a9c0}68.75%{--rainbow-prev:#44a244;--rainbow-next:#00a8c7}70%{--rainbow-prev:#34a44b;--rainbow-next:#00a8cf}71.25%{--rainbow-prev:#1ba553;--rainbow-next:#00a7d5}72.5%{--rainbow-prev:#00a65b;--rainbow-next:#00a6dc}73.75%{--rainbow-prev:#00a663;--rainbow-next:#00a6e2}75%{--rainbow-prev:#00a76c;--rainbow-next:#00a4e7}76.25%{--rainbow-prev:#00a874;--rainbow-next:#00a3ec}77.5%{--rainbow-prev:#00a87d;--rainbow-next:#00a2f1}78.75%{--rainbow-prev:#00a985;--rainbow-next:#00a0f4}80%{--rainbow-prev:#00a98e;--rainbow-next:#009ff7}81.25%{--rainbow-prev:#00a996;--rainbow-next:#009dfa}82.5%{--rainbow-prev:#00a99f;--rainbow-next:#009bfc}83.75%{--rainbow-prev:#00a9a7;--rainbow-next:#0098fd}85%{--rainbow-prev:#00a9b0;--rainbow-next:#0096fd}86.25%{--rainbow-prev:#00a9b8;--rainbow-next:#0093fd}87.5%{--rainbow-prev:#00a9c0;--rainbow-next:#2e90fc}88.75%{--rainbow-prev:#00a8c7;--rainbow-next:#4d8dfa}90%{--rainbow-prev:#00a8cf;--rainbow-next:#638af8}91.25%{--rainbow-prev:#00a7d5;--rainbow-next:#7587f5}92.5%{--rainbow-prev:#00a6dc;--rainbow-next:#8583f1}93.75%{--rainbow-prev:#00a6e2;--rainbow-next:#9280ed}95%{--rainbow-prev:#00a4e7;--rainbow-next:#9f7ce9}96.25%{--rainbow-prev:#00a3ec;--rainbow-next:#aa78e3}97.5%{--rainbow-prev:#00a2f1;--rainbow-next:#b574dd}98.75%{--rainbow-prev:#00a0f4;--rainbow-next:#be71d7}to{--rainbow-prev:#009ff7;--rainbow-next:#c76dd1}}:root{--rainbow-prev:#009ff7;--rainbow-next:#c76dd1;--vp-home-hero-name-color:transparent;--vp-home-hero-name-background:-webkit-linear-gradient(120deg,var(--rainbow-prev) 30%,var(--rainbow-next));--vp-home-hero-image-background-image:linear-gradient(-45deg,var(--rainbow-prev) 30%,var(--rainbow-next));--vp-home-hero-image-filter:blur(80px)}.tk-banner-content__desc{-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);background-color:#fff6;border-radius:8px;display:inline-block;padding:8px}.tk-banner-content__desc span{background:linear-gradient(90deg,#f37055,#ef4e7b,#a166ab,#5073b8,#1098ad,#07b39b,#6fba82);-webkit-background-clip:text;background-clip:text;color:transparent;font-weight:700;letter-spacing:.1em}.tk-post-item{border-radius:10px}.tk-post-item:hover{box-shadow:0 8px 32px var(--vp-c-brand-1);transform:scale(1.02)}.tk-page-card{border-radius:10px}.tk-page-card:hover{box-shadow:0 8px 32px var(--vp-c-brand-1);transform:scale(1.02)}.tk-post-item-card{border-radius:10px}.tk-post-item-card:hover{box-shadow:0 8px 32px var(--vp-c-brand-1);transform:scale(1.02)}.tk-archives,.tk-article-banner__info,.tk-article-page .tk-aside-outline,.tk-article-page .tk-doc>div,.tk-banner__content,.tk-footer-group,.tk-home-card-list,.tk-home-feature,.tk-login,.tk-post-list,.tk-risk-link>*{animation:fade-up .6s .1s backwards}.VPDoc .VPDocAsideOutline,.VPDoc .vp-doc>div,.VPSidebar .group{animation:fade-up-slide .7s ease-out forwards}@keyframes fade-up{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}@keyframes fade-up-slide{0%{opacity:0;transform:translateY(40px)}30%{animation-timing-function:ease-out}to{opacity:1;transform:translateY(0)}}:root{--vp-code-block-bg: var(--tk-fill-color-light)}.tk-iframe .tk-article-page__aside{display:block}.tk-home .tk-banner-bg-pure{background:linear-gradient(180deg,#f7f5fa,#fff)}.tk-home .tk-banner-feature__feature__item{color:#000;letter-spacing:.3px;font-weight:600}.katex-display{margin:2em auto!important;text-align:center!important;display:flex!important;justify-content:center!important;align-items:center!important;width:100%!important;max-width:100%!important}.katex-display .katex{font-family:Kalam,Comic Sans MS,Marker Felt,Bradley Hand,cursive!important;font-size:1.5em!important;font-weight:700!important;padding:1.2em 1.8em;display:inline-flex!important;align-items:center!important;position:relative;margin:0 auto!important;vertical-align:middle!important;line-height:normal!important}.katex-display .katex>*{vertical-align:middle!important}.katex-display .katex .katex-html{display:inline-flex!important;align-items:center!important;vertical-align:middle!important}.katex-display .katex .katex-html>*{display:inline-flex!important;align-items:center!important;vertical-align:middle!important}.katex-display .katex .katex-mathml{display:inline-flex!important;align-items:center!important;vertical-align:middle!important}.katex-display .katex .frac{display:inline-flex!important;flex-direction:column!important;align-items:center!important;vertical-align:middle!important;justify-content:center!important;margin:0!important}.katex-display .katex .mrel,.katex-display .katex .mbin,.katex-display .katex .mop,.katex-display .katex .mord{display:inline-flex!important;align-items:center!important;vertical-align:middle!important}.katex-display .katex .mrel{align-self:center!important}.katex-display .katex{border:3px solid #ff6b6b;border-radius:12px;box-shadow:0 4px 6px #0000001a,0 2px 4px #0000000f,inset 0 1px #fffc;background:linear-gradient(135deg,#fff8f0f2,#ffefd5f2,#fff8f0f2);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}.katex-display .katex:before{content:"";position:absolute;inset:-2px;border:2px solid rgba(255,107,107,.3);border-radius:14px;z-index:-1;background:linear-gradient(135deg,#ffb6c14d,#ffdab94d)}.katex-display .katex{color:#2c3e50;letter-spacing:.03em}.katex-display .katex .katex-mathml .base,.katex-display .katex .katex-html .base{font-weight:700!important}.katex-display .katex .katex-mathml .mbin,.katex-display .katex .katex-mathml .mrel,.katex-display .katex .katex-html .mbin,.katex-display .katex .katex-html .mrel{margin:0 .4em!important}.katex-display .katex .katex-mathml .mopen,.katex-display .katex .katex-mathml .mclose,.katex-display .katex .katex-html .mopen,.katex-display .katex .katex-html .mclose{margin:0 .2em!important}.katex-display .katex *{letter-spacing:.03em}.katex-display .katex .mbin,.katex-display .katex .mrel,.katex-display .katex .mopen,.katex-display .katex .mclose{letter-spacing:.05em}.dark .katex-display .katex{border-color:#ff8787;background:linear-gradient(135deg,#2d3440f2,#3c4655f2,#2d3440f2);color:#e8e8e8;box-shadow:0 4px 6px #0000004d,0 2px 4px #0003,inset 0 1px #ffffff1a}.dark .katex-display .katex:before{border-color:#ff878766;background:linear-gradient(135deg,#ff6b6b33,#ffa50033)}@media(max-width:768px){.katex-display .katex{font-size:1.2em!important;padding:1em 1.2em}}.katex:not(.katex-display .katex){font-weight:600;font-family:Kalam,Comic Sans MS,cursive}.vp-doc table{display:table;border-collapse:collapse;border-spacing:0;width:100%;margin:1.5em 0;box-shadow:0 0 0 1px var(--vp-c-divider);border-radius:8px;overflow:hidden}.vp-doc table thead{background:linear-gradient(135deg,#3b82f61a,#8b5cf61a)}.vp-doc table thead tr{border-bottom:2px solid var(--vp-c-divider)}.vp-doc table thead th{padding:.75em 1em;text-align:left;font-weight:600;color:var(--vp-c-text-1);border-right:1px solid var(--vp-c-divider)}.vp-doc table thead th:last-child{border-right:none}.vp-doc table tbody tr{border-bottom:1px solid var(--vp-c-divider);transition:background-color .2s}.vp-doc table tbody tr:hover{background-color:var(--vp-c-bg-soft)}.vp-doc table tbody tr:last-child{border-bottom:none}.vp-doc table tbody td{padding:.75em 1em;border-right:1px solid var(--vp-c-divider);vertical-align:top}.vp-doc table tbody td:last-child{border-right:none}.vp-doc table tbody tr td:first-child{font-weight:600;color:var(--vp-c-text-1)}.dark .vp-doc table thead{background:linear-gradient(135deg,#3b82f626,#8b5cf626)}.dark .vp-doc table tbody tr:hover{background-color:var(--vp-c-bg-soft)}@media(max-width:768px){.vp-doc table{font-size:.875em}.vp-doc table thead th,.vp-doc table tbody td{padding:.5em .75em}}.tk-home-card-list .scroll__animate:has(.tk-page-card.tk-my){display:none!important}.tk-home-card-list .scroll__animate:not(:has(*)){display:none}.article-card-list[data-v-d45a9e33]{margin:2rem 0}.category-section[data-v-d45a9e33]{margin-bottom:2.5rem}.category-header[data-v-d45a9e33]{display:flex;align-items:center;gap:1rem;margin-bottom:1.25rem;position:relative}.category-icon-wrap[data-v-d45a9e33]{width:48px;height:48px;border-radius:14px;display:flex;align-items:center;justify-content:center;flex-shrink:0;box-shadow:0 4px 12px #00000014}.category-icon[data-v-d45a9e33]{font-size:22px;display:flex;align-items:center;justify-content:center}.category-info[data-v-d45a9e33]{display:flex;align-items:baseline;gap:.5rem}.category-index[data-v-d45a9e33]{font-size:.75rem;font-weight:700;font-family:SF Mono,Monaco,monospace;opacity:.8}.category-title[data-v-d45a9e33]{font-size:1.125rem;font-weight:600;color:var(--vp-c-text-1);margin:0;letter-spacing:-.01em}.category-line[data-v-d45a9e33]{flex:1;height:2px;border-radius:1px;margin-left:.5rem}.article-grid[data-v-d45a9e33]{display:grid;gap:.875rem}.article-card[data-v-d45a9e33]{display:flex;align-items:stretch;background:var(--vp-c-bg);border:1px solid var(--vp-c-divider);border-radius:14px;text-decoration:none;overflow:hidden;transition:all .25s cubic-bezier(.4,0,.2,1);position:relative}.article-card[data-v-d45a9e33]:before{content:"";position:absolute;inset:0;background:linear-gradient(135deg,var(--vp-c-brand-3) 0%,transparent 60%);opacity:0;transition:opacity .25s ease}.article-card[data-v-d45a9e33]:hover{border-color:var(--vp-c-brand-2);transform:translateY(-2px);box-shadow:0 8px 24px #0000001a,0 2px 8px #0000000f}.article-card[data-v-d45a9e33]:hover:before{opacity:.03}.card-indicator[data-v-d45a9e33]{width:4px;flex-shrink:0;opacity:.7;transition:all .25s ease}.article-card:hover .card-indicator[data-v-d45a9e33]{opacity:1;box-shadow:0 0 12px currentColor}.card-body[data-v-d45a9e33]{flex:1;padding:1rem 1.25rem;min-width:0}.article-meta[data-v-d45a9e33]{display:flex;align-items:center;gap:.5rem;margin-bottom:.375rem}.article-index[data-v-d45a9e33]{font-size:.6875rem;font-weight:700;font-family:SF Mono,Monaco,monospace;opacity:.7}.article-tag[data-v-d45a9e33]{font-size:.625rem;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--vp-c-text-3);background:var(--vp-c-bg-soft);padding:.125rem .5rem;border-radius:4px}.article-title[data-v-d45a9e33]{font-size:.9375rem;font-weight:600;color:var(--vp-c-text-1);margin:0 0 .375rem;line-height:1.45;letter-spacing:-.01em;transition:color .2s ease}.article-card:hover .article-title[data-v-d45a9e33]{color:var(--vp-c-brand-1)}.article-desc[data-v-d45a9e33]{font-size:.8125rem;color:var(--vp-c-text-2);margin:0;line-height:1.5;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.card-action[data-v-d45a9e33]{display:flex;align-items:center;gap:.375rem;padding:0 1.25rem;color:var(--vp-c-text-3);transition:all .25s ease;flex-shrink:0}.article-card:hover .card-action[data-v-d45a9e33]{color:var(--vp-c-brand-1)}.action-text[data-v-d45a9e33]{font-size:.75rem;font-weight:600;opacity:0;transform:translate(-8px);transition:all .25s ease}.action-icon[data-v-d45a9e33]{transition:transform .25s ease}.article-card:hover .action-text[data-v-d45a9e33]{opacity:1;transform:translate(0)}.article-card:hover .action-icon[data-v-d45a9e33]{transform:translate(4px)}@media(max-width:640px){.category-icon-wrap[data-v-d45a9e33]{width:42px;height:42px;border-radius:12px}.category-icon[data-v-d45a9e33]{font-size:18px}.category-title[data-v-d45a9e33]{font-size:1rem}.article-grid[data-v-d45a9e33]{gap:.75rem}.card-body[data-v-d45a9e33]{padding:.875rem 1rem}.article-title[data-v-d45a9e33]{font-size:.875rem}.card-action[data-v-d45a9e33]{padding:0 .875rem}.action-text[data-v-d45a9e33]{display:none}}.highlight-text[data-v-f601581b]{--hl-bg-color: var(--highlight-text-warning-bg, #fff3cd);--hl-text-color: var(--highlight-text-warning-text, #856404);display:inline;padding:var(--hl-padding);border-radius:var(--hl-border-radius);background-color:var(--hl-bg-color);color:var(--hl-text-color);line-height:1.4}.highlight-text--warning[data-v-f601581b]{--hl-bg-color: var(--highlight-text-warning-bg, #fff3cd);--hl-text-color: var(--highlight-text-warning-text, #856404)}.highlight-text--info[data-v-f601581b]{--hl-bg-color: var(--highlight-text-info-bg, #d1ecf1);--hl-text-color: var(--highlight-text-info-text, #0c5460)}.highlight-text--success[data-v-f601581b]{--hl-bg-color: var(--highlight-text-success-bg, #d4edda);--hl-text-color: var(--highlight-text-success-text, #155724)}.highlight-text--danger[data-v-f601581b]{--hl-bg-color: var(--highlight-text-danger-bg, #f8d7da);--hl-text-color: var(--highlight-text-danger-text, #721c24)}.highlight-text--note[data-v-f601581b]{--hl-bg-color: var(--highlight-text-note-bg, #e7d5f1);--hl-text-color: var(--highlight-text-note-text, #492866)}.highlight-text--custom[data-v-f601581b]{--hl-bg-color: var(--hl-custom-bg, #fff3cd);--hl-text-color: var(--hl-custom-text, #856404);background-color:var(--hl-bg-color);color:var(--hl-text-color)}:root{--highlight-text-warning-bg: #fff3cd;--highlight-text-warning-text: #856404;--highlight-text-info-bg: #d1ecf1;--highlight-text-info-text: #0c5460;--highlight-text-success-bg: #d4edda;--highlight-text-success-text: #155724;--highlight-text-danger-bg: #f8d7da;--highlight-text-danger-text: #721c24;--highlight-text-note-bg: #e7d5f1;--highlight-text-note-text: #492866}html.dark{--highlight-text-warning-bg: #3e331b;--highlight-text-warning-text: #ffd78a;--highlight-text-info-bg: #163a42;--highlight-text-info-text: #8edce6;--highlight-text-success-bg: #163c20;--highlight-text-success-text: #98e8a7;--highlight-text-danger-bg: #3d1b1e;--highlight-text-danger-text: #f5a3a9;--highlight-text-note-bg: #2a1d36;--highlight-text-note-text: #c9a7e0}.two-column-image[data-v-1bf3bb09]{display:flex;justify-content:space-between;align-items:flex-end}.image-column[data-v-1bf3bb09]{width:49%;text-align:center}.image[data-v-1bf3bb09]{width:100%;border-radius:8px}.caption[data-v-1bf3bb09]{font-size:14px;color:#666;margin-top:8px}.book-panel[data-v-1ddfc013]{position:fixed;inset:0;z-index:1000;display:flex;justify-content:flex-end;align-items:stretch}.book-panel__overlay[data-v-1ddfc013]{position:absolute;inset:0;background:#0006;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px)}.book-panel__drawer[data-v-1ddfc013]{position:relative;z-index:1;width:45%;max-width:92vw;height:100%;background:#fff;box-shadow:-12px 0 48px #00000024;display:flex;flex-direction:column;overflow-y:auto;overscroll-behavior:contain;--panel-leave-transform: translateX(100%)}.book-panel__header[data-v-1ddfc013]{position:relative;padding:52px 28px 28px;flex-shrink:0}.book-panel__close[data-v-1ddfc013]{position:absolute;top:14px;right:16px;width:30px;height:30px;border-radius:50%;border:none;background:#ffffffbf;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);display:flex;align-items:center;justify-content:center;cursor:pointer;color:#444;transition:background .2s,transform .15s;flex-shrink:0;z-index:2}.book-panel__close[data-v-1ddfc013]:hover{background:#fff;transform:rotate(90deg)}.book-panel__header-meta[data-v-1ddfc013]{display:flex;flex-direction:column;gap:6px}.book-panel__header-label[data-v-1ddfc013]{font-size:11px;font-weight:600;letter-spacing:1.2px;text-transform:uppercase;color:#00000073;margin:0}.book-panel__title[data-v-1ddfc013]{font-size:22px;font-weight:800;color:#1a1a1a;margin:0;line-height:1.35;display:-webkit-box;-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.book-panel__author[data-v-1ddfc013]{font-size:13px;color:#00000080;margin:0}.book-panel__body[data-v-1ddfc013]{padding:22px 28px 36px;display:flex;flex-direction:column;gap:16px;flex:1}.book-panel__top-bar[data-v-1ddfc013]{display:flex;justify-content:space-between;align-items:flex-start;gap:16px}.book-panel__top-left[data-v-1ddfc013]{display:flex;flex-direction:column;gap:10px;flex:1;min-width:0}.book-panel__links[data-v-1ddfc013]{display:flex;gap:8px;flex-shrink:0}.book-panel__link-btn[data-v-1ddfc013]{display:inline-flex;align-items:center;gap:5px;padding:7px 13px;border-radius:20px;background:#ffffffe6;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);color:#333;font-size:12px;font-weight:500;text-decoration:none;transition:background .2s,transform .2s,box-shadow .2s;box-shadow:0 1px 4px #0000000f;border:1px solid rgba(0,0,0,.05)}.book-panel__link-btn[data-v-1ddfc013]:hover{background:#fff;transform:translateY(-1px);box-shadow:0 3px 10px #0000001a}.book-panel__tags[data-v-1ddfc013]{display:flex;flex-wrap:wrap;gap:7px}.book-panel__tag[data-v-1ddfc013]{display:inline-block;padding:4px 13px;border-radius:20px;font-size:12px;font-weight:500;line-height:1.6;white-space:nowrap}.book-panel__rating[data-v-1ddfc013]{display:flex;align-items:center;gap:8px}.book-panel__rating .stars[data-v-1ddfc013]{display:flex;gap:2px}.book-panel__rating .star[data-v-1ddfc013]{width:18px;height:18px;color:#fbbf24}.book-panel__rating .star svg[data-v-1ddfc013]{width:100%;height:100%}.book-panel__rating .rating-label[data-v-1ddfc013]{font-size:13px;font-weight:500;color:#6b7280}.book-panel__rating .rating-text[data-v-1ddfc013]{font-size:14px;font-weight:600;color:#f59e0b}.book-panel__divider[data-v-1ddfc013]{height:1px;background:#00000012}.book-panel__section[data-v-1ddfc013]{display:flex;flex-direction:column;gap:10px}.book-panel__section-title[data-v-1ddfc013]{font-size:14px;font-weight:600;color:#aaa;margin:0;letter-spacing:.4px;line-height:1;display:flex;align-items:center;gap:6px}.book-panel__section-icon[data-v-1ddfc013]{font-style:normal;font-size:14px}.book-panel__desc[data-v-1ddfc013]{font-size:14px;color:#444;line-height:1.85;margin:0}.book-panel__highlights[data-v-1ddfc013]{list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:8px}.book-panel__highlight-item[data-v-1ddfc013]{font-size:14px;font-weight:500;color:#444;line-height:1.7;padding:10px 14px;background:linear-gradient(135deg,#fef9c3,#fef3c7);border-radius:8px;border-left:3px solid #f59e0b}.book-panel__highlight-item[data-v-1ddfc013]:before{content:"✓ ";color:#f59e0b;font-weight:700;margin-right:4px}.panel-slide-enter-active[data-v-1ddfc013],.panel-slide-leave-active[data-v-1ddfc013]{transition:opacity .28s ease}.panel-slide-enter-active .book-panel__drawer[data-v-1ddfc013],.panel-slide-leave-active .book-panel__drawer[data-v-1ddfc013]{transition:transform .3s cubic-bezier(.4,0,.2,1)}.panel-slide-enter-from[data-v-1ddfc013],.panel-slide-leave-to[data-v-1ddfc013]{opacity:0}.panel-slide-enter-from .book-panel__drawer[data-v-1ddfc013]{transform:translate(100%)}.panel-slide-leave-to .book-panel__drawer[data-v-1ddfc013]{transform:var(--panel-leave-transform, translateX(100%))}@media(max-width:640px){.book-panel[data-v-1ddfc013]{align-items:flex-end;justify-content:center}.book-panel__drawer[data-v-1ddfc013]{width:100%;max-width:100%;height:82vh;border-radius:20px 20px 0 0;box-shadow:0 -8px 40px #0000002e;--panel-leave-transform: translateY(100%)}.book-panel__drawer[data-v-1ddfc013]:before{content:"";display:block;width:36px;height:4px;border-radius:2px;background:#00000026;margin:10px auto 0;flex-shrink:0}.book-panel__header[data-v-1ddfc013]{padding:20px 22px 24px}.book-panel__title[data-v-1ddfc013]{font-size:19px}.book-panel__body[data-v-1ddfc013]{padding:18px 22px 40px}.book-panel__close[data-v-1ddfc013]{top:16px;right:16px}.book-panel__top-bar[data-v-1ddfc013]{flex-direction:column;align-items:stretch;gap:14px}.book-panel__links[data-v-1ddfc013]{justify-content:flex-start}.book-panel__link-btn[data-v-1ddfc013]{padding:6px 11px;font-size:11px}.panel-slide-enter-from .book-panel__drawer[data-v-1ddfc013]{transform:translateY(100%)}}.dark{background:var(--vp-c-bg, #1a1a2e)}.dark{color:#fff6}.dark{color:#e8e8e8}.dark{color:#b8b8c8}.dark{background:#ffffff14}.dark{color:#ffffff59}.dark{background:#ffffff26;color:#ccc}.dark{background:#ffffff40}.dark{color:#ffffff73}.dark{background:#ffffff26}.dark{background:linear-gradient(135deg,#fbbf2426,#f59e0b1a);border-left-color:#f59e0b;color:#e8e8e8}.dark{background:#28283ce6;color:#e8e8e8;box-shadow:0 1px 4px #0003;border-color:#ffffff14}.dark{background:#373750fa}.book-list[data-v-fd79cd55]{margin-top:16px;display:grid;grid-template-columns:repeat(3,1fr);gap:20px;padding:4px 0 28px}@media(max-width:768px){.book-list[data-v-fd79cd55]{grid-template-columns:repeat(2,1fr)}}@media(max-width:480px){.book-list[data-v-fd79cd55]{grid-template-columns:1fr}}.book-card[data-v-fd79cd55]{display:flex;flex-direction:column;border-radius:14px;overflow:hidden;box-shadow:0 2px 10px #00000012;border:1px solid rgba(0,0,0,.05);transition:transform .25s ease,box-shadow .25s ease;cursor:pointer;background:#fff;text-decoration:none;color:inherit}.book-card[data-v-fd79cd55]:hover{transform:translateY(-5px);box-shadow:0 10px 28px #0000001f}.book-card--active[data-v-fd79cd55]{box-shadow:0 0 0 2px var(--vp-c-brand, #3b82f6),0 10px 28px #0000001f;transform:translateY(-5px)}.book-cover[data-v-fd79cd55]{position:relative;width:100%;aspect-ratio:16 / 9;overflow:hidden}.book-cover__img[data-v-fd79cd55]{width:100%;height:100%;object-fit:cover;display:block;transition:transform .3s ease}.book-card:hover .book-cover__img[data-v-fd79cd55]{transform:scale(1.04)}.book-cover__overlay[data-v-fd79cd55]{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:#0000;transition:background .25s ease}.book-card:hover .book-cover__overlay[data-v-fd79cd55]{background:#00000052}.book-cover__hint[data-v-fd79cd55]{color:#fff;font-size:13px;font-weight:500;letter-spacing:.5px;opacity:0;transform:translateY(6px);transition:opacity .25s ease,transform .25s ease;text-decoration:none;padding:6px 14px;border:1px solid rgba(255,255,255,.7);border-radius:20px;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.book-card:hover .book-cover__hint[data-v-fd79cd55]{opacity:1;transform:translateY(0)}.book-info[data-v-fd79cd55]{padding:14px 16px 16px;display:flex;flex-direction:column;gap:7px;flex:1;background:#fff}.book-info__title[data-v-fd79cd55]{font-size:14px;font-weight:700;line-height:1.4;color:#1a1a1a;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.book-info__author[data-v-fd79cd55]{font-size:12px;color:#888}.book-info__rating[data-v-fd79cd55]{display:flex;align-items:center;gap:6px}.book-info__rating .stars[data-v-fd79cd55]{display:flex;gap:1px}.book-info__rating .star[data-v-fd79cd55]{width:14px;height:14px;color:#fbbf24}.book-info__rating .star svg[data-v-fd79cd55]{width:100%;height:100%}.book-info__rating .rating-label[data-v-fd79cd55]{font-size:11px;font-weight:500;color:#6b7280}.book-info__rating .rating-text[data-v-fd79cd55]{font-size:12px;font-weight:600;color:#f59e0b}.book-info__tags[data-v-fd79cd55]{display:flex;flex-wrap:wrap;gap:5px}.book-info__desc[data-v-fd79cd55]{font-size:12px;color:#666;line-height:1.7;margin:0;display:-webkit-box;-webkit-line-clamp:3;line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}.tag[data-v-fd79cd55]{display:inline-block;padding:2px 8px;border-radius:20px;font-size:11px;font-weight:500;line-height:1.6;white-space:nowrap}.dark .book-card[data-v-fd79cd55]{background:var(--vp-c-bg-soft, #1e1e2e);border-color:#ffffff14}.dark .book-info[data-v-fd79cd55]{background:var(--vp-c-bg-soft, #1e1e2e)}.dark .book-info__title[data-v-fd79cd55]{color:#e8e8e8}.dark .book-info__desc[data-v-fd79cd55]{color:#aaa}:root{animation:rainbow 12s linear infinite}.tk-avatar{height:var(--tk-avatar-size)!important;width:var(--tk-avatar-size)!important}.tk-avatar--circle{border-radius:50%!important}.vp-doc #hero-text{display:none!important}@media(min-width:640px){:root{--vp-home-hero-image-filter: blur(56px)}}@media(min-width:960px){:root{--vp-home-hero-image-filter: blur(68px)}}.VPLocalSearchBox[data-v-400916ea]{position:fixed;z-index:100;inset:0;display:flex}.backdrop[data-v-400916ea]{position:absolute;inset:0;background:var(--vp-backdrop-bg-color);transition:opacity .5s}.shell[data-v-400916ea]{position:relative;padding:12px;margin:64px auto;display:flex;flex-direction:column;gap:16px;background:var(--vp-local-search-bg);width:min(100vw - 60px,900px);height:min-content;max-height:min(100vh - 128px,900px);border-radius:6px}@media(max-width:767px){.shell[data-v-400916ea]{margin:0;width:100vw;height:100vh;max-height:none;border-radius:0}}.search-bar[data-v-400916ea]{border:1px solid var(--vp-c-divider);border-radius:4px;display:flex;align-items:center;padding:0 12px;cursor:text}@media(max-width:767px){.search-bar[data-v-400916ea]{padding:0 8px}}.search-bar[data-v-400916ea]:focus-within{border-color:var(--vp-c-brand-1)}.local-search-icon[data-v-400916ea]{display:block;font-size:18px}.navigate-icon[data-v-400916ea]{display:block;font-size:14px}.search-icon[data-v-400916ea]{margin:8px}@media(max-width:767px){.search-icon[data-v-400916ea]{display:none}}.search-input[data-v-400916ea]{padding:6px 12px;font-size:inherit;width:100%}.search-input[data-v-400916ea]::-webkit-search-cancel-button{display:none}@media(max-width:767px){.search-input[data-v-400916ea]{padding:6px 4px}}.search-actions[data-v-400916ea]{display:flex;gap:4px}@media(any-pointer:coarse){.search-actions[data-v-400916ea]{gap:8px}}@media(min-width:769px){.search-actions.before[data-v-400916ea]{display:none}}.search-actions button[data-v-400916ea]{padding:8px}.search-actions button[data-v-400916ea]:not([disabled]):hover,.toggle-layout-button.detailed-list[data-v-400916ea]{color:var(--vp-c-brand-1)}.search-actions button.clear-button[data-v-400916ea]:disabled{opacity:.37}.search-keyboard-shortcuts[data-v-400916ea]{font-size:.8rem;opacity:75%;display:flex;flex-wrap:wrap;gap:16px;line-height:14px}.search-keyboard-shortcuts span[data-v-400916ea]{display:flex;align-items:center;gap:4px}@media(max-width:767px){.search-keyboard-shortcuts[data-v-400916ea]{display:none}}.search-keyboard-shortcuts kbd[data-v-400916ea]{background:#8080801a;border-radius:4px;padding:3px 6px;min-width:24px;display:inline-block;text-align:center;vertical-align:middle;border:1px solid rgba(128,128,128,.15);box-shadow:0 2px 2px #0000001a}.results[data-v-400916ea]{display:flex;flex-direction:column;gap:6px;overflow-x:hidden;overflow-y:auto;overscroll-behavior:contain}.result[data-v-400916ea]{display:flex;align-items:center;gap:8px;border-radius:4px;transition:none;line-height:1rem;border:solid 2px var(--vp-local-search-result-border);outline:none}.result>div[data-v-400916ea]{margin:12px;width:100%;overflow:hidden}@media(max-width:767px){.result>div[data-v-400916ea]{margin:8px}}.titles[data-v-400916ea]{display:flex;flex-wrap:wrap;gap:4px;position:relative;z-index:1001;padding:2px 0}.title[data-v-400916ea]{display:flex;align-items:center;gap:4px}.title.main[data-v-400916ea]{font-weight:500}.title-icon[data-v-400916ea]{opacity:.5;font-weight:500;color:var(--vp-c-brand-1)}.title svg[data-v-400916ea]{opacity:.5}.result.selected[data-v-400916ea]{--vp-local-search-result-bg: var(--vp-local-search-result-selected-bg);border-color:var(--vp-local-search-result-selected-border)}.excerpt-wrapper[data-v-400916ea]{position:relative}.excerpt[data-v-400916ea]{opacity:50%;pointer-events:none;max-height:140px;overflow:hidden;position:relative;margin-top:4px}.result.selected .excerpt[data-v-400916ea]{opacity:1}.excerpt[data-v-400916ea] *{font-size:.8rem!important;line-height:130%!important}.titles[data-v-400916ea] mark,.excerpt[data-v-400916ea] mark{background-color:var(--vp-local-search-highlight-bg);color:var(--vp-local-search-highlight-text);border-radius:2px;padding:0 2px}.excerpt[data-v-400916ea] .vp-code-group .tabs{display:none}.excerpt[data-v-400916ea] .vp-code-group div[class*=language-]{border-radius:8px!important}.excerpt-gradient-bottom[data-v-400916ea]{position:absolute;bottom:-1px;left:0;width:100%;height:8px;background:linear-gradient(transparent,var(--vp-local-search-result-bg));z-index:1000}.excerpt-gradient-top[data-v-400916ea]{position:absolute;top:-1px;left:0;width:100%;height:8px;background:linear-gradient(var(--vp-local-search-result-bg),transparent);z-index:1000}.result.selected .titles[data-v-400916ea],.result.selected .title-icon[data-v-400916ea]{color:var(--vp-c-brand-1)!important}.no-results[data-v-400916ea]{font-size:.9rem;text-align:center;padding:12px}svg[data-v-400916ea]{flex:none} +@charset "UTF-8";@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/assets/inter-roman-cyrillic-ext.BBPuwvHQ.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/assets/inter-roman-cyrillic.C5lxZ8CY.woff2) format("woff2");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/assets/inter-roman-greek-ext.CqjqNYQ-.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/assets/inter-roman-greek.BBVDIX6e.woff2) format("woff2");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/assets/inter-roman-vietnamese.BjW4sHH5.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/assets/inter-roman-latin-ext.4ZJIpNVo.woff2) format("woff2");unicode-range:U+0100-02AF,U+0304,U+0308,U+0329,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/assets/inter-roman-latin.Di8DUHzh.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/assets/inter-italic-cyrillic-ext.r48I6akx.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/assets/inter-italic-cyrillic.By2_1cv3.woff2) format("woff2");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/assets/inter-italic-greek-ext.1u6EdAuj.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/assets/inter-italic-greek.DJ8dCoTZ.woff2) format("woff2");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/assets/inter-italic-vietnamese.BSbpV94h.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/assets/inter-italic-latin-ext.CN1xVJS-.woff2) format("woff2");unicode-range:U+0100-02AF,U+0304,U+0308,U+0329,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/assets/inter-italic-latin.C2AdPX0b.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Punctuation SC;font-weight:400;src:local("PingFang SC Regular"),local("Noto Sans CJK SC"),local("Microsoft YaHei");unicode-range:U+201C,U+201D,U+2018,U+2019,U+2E3A,U+2014,U+2013,U+2026,U+00B7,U+007E,U+002F}@font-face{font-family:Punctuation SC;font-weight:500;src:local("PingFang SC Medium"),local("Noto Sans CJK SC"),local("Microsoft YaHei");unicode-range:U+201C,U+201D,U+2018,U+2019,U+2E3A,U+2014,U+2013,U+2026,U+00B7,U+007E,U+002F}@font-face{font-family:Punctuation SC;font-weight:600;src:local("PingFang SC Semibold"),local("Noto Sans CJK SC Bold"),local("Microsoft YaHei Bold");unicode-range:U+201C,U+201D,U+2018,U+2019,U+2E3A,U+2014,U+2013,U+2026,U+00B7,U+007E,U+002F}@font-face{font-family:Punctuation SC;font-weight:700;src:local("PingFang SC Semibold"),local("Noto Sans CJK SC Bold"),local("Microsoft YaHei Bold");unicode-range:U+201C,U+201D,U+2018,U+2019,U+2E3A,U+2014,U+2013,U+2026,U+00B7,U+007E,U+002F}:root{--vp-c-white: #ffffff;--vp-c-black: #000000;--vp-c-neutral: var(--vp-c-black);--vp-c-neutral-inverse: var(--vp-c-white)}.dark{--vp-c-neutral: var(--vp-c-white);--vp-c-neutral-inverse: var(--vp-c-black)}:root{--vp-c-gray-1: #dddde3;--vp-c-gray-2: #e4e4e9;--vp-c-gray-3: #ebebef;--vp-c-gray-soft: rgba(142, 150, 170, .14);--vp-c-indigo-1: #3451b2;--vp-c-indigo-2: #3a5ccc;--vp-c-indigo-3: #5672cd;--vp-c-indigo-soft: rgba(100, 108, 255, .14);--vp-c-purple-1: #6f42c1;--vp-c-purple-2: #7e4cc9;--vp-c-purple-3: #8e5cd9;--vp-c-purple-soft: rgba(159, 122, 234, .14);--vp-c-green-1: #18794e;--vp-c-green-2: #299764;--vp-c-green-3: #30a46c;--vp-c-green-soft: rgba(16, 185, 129, .14);--vp-c-yellow-1: #915930;--vp-c-yellow-2: #946300;--vp-c-yellow-3: #9f6a00;--vp-c-yellow-soft: rgba(234, 179, 8, .14);--vp-c-red-1: #b8272c;--vp-c-red-2: #d5393e;--vp-c-red-3: #e0575b;--vp-c-red-soft: rgba(244, 63, 94, .14);--vp-c-sponsor: #db2777}.dark{--vp-c-gray-1: #515c67;--vp-c-gray-2: #414853;--vp-c-gray-3: #32363f;--vp-c-gray-soft: rgba(101, 117, 133, .16);--vp-c-indigo-1: #a8b1ff;--vp-c-indigo-2: #5c73e7;--vp-c-indigo-3: #3e63dd;--vp-c-indigo-soft: rgba(100, 108, 255, .16);--vp-c-purple-1: #c8abfa;--vp-c-purple-2: #a879e6;--vp-c-purple-3: #8e5cd9;--vp-c-purple-soft: rgba(159, 122, 234, .16);--vp-c-green-1: #3dd68c;--vp-c-green-2: #30a46c;--vp-c-green-3: #298459;--vp-c-green-soft: rgba(16, 185, 129, .16);--vp-c-yellow-1: #f9b44e;--vp-c-yellow-2: #da8b17;--vp-c-yellow-3: #a46a0a;--vp-c-yellow-soft: rgba(234, 179, 8, .16);--vp-c-red-1: #f66f81;--vp-c-red-2: #f14158;--vp-c-red-3: #b62a3c;--vp-c-red-soft: rgba(244, 63, 94, .16)}:root{--vp-c-bg: #ffffff;--vp-c-bg-alt: #f6f6f7;--vp-c-bg-elv: #ffffff;--vp-c-bg-soft: #f6f6f7}.dark{--vp-c-bg: #1b1b1f;--vp-c-bg-alt: #161618;--vp-c-bg-elv: #202127;--vp-c-bg-soft: #202127}:root{--vp-c-border: #c2c2c4;--vp-c-divider: #e2e2e3;--vp-c-gutter: #e2e2e3}.dark{--vp-c-border: #3c3f44;--vp-c-divider: #2e2e32;--vp-c-gutter: #000000}:root{--vp-c-text-1: #3c3c43;--vp-c-text-2: #67676c;--vp-c-text-3: #929295}.dark{--vp-c-text-1: #dfdfd6;--vp-c-text-2: #98989f;--vp-c-text-3: #6a6a71}:root{--vp-c-default-1: var(--vp-c-gray-1);--vp-c-default-2: var(--vp-c-gray-2);--vp-c-default-3: var(--vp-c-gray-3);--vp-c-default-soft: var(--vp-c-gray-soft);--vp-c-brand-1: var(--vp-c-indigo-1);--vp-c-brand-2: var(--vp-c-indigo-2);--vp-c-brand-3: var(--vp-c-indigo-3);--vp-c-brand-soft: var(--vp-c-indigo-soft);--vp-c-brand: var(--vp-c-brand-1);--vp-c-tip-1: var(--vp-c-brand-1);--vp-c-tip-2: var(--vp-c-brand-2);--vp-c-tip-3: var(--vp-c-brand-3);--vp-c-tip-soft: var(--vp-c-brand-soft);--vp-c-note-1: var(--vp-c-brand-1);--vp-c-note-2: var(--vp-c-brand-2);--vp-c-note-3: var(--vp-c-brand-3);--vp-c-note-soft: var(--vp-c-brand-soft);--vp-c-success-1: var(--vp-c-green-1);--vp-c-success-2: var(--vp-c-green-2);--vp-c-success-3: var(--vp-c-green-3);--vp-c-success-soft: var(--vp-c-green-soft);--vp-c-important-1: var(--vp-c-purple-1);--vp-c-important-2: var(--vp-c-purple-2);--vp-c-important-3: var(--vp-c-purple-3);--vp-c-important-soft: var(--vp-c-purple-soft);--vp-c-warning-1: var(--vp-c-yellow-1);--vp-c-warning-2: var(--vp-c-yellow-2);--vp-c-warning-3: var(--vp-c-yellow-3);--vp-c-warning-soft: var(--vp-c-yellow-soft);--vp-c-danger-1: var(--vp-c-red-1);--vp-c-danger-2: var(--vp-c-red-2);--vp-c-danger-3: var(--vp-c-red-3);--vp-c-danger-soft: var(--vp-c-red-soft);--vp-c-caution-1: var(--vp-c-red-1);--vp-c-caution-2: var(--vp-c-red-2);--vp-c-caution-3: var(--vp-c-red-3);--vp-c-caution-soft: var(--vp-c-red-soft)}:root{--vp-font-family-base: "Inter", ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--vp-font-family-mono: ui-monospace, "Menlo", "Monaco", "Consolas", "Liberation Mono", "Courier New", monospace;font-optical-sizing:auto}:root:where(:lang(zh)){--vp-font-family-base: "Punctuation SC", "Inter", ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"}:root{--vp-shadow-1: 0 1px 2px rgba(0, 0, 0, .04), 0 1px 2px rgba(0, 0, 0, .06);--vp-shadow-2: 0 3px 12px rgba(0, 0, 0, .07), 0 1px 4px rgba(0, 0, 0, .07);--vp-shadow-3: 0 12px 32px rgba(0, 0, 0, .1), 0 2px 6px rgba(0, 0, 0, .08);--vp-shadow-4: 0 14px 44px rgba(0, 0, 0, .12), 0 3px 9px rgba(0, 0, 0, .12);--vp-shadow-5: 0 18px 56px rgba(0, 0, 0, .16), 0 4px 12px rgba(0, 0, 0, .16)}:root{--vp-z-index-footer: 10;--vp-z-index-local-nav: 20;--vp-z-index-nav: 30;--vp-z-index-layout-top: 40;--vp-z-index-backdrop: 50;--vp-z-index-sidebar: 60}@media(min-width:960px){:root{--vp-z-index-sidebar: 25}}:root{--vp-layout-max-width: 1440px}:root{--vp-header-anchor-symbol: "#"}:root{--vp-code-line-height: 1.7;--vp-code-font-size: .875em;--vp-code-color: var(--vp-c-brand-1);--vp-code-link-color: var(--vp-c-brand-1);--vp-code-link-hover-color: var(--vp-c-brand-2);--vp-code-bg: var(--vp-c-default-soft);--vp-code-block-color: var(--vp-c-text-2);--vp-code-block-bg: var(--vp-c-bg-alt);--vp-code-block-divider-color: var(--vp-c-gutter);--vp-code-lang-color: var(--vp-c-text-2);--vp-code-line-highlight-color: var(--vp-c-default-soft);--vp-code-line-number-color: var(--vp-c-text-2);--vp-code-line-diff-add-color: var(--vp-c-success-soft);--vp-code-line-diff-add-symbol-color: var(--vp-c-success-1);--vp-code-line-diff-remove-color: var(--vp-c-danger-soft);--vp-code-line-diff-remove-symbol-color: var(--vp-c-danger-1);--vp-code-line-warning-color: var(--vp-c-warning-soft);--vp-code-line-error-color: var(--vp-c-danger-soft);--vp-code-copy-code-border-color: var(--vp-c-divider);--vp-code-copy-code-bg: var(--vp-c-bg-soft);--vp-code-copy-code-hover-border-color: var(--vp-c-divider);--vp-code-copy-code-hover-bg: var(--vp-c-bg);--vp-code-copy-code-active-text: var(--vp-c-text-2);--vp-code-copy-copied-text-content: "Copied";--vp-code-tab-divider: var(--vp-code-block-divider-color);--vp-code-tab-text-color: var(--vp-c-text-2);--vp-code-tab-bg: var(--vp-code-block-bg);--vp-code-tab-hover-text-color: var(--vp-c-text-1);--vp-code-tab-active-text-color: var(--vp-c-text-1);--vp-code-tab-active-bar-color: var(--vp-c-brand-1)}:lang(es),:lang(pt){--vp-code-copy-copied-text-content: "Copiado"}:lang(fa){--vp-code-copy-copied-text-content: "کپی شد"}:lang(ko){--vp-code-copy-copied-text-content: "복사됨"}:lang(ru){--vp-code-copy-copied-text-content: "Скопировано"}:lang(zh){--vp-code-copy-copied-text-content: "已复制"}:root{--vp-button-brand-border: transparent;--vp-button-brand-text: var(--vp-c-white);--vp-button-brand-bg: var(--vp-c-brand-3);--vp-button-brand-hover-border: transparent;--vp-button-brand-hover-text: var(--vp-c-white);--vp-button-brand-hover-bg: var(--vp-c-brand-2);--vp-button-brand-active-border: transparent;--vp-button-brand-active-text: var(--vp-c-white);--vp-button-brand-active-bg: var(--vp-c-brand-1);--vp-button-alt-border: transparent;--vp-button-alt-text: var(--vp-c-text-1);--vp-button-alt-bg: var(--vp-c-default-3);--vp-button-alt-hover-border: transparent;--vp-button-alt-hover-text: var(--vp-c-text-1);--vp-button-alt-hover-bg: var(--vp-c-default-2);--vp-button-alt-active-border: transparent;--vp-button-alt-active-text: var(--vp-c-text-1);--vp-button-alt-active-bg: var(--vp-c-default-1);--vp-button-sponsor-border: var(--vp-c-text-2);--vp-button-sponsor-text: var(--vp-c-text-2);--vp-button-sponsor-bg: transparent;--vp-button-sponsor-hover-border: var(--vp-c-sponsor);--vp-button-sponsor-hover-text: var(--vp-c-sponsor);--vp-button-sponsor-hover-bg: transparent;--vp-button-sponsor-active-border: var(--vp-c-sponsor);--vp-button-sponsor-active-text: var(--vp-c-sponsor);--vp-button-sponsor-active-bg: transparent}:root{--vp-custom-block-font-size: 14px;--vp-custom-block-code-font-size: 13px;--vp-custom-block-info-border: transparent;--vp-custom-block-info-text: var(--vp-c-text-1);--vp-custom-block-info-bg: var(--vp-c-default-soft);--vp-custom-block-info-code-bg: var(--vp-c-default-soft);--vp-custom-block-note-border: transparent;--vp-custom-block-note-text: var(--vp-c-text-1);--vp-custom-block-note-bg: var(--vp-c-default-soft);--vp-custom-block-note-code-bg: var(--vp-c-default-soft);--vp-custom-block-tip-border: transparent;--vp-custom-block-tip-text: var(--vp-c-text-1);--vp-custom-block-tip-bg: var(--vp-c-tip-soft);--vp-custom-block-tip-code-bg: var(--vp-c-tip-soft);--vp-custom-block-important-border: transparent;--vp-custom-block-important-text: var(--vp-c-text-1);--vp-custom-block-important-bg: var(--vp-c-important-soft);--vp-custom-block-important-code-bg: var(--vp-c-important-soft);--vp-custom-block-warning-border: transparent;--vp-custom-block-warning-text: var(--vp-c-text-1);--vp-custom-block-warning-bg: var(--vp-c-warning-soft);--vp-custom-block-warning-code-bg: var(--vp-c-warning-soft);--vp-custom-block-danger-border: transparent;--vp-custom-block-danger-text: var(--vp-c-text-1);--vp-custom-block-danger-bg: var(--vp-c-danger-soft);--vp-custom-block-danger-code-bg: var(--vp-c-danger-soft);--vp-custom-block-caution-border: transparent;--vp-custom-block-caution-text: var(--vp-c-text-1);--vp-custom-block-caution-bg: var(--vp-c-caution-soft);--vp-custom-block-caution-code-bg: var(--vp-c-caution-soft);--vp-custom-block-details-border: var(--vp-custom-block-info-border);--vp-custom-block-details-text: var(--vp-custom-block-info-text);--vp-custom-block-details-bg: var(--vp-custom-block-info-bg);--vp-custom-block-details-code-bg: var(--vp-custom-block-info-code-bg)}:root{--vp-input-border-color: var(--vp-c-border);--vp-input-bg-color: var(--vp-c-bg-alt);--vp-input-switch-bg-color: var(--vp-c-default-soft)}:root{--vp-nav-height: 64px;--vp-nav-bg-color: var(--vp-c-bg);--vp-nav-screen-bg-color: var(--vp-c-bg);--vp-nav-logo-height: 24px}.hide-nav{--vp-nav-height: 0px}.hide-nav .VPSidebar{--vp-nav-height: 22px}:root{--vp-local-nav-bg-color: var(--vp-c-bg)}:root{--vp-sidebar-width: 272px;--vp-sidebar-bg-color: var(--vp-c-bg-alt)}:root{--vp-backdrop-bg-color: rgba(0, 0, 0, .6)}:root{--vp-home-hero-name-color: var(--vp-c-brand-1);--vp-home-hero-name-background: transparent;--vp-home-hero-image-background-image: none;--vp-home-hero-image-filter: none}:root{--vp-badge-info-border: transparent;--vp-badge-info-text: var(--vp-c-text-2);--vp-badge-info-bg: var(--vp-c-default-soft);--vp-badge-tip-border: transparent;--vp-badge-tip-text: var(--vp-c-tip-1);--vp-badge-tip-bg: var(--vp-c-tip-soft);--vp-badge-warning-border: transparent;--vp-badge-warning-text: var(--vp-c-warning-1);--vp-badge-warning-bg: var(--vp-c-warning-soft);--vp-badge-danger-border: transparent;--vp-badge-danger-text: var(--vp-c-danger-1);--vp-badge-danger-bg: var(--vp-c-danger-soft)}:root{--vp-carbon-ads-text-color: var(--vp-c-text-1);--vp-carbon-ads-poweredby-color: var(--vp-c-text-2);--vp-carbon-ads-bg-color: var(--vp-c-bg-soft);--vp-carbon-ads-hover-text-color: var(--vp-c-brand-1);--vp-carbon-ads-hover-poweredby-color: var(--vp-c-text-1)}:root{--vp-local-search-bg: var(--vp-c-bg);--vp-local-search-result-bg: var(--vp-c-bg);--vp-local-search-result-border: var(--vp-c-divider);--vp-local-search-result-selected-bg: var(--vp-c-bg);--vp-local-search-result-selected-border: var(--vp-c-brand-1);--vp-local-search-highlight-bg: var(--vp-c-brand-1);--vp-local-search-highlight-text: var(--vp-c-neutral-inverse)}@media(prefers-reduced-motion:reduce){*,:before,:after{animation-delay:-1ms!important;animation-duration:1ms!important;animation-iteration-count:1!important;background-attachment:initial!important;scroll-behavior:auto!important;transition-duration:0s!important;transition-delay:0s!important}}*,:before,:after{box-sizing:border-box}html{line-height:1.4;font-size:16px;-webkit-text-size-adjust:100%}html.dark{color-scheme:dark}body{margin:0;width:100%;min-width:320px;min-height:100vh;line-height:24px;font-family:var(--vp-font-family-base);font-size:16px;font-weight:400;color:var(--vp-c-text-1);background-color:var(--vp-c-bg);font-synthesis:style;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}main{display:block}h1,h2,h3,h4,h5,h6{margin:0;line-height:24px;font-size:16px;font-weight:400}p{margin:0}strong,b{font-weight:600}a,area,button,[role=button],input,label,select,summary,textarea{touch-action:manipulation}a{color:inherit;text-decoration:inherit}ol,ul{list-style:none;margin:0;padding:0}blockquote{margin:0}pre,code,kbd,samp{font-family:var(--vp-font-family-mono)}img,svg,video,canvas,audio,iframe,embed,object{display:block}figure{margin:0}img,video{max-width:100%;height:auto}button,input,optgroup,select,textarea{border:0;padding:0;line-height:inherit;color:inherit}button{padding:0;font-family:inherit;background-color:transparent;background-image:none}button:enabled,[role=button]:enabled{cursor:pointer}button:focus,button:focus-visible{outline:1px dotted;outline:4px auto -webkit-focus-ring-color}button:focus:not(:focus-visible){outline:none!important}input:focus,textarea:focus,select:focus{outline:none}table{border-collapse:collapse}input{background-color:transparent}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:var(--vp-c-text-3)}input::-ms-input-placeholder,textarea::-ms-input-placeholder{color:var(--vp-c-text-3)}input::placeholder,textarea::placeholder{color:var(--vp-c-text-3)}input::-webkit-outer-spin-button,input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}input[type=number]{-moz-appearance:textfield}textarea{resize:vertical}select{-webkit-appearance:none}fieldset{margin:0;padding:0}h1,h2,h3,h4,h5,h6,li,p{overflow-wrap:break-word}vite-error-overlay{z-index:9999}mjx-container{overflow-x:auto}mjx-container>svg{display:inline-block;margin:auto}[class^=vpi-],[class*=" vpi-"],.vp-icon{width:1em;height:1em}[class^=vpi-].bg,[class*=" vpi-"].bg,.vp-icon.bg{background-size:100% 100%;background-color:transparent}[class^=vpi-]:not(.bg),[class*=" vpi-"]:not(.bg),.vp-icon:not(.bg){-webkit-mask:var(--icon) no-repeat;mask:var(--icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit}.vpi-align-left{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='none' stroke='black' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M15 12H3m14 6H3M21 6H3'/%3E%3C/svg%3E")}.vpi-arrow-right,.vpi-arrow-down,.vpi-arrow-left,.vpi-arrow-up{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='none' stroke='black' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M5 12h14m-7-7l7 7l-7 7'/%3E%3C/svg%3E")}.vpi-chevron-right,.vpi-chevron-down,.vpi-chevron-left,.vpi-chevron-up{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='none' stroke='black' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m9 18l6-6l-6-6'/%3E%3C/svg%3E")}.vpi-chevron-down,.vpi-arrow-down{transform:rotate(90deg)}.vpi-chevron-left,.vpi-arrow-left{transform:rotate(180deg)}.vpi-chevron-up,.vpi-arrow-up{transform:rotate(-90deg)}.vpi-square-pen{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='none' stroke='black' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7'/%3E%3Cpath d='M18.375 2.625a1 1 0 0 1 3 3l-9.013 9.014a2 2 0 0 1-.853.505l-2.873.84a.5.5 0 0 1-.62-.62l.84-2.873a2 2 0 0 1 .506-.852z'/%3E%3C/g%3E%3C/svg%3E")}.vpi-plus{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='none' stroke='black' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M5 12h14m-7-7v14'/%3E%3C/svg%3E")}.vpi-sun{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='none' stroke='black' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Ccircle cx='12' cy='12' r='4'/%3E%3Cpath d='M12 2v2m0 16v2M4.93 4.93l1.41 1.41m11.32 11.32l1.41 1.41M2 12h2m16 0h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41'/%3E%3C/g%3E%3C/svg%3E")}.vpi-moon{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='none' stroke='black' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M12 3a6 6 0 0 0 9 9a9 9 0 1 1-9-9'/%3E%3C/svg%3E")}.vpi-more-horizontal{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='none' stroke='black' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Ccircle cx='12' cy='12' r='1'/%3E%3Ccircle cx='19' cy='12' r='1'/%3E%3Ccircle cx='5' cy='12' r='1'/%3E%3C/g%3E%3C/svg%3E")}.vpi-languages{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='none' stroke='black' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m5 8l6 6m-7 0l6-6l2-3M2 5h12M7 2h1m14 20l-5-10l-5 10m2-4h6'/%3E%3C/svg%3E")}.vpi-heart{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='none' stroke='black' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2c-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z'/%3E%3C/svg%3E")}.vpi-search{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='none' stroke='black' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.6'%3E%3Cpath d='m21 21l-4.34-4.34'/%3E%3Ccircle cx='11' cy='11' r='8' stroke-width='1.4'/%3E%3C/g%3E%3C/svg%3E")}.vpi-layout-list{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='none' stroke='black' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Crect width='7' height='7' x='3' y='3' rx='1'/%3E%3Crect width='7' height='7' x='3' y='14' rx='1'/%3E%3Cpath d='M14 4h7m-7 5h7m-7 6h7m-7 5h7'/%3E%3C/g%3E%3C/svg%3E")}.vpi-delete{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='none' stroke='black' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M10 5a2 2 0 0 0-1.344.519l-6.328 5.74a1 1 0 0 0 0 1.481l6.328 5.741A2 2 0 0 0 10 19h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2zm2 4l6 6m0-6l-6 6'/%3E%3C/svg%3E")}.vpi-corner-down-left{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='none' stroke='black' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='M20 4v7a4 4 0 0 1-4 4H4'/%3E%3Cpath d='m9 10l-5 5l5 5'/%3E%3C/g%3E%3C/svg%3E")}:root{--vp-icon-copy: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='none' stroke='rgba(128,128,128,1)' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Crect width='8' height='4' x='8' y='2' rx='1' ry='1'/%3E%3Cpath d='M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2'/%3E%3C/g%3E%3C/svg%3E");--vp-icon-copied: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='none' stroke='rgba(128,128,128,1)' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Crect width='8' height='4' x='8' y='2' rx='1' ry='1'/%3E%3Cpath d='M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2'/%3E%3Cpath d='m9 14l2 2l4-4'/%3E%3C/g%3E%3C/svg%3E")}.visually-hidden{position:absolute;width:1px;height:1px;white-space:nowrap;clip:rect(0 0 0 0);clip-path:inset(50%);overflow:hidden}.custom-block{border:1px solid transparent;border-radius:8px;padding:16px 16px 8px;line-height:24px;font-size:var(--vp-custom-block-font-size);color:var(--vp-c-text-2)}.custom-block.info{border-color:var(--vp-custom-block-info-border);color:var(--vp-custom-block-info-text);background-color:var(--vp-custom-block-info-bg)}.custom-block.info a,.custom-block.info code{color:var(--vp-c-brand-1)}.custom-block.info a:hover,.custom-block.info a:hover>code{color:var(--vp-c-brand-2)}.custom-block.info code{background-color:var(--vp-custom-block-info-code-bg)}.custom-block.note{border-color:var(--vp-custom-block-note-border);color:var(--vp-custom-block-note-text);background-color:var(--vp-custom-block-note-bg)}.custom-block.note a,.custom-block.note code{color:var(--vp-c-brand-1)}.custom-block.note a:hover,.custom-block.note a:hover>code{color:var(--vp-c-brand-2)}.custom-block.note code{background-color:var(--vp-custom-block-note-code-bg)}.custom-block.tip{border-color:var(--vp-custom-block-tip-border);color:var(--vp-custom-block-tip-text);background-color:var(--vp-custom-block-tip-bg)}.custom-block.tip a,.custom-block.tip code{color:var(--vp-c-tip-1)}.custom-block.tip a:hover,.custom-block.tip a:hover>code{color:var(--vp-c-tip-2)}.custom-block.tip code{background-color:var(--vp-custom-block-tip-code-bg)}.custom-block.important{border-color:var(--vp-custom-block-important-border);color:var(--vp-custom-block-important-text);background-color:var(--vp-custom-block-important-bg)}.custom-block.important a,.custom-block.important code{color:var(--vp-c-important-1)}.custom-block.important a:hover,.custom-block.important a:hover>code{color:var(--vp-c-important-2)}.custom-block.important code{background-color:var(--vp-custom-block-important-code-bg)}.custom-block.warning{border-color:var(--vp-custom-block-warning-border);color:var(--vp-custom-block-warning-text);background-color:var(--vp-custom-block-warning-bg)}.custom-block.warning a,.custom-block.warning code{color:var(--vp-c-warning-1)}.custom-block.warning a:hover,.custom-block.warning a:hover>code{color:var(--vp-c-warning-2)}.custom-block.warning code{background-color:var(--vp-custom-block-warning-code-bg)}.custom-block.danger{border-color:var(--vp-custom-block-danger-border);color:var(--vp-custom-block-danger-text);background-color:var(--vp-custom-block-danger-bg)}.custom-block.danger a,.custom-block.danger code{color:var(--vp-c-danger-1)}.custom-block.danger a:hover,.custom-block.danger a:hover>code{color:var(--vp-c-danger-2)}.custom-block.danger code{background-color:var(--vp-custom-block-danger-code-bg)}.custom-block.caution{border-color:var(--vp-custom-block-caution-border);color:var(--vp-custom-block-caution-text);background-color:var(--vp-custom-block-caution-bg)}.custom-block.caution a,.custom-block.caution code{color:var(--vp-c-caution-1)}.custom-block.caution a:hover,.custom-block.caution a:hover>code{color:var(--vp-c-caution-2)}.custom-block.caution code{background-color:var(--vp-custom-block-caution-code-bg)}.custom-block.details{border-color:var(--vp-custom-block-details-border);color:var(--vp-custom-block-details-text);background-color:var(--vp-custom-block-details-bg)}.custom-block.details a{color:var(--vp-c-brand-1)}.custom-block.details a:hover,.custom-block.details a:hover>code{color:var(--vp-c-brand-2)}.custom-block.details code{background-color:var(--vp-custom-block-details-code-bg)}.custom-block-title{font-weight:600}.custom-block p+p{margin:8px 0}.custom-block.details summary{margin:0 0 8px;font-weight:700;cursor:pointer;-webkit-user-select:none;user-select:none}.custom-block.details summary+p{margin:8px 0}.custom-block a{color:inherit;font-weight:600;text-decoration:underline;text-underline-offset:2px;transition:opacity .25s}.custom-block a:hover{opacity:.75}.custom-block code{font-size:var(--vp-custom-block-code-font-size)}.custom-block.custom-block th,.custom-block.custom-block blockquote>p{font-size:var(--vp-custom-block-font-size);color:inherit}.dark .shiki span{color:var(--shiki-dark, inherit)}html:not(.dark) .shiki span{color:var(--shiki-light, inherit)}.vp-code-group{margin-top:16px}.vp-code-group .tabs{position:relative;display:flex;margin-right:-24px;margin-left:-24px;padding:0 12px;background-color:var(--vp-code-tab-bg);overflow-x:auto;overflow-y:hidden;box-shadow:inset 0 -1px var(--vp-code-tab-divider)}@media(min-width:640px){.vp-code-group .tabs{margin-right:0;margin-left:0;border-radius:8px 8px 0 0}}.vp-code-group .tabs input{position:fixed;opacity:0;pointer-events:none}.vp-code-group .tabs label{position:relative;display:inline-block;border-bottom:1px solid transparent;padding:0 12px;line-height:48px;font-size:14px;font-weight:500;color:var(--vp-code-tab-text-color);white-space:nowrap;cursor:pointer;transition:color .25s}.vp-code-group .tabs label:after{position:absolute;right:8px;bottom:-1px;left:8px;z-index:1;height:2px;border-radius:2px;content:"";background-color:transparent;transition:background-color .25s}.vp-code-group label:hover{color:var(--vp-code-tab-hover-text-color)}.vp-code-group input:checked+label{color:var(--vp-code-tab-active-text-color)}.vp-code-group input:checked+label:after{background-color:var(--vp-code-tab-active-bar-color)}.vp-code-group div[class*=language-],.vp-block{display:none;margin-top:0!important;border-top-left-radius:0!important;border-top-right-radius:0!important}.vp-code-group div[class*=language-].active,.vp-block.active{display:block}.vp-block{padding:20px 24px}.vp-doc h1,.vp-doc h2,.vp-doc h3,.vp-doc h4,.vp-doc h5,.vp-doc h6{position:relative;font-weight:600;outline:none}.vp-doc h1{letter-spacing:-.02em;line-height:40px;font-size:28px}.vp-doc h2{margin:48px 0 16px;border-top:1px solid var(--vp-c-divider);padding-top:24px;letter-spacing:-.02em;line-height:32px;font-size:24px}.vp-doc h3{margin:32px 0 0;letter-spacing:-.01em;line-height:28px;font-size:20px}.vp-doc h4{margin:24px 0 0;letter-spacing:-.01em;line-height:24px;font-size:18px}.vp-doc .header-anchor{position:absolute;top:0;left:0;margin-left:-.87em;font-weight:500;-webkit-user-select:none;user-select:none;opacity:0;text-decoration:none;transition:color .25s,opacity .25s}.vp-doc .header-anchor:before{content:var(--vp-header-anchor-symbol)}.vp-doc h1:hover .header-anchor,.vp-doc h1 .header-anchor:focus,.vp-doc h2:hover .header-anchor,.vp-doc h2 .header-anchor:focus,.vp-doc h3:hover .header-anchor,.vp-doc h3 .header-anchor:focus,.vp-doc h4:hover .header-anchor,.vp-doc h4 .header-anchor:focus,.vp-doc h5:hover .header-anchor,.vp-doc h5 .header-anchor:focus,.vp-doc h6:hover .header-anchor,.vp-doc h6 .header-anchor:focus{opacity:1}@media(min-width:768px){.vp-doc h1{letter-spacing:-.02em;line-height:40px;font-size:32px}}.vp-doc h2 .header-anchor{top:24px}.vp-doc p,.vp-doc summary{margin:16px 0}.vp-doc p{line-height:28px}.vp-doc blockquote{margin:16px 0;border-left:2px solid var(--vp-c-divider);padding-left:16px;transition:border-color .5s;color:var(--vp-c-text-2)}.vp-doc blockquote>p{margin:0;font-size:16px;transition:color .5s}.vp-doc a{font-weight:500;color:var(--vp-c-brand-1);text-decoration:underline;text-underline-offset:2px;transition:color .25s,opacity .25s}.vp-doc a:hover{color:var(--vp-c-brand-2)}.vp-doc strong{font-weight:600}.vp-doc ul,.vp-doc ol{padding-left:1.25rem;margin:16px 0}.vp-doc ul{list-style:disc}.vp-doc ol{list-style:decimal}.vp-doc li+li{margin-top:8px}.vp-doc li>ol,.vp-doc li>ul{margin:8px 0 0}.vp-doc table{display:block;border-collapse:collapse;margin:20px 0;overflow-x:auto}.vp-doc tr{background-color:var(--vp-c-bg);border-top:1px solid var(--vp-c-divider);transition:background-color .5s}.vp-doc tr:nth-child(2n){background-color:var(--vp-c-bg-soft)}.vp-doc th,.vp-doc td{border:1px solid var(--vp-c-divider);padding:8px 16px}.vp-doc th{text-align:left;font-size:14px;font-weight:600;color:var(--vp-c-text-2);background-color:var(--vp-c-bg-soft)}.vp-doc td{font-size:14px}.vp-doc hr{margin:16px 0;border:none;border-top:1px solid var(--vp-c-divider)}.vp-doc .custom-block{margin:16px 0}.vp-doc .custom-block p{margin:8px 0;line-height:24px}.vp-doc .custom-block p:first-child{margin:0}.vp-doc .custom-block div[class*=language-]{margin:8px 0!important;border-radius:8px}.vp-doc .custom-block div[class*=language-] code{font-weight:400;background-color:transparent}.vp-doc .custom-block .vp-code-group .tabs{margin:0;border-radius:8px 8px 0 0}.vp-doc :not(pre,h1,h2,h3,h4,h5,h6)>code{font-size:var(--vp-code-font-size);color:var(--vp-code-color)}.vp-doc :not(pre)>code{border-radius:4px;padding:3px 6px;background-color:var(--vp-code-bg);transition:color .25s,background-color .5s}.vp-doc a>code{color:var(--vp-code-link-color)}.vp-doc a:hover>code{color:var(--vp-code-link-hover-color)}.vp-doc h1>code,.vp-doc h2>code,.vp-doc h3>code,.vp-doc h4>code{font-size:.9em}.vp-doc div[class*=language-],.vp-block{position:relative;margin:16px -24px;background-color:var(--vp-code-block-bg);overflow-x:auto;transition:background-color .5s}@media(min-width:640px){.vp-doc div[class*=language-],.vp-block{border-radius:8px;margin:16px 0}}@media(max-width:639px){.vp-doc li div[class*=language-]{border-radius:8px 0 0 8px}}.vp-doc div[class*=language-]+div[class*=language-],.vp-doc div[class$=-api]+div[class*=language-],.vp-doc div[class*=language-]+div[class$=-api]>div[class*=language-]{margin-top:-8px}.vp-doc [class*=language-] pre,.vp-doc [class*=language-] code{-moz-tab-size:4;-o-tab-size:4;tab-size:4}.vp-doc [class*=language-] pre{position:relative;z-index:1;margin:0;padding:20px 0;background:transparent;overflow-x:auto;text-align:left}.vp-doc [class*=language-] code{display:block;padding:0 24px;width:fit-content;min-width:100%;line-height:var(--vp-code-line-height);font-size:var(--vp-code-font-size);color:var(--vp-code-block-color);transition:color .5s}.vp-doc [class*=language-] code .highlighted{background-color:var(--vp-code-line-highlight-color);transition:background-color .5s;margin:0 -24px;padding:0 24px;width:calc(100% + 48px);display:inline-block}.vp-doc [class*=language-] code .highlighted.error{background-color:var(--vp-code-line-error-color)}.vp-doc [class*=language-] code .highlighted.warning{background-color:var(--vp-code-line-warning-color)}.vp-doc [class*=language-] code .diff{transition:background-color .5s;margin:0 -24px;padding:0 24px;width:calc(100% + 48px);display:inline-block}.vp-doc [class*=language-] code .diff:before{position:absolute;left:10px}.vp-doc [class*=language-] .has-focused-lines .line:not(.has-focus){filter:blur(.095rem);opacity:.4;transition:filter .35s,opacity .35s}.vp-doc [class*=language-] .has-focused-lines .line:not(.has-focus){opacity:.7;transition:filter .35s,opacity .35s}.vp-doc [class*=language-]:hover .has-focused-lines .line:not(.has-focus){filter:blur(0);opacity:1}.vp-doc [class*=language-] code .diff.remove{background-color:var(--vp-code-line-diff-remove-color);opacity:.7}.vp-doc [class*=language-] code .diff.remove:before{content:"-";color:var(--vp-code-line-diff-remove-symbol-color)}.vp-doc [class*=language-] code .diff.add{background-color:var(--vp-code-line-diff-add-color)}.vp-doc [class*=language-] code .diff.add:before{content:"+";color:var(--vp-code-line-diff-add-symbol-color)}.vp-doc div[class*=language-].line-numbers-mode{padding-left:32px}.vp-doc .line-numbers-wrapper{position:absolute;top:0;bottom:0;left:0;z-index:3;border-right:1px solid var(--vp-code-block-divider-color);padding-top:20px;width:32px;text-align:center;font-family:var(--vp-font-family-mono);line-height:var(--vp-code-line-height);font-size:var(--vp-code-font-size);color:var(--vp-code-line-number-color);transition:border-color .5s,color .5s}.vp-doc [class*=language-]>button.copy{direction:ltr;position:absolute;top:12px;right:12px;z-index:3;border:1px solid var(--vp-code-copy-code-border-color);border-radius:4px;width:40px;height:40px;background-color:var(--vp-code-copy-code-bg);opacity:0;cursor:pointer;background-image:var(--vp-icon-copy);background-position:50%;background-size:20px;background-repeat:no-repeat;transition:border-color .25s,background-color .25s,opacity .25s}.vp-doc [class*=language-]:hover>button.copy,.vp-doc [class*=language-]>button.copy:focus{opacity:1}.vp-doc [class*=language-]>button.copy:hover,.vp-doc [class*=language-]>button.copy.copied{border-color:var(--vp-code-copy-code-hover-border-color);background-color:var(--vp-code-copy-code-hover-bg)}.vp-doc [class*=language-]>button.copy.copied,.vp-doc [class*=language-]>button.copy:hover.copied{border-radius:0 4px 4px 0;background-color:var(--vp-code-copy-code-hover-bg);background-image:var(--vp-icon-copied)}.vp-doc [class*=language-]>button.copy.copied:before,.vp-doc [class*=language-]>button.copy:hover.copied:before{position:relative;top:-1px;transform:translate(calc(-100% - 1px));display:flex;justify-content:center;align-items:center;border:1px solid var(--vp-code-copy-code-hover-border-color);border-right:0;border-radius:4px 0 0 4px;padding:0 10px;width:fit-content;height:40px;text-align:center;font-size:12px;font-weight:500;color:var(--vp-code-copy-code-active-text);background-color:var(--vp-code-copy-code-hover-bg);white-space:nowrap;content:var(--vp-code-copy-copied-text-content)}.vp-doc [class*=language-]>span.lang{position:absolute;top:2px;right:8px;z-index:2;font-size:12px;font-weight:500;-webkit-user-select:none;user-select:none;color:var(--vp-code-lang-color);transition:color .4s,opacity .4s}.vp-doc [class*=language-]:hover>button.copy+span.lang,.vp-doc [class*=language-]>button.copy:focus+span.lang{opacity:0}.vp-doc .VPTeamMembers{margin-top:24px}.vp-doc .VPTeamMembers.small.count-1 .container{margin:0!important;max-width:calc((100% - 24px)/2)!important}.vp-doc .VPTeamMembers.small.count-2 .container,.vp-doc .VPTeamMembers.small.count-3 .container{max-width:100%!important}.vp-doc .VPTeamMembers.medium.count-1 .container{margin:0!important;max-width:calc((100% - 24px)/2)!important}:is(.vp-external-link-icon,.vp-doc a[href*="://"],.vp-doc a[target=_blank]):not(:is(.no-icon,svg a,:has(img,svg))):after{display:inline-block;margin-top:-1px;margin-left:4px;width:11px;height:11px;background:currentColor;color:var(--vp-c-text-3);flex-shrink:0;--icon: url("data:image/svg+xml, %3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' %3E%3Cpath d='M0 0h24v24H0V0z' fill='none' /%3E%3Cpath d='M9 5v2h6.59L4 18.59 5.41 20 17 8.41V15h2V5H9z' /%3E%3C/svg%3E");-webkit-mask-image:var(--icon);mask-image:var(--icon)}.vp-external-link-icon:after{content:""}.external-link-icon-enabled :is(.vp-doc a[href*="://"],.vp-doc a[target=_blank]):not(:is(.no-icon,svg a,:has(img,svg))):after{content:"";color:currentColor}.vp-sponsor{border-radius:16px;overflow:hidden}.vp-sponsor.aside{border-radius:12px}.vp-sponsor-section+.vp-sponsor-section{margin-top:4px}.vp-sponsor-tier{margin:0 0 4px!important;text-align:center;letter-spacing:1px!important;line-height:24px;width:100%;font-weight:600;color:var(--vp-c-text-2);background-color:var(--vp-c-bg-soft)}.vp-sponsor.normal .vp-sponsor-tier{padding:13px 0 11px;font-size:14px}.vp-sponsor.aside .vp-sponsor-tier{padding:9px 0 7px;font-size:12px}.vp-sponsor-grid+.vp-sponsor-tier{margin-top:4px}.vp-sponsor-grid{display:flex;flex-wrap:wrap;gap:4px}.vp-sponsor-grid.xmini .vp-sponsor-grid-link{height:64px}.vp-sponsor-grid.xmini .vp-sponsor-grid-image{max-width:64px;max-height:22px}.vp-sponsor-grid.mini .vp-sponsor-grid-link{height:72px}.vp-sponsor-grid.mini .vp-sponsor-grid-image{max-width:96px;max-height:24px}.vp-sponsor-grid.small .vp-sponsor-grid-link{height:96px}.vp-sponsor-grid.small .vp-sponsor-grid-image{max-width:96px;max-height:24px}.vp-sponsor-grid.medium .vp-sponsor-grid-link{height:112px}.vp-sponsor-grid.medium .vp-sponsor-grid-image{max-width:120px;max-height:36px}.vp-sponsor-grid.big .vp-sponsor-grid-link{height:184px}.vp-sponsor-grid.big .vp-sponsor-grid-image{max-width:192px;max-height:56px}.vp-sponsor-grid[data-vp-grid="2"] .vp-sponsor-grid-item{width:calc((100% - 4px)/2)}.vp-sponsor-grid[data-vp-grid="3"] .vp-sponsor-grid-item{width:calc((100% - 4px * 2) / 3)}.vp-sponsor-grid[data-vp-grid="4"] .vp-sponsor-grid-item{width:calc((100% - 12px)/4)}.vp-sponsor-grid[data-vp-grid="5"] .vp-sponsor-grid-item{width:calc((100% - 16px)/5)}.vp-sponsor-grid[data-vp-grid="6"] .vp-sponsor-grid-item{width:calc((100% - 4px * 5) / 6)}.vp-sponsor-grid-item{flex-shrink:0;width:100%;background-color:var(--vp-c-bg-soft);transition:background-color .25s}.vp-sponsor-grid-item:hover{background-color:var(--vp-c-default-soft)}.vp-sponsor-grid-item:hover .vp-sponsor-grid-image{filter:grayscale(0) invert(0)}.vp-sponsor-grid-item.empty:hover{background-color:var(--vp-c-bg-soft)}.dark .vp-sponsor-grid-item:hover{background-color:var(--vp-c-white)}.dark .vp-sponsor-grid-item.empty:hover{background-color:var(--vp-c-bg-soft)}.vp-sponsor-grid-link{display:flex}.vp-sponsor-grid-box{display:flex;justify-content:center;align-items:center;width:100%}.vp-sponsor-grid-image{max-width:100%;filter:grayscale(1);transition:filter .25s}.dark .vp-sponsor-grid-image{filter:grayscale(1) invert(1)}.VPBadge{display:inline-block;margin-left:2px;border:1px solid transparent;border-radius:12px;padding:0 10px;line-height:22px;font-size:12px;font-weight:500;white-space:nowrap;transform:translateY(-2px)}.VPBadge.small{padding:0 6px;line-height:18px;font-size:10px;transform:translateY(-8px)}.VPDocFooter .VPBadge{display:none}.vp-doc h1>.VPBadge{margin-top:4px;vertical-align:top}.vp-doc h2>.VPBadge{margin-top:3px;padding:0 8px;vertical-align:top}.vp-doc h3>.VPBadge{vertical-align:middle}.vp-doc h4>.VPBadge,.vp-doc h5>.VPBadge,.vp-doc h6>.VPBadge{vertical-align:middle;line-height:18px}.VPBadge.info{border-color:var(--vp-badge-info-border);color:var(--vp-badge-info-text);background-color:var(--vp-badge-info-bg)}.VPBadge.tip{border-color:var(--vp-badge-tip-border);color:var(--vp-badge-tip-text);background-color:var(--vp-badge-tip-bg)}.VPBadge.warning{border-color:var(--vp-badge-warning-border);color:var(--vp-badge-warning-text);background-color:var(--vp-badge-warning-bg)}.VPBadge.danger{border-color:var(--vp-badge-danger-border);color:var(--vp-badge-danger-text);background-color:var(--vp-badge-danger-bg)}.VPBackdrop[data-v-f703a812]{position:fixed;inset:0;z-index:var(--vp-z-index-backdrop);background:var(--vp-backdrop-bg-color);transition:opacity .5s}.VPBackdrop.fade-enter-from[data-v-f703a812],.VPBackdrop.fade-leave-to[data-v-f703a812]{opacity:0}.VPBackdrop.fade-leave-active[data-v-f703a812]{transition-duration:.25s}@media(min-width:1280px){.VPBackdrop[data-v-f703a812]{display:none}}.NotFound[data-v-1b32e0f1]{padding:64px 24px 96px;text-align:center}@media(min-width:768px){.NotFound[data-v-1b32e0f1]{padding:96px 32px 168px}}.code[data-v-1b32e0f1]{line-height:64px;font-size:64px;font-weight:600}.title[data-v-1b32e0f1]{padding-top:12px;letter-spacing:2px;line-height:20px;font-size:20px;font-weight:700}.divider[data-v-1b32e0f1]{margin:24px auto 18px;width:64px;height:1px;background-color:var(--vp-c-divider)}.quote[data-v-1b32e0f1]{margin:0 auto;max-width:256px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.action[data-v-1b32e0f1]{padding-top:20px}.link[data-v-1b32e0f1]{display:inline-block;border:1px solid var(--vp-c-brand-1);border-radius:16px;padding:3px 16px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1);transition:border-color .25s,color .25s}.link[data-v-1b32e0f1]:hover{border-color:var(--vp-c-brand-2);color:var(--vp-c-brand-2)}.root[data-v-d90f9aed]{position:relative;z-index:1}.nested[data-v-d90f9aed]{padding-right:16px;padding-left:16px}.outline-link[data-v-d90f9aed]{display:block;line-height:32px;font-size:14px;font-weight:400;color:var(--vp-c-text-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:color .5s}.outline-link[data-v-d90f9aed]:hover,.outline-link.active[data-v-d90f9aed]{color:var(--vp-c-text-1);transition:color .25s}.outline-link.nested[data-v-d90f9aed]{padding-left:13px}.VPDocAsideOutline[data-v-3f819b94]{display:none}.VPDocAsideOutline.has-outline[data-v-3f819b94]{display:block}.content[data-v-3f819b94]{position:relative;border-left:1px solid var(--vp-c-divider);padding-left:16px;font-size:13px;font-weight:500}.outline-marker[data-v-3f819b94]{position:absolute;top:32px;left:-1px;z-index:0;opacity:0;width:2px;border-radius:2px;height:18px;background-color:var(--vp-c-brand-1);transition:top .25s cubic-bezier(0,1,.5,1),background-color .5s,opacity .25s}.outline-title[data-v-3f819b94]{line-height:32px;font-size:14px;font-weight:600}.VPDocAside[data-v-77a1b21d]{display:flex;flex-direction:column;flex-grow:1}.spacer[data-v-77a1b21d]{flex-grow:1}.VPDocAside[data-v-77a1b21d] .spacer+.VPDocAsideSponsors,.VPDocAside[data-v-77a1b21d] .spacer+.VPDocAsideCarbonAds{margin-top:24px}.VPDocAside[data-v-77a1b21d] .VPDocAsideSponsors+.VPDocAsideCarbonAds{margin-top:16px}.VPLastUpdated[data-v-8f712c9b]{line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}@media(min-width:640px){.VPLastUpdated[data-v-8f712c9b]{line-height:32px;font-size:14px;font-weight:500}}.VPDocFooter[data-v-af105c74]{margin-top:64px}.edit-info[data-v-af105c74]{padding-bottom:18px}@media(min-width:640px){.edit-info[data-v-af105c74]{display:flex;justify-content:space-between;align-items:center;padding-bottom:14px}}.edit-link-button[data-v-af105c74]{display:flex;align-items:center;border:0;line-height:32px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1);transition:color .25s}.edit-link-button[data-v-af105c74]:hover{color:var(--vp-c-brand-2)}.edit-link-icon[data-v-af105c74]{margin-right:8px}.prev-next[data-v-af105c74]{border-top:1px solid var(--vp-c-divider);padding-top:24px;display:grid;grid-row-gap:8px}@media(min-width:640px){.prev-next[data-v-af105c74]{grid-template-columns:repeat(2,1fr);grid-column-gap:16px}}.pager-link[data-v-af105c74]{display:block;border:1px solid var(--vp-c-divider);border-radius:8px;padding:11px 16px 13px;width:100%;height:100%;transition:border-color .25s}.pager-link[data-v-af105c74]:hover{border-color:var(--vp-c-brand-1)}.pager-link.next[data-v-af105c74]{margin-left:auto;text-align:right}.desc[data-v-af105c74]{display:block;line-height:20px;font-size:12px;font-weight:500;color:var(--vp-c-text-2)}.title[data-v-af105c74]{display:block;line-height:20px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1);transition:color .25s}.VPDoc[data-v-256763c0]{padding:32px 24px 96px;width:100%}@media(min-width:768px){.VPDoc[data-v-256763c0]{padding:48px 32px 128px}}@media(min-width:960px){.VPDoc[data-v-256763c0]{padding:48px 32px 0}.VPDoc:not(.has-sidebar) .container[data-v-256763c0]{display:flex;justify-content:center;max-width:992px}.VPDoc:not(.has-sidebar) .content[data-v-256763c0]{max-width:752px}}@media(min-width:1280px){.VPDoc .container[data-v-256763c0]{display:flex;justify-content:center}.VPDoc .aside[data-v-256763c0]{display:block}}@media(min-width:1440px){.VPDoc:not(.has-sidebar) .content[data-v-256763c0]{max-width:784px}.VPDoc:not(.has-sidebar) .container[data-v-256763c0]{max-width:1104px}}.container[data-v-256763c0]{margin:0 auto;width:100%}.aside[data-v-256763c0]{position:relative;display:none;order:2;flex-grow:1;padding-left:32px;width:100%;max-width:256px}.left-aside[data-v-256763c0]{order:1;padding-left:unset;padding-right:32px}.aside-container[data-v-256763c0]{position:fixed;top:0;padding-top:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + var(--vp-doc-top-height, 0px) + 48px);width:224px;height:100vh;overflow-x:hidden;overflow-y:auto;scrollbar-width:none}.aside-container[data-v-256763c0]::-webkit-scrollbar{display:none}.aside-curtain[data-v-256763c0]{position:fixed;bottom:0;z-index:10;width:224px;height:32px;background:linear-gradient(transparent,var(--vp-c-bg) 70%);pointer-events:none}.aside-content[data-v-256763c0]{display:flex;flex-direction:column;min-height:calc(100vh - (var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 48px));padding-bottom:32px}.content[data-v-256763c0]{position:relative;margin:0 auto;width:100%}@media(min-width:960px){.content[data-v-256763c0]{padding:0 32px 128px}}@media(min-width:1280px){.content[data-v-256763c0]{order:1;margin:0;min-width:640px}}.content-container[data-v-256763c0]{margin:0 auto}.VPDoc.has-aside .content-container[data-v-256763c0]{max-width:688px}.VPButton[data-v-b44745dc]{display:inline-block;border:1px solid transparent;text-align:center;font-weight:600;white-space:nowrap;transition:color .25s,border-color .25s,background-color .25s}.VPButton[data-v-b44745dc]:active{transition:color .1s,border-color .1s,background-color .1s}.VPButton.medium[data-v-b44745dc]{border-radius:20px;padding:0 20px;line-height:38px;font-size:14px}.VPButton.big[data-v-b44745dc]{border-radius:24px;padding:0 24px;line-height:46px;font-size:16px}.VPButton.brand[data-v-b44745dc]{border-color:var(--vp-button-brand-border);color:var(--vp-button-brand-text);background-color:var(--vp-button-brand-bg)}.VPButton.brand[data-v-b44745dc]:hover{border-color:var(--vp-button-brand-hover-border);color:var(--vp-button-brand-hover-text);background-color:var(--vp-button-brand-hover-bg)}.VPButton.brand[data-v-b44745dc]:active{border-color:var(--vp-button-brand-active-border);color:var(--vp-button-brand-active-text);background-color:var(--vp-button-brand-active-bg)}.VPButton.alt[data-v-b44745dc]{border-color:var(--vp-button-alt-border);color:var(--vp-button-alt-text);background-color:var(--vp-button-alt-bg)}.VPButton.alt[data-v-b44745dc]:hover{border-color:var(--vp-button-alt-hover-border);color:var(--vp-button-alt-hover-text);background-color:var(--vp-button-alt-hover-bg)}.VPButton.alt[data-v-b44745dc]:active{border-color:var(--vp-button-alt-active-border);color:var(--vp-button-alt-active-text);background-color:var(--vp-button-alt-active-bg)}.VPButton.sponsor[data-v-b44745dc]{border-color:var(--vp-button-sponsor-border);color:var(--vp-button-sponsor-text);background-color:var(--vp-button-sponsor-bg)}.VPButton.sponsor[data-v-b44745dc]:hover{border-color:var(--vp-button-sponsor-hover-border);color:var(--vp-button-sponsor-hover-text);background-color:var(--vp-button-sponsor-hover-bg)}.VPButton.sponsor[data-v-b44745dc]:active{border-color:var(--vp-button-sponsor-active-border);color:var(--vp-button-sponsor-active-text);background-color:var(--vp-button-sponsor-active-bg)}html:not(.dark) .VPImage.dark[data-v-e0e0d586]{display:none}.dark .VPImage.light[data-v-e0e0d586]{display:none}.VPHero[data-v-09867ed5]{margin-top:calc((var(--vp-nav-height) + var(--vp-layout-top-height, 0px)) * -1);padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 48px) 24px 48px}@media(min-width:640px){.VPHero[data-v-09867ed5]{padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 80px) 48px 64px}}@media(min-width:960px){.VPHero[data-v-09867ed5]{padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 80px) 64px 64px}}.container[data-v-09867ed5]{display:flex;flex-direction:column;margin:0 auto;max-width:1152px}@media(min-width:960px){.container[data-v-09867ed5]{flex-direction:row}}.main[data-v-09867ed5]{position:relative;z-index:10;order:2;flex-grow:1;flex-shrink:0}.VPHero.has-image .container[data-v-09867ed5]{text-align:center}@media(min-width:960px){.VPHero.has-image .container[data-v-09867ed5]{text-align:left}}@media(min-width:960px){.main[data-v-09867ed5]{order:1;width:calc((100% / 3) * 2)}.VPHero.has-image .main[data-v-09867ed5]{max-width:592px}}.heading[data-v-09867ed5]{display:flex;flex-direction:column}.name[data-v-09867ed5],.text[data-v-09867ed5]{width:fit-content;max-width:392px;letter-spacing:-.4px;line-height:40px;font-size:32px;font-weight:700;white-space:pre-wrap}.VPHero.has-image .name[data-v-09867ed5],.VPHero.has-image .text[data-v-09867ed5]{margin:0 auto}.name[data-v-09867ed5]{color:var(--vp-home-hero-name-color)}.clip[data-v-09867ed5]{background:var(--vp-home-hero-name-background);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:var(--vp-home-hero-name-color)}@media(min-width:640px){.name[data-v-09867ed5],.text[data-v-09867ed5]{max-width:576px;line-height:56px;font-size:48px}}@media(min-width:960px){.name[data-v-09867ed5],.text[data-v-09867ed5]{line-height:64px;font-size:56px}.VPHero.has-image .name[data-v-09867ed5],.VPHero.has-image .text[data-v-09867ed5]{margin:0}}.tagline[data-v-09867ed5]{padding-top:8px;max-width:392px;line-height:28px;font-size:18px;font-weight:500;white-space:pre-wrap;color:var(--vp-c-text-2)}.VPHero.has-image .tagline[data-v-09867ed5]{margin:0 auto}@media(min-width:640px){.tagline[data-v-09867ed5]{padding-top:12px;max-width:576px;line-height:32px;font-size:20px}}@media(min-width:960px){.tagline[data-v-09867ed5]{line-height:36px;font-size:24px}.VPHero.has-image .tagline[data-v-09867ed5]{margin:0}}.actions[data-v-09867ed5]{display:flex;flex-wrap:wrap;margin:-6px;padding-top:24px}.VPHero.has-image .actions[data-v-09867ed5]{justify-content:center}@media(min-width:640px){.actions[data-v-09867ed5]{padding-top:32px}}@media(min-width:960px){.VPHero.has-image .actions[data-v-09867ed5]{justify-content:flex-start}}.action[data-v-09867ed5]{flex-shrink:0;padding:6px}.image[data-v-09867ed5]{order:1;margin:-76px -24px -48px}@media(min-width:640px){.image[data-v-09867ed5]{margin:-108px -24px -48px}}@media(min-width:960px){.image[data-v-09867ed5]{flex-grow:1;order:2;margin:0;min-height:100%}}.image-container[data-v-09867ed5]{position:relative;margin:0 auto;width:320px;height:320px}@media(min-width:640px){.image-container[data-v-09867ed5]{width:392px;height:392px}}@media(min-width:960px){.image-container[data-v-09867ed5]{display:flex;justify-content:center;align-items:center;width:100%;height:100%;transform:translate(-32px,-32px)}}.image-bg[data-v-09867ed5]{position:absolute;top:50%;left:50%;border-radius:50%;width:192px;height:192px;background-image:var(--vp-home-hero-image-background-image);filter:var(--vp-home-hero-image-filter);transform:translate(-50%,-50%)}@media(min-width:640px){.image-bg[data-v-09867ed5]{width:256px;height:256px}}@media(min-width:960px){.image-bg[data-v-09867ed5]{width:320px;height:320px}}[data-v-09867ed5] .image-src{position:absolute;top:50%;left:50%;max-width:192px;max-height:192px;width:100%;height:100%;object-fit:contain;transform:translate(-50%,-50%)}@media(min-width:640px){[data-v-09867ed5] .image-src{max-width:256px;max-height:256px}}@media(min-width:960px){[data-v-09867ed5] .image-src{max-width:320px;max-height:320px}}.VPFeature[data-v-684de982]{display:block;border:1px solid var(--vp-c-bg-soft);border-radius:12px;height:100%;background-color:var(--vp-c-bg-soft);transition:border-color .25s,background-color .25s}.VPFeature.link[data-v-684de982]:hover{border-color:var(--vp-c-brand-1)}.box[data-v-684de982]{display:flex;flex-direction:column;padding:24px;height:100%}.box[data-v-684de982]>.VPImage{margin-bottom:20px}.icon[data-v-684de982]{display:flex;justify-content:center;align-items:center;margin-bottom:20px;border-radius:6px;background-color:var(--vp-c-default-soft);width:48px;height:48px;font-size:24px;transition:background-color .25s}.title[data-v-684de982]{line-height:24px;font-size:16px;font-weight:600}.details[data-v-684de982]{flex-grow:1;padding-top:8px;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.link-text[data-v-684de982]{padding-top:8px}.link-text-value[data-v-684de982]{display:flex;align-items:center;font-size:14px;font-weight:500;color:var(--vp-c-brand-1)}.link-text-icon[data-v-684de982]{margin-left:6px}.VPFeatures[data-v-4422ade5]{position:relative;padding:0 24px}@media(min-width:640px){.VPFeatures[data-v-4422ade5]{padding:0 48px}}@media(min-width:960px){.VPFeatures[data-v-4422ade5]{padding:0 64px}}.container[data-v-4422ade5]{margin:0 auto;max-width:1152px}.items[data-v-4422ade5]{display:flex;flex-wrap:wrap;margin:-8px}.item[data-v-4422ade5]{padding:8px;width:100%}@media(min-width:640px){.item.grid-2[data-v-4422ade5],.item.grid-4[data-v-4422ade5],.item.grid-6[data-v-4422ade5]{width:50%}}@media(min-width:768px){.item.grid-2[data-v-4422ade5],.item.grid-4[data-v-4422ade5]{width:50%}.item.grid-3[data-v-4422ade5],.item.grid-6[data-v-4422ade5]{width:calc(100% / 3)}}@media(min-width:960px){.item.grid-4[data-v-4422ade5]{width:25%}}.container[data-v-1b679879]{margin:auto;width:100%;max-width:1280px;padding:0 24px}@media(min-width:640px){.container[data-v-1b679879]{padding:0 48px}}@media(min-width:960px){.container[data-v-1b679879]{width:100%;padding:0 64px}}.vp-doc[data-v-1b679879] .VPHomeSponsors,.vp-doc[data-v-1b679879] .VPTeamPage{margin-left:var(--vp-offset, calc(50% - 50vw) );margin-right:var(--vp-offset, calc(50% - 50vw) )}.vp-doc[data-v-1b679879] .VPHomeSponsors h2{border-top:none;letter-spacing:normal}.vp-doc[data-v-1b679879] .VPHomeSponsors a,.vp-doc[data-v-1b679879] .VPTeamPage a{text-decoration:none}.VPHome[data-v-10bb9ea0]{margin-bottom:96px}@media(min-width:768px){.VPHome[data-v-10bb9ea0]{margin-bottom:128px}}.VPContent[data-v-19ca35aa]{flex-grow:1;flex-shrink:0;margin:var(--vp-layout-top-height, 0px) auto 0;width:100%}.VPContent.is-home[data-v-19ca35aa]{width:100%;max-width:100%}.VPContent.has-sidebar[data-v-19ca35aa]{margin:0}@media(min-width:960px){.VPContent[data-v-19ca35aa]{padding-top:var(--vp-nav-height)}.VPContent.has-sidebar[data-v-19ca35aa]{margin:var(--vp-layout-top-height, 0px) 0 0;padding-left:var(--vp-sidebar-width)}}@media(min-width:1440px){.VPContent.has-sidebar[data-v-19ca35aa]{padding-right:calc((100vw - var(--vp-layout-max-width)) / 2);padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.VPFooter[data-v-105f771f]{position:relative;z-index:var(--vp-z-index-footer);border-top:1px solid var(--vp-c-gutter);padding:32px 24px;background-color:var(--vp-c-bg)}.VPFooter.has-sidebar[data-v-105f771f]{display:none}.VPFooter[data-v-105f771f] a{text-decoration-line:underline;text-underline-offset:2px;transition:color .25s}.VPFooter[data-v-105f771f] a:hover{color:var(--vp-c-text-1)}@media(min-width:768px){.VPFooter[data-v-105f771f]{padding:32px}}.container[data-v-105f771f]{margin:0 auto;max-width:var(--vp-layout-max-width);text-align:center}.message[data-v-105f771f],.copyright[data-v-105f771f]{line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.VPLocalNavOutlineDropdown button[data-v-6ab9adca]{display:block;font-size:12px;font-weight:500;line-height:24px;color:var(--vp-c-text-2);transition:color .5s;position:relative}.VPLocalNavOutlineDropdown button[data-v-6ab9adca]:hover{color:var(--vp-c-text-1);transition:color .25s}.VPLocalNavOutlineDropdown button.open[data-v-6ab9adca]{color:var(--vp-c-text-1)}.icon[data-v-6ab9adca]{display:inline-block;vertical-align:middle;margin-left:2px;font-size:14px;transform:rotate(0);transition:transform .25s}@media(min-width:960px){.VPLocalNavOutlineDropdown button[data-v-6ab9adca]{font-size:14px}.icon[data-v-6ab9adca]{font-size:16px}}.open>.icon[data-v-6ab9adca]{transform:rotate(90deg)}.items[data-v-6ab9adca]{position:absolute;top:40px;right:16px;left:16px;display:grid;gap:1px;border:1px solid var(--vp-c-border);border-radius:8px;background-color:var(--vp-c-gutter);max-height:calc(var(--vp-vh, 100vh) - 86px);overflow:hidden auto;box-shadow:var(--vp-shadow-3)}@media(min-width:960px){.items[data-v-6ab9adca]{right:auto;left:calc(var(--vp-sidebar-width) + 32px);width:320px}}.header[data-v-6ab9adca]{background-color:var(--vp-c-bg-soft)}.top-link[data-v-6ab9adca]{display:block;padding:0 16px;line-height:48px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1)}.outline[data-v-6ab9adca]{padding:8px 0;background-color:var(--vp-c-bg-soft)}.flyout-enter-active[data-v-6ab9adca]{transition:all .2s ease-out}.flyout-leave-active[data-v-6ab9adca]{transition:all .15s ease-in}.flyout-enter-from[data-v-6ab9adca],.flyout-leave-to[data-v-6ab9adca]{opacity:0;transform:translateY(-16px)}.VPLocalNav[data-v-8f018525]{position:sticky;top:0;left:0;z-index:var(--vp-z-index-local-nav);border-bottom:1px solid var(--vp-c-gutter);padding-top:var(--vp-layout-top-height, 0px);width:100%;background-color:var(--vp-local-nav-bg-color)}.VPLocalNav.fixed[data-v-8f018525]{position:fixed}@media(min-width:960px){.VPLocalNav[data-v-8f018525]{top:var(--vp-nav-height)}.VPLocalNav.has-sidebar[data-v-8f018525]{padding-left:var(--vp-sidebar-width)}.VPLocalNav.empty[data-v-8f018525]{display:none}}@media(min-width:1280px){.VPLocalNav[data-v-8f018525]{display:none}}@media(min-width:1440px){.VPLocalNav.has-sidebar[data-v-8f018525]{padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.container[data-v-8f018525]{display:flex;justify-content:space-between;align-items:center}.menu[data-v-8f018525]{display:flex;align-items:center;line-height:24px;font-size:12px;font-weight:500;color:var(--vp-c-text-2);transition:color .5s}.menu[data-v-8f018525]:hover{color:var(--vp-c-text-1);transition:color .25s}@media(min-width:960px){.menu[data-v-8f018525]{display:none}}.menu-icon[data-v-8f018525]{margin-right:8px;font-size:14px}.menu[data-v-8f018525],[data-v-8f018525] .VPLocalNavOutlineDropdown>button{padding:12px 24px 11px}@media(min-width:768px){.menu[data-v-8f018525],[data-v-8f018525] .VPLocalNavOutlineDropdown>button{padding:12px 32px 11px}}.VPSwitch[data-v-5fd96198]{position:relative;border-radius:11px;display:block;width:40px;height:22px;flex-shrink:0;border:1px solid var(--vp-input-border-color);background-color:var(--vp-input-switch-bg-color);transition:border-color .25s!important}.VPSwitch[data-v-5fd96198]:hover{border-color:var(--vp-c-brand-1)}.check[data-v-5fd96198]{position:absolute;top:1px;left:1px;width:18px;height:18px;border-radius:50%;background-color:var(--vp-c-neutral-inverse);box-shadow:var(--vp-shadow-1);transition:transform .25s!important}.icon[data-v-5fd96198]{position:relative;display:block;width:18px;height:18px;border-radius:50%;overflow:hidden}.icon[data-v-5fd96198] [class^=vpi-]{position:absolute;top:3px;left:3px;width:12px;height:12px;color:var(--vp-c-text-2)}.dark .icon[data-v-5fd96198] [class^=vpi-]{color:var(--vp-c-text-1);transition:opacity .25s!important}.sun[data-v-fd2b5f2c]{opacity:1}.moon[data-v-fd2b5f2c],.dark .sun[data-v-fd2b5f2c]{opacity:0}.dark .moon[data-v-fd2b5f2c]{opacity:1}.dark .VPSwitchAppearance[data-v-fd2b5f2c] .check{transform:translate(18px)}.VPNavBarAppearance[data-v-0fac236d]{display:none}@media(min-width:1280px){.VPNavBarAppearance[data-v-0fac236d]{display:flex;align-items:center}}.VPMenuGroup+.VPMenuLink[data-v-c995c7e2]{margin:12px -12px 0;border-top:1px solid var(--vp-c-divider);padding:12px 12px 0}.link[data-v-c995c7e2]{display:block;border-radius:6px;padding:0 12px;line-height:32px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);text-align:left;white-space:nowrap;transition:background-color .25s,color .25s}.link[data-v-c995c7e2]:hover{color:var(--vp-c-brand-1);background-color:var(--vp-c-default-soft)}.link.active[data-v-c995c7e2]{color:var(--vp-c-brand-1)}.VPMenuGroup[data-v-0d91e4ea]{margin:12px -12px 0;border-top:1px solid var(--vp-c-divider);padding:12px 12px 0}.VPMenuGroup[data-v-0d91e4ea]:first-child{margin-top:0;border-top:0;padding-top:0}.VPMenuGroup+.VPMenuGroup[data-v-0d91e4ea]{margin-top:12px;border-top:1px solid var(--vp-c-divider)}.title[data-v-0d91e4ea]{padding:0 12px;line-height:32px;font-size:14px;font-weight:600;color:var(--vp-c-text-2);white-space:nowrap;transition:color .25s}.VPMenu[data-v-62da9740]{border-radius:12px;padding:12px;min-width:128px;border:1px solid var(--vp-c-divider);background-color:var(--vp-c-bg-elv);box-shadow:var(--vp-shadow-3);transition:background-color .5s;max-height:calc(100vh - var(--vp-nav-height));overflow-y:auto}.VPMenu[data-v-62da9740] .group{margin:0 -12px;padding:0 12px 12px}.VPMenu[data-v-62da9740] .group+.group{border-top:1px solid var(--vp-c-divider);padding:11px 12px 12px}.VPMenu[data-v-62da9740] .group:last-child{padding-bottom:0}.VPMenu[data-v-62da9740] .group+.item{border-top:1px solid var(--vp-c-divider);padding:11px 16px 0}.VPMenu[data-v-62da9740] .item{padding:0 16px;white-space:nowrap}.VPMenu[data-v-62da9740] .label{flex-grow:1;line-height:28px;font-size:12px;font-weight:500;color:var(--vp-c-text-2);transition:color .5s}.VPMenu[data-v-62da9740] .action{padding-left:24px}.VPFlyout[data-v-c0d6c551]{position:relative}.VPFlyout[data-v-c0d6c551]:hover{color:var(--vp-c-brand-1);transition:color .25s}.VPFlyout:hover .text[data-v-c0d6c551]{color:var(--vp-c-text-2)}.VPFlyout:hover .icon[data-v-c0d6c551]{fill:var(--vp-c-text-2)}.VPFlyout.active .text[data-v-c0d6c551]{color:var(--vp-c-brand-1)}.VPFlyout.active:hover .text[data-v-c0d6c551]{color:var(--vp-c-brand-2)}.button[aria-expanded=false]+.menu[data-v-c0d6c551]{opacity:0;visibility:hidden;transform:translateY(0)}.VPFlyout:hover .menu[data-v-c0d6c551],.button[aria-expanded=true]+.menu[data-v-c0d6c551]{opacity:1;visibility:visible;transform:translateY(0)}.button[data-v-c0d6c551]{display:flex;align-items:center;padding:0 12px;height:var(--vp-nav-height);color:var(--vp-c-text-1);transition:color .5s}.text[data-v-c0d6c551]{display:flex;align-items:center;line-height:var(--vp-nav-height);font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.option-icon[data-v-c0d6c551]{margin-right:0;font-size:16px}.text-icon[data-v-c0d6c551]{margin-left:4px;font-size:14px}.icon[data-v-c0d6c551]{font-size:20px;transition:fill .25s}.menu[data-v-c0d6c551]{position:absolute;top:calc(var(--vp-nav-height) / 2 + 20px);right:0;opacity:0;visibility:hidden;transition:opacity .25s,visibility .25s,transform .25s}.VPSocialLink[data-v-94c580ff]{display:flex;justify-content:center;align-items:center;width:36px;height:36px;color:var(--vp-c-text-2);transition:color .5s}.VPSocialLink[data-v-94c580ff]:hover{color:var(--vp-c-text-1);transition:color .25s}.VPSocialLink[data-v-94c580ff]>svg,.VPSocialLink[data-v-94c580ff]>[class^=vpi-social-]{width:20px;height:20px;fill:currentColor}.VPSocialLinks[data-v-0f495aab]{display:flex;justify-content:center}.VPNavBarExtra[data-v-cf5e177b]{display:none;margin-right:-12px}@media(min-width:768px){.VPNavBarExtra[data-v-cf5e177b]{display:block}}@media(min-width:1280px){.VPNavBarExtra[data-v-cf5e177b]{display:none}}.trans-title[data-v-cf5e177b]{padding:0 24px 0 12px;line-height:32px;font-size:14px;font-weight:700;color:var(--vp-c-text-1)}.item.appearance[data-v-cf5e177b],.item.social-links[data-v-cf5e177b]{display:flex;align-items:center;padding:0 12px}.item.appearance[data-v-cf5e177b]{min-width:176px}.appearance-action[data-v-cf5e177b]{margin-right:-2px}.social-links-list[data-v-cf5e177b]{margin:-4px -8px}.VPNavBarHamburger[data-v-1d142719]{display:flex;justify-content:center;align-items:center;width:48px;height:var(--vp-nav-height)}@media(min-width:768px){.VPNavBarHamburger[data-v-1d142719]{display:none}}.container[data-v-1d142719]{position:relative;width:16px;height:14px;overflow:hidden}.VPNavBarHamburger:hover .top[data-v-1d142719]{top:0;left:0;transform:translate(4px)}.VPNavBarHamburger:hover .middle[data-v-1d142719]{top:6px;left:0;transform:translate(0)}.VPNavBarHamburger:hover .bottom[data-v-1d142719]{top:12px;left:0;transform:translate(8px)}.VPNavBarHamburger.active .top[data-v-1d142719]{top:6px;transform:translate(0) rotate(225deg)}.VPNavBarHamburger.active .middle[data-v-1d142719]{top:6px;transform:translate(16px)}.VPNavBarHamburger.active .bottom[data-v-1d142719]{top:6px;transform:translate(0) rotate(135deg)}.VPNavBarHamburger.active:hover .top[data-v-1d142719],.VPNavBarHamburger.active:hover .middle[data-v-1d142719],.VPNavBarHamburger.active:hover .bottom[data-v-1d142719]{background-color:var(--vp-c-text-2);transition:top .25s,background-color .25s,transform .25s}.top[data-v-1d142719],.middle[data-v-1d142719],.bottom[data-v-1d142719]{position:absolute;width:16px;height:2px;background-color:var(--vp-c-text-1);transition:top .25s,background-color .5s,transform .25s}.top[data-v-1d142719]{top:0;left:0;transform:translate(0)}.middle[data-v-1d142719]{top:6px;left:0;transform:translate(8px)}.bottom[data-v-1d142719]{top:12px;left:0;transform:translate(4px)}.VPNavBarMenuLink[data-v-bf8a0d28]{display:flex;align-items:center;padding:0 12px;line-height:var(--vp-nav-height);font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.VPNavBarMenuLink.active[data-v-bf8a0d28],.VPNavBarMenuLink[data-v-bf8a0d28]:hover{color:var(--vp-c-brand-1)}.VPNavBarMenu[data-v-39023d39]{display:none}@media(min-width:768px){.VPNavBarMenu[data-v-39023d39]{display:flex}}:root{--docsearch-primary-color:#003dff;--docsearch-soft-primary-color:rgba(0,61,255,.1);--docsearch-subtle-color:#d6d6e7;--docsearch-text-color:#36395a;--docsearch-error-color:#ef5350;--docsearch-success-color:#e8f5e9;--docsearch-secondary-text-color:#5a5e9a;--docsearch-background-color:#f5f5fa;--docsearch-spacing:12px;--docsearch-icon-stroke-width:1.4;--docsearch-focus-color:#005fcc;--docsearch-highlight-color:#003dff;--docsearch-muted-color:#9698c3;--docsearch-muted-color-darker:rgba(120,122,165,.25);--docsearch-icon-color:#5a5e9a;--docsearch-container-background:rgba(101,108,133,.8);--docsearch-logo-color:#003dff;--docsearch-border-radius:4px;--docsearch-modal-width:800px;--docsearch-modal-height:600px;--docsearch-modal-variable-height:60dvh;--docsearch-modal-background:#f5f6f7;--docsearch-modal-shadow:rgba(0,0,0,.2) 0px 12px 28px 0px,rgba(0,0,0,.1) 0px 2px 4px 0px,hsla(0,0%,100%,.05) 0px 0px 0px 1px inset;--docsearch-searchbox-height:56px;--docsearch-searchbox-initial-height:56px;--docsearch-searchbox-background:#ffffffa6;--docsearch-searchbox-focus-background:#ffffffa6;--docsearch-actions-width:99px;--docsearch-actions-height:44px;--docsearch-hit-height:56px;--docsearch-hit-color:#444950;--docsearch-hit-highlight-color:rgba(0,61,255,.1);--docsearch-hit-background:#fff;--docsearch-key-background:#f5f5fa;--docsearch-key-color:#5a5e9a;--docsearch-key-pressed-shadow:inset 0 2px 4px rgba(120,122,165,.25);--docsearch-footer-height:52px;--docsearch-footer-background:#ffffffa6;--docsearch-footer-shadow:0 -1px 0 0 #e0e3e8,0 -3px 6px 0 rgba(69,98,155,.12);--fav-out-dur:.16s;--del-dur:.15s;--ease-smooth:cubic-bezier(.25,.8,.4,1);--ease-fast:cubic-bezier(.45,.15,.6,.9);--shadow-pop:0 4px 12px rgba(0,0,0,.06);--shimmer-bg:linear-gradient(90deg,#e0e3e8 0%,var(--docsearch-muted-color) 20%,var(--docsearch-muted-color) 60%,#e0e3e8 95%);--docsearch-dropdown-menu-background:var(--docsearch-hit-background);--docsearch-dropdown-menu-item-hover-background:var(--docsearch-modal-background)}html.dark{--docsearch-text-color:#c4c7dc;--docsearch-secondary-text-color:#b6b7d5;--docsearch-subtle-color:#212139;--docsearch-error-color:#ef5350;--docsearch-success-color:rgba(67,160,71,.2);--docsearch-highlight-color:#457aff;--docsearch-focus-color:#9ac8ff;--docsearch-background-color:#36395a;--docsearch-icon-color:#b6b7d5;--docsearch-container-background:rgba(9,10,17,.8);--docsearch-modal-background:#15172a;--docsearch-modal-shadow:inset 1px 1px 0 0 #2c2e40,0 3px 8px 0 #000309;--docsearch-searchbox-background:#000000a6;--docsearch-searchbox-focus-background:#000000a6;--docsearch-hit-color:#bec3c9;--docsearch-hit-shadow:none;--docsearch-hit-background:#090a11;--docsearch-key-background:#36395a;--docsearch-key-color:#b6b7d5;--docsearch-key-pressed-shadow:inset 0 2px 4px rgba(12,13,20,.4);--docsearch-footer-background:#000000a6;--docsearch-footer-shadow:inset 0 1px 0 0 rgba(73,76,106,.5),0 -4px 8px 0 rgba(0,0,0,.2);--docsearch-logo-color:#fff;--docsearch-muted-color:#7f8497;--shimmer-bg:linear-gradient(90deg,#e0e3e8 0%,var(--docsearch-muted-color) 20%,var(--docsearch-muted-color) 60%,#e0e3e8 95%);--docsearch-dropdown-menu-item-hover-background:#10121e}.DocSearch-Button{all:unset;align-items:center;background-color:var(--docsearch-searchbox-background);border:1px solid var(--docsearch-subtle-color);border-radius:4px;color:var(--docsearch-muted-color);cursor:pointer;display:flex;height:36px;justify-content:space-between;padding:0 8px;-webkit-user-select:none;user-select:none}.DocSearch-Button-Container{align-items:center;display:flex;height:100%}.DocSearch-Button-Container svg{color:var(--docsearch-muted-color)}.DocSearch-Back-Icon,.DocSearch-Search-Icon{color:var(--docsearch-highlight-color);stroke-width:1.6}.DocSearch-Button-Placeholder{color:var(--docsearch-muted-color);display:inline-block;font-size:1rem;line-height:normal;padding:0 12px 0 8px}.DocSearch-Button-Keys{display:flex;min-width:calc(40px + .8em)}.DocSearch-Button-Key{align-items:center;background:var(--docsearch-key-background);border:0;border:1px solid color-mix(in srgb,var(--docsearch-subtle-color) 20%,transparent);border-radius:4px;box-shadow:none!important;color:var(--docsearch-key-color);display:flex;font-size:14px;height:24px;justify-content:center;position:relative;transition-duration:.1s;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);width:24px}.DocSearch-Button-Key--ctrl{width:33px}.DocSearch-Button-Key:first-child{margin-right:.4em}@media(prefers-reduced-motion){.DocSearch-Button-Key{transition:none}}.DocSearch-Button-Key--pressed{box-shadow:var(--docsearch-key-pressed-shadow)!important;transform:translateY(1px)}@media(max-width:768px){.DocSearch-Button{width:auto}.DocSearch-Button-Keys,.DocSearch-Button-Placeholder{display:none}}.DocSearch--active{overflow:hidden!important}.DocSearch-Container,.DocSearch-Container *{box-sizing:border-box}.DocSearch-Container{-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);background-color:var(--docsearch-container-background);height:100vh;left:0;position:fixed;top:0;width:100vw;z-index:400}.DocSearch-Container a{text-decoration:none}.DocSearch-Link{appearance:none;background:none;border:0;color:var(--docsearch-highlight-color);cursor:pointer;font:inherit;margin:0;padding:0}.DocSearch-Modal{background:var(--docsearch-modal-background);border-radius:4px;box-shadow:var(--docsearch-modal-shadow);display:flex;flex-direction:column;margin:60px auto auto;max-width:var(--docsearch-modal-width);position:relative}.DocSearch-SearchBar{display:flex}.DocSearch-SearchBar-Magnifier{color:var(--docsearch-highlight-color)}.DocSearch-Form{align-items:center;background:var(--docsearch-searchbox-focus-background);border-bottom:1px solid var(--docsearch-subtle-color);border-radius:4px 4px 0 0;display:flex;height:var( --docsearch-searchbox-height,var(--docsearch-searchbox-initial-height) );margin:0;min-height:var(--docsearch-searchbox-initial-height);padding-block:var(--docsearch-spacing);padding-inline:16px;position:relative;width:100%}.DocSearch-Input,.DocSearch-Modal-heading{appearance:none;background:transparent;border:0;color:var(--docsearch-text-color);flex:1;font:inherit;font-size:1.2em;font-weight:300;height:100%;line-height:1.4;outline:none;overflow-y:hidden;padding-block-start:4px;padding-inline-start:8px;resize:none;width:80%}.DocSearch-Input::placeholder{color:var(--docsearch-muted-color);opacity:1}.DocSearch-Input::-webkit-search-cancel-button,.DocSearch-Input::-webkit-search-decoration,.DocSearch-Input::-webkit-search-results-button,.DocSearch-Input::-webkit-search-results-decoration{display:none}.DocSearch-Actions{align-items:center;display:flex;gap:8px;height:var(--docsearch-actions-height);justify-content:flex-end;padding:0 2px;width:var(--docsearch-actions-width)}.DocSearch-Divider{border-left:1px solid var(--docsearch-subtle-color);height:16px}.DocSearch-Action{align-items:center;color:var(--docsearch-highlight-color);display:flex;justify-content:center;min-height:24px;min-width:24px}.DocSearch-Action,.DocSearch-AskAi-Return,.DocSearch-LoadingIndicator,.DocSearch-MagnifierLabel{margin:0;padding:0}.DocSearch-AskAi-Return{cursor:pointer}.DocSearch-AskAi-Return,.DocSearch-LoadingIndicator,.DocSearch-MagnifierLabel{align-items:center;color:var(--docsearch-highlight-color);display:flex;justify-content:center}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Action{animation:none;appearance:none;background:none;border:0;border-radius:50%;color:var(--docsearch-icon-color);cursor:pointer;right:0;stroke-width:var(--docsearch-icon-stroke-width)}}.DocSearch-Action,.DocSearch-AskAi-Return{animation:fade-in .1s ease-in forwards;appearance:none;background:none;border:none;border-radius:var(--docsearch-border-radius);color:var(--docsearch-icon-color);cursor:pointer;padding:2px;right:0;stroke-width:var(--docsearch-icon-stroke-width)}.DocSearch-AskAi-Return[hidden],.DocSearch-Close[hidden],.DocSearch-Input[hidden],.DocSearch-StreamingIndicator[hidden]{display:none}.DocSearch-Action:hover,.DocSearch-AskAi-Return:hover{background:var(--docsearch-soft-primary-color);color:var(--docsearch-highlight-color)}.DocSearch-LoadingIndicator svg,.DocSearch-MagnifierLabel svg{color:var(--docsearch-icon-color);height:24px;width:24px}.DocSearch-Form:focus-within .DocSearch-MagnifierLabel svg{color:var(--docsearch-highlight-color)}.DocSearch-Clear{appearance:none;background:none;border:0;color:var(--docsearch-highlight-color);cursor:pointer;flex:none;font:inherit;font-size:.9em;font-weight:300;height:28px;margin-left:var(--docsearch-spacing);outline:none;overflow:hidden;padding:0;-webkit-user-select:none;user-select:none;white-space:nowrap}.DocSearch-Clear:focus-visible,.DocSearch-Close:focus-visible{border-radius:4px;outline:2px solid var(--docsearch-focus-color);outline-offset:1px}.DocSearch-Dropdown{height:var(--docsearch-modal-variable-height);max-height:calc(var(--docsearch-modal-height) - var(--docsearch-spacing) - var(--docsearch-footer-height));min-height:var(--docsearch-spacing);overflow-y:auto;overflow-y:overlay;padding:0 var(--docsearch-spacing);scrollbar-color:var(--docsearch-muted-color) var(--docsearch-modal-background);scrollbar-width:thin}.DocSearch-Dropdown::-webkit-scrollbar{width:12px}.DocSearch-Dropdown::-webkit-scrollbar-track{background:transparent}.DocSearch-Dropdown::-webkit-scrollbar-thumb{background-color:var(--docsearch-muted-color);border:3px solid var(--docsearch-modal-background);border-radius:20px}.DocSearch-Dropdown-Container ul{list-style:none;margin:0;padding:0}.DocSearch-Label{color:var(--docsearch-secondary-text-color);font-size:.875em;font-weight:400;line-height:1.6em}.DocSearch-Help,.DocSearch-NoResults-Help{color:var(--docsearch-secondary-text-color);font-size:.8em;font-weight:300;line-height:1.5em;margin:0;-webkit-user-select:none;user-select:none}.DocSearch-Title{color:var(--docsearch-text-color);font-size:1.1em;font-weight:300;line-height:.5em;vertical-align:middle}.DocSearch-Title strong{font-weight:500}.DocSearch-Logo a{display:flex}.DocSearch-Logo svg{color:var(--docsearch-logo-color);margin-left:8px}.DocSearch-Hits:last-of-type{margin-bottom:24px}.DocSearch-Hits mark{background:none;color:var(--docsearch-highlight-color)}.DocSearch-HitsFooter{color:var(--docsearch-muted-color);display:flex;font-size:.85em;justify-content:center;margin-bottom:var(--docsearch-spacing);padding:var(--docsearch-spacing)}.DocSearch-HitsFooter a{border-bottom:1px solid;color:inherit}.DocSearch-Hit{border-radius:4px;display:flex;padding-bottom:4px;position:relative;scroll-margin-top:40px}.DocSearch-Hit:first-of-type{margin-top:4px}.DocSearch-Hit a,.DocSearch-Hit--AskAI{background:var(--docsearch-hit-background);border-radius:4px;cursor:pointer;display:block;padding-left:var(--docsearch-spacing);width:100%}.DocSearch-Hit-source{background:var(--docsearch-modal-background);color:var(--docsearch-text-color);font-size:.9em;font-weight:600;line-height:32px;margin:0 -4px;padding:8px 4px 4px;position:sticky;top:0;z-index:10}.DocSearch-Hit-Tree{color:var(--docsearch-muted-color);height:var(--docsearch-hit-height);opacity:.5;stroke-width:var(--docsearch-icon-stroke-width);width:24px}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit--AskAI,.DocSearch-Hit[aria-selected=true] a{background-color:var(--docsearch-hit-highlight-color)}.DocSearch-Conversation-History .DocSearch-Hit[aria-selected=true] a{background-color:var(--docsearch-hit-background)}.DocSearch-Hit mark{color:var(--docsearch-highlight-color);text-decoration:underline;text-underline-offset:.3em}.DocSearch-Hit-Container{align-items:center;color:var(--docsearch-text-color);display:flex;flex-direction:row;height:var(--docsearch-hit-height);padding:0 var(--docsearch-spacing) 0 0}.DocSearch-Hit-icon{color:var(--docsearch-secondary-text-color);height:20px;width:20px}.DocSearch-Hit-action,.DocSearch-Hit-icon{stroke-width:var(--docsearch-icon-stroke-width)}.DocSearch-Hit-action{align-items:center;color:var(--docsearch-muted-color);display:flex;height:22px;width:22px}.DocSearch-Hit-action svg{display:block;height:18px;width:18px}.DocSearch-Hit-action+.DocSearch-Hit-action{margin-left:6px}.DocSearch-Hit-action-button{appearance:none;background:none;border:0;border-radius:50%;color:inherit;cursor:pointer;padding:2px}svg.DocSearch-Hit-Select-Icon{display:none}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-Select-Icon{display:block}.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{background:#0003;transition:background-color .1s ease-in}.DocSearch-Hit-action-button:focus path,.DocSearch-Hit-action-button:hover path{fill:#fff}.DocSearch-Hit-content-wrapper{display:flex;flex:1 1 auto;flex-direction:column;font-weight:400;gap:4px;justify-content:center;line-height:1.2em;margin:0 8px;overflow-x:hidden;position:relative;text-overflow:ellipsis;white-space:nowrap;width:80%}.DocSearch-Hit-title{font-size:.9em}.DocSearch-Hit-path{color:var(--docsearch-secondary-text-color);font-size:.75em}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-Tree,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-text,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-title{color:var(--docsearch-text-color)}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-action,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-icon,.DocSearch-Hit[aria-selected=true] mark{color:var(--docsearch-highlight-color)}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{background:#0003;transition:none}}.DocSearch-AskAiScreen,.DocSearch-ErrorScreen,.DocSearch-NoResults,.DocSearch-StartScreen{align-items:center;color:var(--docsearch-secondary-text-color);display:flex;flex-direction:column;font-size:1.25em;font-weight:400;justify-content:center;margin:0 auto;text-align:center;width:80%}.DocSearch-AskAiScreen,.DocSearch-ErrorScreen,.DocSearch-NoResults{max-height:80%}.DocSearch-StartScreen{height:100%}.DocSearch-NoResults{gap:.8em;margin-top:2em}.DocSearch-NoResults--withAskAi{justify-content:flex-start;margin-top:0}.DocSearch-AskAiScreen,.DocSearch-ErrorScreen,.DocSearch-StartScreen{gap:24px}.DocSearch-StartScreen-Icon{height:64px;stroke:var(--docsearch-icon-color);width:64px}.DocSearch-Screen-Icon{color:var(--docsearch-icon-color)}.DocSearch-NoResults-Prefill-List{display:flex;flex-direction:column;gap:12px;text-align:center}.DocSearch-NoResults-Prefill-List-Items{display:flex;flex-direction:column;gap:2px}.DocSearch-NoResults-Prefill-List-Items p{align-items:center;display:flex;margin:0;text-align:left}.DocSearch-Prefill{align-items:center;appearance:none;background:none;border:0;border-radius:1em;color:var(--docsearch-highlight-color);cursor:pointer;display:inline-flex;font-size:.8em;font-weight:300;gap:4px;height:40px;padding:0 4px}.DocSearch-Prefill:focus,.DocSearch-Prefill:hover{outline:none;text-decoration:underline}.DocSearch-Footer{align-items:center;background:var(--docsearch-footer-background);border-radius:0 0 4px 4px;border-top:1px solid var(--docsearch-subtle-color);display:flex;flex-direction:row-reverse;flex-shrink:0;height:var(--docsearch-footer-height);justify-content:space-between;padding:0 var(--docsearch-spacing);position:relative;-webkit-user-select:none;user-select:none;width:100%;z-index:300}.DocSearch-Commands{color:var(--docsearch-muted-color);display:flex;gap:16px;list-style:none;margin:0;padding:0}.DocSearch-Commands li,.DocSearch-Commands-Key{align-items:center;display:flex}.DocSearch-Commands-Key{background-color:var(--docsearch-background-color);border:0;border-radius:2px;box-shadow:none!important;color:var(--docsearch-icon-color);height:24px;justify-content:center;margin-right:4px;width:24px}.DocSearch-Commands-Key:last-of-type{margin-right:8px}.DocSearch-Escape-Key{font-size:10px;font-weight:300;letter-spacing:normal;line-height:16px;text-align:center;text-transform:uppercase}.DocSearch-VisuallyHiddenForAccessibility{clip:rect(0 0 0 0);clip-path:inset(50%);height:1px;overflow:hidden;position:absolute;white-space:nowrap;width:1px}.DocSearch-AskAi-Section{display:flex;flex-direction:column;gap:8px;padding:12px 0}.DocSearch-Hit-AskAIButton{align-items:center;color:var(--docsearch-text-color);display:flex;flex-direction:row}.DocSearch-Hit-AskAIButton-icon{color:var(--docsearch-icon-color);flex-shrink:0;margin-right:12px}.DocSearch-Hit-AskAIButton-title{color:var(--docsearch-hit-color);display:flex;flex:1 1 auto;font-weight:400;gap:4px;overflow-x:hidden;position:relative;text-overflow:ellipsis;white-space:nowrap;width:80%}.DocSearch-Hit-AskAIButton-title-query{background:none;margin-left:4px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.DocSearch-Hit-AskAIButton-title mark{text-decoration:none}@keyframes fade-in{0%{opacity:0}to{opacity:1}}.DocSearch-AskAiScreen-Container{display:flex;flex-direction:column;gap:0;height:100%;justify-content:flex-start;padding:0;text-align:left;width:100%}.DocSearch-AskAiScreen-Disclaimer{align-self:flex-start;display:flex;font-size:.6em;font-weight:300;margin:0;padding:1.5em 0 .5em;text-align:left}.DocSearch-AskAiScreen-Body{gap:24px;width:100%}.DocSearch-AskAiScreen-Body,.DocSearch-AskAiScreen-Response,.DocSearch-AskAiScreen-Response-Container{display:flex;flex-direction:column}.DocSearch-AskAiScreen-Response{align-self:flex-start;background:var(--docsearch-hit-background);border-radius:4px;color:var(--docsearch-text-color);font-size:.8em;gap:1em;margin-bottom:8px;padding:24px;width:100%}.DocSearch-AskAiScreen-Query{font-size:1.25em;font-weight:600;line-break:loose;line-height:1.4;margin:0}.DocSearch-AskAiScreen-Answer{line-height:1.5}.DocSearch-AskAiScreen-Answer,.DocSearch-AskAiScreen-ThinkingDots{color:var(--docsearch-secondary-text-color);font-weight:400;margin:0}.DocSearch-AskAiScreen-ThinkingDots{font-size:.8em}.DocSearch-AskAiScreen-Answer-Footer{align-items:center;display:flex;flex-direction:row;gap:8px;justify-content:space-between}.DocSearch-AskAiScreen-Actions{align-items:center;display:flex;flex-direction:row;gap:12px;margin-left:auto}.DocSearch-AskAiScreen-ActionButton{align-items:center;background:none;border:none;border-radius:4px;cursor:pointer;display:flex;justify-content:center;margin:0;padding:4px;transition:background-color .2s ease;width:24px}.DocSearch-AskAiScreen-ActionButton:hover{background:var(--docsearch-hit-highlight-color)}.DocSearch-AskAiScreen-ActionButton svg{color:var(--docsearch-icon-color);height:20px;stroke-width:1.5;width:20px}.DocSearch-AskAiScreen-CopyButton--copied{background-color:var(--docsearch-success-color);cursor:default}.DocSearch-AskAiScreen-Error{align-items:baseline;background-color:#ef53501a;border-radius:4px;color:var(--docsearch-error-color);display:flex;font-size:1em;font-weight:400;gap:8px;padding:1em}.DocSearch-AskAiScreen-MessageContent{display:flex;flex-direction:column;row-gap:1em}.DocSearch-AskAiScreen-Error svg,.DocSearch-AskAiScreen-MessageContent-Tool svg{flex-shrink:0;height:16px;width:16px}.DocSearch-AskAiScreen-Error p{margin:0}.DocSearch-AskAiScreen-Error .DocSearch-Markdown-Content{color:var(--docsearch-error-color)}.DocSearch-AskAiScreen-FeedbackText{color:var(--docsearch-muted-color);font-size:.7em;font-weight:400;margin:0}.DocSearch-AskAiScreen-FeedbackText--visible{animation:fade-in .3s ease-in forwards}.DocSearch-AskAiScreen-RelatedSources{display:flex;flex-direction:column;gap:4px;width:100%}.DocSearch-AskAiScreen-RelatedSources-List{display:flex;flex-direction:row;flex-wrap:wrap;gap:12px;width:100%}.DocSearch-AskAiScreen-RelatedSources-Title{color:var(--docsearch-secondary-color);font-size:.7em;font-weight:400;margin:0;padding:6px 0}.DocSearch-AskAiScreen-RelatedSources-NoResults{color:var(--docsearch-text-color);font-size:.8rem;font-weight:400;margin:0}.DocSearch-AskAiScreen-RelatedSources-Error{color:var(--docsearch-error-color);font-size:.8rem;font-weight:400;margin:0}.DocSearch-AskAiScreen-RelatedSources-Item-Link{align-items:center;background:var(--docsearch-hit-background);border-radius:4px;color:var(--docsearch-text-color);display:flex;font-size:.75em;gap:6px;max-width:70%;padding:12px 8px;text-decoration:none;transition:background-color .2s ease}.DocSearch-AskAiScreen-RelatedSources-Item-Link svg{color:var(--docsearch-icon-color);flex-shrink:0;stroke-width:1.2}.DocSearch-AskAiScreen-RelatedSources-Item-Link span{flex:1 1 0;font-weight:500;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.DocSearch-AskAiScreen-ExchangesList{display:flex;flex-direction:column;gap:24px;margin:8px 0}.DocSearch-AskAiScreen-RelatedSources-Item-Link:hover{background:var(--docsearch-hit-highlight-color)}.DocSearch-Markdown-Content{color:var(--docsearch-text-color);font-size:.9355em;line-height:1.6;word-wrap:break-word}.DocSearch-Markdown-Content--streaming{animation:fade-in .3s ease-in-out both}.DocSearch-Markdown-Content p{margin:1em 0}.DocSearch-Markdown-Content p:last-child{margin-bottom:0}.DocSearch-Markdown-Content p:first-child{margin-top:0}.DocSearch-Markdown-Content code{border-radius:3px;font-family:ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace;font-size:.9em;letter-spacing:normal;margin:0;padding:.2em 0}.DocSearch-Markdown-Content code,.DocSearch-Markdown-Content pre{background-color:var(--docsearch-key-background);color:var(--docsearch-text-color)}.DocSearch-Markdown-Content pre{border-radius:6px;margin:1.5em 0;overflow-x:auto;padding:1.2em}.DocSearch-Markdown-Content pre code{background-color:transparent;border-radius:0;color:inherit;font-size:.8em;margin:0;padding:0;white-space:pre-wrap;word-wrap:break-word;line-height:1.5}.DocSearch-Markdown-Content h1,.DocSearch-Markdown-Content h2,.DocSearch-Markdown-Content h3,.DocSearch-Markdown-Content h4,.DocSearch-Markdown-Content h5,.DocSearch-Markdown-Content h6{color:var(--docsearch-text-color);font-weight:600;letter-spacing:-.02em;line-height:1.3;margin:1em 0}.DocSearch-Markdown-Content h1{font-size:1.5em}.DocSearch-Markdown-Content h2{font-size:1.2em}.DocSearch-Markdown-Content h3{font-size:1em}.DocSearch-Markdown-Content h4{font-size:.9em}.DocSearch-Markdown-Content h5,.DocSearch-Markdown-Content h6{font-size:.8em}.DocSearch-Markdown-Content ol,.DocSearch-Markdown-Content ul{color:var(--docsearch-text-color);margin:1.2em 0;padding-left:1.5em}.DocSearch-Markdown-Content ul{list-style-type:disc}.DocSearch-Markdown-Content ol{list-style-type:decimal}.DocSearch-Markdown-Content li{color:var(--docsearch-text-color);line-height:1.6;margin:.8em 0;padding-left:.3em}.DocSearch-Markdown-Content li>ol,.DocSearch-Markdown-Content li>ul{margin:.5em}.DocSearch-Markdown-Content li::marker{color:var(--docsearch-muted-color)}.DocSearch-Markdown-Content a{color:var(--docsearch-highlight-color);text-decoration:none;transition:all .2s ease}.DocSearch-Markdown-Content a:hover{opacity:.9;text-decoration:underline}.DocSearch-Markdown-Content blockquote{border-left:4px solid var(--docsearch-hit-highlight-color);color:var(--docsearch-secondary-text-color);font-style:italic;margin:1.5em 0;padding:.5em 0 .5em 1em}.DocSearch-Markdown-Content hr{border:none;border-top:1px solid var(--docsearch-subtle-color);margin:1em 0}.DocSearch-Markdown-Content table{border-collapse:collapse;margin:1.5em 0;width:100%}.DocSearch-Markdown-Content td,.DocSearch-Markdown-Content th{border:1px solid var(--docsearch-subtle-color);padding:.75em;text-align:left}.DocSearch-Markdown-Content th{background-color:var(--docsearch-hit-background);font-weight:600}.DocSearch-AskAiScreen-MessageContent-Reasoning{align-items:center;color:var(--docsearch-muted-color);display:flex;font-size:1em;gap:4px}.DocSearch-AskAiScreen-MessageContent-Reasoning svg{color:var(--docsearch-icon-color)}.DocSearch-AskAiScreen-MessageContent-Tool{align-items:center;color:var(--docsearch-muted-color);display:flex;line-height:1.2;width:100%}.DocSearch-AskAiScreen-MessageContent-Tool.Tool--Result{padding-top:0}.DocSearch-AskAiScreen-MessageContent-Tool>svg{color:var(--docsearch-icon-color);margin-right:8px}.DocSearch-AskAiScreen-MessageContent-Tool-Query{color:var(--docsearch-muted-color);transition:box-shadow .2s ease}.DocSearch-AskAiScreen-MessageContent-Tool-Query svg{color:var(--docsearch-muted-color)}.DocSearch-AskAiScreen-MessageContent-Tool-Query:hover{box-shadow:0 1px 0 0 var(--docsearch-highlight-color);color:var(--docsearch-highlight-color);cursor:pointer}.DocSearch-AskAiScreen-MessageContent-Tool-Query:hover svg{color:var(--docsearch-highlight-color)}.DocSearck-AskAiScreen-MessageContent-Stopped{color:var(--docsearch-muted-color);font-style:italic;margin-top:1em}.DocSearch-AskAiScreen-SmallerLoadingIcon{height:16px;width:16px}.shimmer{background:var(--shimmer-bg);background-clip:text;-webkit-background-clip:text;background-size:200% auto;color:transparent;display:flex;-webkit-text-fill-color:transparent;animation:shimmerText 2.5s linear infinite;pointer-events:none}@keyframes shimmerText{0%{background-position:200% 0}to{background-position:-200% 0}}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes pulse{0%,to{opacity:.3}50%{opacity:.6}}@media(max-width:768px){:root{--docsearch-spacing:10px;--docsearch-footer-height:48px}.DocSearch-Input{font-size:1rem}.DocSearch-Hit-AskAIButton-icon{margin-right:8px}body:has(.DocSearch-Container){overflow:hidden;position:fixed}.DocSearch-Dropdown{height:100%}.DocSearch-Container{height:calc(var(--docsearch-vh, 1vh)*100);height:100dvh}.DocSearch-Footer{border-radius:0;bottom:0;position:static}.DocSearch-Hit-content-wrapper{display:flex;position:relative;width:80%}.DocSearch-Modal{border-radius:0;box-shadow:none;height:calc(var(--docsearch-vh, 1vh)*100);height:100dvh;margin:0;max-width:100%;width:100%}.DocSearch-Dropdown{max-height:none}.DocSearch-Commands,.DocSearch-Hit-Tree{display:none}.DocSearch-AskAiScreen-Response-Container{flex-direction:column}.DocSearch-AskAiScreen-RelatedSources,.DocSearch-AskAiScreen-Response{width:100%}}.DocSearch-CodeSnippet{position:relative}.DocSearch-CodeSnippet-CopyButton{align-items:center;background:var(--docsearch-key-background);border:none;border-radius:4px;color:var(--docsearch-text-color);cursor:pointer;display:flex;font-size:.75em;padding:.2em .6em;position:absolute;right:8px;top:8px;transition:opacity .2s ease}.DocSearch-CodeSnippet-CopyButton:hover{opacity:.8}.DocSearch-CodeSnippet-CopyButton:active{opacity:.6}.DocSearch-CodeSnippet-CopyButton svg{height:16px;margin-right:4px;width:16px}.DocSearch-CodeSnippet-CheckIcon,.DocSearch-CodeSnippet-CopyButton--copied .DocSearch-CodeSnippet-CopyIcon{display:none}.DocSearch-CodeSnippet-CopyButton--copied .DocSearch-CodeSnippet-CheckIcon{display:inline-block}.DocSearch-Markdown-Content--streaming .DocSearch-CodeSnippet-CopyButton{display:none}.DocSearch-NewConversationScreen{padding:3em var(--docsearch-spacing)}.DocSearch-NewConversationScreen-Title{color:var(--docsearch-text-color);font-size:26px;font-weight:600;margin-bottom:.15em}.DocSearch-NewConversationScreen-Description{color:var(--docsearch-muted-color);font-size:14px}.DocSearch-NewConversationScreen-SuggestedQuestions{align-items:start;display:flex;flex-direction:column;gap:var(--docsearch-spacing);margin-top:1.5em}.DocSearch-NewConversationScreen-SuggestedQuestion{align-items:center;background-color:var(--docsearch-searchbox-background);border:1px solid var(--docsearch-subtle-color);border-radius:var(--docsearch-border-radius);color:var(--docsearch-text-color);cursor:pointer;display:inline-flex;height:40px;justify-content:center;padding:12px}.DocSearch-Menu{position:relative}.DocSearch-Menu-content{background-color:var(--docsearch-dropdown-menu-background);border-radius:var(--docsearch-border-radius);box-shadow:0 0 0 1px #21243d0d,0 8px 16px -4px #21243d40;display:none;flex-direction:column;min-width:195px;padding:8px 0;position:absolute;right:0;top:calc(100% + 12px);z-index:422}.DocSearch-Menu-content.open{display:flex}.DocSearch-Menu-item{align-items:center;background-color:transparent;border:0;color:var(--docsearch-text-color);cursor:pointer;display:flex;font-size:14px;gap:8px;padding:10px 16px;white-space:nowrap}.DocSearch-Menu-item:hover{background-color:var(--docsearch-dropdown-menu-item-hover-background)}[class*=DocSearch]{--docsearch-actions-height: auto;--docsearch-actions-width: auto;--docsearch-background-color: var(--vp-c-bg-soft);--docsearch-container-background: var(--vp-backdrop-bg-color);--docsearch-focus-color: var(--vp-c-brand-1);--docsearch-footer-background: var(--vp-c-bg);--docsearch-highlight-color: var(--vp-c-brand-1);--docsearch-hit-background: var(--vp-c-default-soft);--docsearch-hit-color: var(--vp-c-text-1);--docsearch-hit-highlight-color: var(--vp-c-brand-soft);--docsearch-icon-color: var(--vp-c-text-2);--docsearch-key-background: transparent;--docsearch-key-color: var(--vp-c-text-2);--docsearch-modal-background: var(--vp-c-bg-soft);--docsearch-muted-color: var(--vp-c-text-2);--docsearch-primary-color: var(--vp-c-brand-1);--docsearch-searchbox-focus-background: transparent;--docsearch-secondary-text-color: var(--vp-c-text-2);--docsearch-soft-primary-color: var(--vp-c-brand-soft);--docsearch-subtle-color: var(--vp-c-divider);--docsearch-success-color: var(--vp-c-brand-soft);--docsearch-text-color: var(--vp-c-text-1)}.dark [class*=DocSearch]{--docsearch-modal-shadow: none}.DocSearch-Clear{padding:0 8px}.DocSearch-Commands-Key{padding:4px;border:1px solid var(--docsearch-subtle-color);border-radius:4px}.DocSearch-Hit a:focus-visible{outline:2px solid var(--docsearch-focus-color)}.DocSearch-Logo [class^=cls-]{fill:currentColor}.DocSearch-SearchBar+.DocSearch-Footer{border-top-color:transparent}.DocSearch-Title{font-size:revert;line-height:revert}.DocSearch-Button{--docsearch-muted-color: var(--docsearch-text-color);--docsearch-searchbox-background: transparent;width:auto;padding:2px 12px;border:none;border-radius:8px}.DocSearch-Search-Icon{color:inherit!important;width:20px;height:20px}@media(min-width:768px){.DocSearch-Button{--docsearch-muted-color: var(--docsearch-secondary-text-color);--docsearch-searchbox-background: var(--vp-c-bg-alt)}.DocSearch-Search-Icon{width:15px;height:15px}.DocSearch-Button-Placeholder{font-size:13px}}.DocSearch-Button-Keys{min-width:auto;margin:0;padding:4px 6px;background-color:var(--docsearch-key-background);border:1px solid var(--docsearch-subtle-color);border-radius:4px;font-size:12px;line-height:1;color:var(--docsearch-key-color)}.DocSearch-Button-Keys>*{display:none}.DocSearch-Button-Keys:after{direction:ltr;content:"Ctrl K"}.mac .DocSearch-Button-Keys:after{content:"⌘ K"}.VPNavBarSearch{display:flex;align-items:center}@media(min-width:768px){.VPNavBarSearch{flex-grow:1;padding-left:24px}}@media(min-width:960px){.VPNavBarSearch{padding-left:32px}}.VPNavBarSocialLinks[data-v-cd4c0ab6]{display:none}@media(min-width:1280px){.VPNavBarSocialLinks[data-v-cd4c0ab6]{display:flex;align-items:center}}.title[data-v-e5d5fdf8]{display:flex;align-items:center;border-bottom:1px solid transparent;width:100%;height:var(--vp-nav-height);font-size:16px;font-weight:600;color:var(--vp-c-text-1);transition:opacity .25s}@media(min-width:960px){.title[data-v-e5d5fdf8]{flex-shrink:0}.VPNavBarTitle.has-sidebar .title[data-v-e5d5fdf8]{border-bottom-color:var(--vp-c-divider)}}[data-v-e5d5fdf8] .logo{margin-right:8px;height:var(--vp-nav-logo-height)}.VPNavBarTranslations[data-v-1c347a57]{display:none}@media(min-width:1280px){.VPNavBarTranslations[data-v-1c347a57]{display:flex;align-items:center}}.title[data-v-1c347a57]{padding:0 24px 0 12px;line-height:32px;font-size:14px;font-weight:700;color:var(--vp-c-text-1)}.VPNavBar[data-v-a10c09a7]{position:relative;height:var(--vp-nav-height);pointer-events:none;white-space:nowrap;transition:background-color .25s}.VPNavBar.screen-open[data-v-a10c09a7]{transition:none;background-color:var(--vp-nav-bg-color);border-bottom:1px solid var(--vp-c-divider)}.VPNavBar[data-v-a10c09a7]:not(.home){background-color:var(--vp-nav-bg-color)}@media(min-width:960px){.VPNavBar[data-v-a10c09a7]:not(.home){background-color:transparent}.VPNavBar[data-v-a10c09a7]:not(.has-sidebar):not(.home.top){background-color:var(--vp-nav-bg-color)}}.wrapper[data-v-a10c09a7]{padding:0 8px 0 24px}@media(min-width:768px){.wrapper[data-v-a10c09a7]{padding:0 32px}}@media(min-width:960px){.VPNavBar.has-sidebar .wrapper[data-v-a10c09a7]{padding:0}}.container[data-v-a10c09a7]{display:flex;justify-content:space-between;margin:0 auto;max-width:calc(var(--vp-layout-max-width) - 64px);height:var(--vp-nav-height);pointer-events:none}.container>.title[data-v-a10c09a7],.container>.content[data-v-a10c09a7]{pointer-events:none}.container[data-v-a10c09a7] *{pointer-events:auto}@media(min-width:960px){.VPNavBar.has-sidebar .container[data-v-a10c09a7]{max-width:100%}}.title[data-v-a10c09a7]{flex-shrink:0;height:calc(var(--vp-nav-height) - 1px);transition:background-color .5s}@media(min-width:960px){.VPNavBar.has-sidebar .title[data-v-a10c09a7]{position:absolute;top:0;left:0;z-index:2;padding:0 32px;width:var(--vp-sidebar-width);height:var(--vp-nav-height);background-color:transparent}}@media(min-width:1440px){.VPNavBar.has-sidebar .title[data-v-a10c09a7]{padding-left:max(32px,calc((100% - (var(--vp-layout-max-width) - 64px)) / 2));width:calc((100% - (var(--vp-layout-max-width) - 64px)) / 2 + var(--vp-sidebar-width) - 32px)}}.content[data-v-a10c09a7]{flex-grow:1}@media(min-width:960px){.VPNavBar.has-sidebar .content[data-v-a10c09a7]{position:relative;z-index:1;padding-left:var(--vp-sidebar-width)}.VPNavBar.has-sidebar .content-body[data-v-a10c09a7]{padding-right:32px}}@media(min-width:1440px){.VPNavBar.has-sidebar .content[data-v-a10c09a7]{padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}.VPNavBar.has-sidebar .content-body[data-v-a10c09a7]{padding-right:calc((100vw - var(--vp-layout-max-width)) / 2 + 32px)}}.content-body[data-v-a10c09a7]{display:flex;justify-content:flex-end;align-items:center;height:var(--vp-nav-height);transition:background-color .5s}@media(min-width:960px){.VPNavBar:not(.home.top) .content-body[data-v-a10c09a7]{position:relative;background-color:var(--vp-nav-bg-color)}.VPNavBar:not(.has-sidebar):not(.home.top) .content-body[data-v-a10c09a7]{background-color:transparent}}@media(max-width:767px){.content-body[data-v-a10c09a7]{column-gap:.5rem}}.menu+.translations[data-v-a10c09a7]:before,.menu+.appearance[data-v-a10c09a7]:before,.menu+.social-links[data-v-a10c09a7]:before,.translations+.appearance[data-v-a10c09a7]:before,.appearance+.social-links[data-v-a10c09a7]:before{margin-right:8px;margin-left:8px;width:1px;height:24px;background-color:var(--vp-c-divider);content:""}.menu+.appearance[data-v-a10c09a7]:before,.translations+.appearance[data-v-a10c09a7]:before{margin-right:16px}.appearance+.social-links[data-v-a10c09a7]:before{margin-left:16px}.social-links[data-v-a10c09a7]{margin-right:-8px}.divider[data-v-a10c09a7]{width:100%;height:1px}@media(min-width:960px){.VPNavBar.has-sidebar .divider[data-v-a10c09a7]{padding-left:var(--vp-sidebar-width)}}@media(min-width:1440px){.VPNavBar.has-sidebar .divider[data-v-a10c09a7]{padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.divider-line[data-v-a10c09a7]{width:100%;height:1px;transition:background-color .5s}.VPNavBar:not(.home) .divider-line[data-v-a10c09a7]{background-color:var(--vp-c-gutter)}@media(min-width:960px){.VPNavBar:not(.home.top) .divider-line[data-v-a10c09a7]{background-color:var(--vp-c-gutter)}.VPNavBar:not(.has-sidebar):not(.home.top) .divider[data-v-a10c09a7]{background-color:var(--vp-c-gutter)}}.VPNavScreenAppearance[data-v-0c49eb9f]{display:flex;justify-content:space-between;align-items:center;border-radius:8px;padding:12px 14px 12px 16px;background-color:var(--vp-c-bg-soft)}.text[data-v-0c49eb9f]{line-height:24px;font-size:12px;font-weight:500;color:var(--vp-c-text-2)}.VPNavScreenMenuLink[data-v-f0c07abe]{display:block;border-bottom:1px solid var(--vp-c-divider);padding:12px 0 11px;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:border-color .25s,color .25s}.VPNavScreenMenuLink[data-v-f0c07abe]:hover{color:var(--vp-c-brand-1)}.VPNavScreenMenuGroupLink[data-v-1c460cf9]{display:block;margin-left:12px;line-height:32px;font-size:14px;font-weight:400;color:var(--vp-c-text-1);transition:color .25s}.VPNavScreenMenuGroupLink[data-v-1c460cf9]:hover{color:var(--vp-c-brand-1)}.VPNavScreenMenuGroupSection[data-v-b9d15d51]{display:block}.title[data-v-b9d15d51]{line-height:32px;font-size:13px;font-weight:700;color:var(--vp-c-text-2);transition:color .25s}.VPNavScreenMenuGroup[data-v-8ab0c53a]{border-bottom:1px solid var(--vp-c-divider);height:48px;overflow:hidden;transition:border-color .5s}.VPNavScreenMenuGroup .items[data-v-8ab0c53a]{visibility:hidden}.VPNavScreenMenuGroup.open .items[data-v-8ab0c53a]{visibility:visible}.VPNavScreenMenuGroup.open[data-v-8ab0c53a]{padding-bottom:10px;height:auto}.VPNavScreenMenuGroup.open .button[data-v-8ab0c53a]{padding-bottom:6px;color:var(--vp-c-brand-1)}.VPNavScreenMenuGroup.open .button-icon[data-v-8ab0c53a]{transform:rotate(45deg)}.button[data-v-8ab0c53a]{display:flex;justify-content:space-between;align-items:center;padding:12px 4px 11px 0;width:100%;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.button[data-v-8ab0c53a]:hover{color:var(--vp-c-brand-1)}.button-icon[data-v-8ab0c53a]{transition:transform .25s}.group[data-v-8ab0c53a]:first-child{padding-top:0}.group+.group[data-v-8ab0c53a],.group+.item[data-v-8ab0c53a]{padding-top:4px}.VPNavScreenTranslations[data-v-85de7b6f]{height:24px;overflow:hidden}.VPNavScreenTranslations.open[data-v-85de7b6f]{height:auto}.title[data-v-85de7b6f]{display:flex;align-items:center;font-size:14px;font-weight:500;color:var(--vp-c-text-1)}.icon[data-v-85de7b6f]{font-size:16px}.icon.lang[data-v-85de7b6f]{margin-right:8px}.icon.chevron[data-v-85de7b6f]{margin-left:4px}.list[data-v-85de7b6f]{padding:4px 0 0 24px}.link[data-v-85de7b6f]{line-height:32px;font-size:13px;color:var(--vp-c-text-1)}.VPNavScreen[data-v-e0c26501]{position:fixed;top:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px));right:0;bottom:0;left:0;padding:0 32px;width:100%;background-color:var(--vp-nav-screen-bg-color);overflow-y:auto;transition:background-color .25s;pointer-events:auto}.VPNavScreen.fade-enter-active[data-v-e0c26501],.VPNavScreen.fade-leave-active[data-v-e0c26501]{transition:opacity .25s}.VPNavScreen.fade-enter-active .container[data-v-e0c26501],.VPNavScreen.fade-leave-active .container[data-v-e0c26501]{transition:transform .25s ease}.VPNavScreen.fade-enter-from[data-v-e0c26501],.VPNavScreen.fade-leave-to[data-v-e0c26501]{opacity:0}.VPNavScreen.fade-enter-from .container[data-v-e0c26501],.VPNavScreen.fade-leave-to .container[data-v-e0c26501]{transform:translateY(-8px)}@media(min-width:768px){.VPNavScreen[data-v-e0c26501]{display:none}}.container[data-v-e0c26501]{margin:0 auto;padding:24px 0 96px;max-width:288px}.menu+.translations[data-v-e0c26501],.menu+.appearance[data-v-e0c26501],.translations+.appearance[data-v-e0c26501]{margin-top:24px}.menu+.social-links[data-v-e0c26501]{margin-top:16px}.appearance+.social-links[data-v-e0c26501]{margin-top:16px}.VPNav[data-v-d78ad477]{position:relative;top:var(--vp-layout-top-height, 0px);left:0;z-index:var(--vp-z-index-nav);width:100%;pointer-events:none;transition:background-color .5s}@media(min-width:960px){.VPNav[data-v-d78ad477]{position:fixed}}.VPSidebarItem.level-0[data-v-c0d2b08d]{padding-bottom:24px}.VPSidebarItem.collapsed.level-0[data-v-c0d2b08d]{padding-bottom:10px}.item[data-v-c0d2b08d]{position:relative;display:flex;width:100%}.VPSidebarItem.collapsible>.item[data-v-c0d2b08d]{cursor:pointer}.indicator[data-v-c0d2b08d]{position:absolute;top:6px;bottom:6px;left:-17px;width:2px;border-radius:2px;transition:background-color .25s}.VPSidebarItem.level-2.is-active>.item>.indicator[data-v-c0d2b08d],.VPSidebarItem.level-3.is-active>.item>.indicator[data-v-c0d2b08d],.VPSidebarItem.level-4.is-active>.item>.indicator[data-v-c0d2b08d],.VPSidebarItem.level-5.is-active>.item>.indicator[data-v-c0d2b08d]{background-color:var(--vp-c-brand-1)}.link[data-v-c0d2b08d]{display:flex;align-items:center;flex-grow:1}.text[data-v-c0d2b08d]{flex-grow:1;padding:4px 0;line-height:24px;font-size:14px;transition:color .25s}.VPSidebarItem.level-0 .text[data-v-c0d2b08d]{font-weight:700;color:var(--vp-c-text-1)}.VPSidebarItem.level-1 .text[data-v-c0d2b08d],.VPSidebarItem.level-2 .text[data-v-c0d2b08d],.VPSidebarItem.level-3 .text[data-v-c0d2b08d],.VPSidebarItem.level-4 .text[data-v-c0d2b08d],.VPSidebarItem.level-5 .text[data-v-c0d2b08d]{font-weight:500;color:var(--vp-c-text-2)}.VPSidebarItem.level-0.is-link>.item>.link:hover .text[data-v-c0d2b08d],.VPSidebarItem.level-1.is-link>.item>.link:hover .text[data-v-c0d2b08d],.VPSidebarItem.level-2.is-link>.item>.link:hover .text[data-v-c0d2b08d],.VPSidebarItem.level-3.is-link>.item>.link:hover .text[data-v-c0d2b08d],.VPSidebarItem.level-4.is-link>.item>.link:hover .text[data-v-c0d2b08d],.VPSidebarItem.level-5.is-link>.item>.link:hover .text[data-v-c0d2b08d]{color:var(--vp-c-brand-1)}.VPSidebarItem.level-0.has-active>.item>.text[data-v-c0d2b08d],.VPSidebarItem.level-1.has-active>.item>.text[data-v-c0d2b08d],.VPSidebarItem.level-2.has-active>.item>.text[data-v-c0d2b08d],.VPSidebarItem.level-3.has-active>.item>.text[data-v-c0d2b08d],.VPSidebarItem.level-4.has-active>.item>.text[data-v-c0d2b08d],.VPSidebarItem.level-5.has-active>.item>.text[data-v-c0d2b08d],.VPSidebarItem.level-0.has-active>.item>.link>.text[data-v-c0d2b08d],.VPSidebarItem.level-1.has-active>.item>.link>.text[data-v-c0d2b08d],.VPSidebarItem.level-2.has-active>.item>.link>.text[data-v-c0d2b08d],.VPSidebarItem.level-3.has-active>.item>.link>.text[data-v-c0d2b08d],.VPSidebarItem.level-4.has-active>.item>.link>.text[data-v-c0d2b08d],.VPSidebarItem.level-5.has-active>.item>.link>.text[data-v-c0d2b08d]{color:var(--vp-c-text-1)}.VPSidebarItem.level-0.is-active>.item .link>.text[data-v-c0d2b08d],.VPSidebarItem.level-1.is-active>.item .link>.text[data-v-c0d2b08d],.VPSidebarItem.level-2.is-active>.item .link>.text[data-v-c0d2b08d],.VPSidebarItem.level-3.is-active>.item .link>.text[data-v-c0d2b08d],.VPSidebarItem.level-4.is-active>.item .link>.text[data-v-c0d2b08d],.VPSidebarItem.level-5.is-active>.item .link>.text[data-v-c0d2b08d]{color:var(--vp-c-brand-1)}.caret[data-v-c0d2b08d]{display:flex;justify-content:center;align-items:center;margin-right:-7px;width:32px;height:32px;color:var(--vp-c-text-3);cursor:pointer;transition:color .25s;flex-shrink:0}.item:hover .caret[data-v-c0d2b08d]{color:var(--vp-c-text-2)}.item:hover .caret[data-v-c0d2b08d]:hover{color:var(--vp-c-text-1)}.caret-icon[data-v-c0d2b08d]{font-size:18px;transform:rotate(90deg);transition:transform .25s}.VPSidebarItem.collapsed .caret-icon[data-v-c0d2b08d]{transform:rotate(0)}.VPSidebarItem.level-1 .items[data-v-c0d2b08d],.VPSidebarItem.level-2 .items[data-v-c0d2b08d],.VPSidebarItem.level-3 .items[data-v-c0d2b08d],.VPSidebarItem.level-4 .items[data-v-c0d2b08d],.VPSidebarItem.level-5 .items[data-v-c0d2b08d]{border-left:1px solid var(--vp-c-divider);padding-left:16px}.VPSidebarItem.collapsed .items[data-v-c0d2b08d]{display:none}.no-transition[data-v-3423a55b] .caret-icon{transition:none}.group+.group[data-v-3423a55b]{border-top:1px solid var(--vp-c-divider);padding-top:10px}@media(min-width:960px){.group[data-v-3423a55b]{padding-top:10px;width:calc(var(--vp-sidebar-width) - 64px)}}.VPSidebar[data-v-3ad41a46]{position:fixed;top:var(--vp-layout-top-height, 0px);bottom:0;left:0;z-index:var(--vp-z-index-sidebar);padding:32px 32px 96px;width:calc(100vw - 64px);max-width:320px;background-color:var(--vp-sidebar-bg-color);opacity:0;box-shadow:var(--vp-c-shadow-3);overflow-x:hidden;overflow-y:auto;transform:translate(-100%);transition:opacity .5s,transform .25s ease;overscroll-behavior:contain}.VPSidebar.open[data-v-3ad41a46]{opacity:1;visibility:visible;transform:translate(0);transition:opacity .25s,transform .5s cubic-bezier(.19,1,.22,1)}.dark .VPSidebar[data-v-3ad41a46]{box-shadow:var(--vp-shadow-1)}@media(min-width:960px){.VPSidebar[data-v-3ad41a46]{padding-top:var(--vp-nav-height);width:var(--vp-sidebar-width);max-width:100%;background-color:var(--vp-sidebar-bg-color);opacity:1;visibility:visible;box-shadow:none;transform:translate(0)}}@media(min-width:1440px){.VPSidebar[data-v-3ad41a46]{padding-left:max(32px,calc((100vw - (var(--vp-layout-max-width) - 64px)) / 2));width:calc((100vw - (var(--vp-layout-max-width) - 64px)) / 2 + var(--vp-sidebar-width) - 32px)}}@media(min-width:960px){.curtain[data-v-3ad41a46]{position:sticky;top:calc(var(--vp-nav-height) * -1);left:0;z-index:1;margin-top:calc(var(--vp-nav-height) * -1);margin-right:-32px;margin-left:-32px;height:var(--vp-nav-height);background-color:var(--vp-sidebar-bg-color)}}.nav[data-v-3ad41a46]{outline:0}.VPSkipLink[data-v-84877a60]{position:fixed;top:8px;left:8px;padding:8px 16px;z-index:999;border-radius:8px;font-size:12px;font-weight:700;text-decoration:none;color:var(--vp-c-brand-1);box-shadow:var(--vp-shadow-3);background-color:var(--vp-c-bg)}.VPSkipLink[data-v-84877a60]:focus{height:auto;width:auto;clip:auto;clip-path:none}@media(min-width:1280px){.VPSkipLink[data-v-84877a60]{top:14px;left:16px}}.Layout[data-v-e9f8e490]{display:flex;flex-direction:column;min-height:100vh}.tk-copy-banner{background:var(--vp-c-brand-1);left:0;overflow:hidden;position:fixed;text-align:center;top:0;transform:translateY(-100%);transition:transform 1s ease,opacity 1s ease;width:100%;z-index:9999}.tk-copy-banner__content{-webkit-backdrop-filter:blur(5px);backdrop-filter:blur(5px);padding:16px;position:relative;z-index:2}@media(max-width:768px){.tk-copy-banner__content{padding:10px}}.tk-copy-banner__desc{color:#fff;font-size:19px;font-weight:700}@media(max-width:768px){.tk-copy-banner__desc{font-size:16px}}.tk-copy-banner__slide{animation:remove-corner 2s ease-in-out forwards;background-color:var(--vp-c-brand-2);border-bottom-right-radius:25px;border-top-right-radius:25px;height:100%;left:0;position:absolute;top:0;transition:width 2s ease-in-out;width:0;z-index:1}.tk-copy-banner.is-show{transform:translateY(0)}.tk-copy-banner.is-hide{opacity:0;transform:translateY(-100%)}.tk-copy-banner.is-hide .slide-block{border-radius:0;width:100%}@keyframes remove-corner{0%{border-bottom-right-radius:25px;border-top-right-radius:25px}80%{border-bottom-right-radius:15px;border-top-right-radius:15px}to{border-bottom-right-radius:0;border-top-right-radius:0}}.tk-article-page.tk-archives{width:1220px}.tk-archives .contribute__chart{width:100%;height:260px}.tk-archives .contribute__chart .chart__box{margin:auto;width:100%;height:100%}.error-page[data-v-9553caa6]{width:100%;height:calc(100vh - var(--vp-nav-height));gap:120px}.error-page__detail h2[data-v-9553caa6]{font-size:60px;color:var(--vp-c-text-1);line-height:1}.error-page__detail h4[data-v-9553caa6]{margin:10px 0 20px;font-size:19px;font-weight:400;color:var(--vp-c-text-2)}.error-page__detail button[data-v-9553caa6]{color:#fff;background-color:#395ae3;box-shadow:0 2px #0591ff1a;font-size:14px;width:100px;height:32px;padding:4px 15px;border-radius:6px;outline:none;position:relative;display:inline-block;font-weight:400;white-space:nowrap;text-align:center;background-image:none;border:1px solid transparent;cursor:pointer;transition:all .2s cubic-bezier(.645,.045,.355,1);-webkit-user-select:none;user-select:none;touch-action:manipulation;line-height:1.5714285714}.error-page__detail button[data-v-9553caa6]:hover{background-color:#5a79f4}@media(max-width:768px){.error-page[data-v-9553caa6]{flex-direction:column;gap:60px;transform:translateY(-10%)}.error-page__detail[data-v-9553caa6]{align-items:center}}.contact-card[data-v-4b99f778]{--link-bg: #f0f2f5;--link-bg-hover: #e8eaed;--text-primary: #333;--text-secondary: #666;--accent-color: var(--vp-c-brand-1)}html.dark .contact-card[data-v-4b99f778]{--link-bg: #2a2d31;--link-bg-hover: #36393f;--text-primary: #e5e7eb;--text-secondary: #9ca3af}.contact-description[data-v-4b99f778]{margin-bottom:16px;text-align:center}.contact-description p[data-v-4b99f778]{color:var(--text-secondary);font-size:14px;margin:0}.contact-links[data-v-4b99f778]{display:flex;flex-direction:column;gap:8px}.contact-link[data-v-4b99f778]{display:flex;align-items:center;padding:12px 16px;background-color:var(--link-bg);border-radius:8px;text-decoration:none;color:var(--text-primary);transition:all .2s ease;gap:12px}.contact-link[data-v-4b99f778]:hover{background-color:var(--link-bg-hover);transform:translate(4px)}.contact-icon[data-v-4b99f778]{display:flex;align-items:center;justify-content:center;width:24px;height:24px}.contact-icon[data-v-4b99f778] svg{width:20px;height:20px}.contact-name[data-v-4b99f778]{flex:1;font-size:15px;font-weight:500}.contact-arrow[data-v-4b99f778]{color:var(--accent-color);opacity:0;transform:translate(-8px);transition:all .2s ease;font-size:14px}.contact-link:hover .contact-arrow[data-v-4b99f778]{opacity:1;transform:translate(0)}.contact-footer[data-v-4b99f778]{margin-top:16px;text-align:center;padding-top:12px;border-top:1px dashed var(--link-bg-hover)}.contact-footer p[data-v-4b99f778]{color:var(--text-secondary);font-size:13px;margin:0}@media(max-width:768px){.contact-link[data-v-4b99f778]{padding:10px 14px}.contact-name[data-v-4b99f778]{font-size:14px}}.wechat-modal-overlay[data-v-4b99f778]{position:fixed;inset:0;background-color:#0009;display:flex;align-items:center;justify-content:center;z-index:9999;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.wechat-modal[data-v-4b99f778]{background-color:var(--vp-c-bg);border-radius:12px;max-width:320px;width:90%;box-shadow:0 20px 40px #0000004d;overflow:hidden;animation:modalSlideIn-4b99f778 .3s ease}@keyframes modalSlideIn-4b99f778{0%{opacity:0;transform:scale(.9) translateY(-20px)}to{opacity:1;transform:scale(1) translateY(0)}}.wechat-modal-header[data-v-4b99f778]{display:flex;align-items:center;justify-content:space-between;padding:16px 20px;border-bottom:1px solid var(--vp-c-divider);font-weight:600;font-size:16px}.wechat-modal-close[data-v-4b99f778]{background:none;border:none;font-size:24px;cursor:pointer;color:var(--vp-c-text-2);line-height:1;padding:0;transition:color .2s}.wechat-modal-close[data-v-4b99f778]:hover{color:var(--vp-c-text-1)}.wechat-modal-body[data-v-4b99f778]{padding:20px;text-align:center;display:flex;justify-content:center}.wechat-qrcode[data-v-4b99f778]{max-width:200px;border-radius:8px;border:1px solid var(--vp-c-divider)}.wechat-placeholder[data-v-4b99f778]{color:var(--vp-c-text-2);font-size:14px;margin:0}.tk-my.is-circle-bg{margin-bottom:20px}.tk-my.is-circle-bg .tk-my__avatar.circle-rotate{margin-top:200px}.tk-pointer{cursor:pointer}.tk-center{left:50%;position:absolute;top:50%;transform:translate(-50%,-50%)}.VPBadge.success{background-color:var(--tk-el-color-success-light-9);border-color:var(--tk-el-color-success-light-8);color:var(--tk-el-color-success)}.hover-color{cursor:pointer!important;transition:color var(--tk-transition-duration-fast)}.hover-color:hover{color:var(--tk-theme-color)}.scroll__animate{opacity:0;transform:translateY(20px)}.scroll__animate.visible{opacity:1;transform:translateY(0);transition:opacity .6s ease-out,transform .7s ease-out}.skeleton-image:has(:not(.loaded)){animation:skeleton-loading 1.4s ease infinite;background-image:linear-gradient(90deg,var(--tk-fill-color-dark) 25%,var(--tk-bg-color) 37%,var(--tk-fill-color-dark) 63%);background-size:400% 100%}.skeleton-image:has(:not(.loaded))>img{background-color:var(--tk-bg-color);filter:blur(10px);opacity:0;transition:filter .3s,opacity .3s}.skeleton-image:has(:not(.loaded))>img.loaded{filter:blur(0);opacity:1}@keyframes skeleton-loading{0%{background-position:100% 50%}to{background-position:0 50%}}.flx,.flx-column{display:flex}.flx-column{flex-direction:column}.flx-center,.flx-column-center{align-items:center;display:flex;justify-content:center}.flx-column-center{flex-direction:column}.flx-align-center{align-items:center;display:flex}.flx-justify-center{display:flex;justify-content:center}.flx-justify-between{align-items:center;display:flex;justify-content:space-between}.flx-justify-around{align-items:center;display:flex;justify-content:space-around}.flx-start-justify-center{align-items:flex-start;display:flex;justify-content:center}.flx-wrap-between{display:flex;flex-wrap:wrap;justify-content:space-between}.flx-wrap-justify-center{display:flex;flex-wrap:wrap;justify-content:center}.flx-1{flex:1}.flx-wrap{flex-wrap:wrap}.flx-space-y-20{display:flex;flex-direction:column;gap:20px}.sle{white-space:nowrap}.mle,.sle{overflow:hidden;text-overflow:ellipsis}.mle{display:-webkit-box;-webkit-box-orient:vertical;line-clamp:2;-webkit-line-clamp:2}.display-none{display:none!important}*{scrollbar-color:#f5f7fa}::-webkit-scrollbar{width:6px}::-webkit-scrollbar:horizontal{height:6px}::-webkit-scrollbar-track{border-radius:10px}::-webkit-scrollbar-thumb{background-color:#0003;border-radius:10px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}::-webkit-scrollbar-thumb:hover{background-color:#0000004d;cursor:pointer}.dark ::-webkit-scrollbar-thumb{background-color:#fff3}.dark ::-webkit-scrollbar-thumb:hover{background-color:#fff6}.tk-collapse-transition-enter-active,.tk-collapse-transition-leave-active{transition:max-height .3s ease-in-out,padding-top .3s ease-in-out,padding-bottom .3s ease-in-out}::view-transition-new(root),::view-transition-old(root){animation:none;mix-blend-mode:normal}html[view-transition=out-in].dark::view-transition-new(root),html[view-transition=out-in]::view-transition-old(root){z-index:1}html[view-transition=out-in].dark::view-transition-old(root),html[view-transition=out-in]::view-transition-new(root){z-index:9999}.tk-fade-scale-enter-active,.tk-fade-scale-leave-active{transition:opacity .3s cubic-bezier(.55,0,.1,1),transform .3s cubic-bezier(.55,0,.1,1)}.tk-fade-scale-enter-from,.tk-fade-scale-leave-to{opacity:0;transform:scale(.8)}.tk-fade-enter-active,.tk-fade-leave-active{transition:opacity .3s cubic-bezier(.55,0,.1,1)}.tk-fade-enter-from,.tk-fade-leave-to{opacity:0}.tk-fade-linear-enter-active,.tk-fade-linear-leave-active{transition:opacity .2s linear}.tk-fade-linear-enter-from,.tk-fade-linear-leave-to{opacity:0}.tk-slide-next-enter-active,.tk-slide-next-leave-active,.tk-slide-next-move{transition:opacity .5s ease,transform .5s ease}.tk-slide-next-enter-from{opacity:0;transform:translate(100%)}.tk-slide-next-leave-to{opacity:0;transform:translate(-100%)}.tk-slide-next-leave-active{position:absolute}.tk-slide-prev-enter-active,.tk-slide-prev-leave-active,.tk-slide-prev-move{transition:opacity .5s ease,transform .5s ease}.tk-slide-prev-enter-from{opacity:0;transform:translate(-100%)}.tk-slide-prev-leave-to{opacity:0;transform:translate(100%)}.tk-slide-prev-leave-active{position:absolute}.tk-slide-fade-enter-active,.tk-slide-fade-leave-active,.tk-slide-fade-move{transition:opacity .3s ease,transform .3s ease}.tk-slide-fade-enter-from{opacity:0;transform:translate(-20px)}.tk-slide-fade-leave-to{display:none;transform:translate(0)}.tk-scroll-enter-active,.tk-scroll-leave-active,.tk-scroll-move{transition:opacity .5s ease,transform .5s ease}.tk-scroll-enter-from{opacity:0;transform:translateY(70px)}.tk-scroll-leave-to{opacity:0;transform:translateY(-30px)}.tk-scroll-leave-active{position:absolute}:root{--tk-theme-color:var(--vp-c-brand-1);--tk-line-color:rgba(0,0,0,.12);--tk-text-color-regular:var(--vp-c-text-2);--tk-text-color-secondary:#86909c;--tk-text-color-placeholder:#a8abb2;--tk-text-color-disabled:#c0c4cc;--tk-bg-color:var(--vp-c-bg);--tk-bg-color-elm:var(--vp-c-bg-elv);--tk-bg-color-mute:#f4f4f4;--tk-fill-color:#f0f2f5;--tk-fill-color-blank:#fff;--tk-fill-color-light:#f5f7fa;--tk-fill-color-dark:#ebedf0;--tk-card-shadow:0 2px 10px 2px rgba(0,0,0,.1);--tk-hover-shadow:0 1px 16px 4px rgba(0,0,0,.2);--tk-home-bg-color:#fff;--tk-transition-duration:.3s;--tk-transition-duration-fast:.2s;--tk-transition-duration-slow:.5s;--tk-transition-duration-slow-plus:.6s}:root.dark{--tk-theme-color:var(--vp-c-brand-1);--tk-line-color:rgba(0,0,0,.12);--tk-text-color-regular:var(--vp-c-text-2);--tk-text-color-secondary:#9facba;--tk-text-color-placeholder:#8d9095;--tk-text-color-disabled:#6c6e72;--tk-bg-color:var(--vp-c-bg);--tk-bg-color-elm:var(--vp-c-bg-elv);--tk-bg-color-mute:#27272b;--tk-fill-color:#303030;--tk-fill-color-blank:transparent;--tk-fill-color-light:#262727;--tk-fill-color-dark:#2c2f35;--tk-card-shadow:0 2px 10px 2px hsla(0,0%,100%,.12);--tk-hover-shadow:0 3px 12px 3px hsla(0,0%,100%,.2);--tk-home-bg-color:#1b1b1f}:root{--tk-gap1:10px;--tk-gap2:20px;--tk-gap3:30px;--tk-el-color-primary:#409eff;--tk-el-color-primary-light-3:#79bbff;--tk-el-color-primary-light-5:#a0cfff;--tk-el-color-primary-light-7:#c6e2ff;--tk-el-color-primary-light-8:#d9ecff;--tk-el-color-primary-light-9:#ecf5ff;--tk-el-color-primary-dark-2:#337ecc;--tk-el-color-success:#67c23a;--tk-el-color-success-light-3:#95d475;--tk-el-color-success-light-5:#b3e19d;--tk-el-color-success-light-7:#d1edc4;--tk-el-color-success-light-8:#e1f3d8;--tk-el-color-success-light-9:#f0f9eb;--tk-el-color-success-dark-2:#529b2e;--tk-el-color-warning:#e6a23c;--tk-el-color-warning-light-3:#eebe77;--tk-el-color-warning-light-5:#f3d19e;--tk-el-color-warning-light-7:#f8e3c5;--tk-el-color-warning-light-8:#faecd8;--tk-el-color-warning-light-9:#fdf6ec;--tk-el-color-warning-dark-2:#b88230;--tk-el-color-danger:#f56c6c;--tk-el-color-danger-light-3:#f89898;--tk-el-color-danger-light-5:#fab6b6;--tk-el-color-danger-light-7:#fcd3d3;--tk-el-color-danger-light-8:#fde2e2;--tk-el-color-danger-light-9:#fef0f0;--tk-el-color-danger-dark-2:#c45656;--tk-el-color-error:#f56c6c;--tk-el-color-error-light-3:#f89898;--tk-el-color-error-light-5:#fab6b6;--tk-el-color-error-light-7:#fcd3d3;--tk-el-color-error-light-8:#fde2e2;--tk-el-color-error-light-9:#fef0f0;--tk-el-color-error-dark-2:#c45656;--tk-el-color-info:#909399;--tk-el-color-info-light-3:#b1b3b8;--tk-el-color-info-light-5:#c8c9cc;--tk-el-color-info-light-7:#dedfe0;--tk-el-color-info-light-8:#e9e9eb;--tk-el-color-info-light-9:#f4f4f5;--tk-el-color-info-dark-2:#73767a}:root.dark{--tk-el-color-primary:#409eff;--tk-el-color-primary-light-3:#3375b9;--tk-el-color-primary-light-5:#2a598a;--tk-el-color-primary-light-7:#213d5b;--tk-el-color-primary-light-8:#1d3043;--tk-el-color-primary-light-9:#18222c;--tk-el-color-primary-dark-2:#66b1ff;--tk-el-color-success:#67c23a;--tk-el-color-success-light-3:#4e8e2f;--tk-el-color-success-light-5:#3e6b27;--tk-el-color-success-light-7:#2d481f;--tk-el-color-success-light-8:#25371c;--tk-el-color-success-light-9:#1c2518;--tk-el-color-success-dark-2:#85ce61;--tk-el-color-warning:#e6a23c;--tk-el-color-warning-light-3:#a77730;--tk-el-color-warning-light-5:#7d5b28;--tk-el-color-warning-light-7:#533f20;--tk-el-color-warning-light-8:#3e301c;--tk-el-color-warning-light-9:#292218;--tk-el-color-warning-dark-2:#ebb563;--tk-el-color-danger:#f56c6c;--tk-el-color-danger-light-3:#b25252;--tk-el-color-danger-light-5:#854040;--tk-el-color-danger-light-7:#582e2e;--tk-el-color-danger-light-8:#412626;--tk-el-color-danger-light-9:#2b1d1d;--tk-el-color-danger-dark-2:#f78989;--tk-el-color-error:#f56c6c;--tk-el-color-error-light-3:#b25252;--tk-el-color-error-light-5:#854040;--tk-el-color-error-light-7:#582e2e;--tk-el-color-error-light-8:#412626;--tk-el-color-error-light-9:#2b1d1d;--tk-el-color-error-dark-2:#f78989;--tk-el-color-info:#909399;--tk-el-color-info-light-3:#6b6d71;--tk-el-color-info-light-5:#525457;--tk-el-color-info-light-7:#393a3c;--tk-el-color-info-light-8:#2d2d2f;--tk-el-color-info-light-9:#202121;--tk-el-color-info-dark-2:#a6a9ad}html[theme-color=vp-green]{--vp-c-brand-1:var(--vp-c-green-1);--vp-c-brand-2:var(--vp-c-green-2);--vp-c-brand-3:var(--vp-c-green-3);--vp-c-brand-soft:var(--vp-c-green-soft)}html[theme-color=vp-yellow]{--vp-c-brand-1:var(--vp-c-yellow-1);--vp-c-brand-2:var(--vp-c-yellow-2);--vp-c-brand-3:var(--vp-c-yellow-3);--vp-c-brand-soft:var(--vp-c-yellow-soft)}html[theme-color=vp-red]{--vp-c-brand-1:var(--vp-c-red-1);--vp-c-brand-2:var(--vp-c-red-2);--vp-c-brand-3:var(--vp-c-red-3);--vp-c-brand-soft:var(--vp-c-red-soft)}html[theme-color=ep-blue]{--vp-c-brand-1:var(--tk-el-color-primary);--vp-c-brand-2:var(--tk-el-color-primary-light-3);--vp-c-brand-3:var(--tk-el-color-primary-light-5);--vp-c-brand-soft:var(--tk-el-color-primary-light-8)}html[theme-color=ep-green]{--vp-c-brand-1:var(--tk-el-color-success);--vp-c-brand-2:var(--tk-el-color-success-light-3);--vp-c-brand-3:var(--tk-el-color-success-light-5);--vp-c-brand-soft:var(--tk-el-color-success-light-8)}html[theme-color=ep-yellow]{--vp-c-brand-1:var(--tk-el-color-warning);--vp-c-brand-2:var(--tk-el-color-warning-light-3);--vp-c-brand-3:var(--tk-el-color-warning-light-5);--vp-c-brand-soft:var(--tk-el-color-warning-light-8)}html[theme-color=ep-red]{--vp-c-brand-1:var(--tk-el-color-danger);--vp-c-brand-2:var(--tk-el-color-danger-light-3);--vp-c-brand-3:var(--tk-el-color-danger-light-5);--vp-c-brand-soft:var(--tk-el-color-danger-light-8)}html[tk-theme-size=wide]{--tk-home-max-width:1420px;--tk-home-gap:var(--tk-gap3);--tk-home-post-simple-img-width:160px;--tk-home-post-full-img-width:480px;--tk-home-post-full-img-height:100%;--tk-home-post-line-clamp:4;--tk-home-card-padding:15px;--tk-home-card-width:350px;--tk-home-card-svg-margin-left:10px;--tk-home-font-size-large:19px;--tk-home-font-size-base:17px;--tk-home-font-size-middle:15px;--tk-home-font-size-sm:14px;--tk-home-font-size-small:13px;--tk-home-page-width:1100px;--tk-home-footer-group-width:100%}html[tk-theme-size=large]{--tk-home-max-width:1330px;--tk-home-gap:var(--tk-gap3);--tk-home-post-simple-img-width:160px;--tk-home-post-full-img-width:420px;--tk-home-post-full-img-height:100%;--tk-home-post-line-clamp:4;--tk-home-card-padding:15px;--tk-home-card-width:350px;--tk-home-card-svg-margin-left:10px;--tk-home-font-size-large:19px;--tk-home-font-size-base:17px;--tk-home-font-size-middle:15px;--tk-home-font-size-sm:14px;--tk-home-font-size-small:13px;--tk-home-page-width:1000px;--tk-home-footer-group-width:90%}:root,html[tk-theme-size=default]{--tk-home-max-width:1140px;--tk-home-gap:var(--tk-gap2);--tk-home-post-simple-img-width:120px;--tk-home-post-simple-img-height:80px;--tk-home-post-full-img-width:360px;--tk-home-post-full-img-height:100%;--tk-home-post-line-clamp:3;--tk-home-card-padding:10px;--tk-home-card-width:280px;--tk-home-card-svg-margin-left:5px;--tk-home-card-border-radius:4px;--tk-home-font-size-large:18px;--tk-home-font-size-base:16px;--tk-home-font-size-middle:14px;--tk-home-font-size-sm:13px;--tk-home-font-size-small:12px;--tk-page-width:900px;--tk-home-footer-group-width:80%}html[tk-theme-size=small]{--tk-home-max-width:1000px;--tk-home-gap:var(--tk-gap2);--tk-home-post-simple-img-width:100px;--tk-home-post-simple-img-height:80px;--tk-home-post-full-img-width:240px;--tk-home-post-full-img-height:100%;--tk-home-post-line-clamp:2;--tk-home-card-padding:8px;--tk-home-card-width:260px;--tk-home-card-svg-margin-left:4px;--tk-home-font-size-large:17px;--tk-home-font-size-base:15px;--tk-home-font-size-middle:13px;--tk-home-font-size-sm:13px;--tk-home-font-size-small:12px;--tk-page-width:800px;--tk-home-footer-group-width:70%}@media(min-width:768px){:root,html[tk-theme-size=default],html[tk-theme-size=large],html[tk-theme-size=small]{--tk-home-card-width:280px}}@media(max-width:768px){:root,html[tk-theme-size=default],html[tk-theme-size=large],html[tk-theme-size=small]{--tk-home-card-width:100%}}.todo{list-style:none}.todo .todo-checkbox{-webkit-appearance:none;-moz-appearance:none;appearance:none;border:2px solid var(--tk-theme-color);border-radius:4px;cursor:pointer;height:16px;margin-right:8px;position:relative;vertical-align:middle;width:16px}.todo .todo-checkbox:checked{background-color:var(--tk-theme-color);border-color:var(--tk-theme-color)}.todo .todo-checkbox:checked:after{color:#fff;content:"✓";font-size:12px;left:53%;position:absolute;top:53%;transform:translate(-50%,-50%)}.todo .todo-checkbox:disabled{cursor:not-allowed;opacity:.9}.tk-center-container{text-align:center}.tk-right-container{text-align:right}.custom-block .tk-right-container{font-size:14px;margin:-8px 0 0}:root{--tk-custom-block-note-bg:#e8f5fa}:root.dark{--tk-custom-block-note-bg:#003a4d}.custom-block.note{background-color:var(--tk-custom-block-note-bg)}.container.share-card-container{margin:11px 0}.container.share-card-container .share-card{-moz-column-gap:var(--column-gap);column-gap:var(--column-gap);display:grid;grid-auto-flow:row dense;grid-template-columns:repeat(auto-fill,minmax(var(--column-min-width),1fr));row-gap:var(--row-gap)}.container.share-card-container .share-card__item{background-color:var(--item-bg-color);border-radius:6px;color:var(--item-text-color);cursor:pointer;display:flex;overflow:hidden;text-decoration:none;transition:all .3s}.container.share-card-container .share-card__item:hover{box-shadow:0 10px 20px -10px var(--item-bg-color,rgba(0,0,0,.15));color:var(--item-text-color);transform:translateY(-3px) scale(1.01)}.container.share-card-container .share-card__item:hover img{box-shadow:3px 2px 7px #00000026}.container.share-card-container .share-card__item:hover div p{text-shadow:3px 2px 5px rgba(0,0,0,.15)}.container.share-card-container .share-card__item__img{border:2px solid var(--vp-c-bg);border-radius:50%;box-shadow:3px 2px 5px #00000014;height:60px;margin:16px 0 16px 16px;max-width:60px;overflow:hidden;transition:all .4s;width:60px}.container.share-card-container .share-card__item__img img{height:100%;width:100%}.container.share-card-container .share-card__item__content{flex:1;padding:16px 0}.container.share-card-container .share-card__item__content p{margin:0;padding:0 16px;text-align:center;transition:text-shadow .4s}.container.share-card-container .share-card__item__content .name{margin:3px 0 5px}.container.share-card-container .share-card__item__content .desc{font-size:13px;line-height:17px;margin-bottom:3px;opacity:.8}.container.share-card-container .share-card.index-auto{grid-template-columns:repeat(auto-fill,minmax(240px,1fr))}@media(max-width:1440px){.container.share-card-container .share-card.index-4{grid-template-columns:repeat(auto-fill,minmax(calc(33.33333% - var(--column-gap)*2),1fr))}}@media(max-width:768px){.container.share-card-container .share-card.index-3,.container.share-card-container .share-card.index-4{grid-template-columns:repeat(auto-fill,minmax(calc(50% - var(--column-gap)),1fr))}}@media(max-width:640px){.container.share-card-container .share-card.index-2,.container.share-card-container .share-card.index-3,.container.share-card-container .share-card.index-4{grid-template-columns:repeat(auto-fill,minmax(100%,1fr))}}.container.img-card-container{margin:11px 0}.container.img-card-container .img-card{-moz-column-gap:var(--column-gap);column-gap:var(--column-gap);display:grid;grid-auto-flow:row dense;grid-template-columns:repeat(auto-fill,minmax(var(--column-min-width),1fr));row-gap:var(--row-gap)}.container.img-card-container .img-card__item{background-color:var(--vp-c-bg);border:1px solid var(--vp-c-divider);border-radius:6px;color:var(--vp-c-text-1);cursor:pointer;display:block;overflow:hidden;text-decoration:none;transition:all .3s}.container.img-card-container .img-card__item:hover{box-shadow:var(--vp-shadow-2);color:var(--vp-c-text-1);transform:translateY(-3px)}.container.img-card-container .img-card__item__img{background-color:#eee;height:var(--img-height);overflow:hidden;position:relative;transition:all .3s}.container.img-card-container .img-card__item__img img{display:block;height:100%;-o-object-fit:var(--img-object-fit);object-fit:var(--img-object-fit);width:100%}.container.img-card-container .img-card__item__info{padding:13px 16px}.container.img-card-container .img-card__item__info p{margin:0}.container.img-card-container .img-card__item__info .desc{display:-webkit-box;font-size:14.4px;line-height:17.6px;margin-top:5px;opacity:.8;overflow:hidden;text-overflow:ellipsis;white-space:normal;-webkit-box-orient:vertical;line-clamp:var(--desc-line-clamp);-webkit-line-clamp:var(--desc-line-clamp)}.container.img-card-container .img-card__item__footer{border-top:1px solid var(--vp-c-divider);display:flex;overflow:hidden;padding:13px 16px}.container.img-card-container .img-card__item__footer img{border-radius:50%;height:29px;width:29px}.container.img-card-container .img-card__item__footer span{font-size:12.8px;line-height:29px;margin-left:10px}.container.img-card-container .img-card.index-auto{grid-template-columns:repeat(auto-fill,minmax(240px,1fr))}@media(max-width:960px){.container.img-card-container .img-card.index-4{grid-template-columns:repeat(auto-fill,minmax(calc(33.33333% - var(--column-gap)*2),1fr))}}@media(max-width:768px){.container.img-card-container .img-card.index-3,.container.img-card-container .img-card.index-4{grid-template-columns:repeat(auto-fill,minmax(calc(50% - var(--column-gap)),1fr))}}@media(max-width:640px){.container.img-card-container .img-card.index-2,.container.img-card-container .img-card.index-3,.container.img-card-container .img-card.index-4{grid-template-columns:repeat(auto-fill,minmax(100%,1fr))}}html[theme-size=wide] .img-card-container .index-auto{grid-template-columns:repeat(auto-fill,minmax(calc(25% - var(--column-gap)*2),1fr))}html[theme-size=large] .img-card-container .index-auto{grid-template-columns:repeat(auto-fill,minmax(calc(33.33333% - var(--column-gap)*2),1fr))}html[theme-size=default] .img-card-container .index-auto,html[theme-size=small] .img-card-container .index-auto{grid-template-columns:repeat(auto-fill,minmax(calc(50% - var(--column-gap)*2),1fr))}.container.nav-card-container{margin:11px 0}.container.nav-card-container .nav-card{-moz-column-gap:var(--column-gap);column-gap:var(--column-gap);display:grid;grid-auto-flow:row dense;grid-template-columns:repeat(auto-fill,minmax(var(--column-min-width),1fr));row-gap:var(--row-gap)}.container.nav-card-container .nav-card__item{background-color:var(--vp-c-bg-soft);border:1px solid var(--vp-c-bg-soft);border-radius:6px;color:var(--vp-c-text-1);cursor:pointer;display:block;overflow:hidden;padding:10px;position:relative;text-decoration:none;transition:all .3s}.container.nav-card-container .nav-card__item:hover{background-color:var(--vp-c-bg-soft-up);border-color:var(--vp-c-brand);box-shadow:var(--vp-shadow-2);color:var(--vp-c-text-1);transform:translateY(-4px)}.container.nav-card-container .nav-card__item__img{border-radius:6px;height:40px;margin-right:10px;min-width:40px;overflow:hidden}.container.nav-card-container .nav-card__item__img img{height:100%;width:100%}.container.nav-card-container .nav-card__item__info{align-items:center;display:flex}.container.nav-card-container .nav-card__item__info .name{flex:1;font-size:16px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.container.nav-card-container .nav-card__item .desc{color:var(--vp-c-text-2);display:-webkit-box;font-size:12px;line-height:1.5;margin:12px 0 0;overflow:hidden;text-overflow:ellipsis;white-space:normal;-webkit-box-orient:vertical;line-clamp:var(--desc-line-clamp);-webkit-line-clamp:var(--desc-line-clamp)}.container.nav-card-container .nav-card__item .badge{position:absolute;right:3px;top:6px}.container.nav-card-container .nav-card.index-auto{grid-template-columns:repeat(auto-fill,minmax(240px,1fr))}@media(max-width:960px){.container.nav-card-container .nav-card.index-4{grid-template-columns:repeat(auto-fill,minmax(calc(33.33333% - var(--column-gap)*2),1fr))}}@media(max-width:768px){.container.nav-card-container .nav-card.index-3,.container.nav-card-container .nav-card.index-4{grid-template-columns:repeat(auto-fill,minmax(calc(50% - var(--column-gap)),1fr))}}@media(max-width:640px){.container.nav-card-container .nav-card.index-2,.container.nav-card-container .nav-card.index-3,.container.nav-card-container .nav-card.index-4{grid-template-columns:repeat(auto-fill,minmax(100%,1fr))}}.video-container{align-items:center;display:flex;justify-content:center;padding:.5em}.video-container .video-iframe{aspect-ratio:16/9;border:none;border-radius:.5em;box-shadow:0 4px 6px #0000001a;height:auto;max-width:100%;width:100%}.tk-article-page{margin:25px auto;width:100%}@media(min-width:1280px){.tk-article-page{width:var(--tk-page-width)}}@media(max-width:1280px){.tk-article-page{padding:0 10px}}.tk-article-page.is-aside{display:flex}@media(min-width:1280px){.tk-article-page.is-aside{width:calc(var(--tk-page-width) + 360px)}.tk-article-page.is-aside .tk-doc{transform:translate(80px)}}.tk-article-page .tk-doc{background-color:var(--tk-bg-color);border-radius:10px;box-shadow:var(--vp-shadow-3);flex:1;overflow-y:auto;padding:20px 30px}.tk-article-page__aside{display:none;flex-grow:1;max-width:256px;order:2;padding-left:112px;position:relative}@media(min-width:1280px){.tk-article-page__aside{display:block}}.tk-article-page__aside__container{height:100vh;overflow-x:hidden;overflow-y:auto;padding-top:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + var(--vp-doc-top-height, 0px) + 48px);position:fixed;scrollbar-width:none;top:0;width:224px}.tk-article-page~div{display:none}.tk-article-page h1{font-size:32px;font-weight:600;line-height:32px}.tk-article-page h2{font-size:27px;font-weight:600;line-height:27px}.tk-article-page h3{font-size:22px;font-weight:500;line-height:22px}.tk-aside-outline{display:none}.tk-aside-outline.has-outline{display:block}.tk-aside-outline__content{border-left:1px solid var(--vp-c-divider);font-size:13px;font-weight:500;padding-left:16px;position:relative}.tk-aside-outline--marker{background-color:var(--vp-c-brand-1);border-radius:2px;height:18px;left:-1px;opacity:0;position:absolute;top:32px;transition:top .25s cubic-bezier(0,1,.5,1),background-color .5s,opacity .25s;width:2px;z-index:0}.tk-aside-outline--title{font-size:14px;font-weight:600;line-height:32px}.tk-aside-outline-item.is-root{position:relative;z-index:1}.tk-aside-outline-item.is-nested{padding-left:16px;padding-right:16px}.tk-aside-outline-item--link{color:var(--vp-c-text-2);display:block;font-size:14px;font-weight:400;line-height:32px;overflow:hidden;text-overflow:ellipsis;transition:color .3s;white-space:nowrap}.tk-aside-outline-item--link:hover{font-weight:700}.tk-aside-outline-item--link.active{color:var(--tk-theme-color)}:root{--tk-avatar-bg-color:var(--tk-text-color-disabled);--tk-avatar-text-color:var(--vp-c-white);--tk-avatar-text-size:14px;--tk-avatar-icon-size:18px;--tk-avatar-border-radius:4px;--tk-avatar-size-small:24px;--tk-avatar-size:40px;--tk-avatar-size-large:56px}.tk-avatar{align-items:center;background:var(--tk-avatar-bg-color);box-sizing:border-box;color:var(--tk-avatar-text-color);display:inline-flex;font-size:var(--tk-avatar-text-size);height:var(--tk-avatar-size);justify-content:center;outline:none;overflow:hidden;text-align:center;width:var(--tk-avatar-size)}.tk-avatar>img{display:block;height:100%;width:100%}.tk-avatar--circle{border-radius:50%}.tk-avatar--square{border-radius:var(--tk-avatar-border-radius)}.tk-avatar--icon{font-size:var(--tk-avatar-icon-size)}.tk-avatar--small{height:var(--tk-avatar-size-small);width:var(--tk-avatar-size-small)}.tk-avatar--large{height:var(--tk-avatar-size-large);width:var(--tk-avatar-size-large)}.tk-breadcrumb{font-size:14px;line-height:1}.tk-breadcrumb__separator{color:var(--vp-c-border);margin:0 7px}.tk-breadcrumb__item{align-items:center;display:inline-flex;float:left}.tk-breadcrumb__inner{color:var(--vp-c-text-1)}.tk-breadcrumb__inner a{font-weight:700;text-decoration:none;transition:color var(--tk-transition-duration-fast) cubic-bezier(.645,.045,.355,1)}.tk-breadcrumb__inner a:hover{color:var(--tk-theme-color);cursor:pointer}.tk-breadcrumb__item:last-child .tk-breadcrumb__inner,.tk-breadcrumb__item:last-child .tk-breadcrumb__inner a,.tk-breadcrumb__item:last-child .tk-breadcrumb__inner a:hover,.tk-breadcrumb__item:last-child .tk-breadcrumb__inner:hover{color:var(--vp-c-text-1);cursor:text;font-weight:400}.tk-breadcrumb__item:last-child .tk-breadcrumb__separator{display:none}.tk-icon{align-items:center;color:var(--icon-color,inherit);display:inline-flex;font-size:var(--icon-size,inherit);justify-content:center;line-height:1em;position:relative;fill:var(--icon-color,currentColor);transition:color var(--tk-transition-duration)}.tk-icon,.tk-icon svg{height:var(--icon-size,1em);width:var(--icon-size,1em)}.tk-icon svg{vertical-align:middle;fill:currentcolor}.tk-icon svg:focus{outline:none}.tk-icon .iconfont{color:var(--icon-color,inherit);font-size:var(--icon-size,1em)}.tk-icon.is-hover:hover i,.tk-icon.is-hover:hover svg,i.tk-icon.is-hover:hover{color:var(--icon-color-hover,inherit)}.tk-image-viewer__wrapper{inset:0;position:fixed}.tk-image-viewer__wrapper:focus{outline:none!important}.tk-image-viewer__btn{align-items:center;border-radius:50%;box-sizing:border-box;cursor:pointer;display:flex;justify-content:center;opacity:.8;position:absolute;-webkit-user-select:none;-moz-user-select:none;user-select:none;z-index:1}.tk-image-viewer__btn .tk-icon{cursor:pointer}.tk-image-viewer__close{font-size:40px;height:40px;right:40px;top:40px;width:40px}.tk-image-viewer__canvas{align-items:center;display:flex;height:100%;justify-content:center;position:static;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:100%}.tk-image-viewer__actions{background-color:var(--vp-c-text-1);border-color:#fff;border-radius:22px;bottom:30px;height:44px;left:50%;padding:0 23px;transform:translate(-50%)}.tk-image-viewer__actions__inner{align-items:center;color:#fff;cursor:default;display:flex;font-size:23px;gap:22px;height:100%;justify-content:space-around;padding:0 6px;width:100%}.tk-image-viewer__actions__divider{margin:0 -6px}.tk-image-viewer__progress{bottom:90px;color:#fff;cursor:default;left:50%;transform:translate(-50%)}.tk-image-viewer__prev{left:40px}.tk-image-viewer__next,.tk-image-viewer__prev{background-color:var(--vp-c-text-1);border-color:#fff;color:#fff;font-size:24px;height:44px;top:50%;transform:translateY(-50%);width:44px}.tk-image-viewer__next{right:40px;text-indent:2px}.tk-image-viewer__close{background-color:var(--vp-c-text-1);border-color:#fff;color:#fff;font-size:24px;height:44px;width:44px}.tk-image-viewer__mask{background:#000;height:100%;left:0;opacity:.5;position:absolute;top:0;width:100%}.viewer-fade-enter-active{animation:viewer-fade-in .3s}.viewer-fade-leave-active{animation:viewer-fade-out .3s}@keyframes viewer-fade-in{0%{opacity:0;transform:translate3d(0,-20px,0)}to{opacity:1;transform:translateZ(0)}}@keyframes viewer-fade-out{0%{opacity:1;transform:translateZ(0)}to{opacity:0;transform:translate3d(0,-20px,0)}}:root{--tk-slider-height:32px;--tk-slider-shadow-color:var(--tk-text-color-disabled);--tk-slider-thumb-height:32px;--tk-slider-thumb-width:32px;--tk-slider-thumb-border-radius:6px;--tk-slider-thumb-color:#fff;--tk-slider-track-height:calc(var(--tk-slider-height) - var(--tk-slider-track-progress-padding)*2);--tk-slider-track-border-radius:6px;--tk-slider-track-color:#fff;--tk-slider-track-progress-color:#fff;--tk-slider-track-progress-padding:0px;--tk-slider-transition-duration:var(--tk-transition-duration-fast)}:root.dark{--tk-slider-thumb-color:#e1e2da;--tk-slider-track-color:#e1e2da;--tk-slider-track-progress-color:#e1e2da}.tk-input-slide{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#e1e4e880;border:none;border-radius:8px;color:#d1d5db;display:flex;flex-direction:row;font-size:14px;padding:4px;width:100%}.tk-input-slide__label{position:relative;-webkit-user-select:none;-moz-user-select:none;user-select:none}.tk-input-slide__label,.tk-input-slide__label__input{cursor:col-resize;height:var(--tk-slider-height);width:100%}.tk-input-slide__label__input{-moz-appearance:none;appearance:none;-webkit-appearance:none;margin:0;transition:background-color var(--tk-slider-transition-duration) ease}.tk-input-slide__label__input:focus{outline:none}.tk-input-slide__label__input::-webkit-slider-thumb{-webkit-appearance:none;background:var(--tk-slider-thumb-color);border:none;border-radius:var(--tk-slider-thumb-border-radius);box-shadow:0 2px 4px 0 var(--tk-slider-shadow-color);cursor:col-resize;height:var(--tk-slider-thumb-height);margin-left:calc(0 - var(--tk-slider-track-progress-padding));margin-top:calc(var(--tk-slider-track-height)*.5 - var(--tk-slider-thumb-height)*.5);width:var(--tk-slider-thumb-width)}.tk-input-slide__label__input::-webkit-slider-runnable-track{background:#f2f2f200;border:none;border-radius:var(--tk-slider-track-border-radius);box-shadow:none;cursor:col-resize;height:var(--tk-slider-track-height)}.tk-input-slide__label__input::-moz-range-thumb{background:var(--tk-slider-thumb-color);border:none;border-radius:var(--tk-slider-thumb-border-radius);box-shadow:0 2px 4px 0 var(--tk-slider-shadow-color);cursor:col-resize;height:var(--tk-slider-thumb-height);margin-left:calc(0 - var(--tk-slider-track-progress-padding));width:var(--tk-slider-thumb-width)}.tk-input-slide__label__input::-moz-range-track{background:#f2f2f200;border:none;border-radius:var(--tk-slider-track-border-radius);box-shadow:none;cursor:col-resize;height:var(--tk-slider-track-height)}.tk-input-slide__label__input::-ms-fill-lower,.tk-input-slide__label__input::-ms-fill-upper{background:transparent;border-color:transparent}.tk-input-slide__label__input::-ms-thumb{background:var(--tk-slider-thumb-color);border:none;border-radius:var(--tk-slider-thumb-border-radius);box-shadow:0 2px 4px 0 var(--tk-slider-shadow-color);cursor:col-resize;height:var(--tk-slider-thumb-height);margin-left:calc(0 - var(--tk-slider-track-progress-padding));margin-top:0;width:var(--tk-slider-thumb-width)}.tk-input-slide__label__input::-ms-track{background:#f2f2f200;border:none;border-radius:var(--tk-slider-track-border-radius);box-shadow:none;cursor:col-resize;height:var(--tk-slider-track-height)}.tk-input-slide__label__input-progress{--tk-slider-range:calc(var(--tk-slider-max) - var(--tk-slider-min));--tk-slider-ratio:calc((var(--tk-slider-value) - var(--tk-slider-min))/var(--tk-slider-range));--tk-slider-sx:calc(var(--tk-slider-thumb-width)*.5 + var(--tk-slider-ratio)*(100% - var(--tk-slider-thumb-width)))}.tk-input-slide__label__input-progress::-webkit-slider-runnable-track{background:linear-gradient(var(--tk-slider-track-progress-color),var(--tk-slider-track-progress-color)) 0/var(--tk-slider-sx) 100% no-repeat,#fff0;cursor:col-resize;margin-left:var(--tk-slider-track-progress-padding);margin-right:calc(0 - var(--tk-slider-track-progress-padding))}.tk-input-slide__label__input-progress::-moz-range-track{background:linear-gradient(var(--tk-slider-track-progress-color),var(--tk-slider-track-progress-color)) 0/var(--tk-slider-sx) 100% no-repeat,#fff0;cursor:col-resize;display:block;width:calc(100% - var(--tk-slider-track-progress-padding) - var(--tk-slider-track-progress-padding))}.tk-input-slide__label__input-progress::-ms-fill-lower{background:var(--tk-slider-track-progress-color);border:none;border-radius:var(--tk-slider-track-border-radius) 0 0 var(--tk-slider-track-border-radius);border-right:0;cursor:col-resize;height:var(--tk-slider-track-height);margin-bottom:0;margin-left:calc(var(--tk-slider-track-progress-padding));margin-right:calc(0 - var(--tk-slider-track-progress-padding));margin-top:0}.tk-input-slide__label__tooltip{background-color:#000;border-radius:8px;color:#fff;min-width:48px;padding:8px;position:absolute;text-align:center;top:calc(-16px - var(--tk-slider-height))}:root{--tk-message-bg-color:var(--tk-el-color-info-light-9);--tk-message-border-color:var(--vp-c-border);--tk-message-border-width:1px;--tk-message-border-radius:4px;--tk-message-border-style:solid;--tk-message-padding:11px 15px;--tk-message-close-size:16px;--tk-message-close-icon-color:var(--tk-text-color-placeholder);--tk-message-close-hover-color:var(--vp-c-brand-3);--tk-message-bg-color-overlay:#fff}:root.dark{--tk-message-bg-color-overlay:#1d1e1f}.tk-message{align-items:center;background-color:var(--tk-message-bg-color);border-color:var(--tk-message-border-color);border-radius:var(--tk-message-border-radius);border-style:var(--tk-message-border-style);border-width:var(--tk-message-border-width);box-sizing:border-box;display:flex;gap:8px;left:50%;max-width:calc(100% - 32px);padding:var(--tk-message-padding);position:fixed;top:20px;transform:translate(-50%);transition:opacity .2s,transform .4s,top .4s;width:-moz-fit-content;width:fit-content}.tk-message.is-center{justify-content:center}.tk-message.is-plain{background-color:var(--tk-message-bg-color-overlay);border-color:var(--tk-message-bg-color-overlay);box-shadow:var(--tk-card-shadow)}.tk-message p{margin:0}.tk-message--primary{--tk-message-bg-color:var(--tk-el-color-primary-light-9);--tk-message-border-color:var(--tk-el-color-primary-light-8);--tk-message-text-color:var(--tk-el-color-primary)}.tk-message--primary .tk-message__content{color:var(--tk-message-text-color);overflow-wrap:break-word}.tk-message .tk-message-icon--primary{color:var(--tk-message-text-color)}.tk-message--success{--tk-message-bg-color:var(--tk-el-color-success-light-9);--tk-message-border-color:var(--tk-el-color-success-light-8);--tk-message-text-color:var(--tk-el-color-success)}.tk-message--success .tk-message__content{color:var(--tk-message-text-color);overflow-wrap:break-word}.tk-message .tk-message-icon--success{color:var(--tk-message-text-color)}.tk-message--info{--tk-message-bg-color:var(--tk-el-color-info-light-9);--tk-message-border-color:var(--tk-el-color-info-light-8);--tk-message-text-color:var(--tk-el-color-info)}.tk-message--info .tk-message__content{color:var(--tk-message-text-color);overflow-wrap:break-word}.tk-message .tk-message-icon--info{color:var(--tk-message-text-color)}.tk-message--warning{--tk-message-bg-color:var(--tk-el-color-warning-light-9);--tk-message-border-color:var(--tk-el-color-warning-light-8);--tk-message-text-color:var(--tk-el-color-warning)}.tk-message--warning .tk-message__content{color:var(--tk-message-text-color);overflow-wrap:break-word}.tk-message .tk-message-icon--warning{color:var(--tk-message-text-color)}.tk-message--error{--tk-message-bg-color:var(--tk-el-color-error-light-9);--tk-message-border-color:var(--tk-el-color-error-light-8);--tk-message-text-color:var(--tk-el-color-error)}.tk-message--error .tk-message__content{color:var(--tk-message-text-color);overflow-wrap:break-word}.tk-message .tk-message-icon--error{color:var(--tk-message-text-color)}.tk-message .tk-message__badge{position:absolute;right:-8px;top:-8px}.tk-message__content{font-size:14px;line-height:1;padding:0}.tk-message__content:focus{outline-width:0}.tk-message .tk-message__closeBtn{color:var(--tk-message-close-icon-color);cursor:pointer;font-size:var(--tk-message-close-size)}.tk-message .tk-message__closeBtn:focus{outline-width:0}.tk-message .tk-message__closeBtn:hover{color:var(--tk-message-close-hover-color)}.tk-message.antd{background:#fff!important;border-width:0!important;box-shadow:0 3px 6px -4px #0000001f,0 6px 16px #00000014,0 9px 28px 8px #0000000d!important;padding:10px 13px!important}.tk-message.antd.tk-message.is-closable .tk-message__content{padding-right:17px!important}.tk-message.antd .tk-message__content{background-image:none!important;color:#000000d9!important;pointer-events:all!important}.tk-message.antd .tk-message__closeBtn{border-radius:4px;outline:none;right:9px!important;transition:background-color .2s,color .2s}.tk-message.antd .tk-message__closeBtn:hover{background-color:#0000000f}.tk-message-fade-enter-from,.tk-message-fade-leave-to{opacity:0;transform:translate(-50%,-100%)}.tk-page-card{background-color:var(--tk-bg-color-elm);border-radius:var(--tk-home-card-border-radius);box-shadow:var(--tk-card-shadow);overflow:hidden;padding:var(--tk-home-card-padding);transition:box-shadow var(--tk-transition-duration-slow),transform var(--tk-transition-duration-slow);width:var(--tk-home-card-width)}.tk-page-card:hover{box-shadow:var(--tk-hover-shadow);transform:scale(1.01)}.tk-page-card__header{margin-bottom:10px}.tk-page-card__header .title{font-size:var(--tk-home-font-size-large)}.tk-page-card__header .title svg{height:16px;margin-right:var(--tk-home-card-svg-margin-left);width:16px}.tk-page-card__header .page-button{padding:0 3px;-webkit-user-select:none;-moz-user-select:none;user-select:none}.tk-page-card__header .page-button:hover{color:var(--tk-theme-color)}.tk-page-card__header .page-button.pointer{cursor:pointer}.tk-page-card__header .page-button.disabled{cursor:not-allowed;opacity:.5}:root{--tk-pagination-font-size:14px;--tk-pagination-bg-color:var(--tk-fill-color-blank);--tk-pagination-text-color:var(--vp-c-text-1);--tk-pagination-border-radius:2px;--tk-pagination-button-color:var(--vp-c-text-1);--tk-pagination-button-width:32px;--tk-pagination-button-height:32px;--tk-pagination-button-disabled-color:var(--tk-text-color-placeholder);--tk-pagination-button-disabled-bg-color:var(--tk-fill-color-blank);--tk-pagination-button-bg-color:var(--tk-fill-color);--tk-pagination-hover-color:var(--tk-theme-color);--tk-pagination-font-size-small:12px;--tk-pagination-button-width-small:24px;--tk-pagination-button-height-small:24px;--tk-pagination-button-width-large:40px;--tk-pagination-button-height-large:40px;--tk-pagination-item-gap:16px;--tk-pagination-transition-duration:var(--tk-transition-duration-fast)}.tk-pagination{align-items:center;color:var(--tk-pagination-text-color);display:flex;font-size:var(--tk-pagination-font-size);font-weight:400;white-space:nowrap}.tk-pagination .tk-input__inner{-webkit-appearance:textfield;-moz-appearance:textfield;appearance:textfield;text-align:center}.tk-pagination button{align-items:center;background:var(--tk-pagination-bg-color);border:none;border-radius:var(--tk-pagination-border-radius);box-sizing:border-box;color:var(--tk-pagination-button-color);cursor:pointer;display:flex;font-size:var(--tk-pagination-font-size);height:var(--tk-pagination-button-height);justify-content:center;line-height:var(--tk-pagination-button-height);min-width:var(--tk-pagination-button-width);padding:0 4px;text-align:center}.tk-pagination button *{pointer-events:none}.tk-pagination button:focus{outline:none}.tk-pagination button.is-active,.tk-pagination button:hover{color:var(--tk-pagination-hover-color)}.tk-pagination button.is-active{cursor:default;font-weight:700}.tk-pagination button.is-active.is-disabled{color:var(--vp-c-text-3);font-weight:700}.tk-pagination button.is-disabled,.tk-pagination button:disabled{background-color:var(--tk-pagination-button-disabled-bg-color);color:var(--tk-pagination-button-disabled-color);cursor:not-allowed}.tk-pagination button:focus-visible{outline:1px solid var(--tk-pagination-hover-color);outline-offset:-1px}.tk-pagination .btn-next .tk-icon,.tk-pagination .btn-prev .tk-icon{display:block;font-size:12px;font-weight:700;width:inherit}.tk-pagination>.is-first{margin-left:0!important}.tk-pagination>.is-last{margin-right:0!important}.tk-pagination .btn-prev,.tk-pagination__total{margin-left:var(--tk-pagination-item-gap)}.tk-pagination__total{color:var(--vp-c-text-2);font-weight:400}.tk-pagination__total[disabled=true]{color:var(--tk-text-color-placeholder)}.tk-pagination__jump{align-items:center;color:var(--vp-c-text-2);display:flex;font-weight:400;margin-left:var(--tk-pagination-item-gap)}.tk-pagination__jump[disabled=true]{color:var(--tk-text-color-placeholder)}.tk-pagination__goto{margin-right:8px}.tk-pagination__input{align-items:center;background-image:none;border-radius:4px;box-shadow:0 0 0 1px var(--vp-c-divider) inset;box-sizing:border-box;cursor:text;display:inline-flex;flex-grow:1;justify-content:center;padding:1px 11px;text-align:center;transform:translateZ(0);transition:box-shadow var(--tk-pagination-transition-duration) cubic-bezier(.645,.045,.355,1);width:56px}.tk-pagination__input:hover{box-shadow:0 0 0 1px var(--vp-c-border) inset}.tk-pagination__input:focus{box-shadow:0 0 0 1px var(--vp-c-brand-2) inset}.tk-pagination__input--small{font-size:12px;height:22px;padding:1px 7px}.tk-pagination__input--large{height:38px}.tk-pagination__classifier{margin-left:8px}.tk-pagination__right-wrapper{align-items:center;display:flex;flex:1;justify-content:flex-end}.tk-pagination.is-background .btn-next,.tk-pagination.is-background .btn-prev,.tk-pagination.is-background .tk-pager li{background-color:var(--tk-pagination-button-bg-color);margin:0 4px}.tk-pagination.is-background .btn-next.is-active,.tk-pagination.is-background .btn-prev.is-active,.tk-pagination.is-background .tk-pager li.is-active{background-color:var(--tk-theme-color);color:#fff}.tk-pagination.is-background .btn-next.is-disabled,.tk-pagination.is-background .btn-next:disabled,.tk-pagination.is-background .btn-prev.is-disabled,.tk-pagination.is-background .btn-prev:disabled,.tk-pagination.is-background .tk-pager li.is-disabled,.tk-pagination.is-background .tk-pager li:disabled{background-color:var(--tk-fill-color-light);color:var(--tk-text-color-placeholder)}.tk-pagination.is-background .btn-next.is-disabled.is-active,.tk-pagination.is-background .btn-next:disabled.is-active,.tk-pagination.is-background .btn-prev.is-disabled.is-active,.tk-pagination.is-background .btn-prev:disabled.is-active,.tk-pagination.is-background .tk-pager li.is-disabled.is-active,.tk-pagination.is-background .tk-pager li:disabled.is-active{background-color:var(--tk-fill-color-dark);color:var(--vp-c-text-3)}.tk-pagination.is-background .btn-prev{margin-left:var(--tk-pagination-item-gap)}.tk-pagination--small .btn-next,.tk-pagination--small .btn-prev,.tk-pagination--small .tk-pager li{font-size:var(--tk-pagination-font-size-small);height:var(--tk-pagination-button-height-small);line-height:var(--tk-pagination-button-height-small);min-width:var(--tk-pagination-button-width-small)}.tk-pagination--small button,.tk-pagination--small span:not([class*=suffix]){font-size:var(--tk-pagination-font-size-small)}.tk-pagination--small .tk-select{width:100px}.tk-pagination--large .btn-next,.tk-pagination--large .btn-prev,.tk-pagination--large .tk-pager li{height:var(--tk-pagination-button-height-large);line-height:var(--tk-pagination-button-height-large);min-width:var(--tk-pagination-button-width-large)}.tk-pagination--large .tk-select .tk-input{width:160px}.tk-pager{font-size:0;list-style:none;margin:0;padding:0;-webkit-user-select:none;-moz-user-select:none;user-select:none}.tk-pager,.tk-pager li{align-items:center;display:flex}.tk-pager li{background:var(--tk-pagination-bg-color);border:none;border-radius:var(--tk-pagination-border-radius);box-sizing:border-box;color:var(--tk-pagination-button-color);cursor:pointer;font-size:var(--tk-pagination-font-size);height:var(--tk-pagination-button-height);justify-content:center;line-height:var(--tk-pagination-button-height);min-width:var(--tk-pagination-button-width);padding:0 4px;text-align:center}.tk-pager li *{pointer-events:none}.tk-pager li:focus{outline:none}.tk-pager li.is-active,.tk-pager li:hover{color:var(--tk-pagination-hover-color)}.tk-pager li.is-active{cursor:default;font-weight:700}.tk-pager li.is-active.is-disabled{color:var(--vp-c-text-3);font-weight:700}.tk-pager li.is-disabled,.tk-pager li:disabled{background-color:var(--tk-pagination-button-disabled-bg-color);color:var(--tk-pagination-button-disabled-color);cursor:not-allowed}.tk-pager li:focus-visible{outline:1px solid var(--tk-pagination-hover-color);outline-offset:-1px}:root{--tk-popover-color:var(--vp-c-text-1);--tk-popover-bg-color:var(--tk-bg-color-elm);--tk-popover-padding:10px;--tk-popover-font-size:14px;--tk-popover-shadow:var(--vp-shadow-3);--tk-popover-border-color:var(--vp-c-divider);--tk-popover-border-radius:4px}.tk-popover{background-color:var(--tk-popover-bg-color);border:1px solid var(--tk-popover-border-color);border-radius:var(--tk-popover-border-radius);box-shadow:var(--tk-popover-shadow);box-sizing:border-box;color:var(--tk-popover-color);font-size:var(--tk-popover-font-size);max-height:calc(100vh - 100px);max-width:100vw;outline:none;overflow:auto;overflow-wrap:break-word;padding:var(--tk-popover-padding);position:absolute}:root{--tk-segmented-item-text:var(--vp-c-text-1);--tk-segmented-item-active-text:var(--vp-c-text-1);--tk-segmented-item-active-bg:var(--tk-bg-color-elm);--tk-segmented-item-shadow-color:var(--tk-text-color-disabled)}:root.dark{--tk-segmented-item-active-text:var(--tk-bg-color-elm);--tk-segmented-item-active-bg:var(--vp-c-text-1)}.tk-segmented-item{align-items:center;border-radius:6px;color:var(--tk-segmented-item-text);cursor:pointer;display:flex;flex:1;font-size:14px;font-weight:500;justify-content:center;padding:8px 12px;transition:background-color .25s,color .25s,box-shadow .25s;width:100%}.tk-segmented-item.is-active{background-color:var(--tk-segmented-item-active-bg);box-shadow:0 2px 4px 0 var(--tk-segmented-item-shadow-color);color:var(--tk-segmented-item-active-text);font-weight:700}.tk-segmented-item.is-disabled{color:var(--tk-segmented-item-active-text);cursor:not-allowed;opacity:.5}.tk-segmented-item:not(.is-disabled):hover{background-color:var(--tk-segmented-item-active-bg);box-shadow:0 2px 4px 0 var(--tk-segmented-item-shadow-color);color:var(--tk-segmented-item-active-text)}.tk-segmented-item__content{align-items:center;display:inline-flex;gap:4px;justify-content:center;vertical-align:middle}:root{--tk-segmented-padding:4px;--tk-segmented-gap:8px;--tk-segmented-line-height:20px;--tk-segmented-border-radius:6px}.tk-segmented{align-items:stretch;-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:var(--tk-segmented-border-radius);border-style:none;display:inline-flex;flex-wrap:wrap;gap:var(--tk-segmented-gap);line-height:var(--tk-segmented-line-height);padding:var(--tk-segmented-padding);width:100%}.tk-title-tag{border:1px solid var(--tk-theme-color);border-radius:3px;color:var(--tk-theme-color);display:inline-block;font-size:14px;font-weight:500;height:22px;line-height:18px;padding:2px 6px}.tk-title-tag--vp-primary{border:1px solid var(--vp-c-brand-1);color:var(--vp-c-brand-1)}.tk-title-tag--vp-info{border:1px solid var(--vp-c-gray-1);color:var(--vp-c-gray-1)}.tk-title-tag--vp-success{border:1px solid var(--vp-c-green-1);color:var(--vp-c-green-1)}.tk-title-tag--vp-warning{border:1px solid var(--vp-c-yellow-1);color:var(--vp-c-yellow-1)}.tk-title-tag--vp-danger{border:1px solid var(--vp-c-red-1);color:var(--vp-c-red-1)}.tk-title-tag--vp-important{border:1px solid var(--vp-c-purple-1);color:var(--vp-c-purple-1)}.tk-title-tag--ep-primary{border:1px solid var(--tk-el-color-primary);color:var(--tk-el-color-primary)}.tk-title-tag--ep-info{border:1px solid var(--tk-el-color-info);color:var(--tk-el-color-info)}.tk-title-tag--ep-success{border:1px solid var(--tk-el-color-success);color:var(--tk-el-color-success)}.tk-title-tag--ep-warning{border:1px solid var(--tk-el-color-warning);color:var(--tk-el-color-warning)}.tk-title-tag--ep-danger{border:1px solid var(--tk-el-color-danger);color:var(--tk-el-color-danger)}.tk-title-tag--right{margin-left:4px}.tk-title-tag--left{margin-right:4px}.tk-title-tag--large{font-size:16px;font-weight:600;height:24px;line-height:18px}.tk-title-tag--small{font-size:13px;height:19px;line-height:15px}.tk-title-tag--mini{font-size:12px;height:18px;line-height:14px}h1 .tk-title-tag{transform:translateY(-4px)}.tk-vp-container .custom-block.no-title{padding:10px 16px}.tk-archives .count{font-size:13.6px;font-style:oblique;font-weight:300;opacity:.8}.tk-archives__header .count{font-style:normal}.tk-archives__timeline{margin:32px 0}.tk-archives__timeline--year{background-color:var(--tk-bg-color);border-bottom:1px solid var(--tk-line-color);margin-top:32px;position:sticky;top:var(--vp-nav-height);z-index:1}.tk-archives__timeline--year .year{font-size:24px;font-weight:500;padding:8px 0}.tk-archives__timeline__m{margin-top:16px}.tk-archives__timeline__m--month{border-bottom:1px solid var(--tk-line-color);margin-top:16px}.tk-archives__timeline__m--month .month{font-size:19px;padding-bottom:8px}.tk-archives__timeline__m ul{padding:8px 16px}.tk-archives__timeline__m ul li{line-height:2}.tk-archives__timeline__m ul li a{display:block;transition:padding var(--tk-transition-duration)}.tk-archives__timeline__m ul li a:hover{background:var(--tk-fill-color-light);color:var(--tk-theme-color);padding-left:16px}.tk-archives__timeline__m ul li a .date{font-size:13.6px;margin-right:8px;opacity:.6}:root{--tk-home-article-analyze-gap:var(--tk-gap1)}.tk-article-analyze{flex-wrap:wrap;font-size:var(--tk-home-font-size-sm);gap:var(--tk-home-article-analyze-gap);margin-bottom:24px}.tk-article-analyze__wrapper{flex-wrap:wrap;font-size:14px}.tk-article-analyze__wrapper.teleport{margin-bottom:10px;margin-top:10px}.tk-article-analyze__wrapper .tk-icon{margin-right:3px}.tk-article-analyze__wrapper>div:not(:last-child){margin-right:14px}.tk-article-analyze__wrapper a{font-size:14px;font-weight:400;text-decoration:none}.tk-article-analyze__wrapper i{margin-right:3px}:root{--tk-appreciation-gap:var(--tk-gap1)}.tk-article-appreciation{font-size:14px;padding:20px;text-align:center}.tk-article-appreciation__button{align-items:center;-webkit-appearance:none;background-color:var(--tk-theme-color);border:1px solid var(--tk-theme-color);border-radius:4px;color:var(--vp-c-white);cursor:pointer;display:inline-flex;font-size:14px;font-weight:500;height:32px;justify-content:center;line-height:1;outline:none;padding:8px 15px;text-align:center;transition-duration:var(--tk-transition-duration-fast);-webkit-user-select:none;-moz-user-select:none;user-select:none;vertical-align:middle;white-space:nowrap}.tk-article-appreciation__button:hover{background-color:var(--vp-c-brand-3);border-color:var(--vp-c-brand-3)}.tk-article-appreciation__button__icon{margin-right:8px}.tk-article-appreciation__content{align-items:center;display:flex;flex-wrap:wrap;gap:var(--tk-appreciation-gap);justify-content:center;margin-top:10px;position:relative}.tk-article-appreciation--doc-after img{max-width:240px}.tk-article-appreciation--doc-after-popper{margin-top:0}.tk-article-appreciation--doc-after-popper img{max-width:160px}.tk-article-appreciation--aside-bottom img{max-width:100%}:root{--tk-article-banner-height:500px;--tk-article-banner-info-mr:16px;--tk-article-banner-text-color:#fff;--tk-article-banner-text-size:16px}@media(max-width:768px){:root{--tk-article-banner-text-size:15px}}.tk-article-banner{height:var(--tk-article-banner-height);position:relative;width:100%;z-index:1}@media(max-width:768px){.tk-article-banner{height:100vh}}.tk-article-banner__wrapper{background-position:50%;background-repeat:no-repeat;background-size:cover;height:100%;overflow:hidden;position:relative;transition:var(--tk-transition-duration-slow-plus);width:100%}.tk-article-banner__wrapper:before{background-color:var(--tk-article-banner-bg-color,var(--tk-theme-color));content:"";display:block;height:100%;left:0;position:absolute;top:0;transition:var(--tk-transition-duration);width:100%}.tk-article-banner__cover{animation:showCover 1s .3s backwards;display:block;filter:blur(10px);height:100%;margin-bottom:0;opacity:.5;overflow:hidden;position:absolute;top:0;transform:scale(1.3);width:100%}.tk-article-banner__cover img{height:100%;-o-object-fit:cover;object-fit:cover;opacity:.8;transition:all var(--tk-transition-duration-fast) ease 0s;width:100%}@keyframes showCover{0%{opacity:0;transform:scale(1)}}.tk-article-banner__info{align-items:flex-start;color:var(--tk-article-banner-text-color);display:flex;flex-direction:column;height:100%;justify-content:center;margin:0 auto;max-width:1400px;padding:0 60px;width:100%;z-index:10}@media(max-width:768px){.tk-article-banner__info{align-items:center;padding:22rem 6% 0;text-align:left}}.tk-article-banner__info h1{font-size:46px;font-weight:700;line-height:1.2;margin:20px 0;text-align:left;-webkit-line-clamp:2;overflow:hidden;padding:0}@media(max-width:768px){.tk-article-banner__info h1{font-size:30px;margin:10px auto;text-align:center;width:100%;-webkit-line-clamp:3}}.tk-article-banner__info .tk-breadcrumb{font-size:var(--tk-article-banner-text-size);margin-bottom:35px}.tk-article-banner__info .tk-breadcrumb__separator{color:#c2c2c4}.tk-article-banner__info .tk-breadcrumb__inner,.tk-article-banner__info .tk-breadcrumb__item:last-child .tk-breadcrumb__inner,.tk-article-banner__info .tk-breadcrumb__item:last-child .tk-breadcrumb__inner a,.tk-article-banner__info .tk-breadcrumb__item:last-child .tk-breadcrumb__inner a:hover,.tk-article-banner__info .tk-breadcrumb__item:last-child .tk-breadcrumb__inner:hover{color:var(--tk-article-banner-text-color)}@media(max-width:768px){.tk-article-banner__info .tk-article-analyze__wrapper{justify-content:center}}.tk-article-banner__info .tk-article-analyze__wrapper>div:not(:last-child){margin-right:var(--tk-article-banner-info-mr)}.tk-article-banner__info .tk-article-analyze__wrapper .tk-article-info{color:var(--tk-article-banner-text-color)}.tk-article-banner__info .tk-article-analyze__wrapper .tk-article-info>span:not(:last-child){margin-right:var(--tk-article-banner-info-mr)}.tk-article-banner__info .tk-article-analyze__wrapper a,.tk-article-banner__info .tk-article-analyze__wrapper i{font-size:var(--tk-article-banner-text-size);opacity:.85}.tk-article-banner__info .tk-article-analyze__wrapper a:hover,.tk-article-banner__info .tk-article-analyze__wrapper i:hover{color:inherit;opacity:1}.tk-article-banner__meta{font-size:var(--tk-article-banner-text-size);gap:10px}.tk-article-banner__meta a{font-weight:800}.tk-article-banner__meta .meta-info{align-items:center;border-radius:12px;display:flex;flex-direction:row;height:32px;line-height:32px;padding:0 10px;transition:var(--tk-transition-duration) ease-out}.tk-article-banner__meta .categories{gap:8px}.tk-article-banner__meta .categories .category{background-color:#fff3}.tk-article-banner__meta .categories .category:hover{background-color:var(--tk-article-banner-text-color);color:var(--tk-article-banner-bg-color,var(--tk-theme-color))}.tk-article-banner__meta .tags{gap:8px}.tk-article-banner__meta .tags .tag{color:var(--tk-article-banner-text-color);gap:2px}.tk-article-banner__meta .tags .tag:hover{background:#fff3}.tk-article-banner .tk-banner-waves{height:8vh;margin-top:-7vh}.tk-article-banner~.VPNav .VPNavBar:not(.home).top{background-color:transparent;color:var(--tk-article-banner-text-color)}.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPNavBarMenuGroup .text,.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPNavBarMenuLink,.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPNavBarTitle .title,.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPSocialLink{color:var(--tk-article-banner-text-color)}.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPNavBarMenuGroup .text.active,.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPNavBarMenuGroup .text:hover,.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPNavBarMenuLink.active,.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPNavBarMenuLink:hover,.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPNavBarTitle .title.active,.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPNavBarTitle .title:hover,.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPSocialLink.active,.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPSocialLink:hover{color:var(--tk-theme-color)}.tk-article-banner~.VPNav .VPNavBar:not(.home).top .divider{display:none}.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPNavBarSearch .DocSearch-Button{background-color:transparent}.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPNavBarSearch .DocSearch-Button .DocSearch-Button-Placeholder,.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPNavBarSearch .DocSearch-Button .tk-icon,.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPNavBarSearch .DocSearch-Button .vp-icon{color:var(--tk-article-banner-text-color)}.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPNavBarSearch .DocSearch-Button .DocSearch-Button-Key{border:none;color:var(--tk-article-banner-text-color)}.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPNavBarSearch .DocSearch-Button .DocSearch-Button-Key:after,.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPNavBarTranslations .text{color:var(--tk-article-banner-text-color)}.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPNavBarHamburger .bottom,.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPNavBarHamburger .middle,.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPNavBarHamburger .top{background-color:var(--tk-article-banner-text-color)}.tk-article-banner~.VPNav .VPNavBar:not(.home).top .VPNavBarExtra .button{color:var(--tk-article-banner-text-color)}.tk-article-banner~.VPNav .VPNavBar:not(.home).top.screen-open{--tk-article-banner-text-color:var(--vp-c-text-1);background-color:var(--vp-nav-bg-color)}@media(max-width:768px){.tk-article-banner~.VPNav{position:absolute}}.tk-article-breadcrumb .home:hover{color:var(--tk-theme-color)!important;cursor:pointer!important}:root{--tk-heading-highlight-color:var(--vp-c-text-1);--tk-heading-highlight-bg-color:var(--vp-c-brand-soft)}.tk-article-heading-highlight{animation:heading-highlight-animation 1.5s ease-in-out}@keyframes heading-highlight-animation{0%{background-color:transparent;box-shadow:0 0 0 8px transparent}10%,35%{background-color:var(--tk-heading-highlight-bg-color);border-color:transparent;border-radius:4px;box-shadow:0 0 0 8px var(--tk-heading-highlight-bg-color);color:var(--tk-heading-highlight-color)}99%{background-color:transparent;border-radius:4px;box-shadow:0 0 0 8px transparent}to{background-color:transparent;border-radius:0;box-shadow:none}}.tk-article-info{color:var(--tk-text-color-regular);font-size:var(--tk-home-font-size-sm)}.tk-article-info.article>span:not(:last-child){margin-right:14px}.tk-article-info__item:not(.split):not(:last-child){margin-right:16px}.tk-article-info__icon{margin-right:3px;vertical-align:-1px}.tk-article-info .split:not(:last-child):after{background-color:var(--tk-text-color-regular);content:"";display:inline-block;height:8px;margin:0 10px;width:.8px}.tk-article-info .or:not(:last-child):after{background-color:var(--tk-text-color-regular);content:"/";display:inline-block;height:0;width:5.6px}.tk-article-overview h2{border-bottom:1px solid var(--vp-c-divider);border-top:none;padding-bottom:16px;padding-top:0}.tk-article-overview h2 .header-anchor{top:0}:root{--tk-nav-color-dilute:hsla(0,0%,100%,.9);--tk-sidebar-color-dilute:hsla(0,0%,100%,.85)}:root.dark{--tk-nav-color-dilute:rgba(27,27,31,.9);--tk-sidebar-color-dilute:rgba(27,27,31,.85)}html[layout-mode=original] body:not(:has(.is-home)):has(.tk-card,.tk-card-nav,.tk-segment,.tk-segment-nav){background-color:var(--tk-bg-color-mute)}html[layout-mode=original] body:not(:has(.is-home)):has(.tk-card,.tk-card-nav,.tk-segment,.tk-segment-nav) .tk-spotlight-hover__under{z-index:0}html[layout-mode=original] .tk-card .VPContent:not(.is-home) .VPDoc.has-sidebar,html[layout-mode=original] .tk-card-nav .VPContent:not(.is-home) .VPDoc.has-sidebar{background-color:var(--tk-bg-color);padding-left:10px;padding-top:0}html[layout-mode=original] .tk-card .VPContent:not(.is-home) .VPDoc:not(.has-sidebar),html[layout-mode=original] .tk-card-nav .VPContent:not(.is-home) .VPDoc:not(.has-sidebar){padding-top:0}html[layout-mode=original] .tk-card .VPContent:not(.is-home) .VPDoc:not(.has-sidebar) .container,html[layout-mode=original] .tk-card-nav .VPContent:not(.is-home) .VPDoc:not(.has-sidebar) .container{background-color:var(--tk-bg-color)}html[layout-mode=original] .tk-card .VPContent:not(.is-home) .VPDoc:not(.has-sidebar) .container>.content,html[layout-mode=original] .tk-card-nav .VPContent:not(.is-home) .VPDoc:not(.has-sidebar) .container>.content{padding-left:0;padding-right:10px}html[layout-mode=original] .tk-segment .VPContent:not(.is-home) .VPDoc,html[layout-mode=original] .tk-segment-nav .VPContent:not(.is-home) .VPDoc{padding:0}html[layout-mode=original] .tk-segment .VPContent:not(.is-home) .VPDoc:not(.has-sidebar) .container>.content,html[layout-mode=original] .tk-segment-nav .VPContent:not(.is-home) .VPDoc:not(.has-sidebar) .container>.content{max-width:845px}html[layout-mode=original] .tk-segment .VPContent:not(.is-home) .VPDoc .container>.content,html[layout-mode=original] .tk-segment-nav .VPContent:not(.is-home) .VPDoc .container>.content{background-color:var(--tk-bg-color)}@media(max-width:1280px){html[layout-mode=original] .tk-segment .VPContent:not(.is-home) .VPDoc .container>.content,html[layout-mode=original] .tk-segment-nav .VPContent:not(.is-home) .VPDoc .container>.content{padding:32px 24px 96px}}html[layout-mode=original] .tk-segment .VPContent:not(.is-home) .VPDoc .aside .aside-container .aside-content,html[layout-mode=original] .tk-segment-nav .VPContent:not(.is-home) .VPDoc .aside .aside-container .aside-content{padding-bottom:20px}html[layout-mode=original] .tk-segment .VPContent:not(.is-home) .VPDoc .aside .aside-container .aside-content .content,html[layout-mode=original] .tk-segment-nav .VPContent:not(.is-home) .VPDoc .aside .aside-container .aside-content .content{background-color:var(--tk-bg-color);border-left:none;border-radius:4px;padding-bottom:10px;padding-right:15px}html[layout-mode=original] .tk-segment .VPContent:not(.is-home) .VPDoc .aside .aside-curtain,html[layout-mode=original] .tk-segment-nav .VPContent:not(.is-home) .VPDoc .aside .aside-curtain{display:none}html[layout-mode=original] .tk-segment .tk-article-share__button,html[layout-mode=original] .tk-segment-nav .tk-article-share__button{background-color:var(--tk-bg-color)}@media(min-width:1440px){html[layout-mode=original] .tk-card-nav .VPNav .VPNavBar.has-sidebar:not(.home) .container>.title,html[layout-mode=original] .tk-segment-nav .VPNav .VPNavBar.has-sidebar:not(.home) .container>.title{padding-left:20px}html[layout-mode=original] .tk-card-nav .VPNav .VPNavBar.has-sidebar:not(.home) .container>.content,html[layout-mode=original] .tk-segment-nav .VPNav .VPNavBar.has-sidebar:not(.home) .container>.content{padding-left:var(--vp-sidebar-width);padding-right:32px}html[layout-mode=original] .tk-card-nav .VPNav .VPNavBar.has-sidebar:not(.home) .container>.content .content-body,html[layout-mode=original] .tk-segment-nav .VPNav .VPNavBar.has-sidebar:not(.home) .container>.content .content-body{background:transparent}html[layout-mode=original] .tk-card-nav .VPNav .VPNavBar.has-sidebar:not(.home) .container>.content .content-body .VPNavBarSearch,html[layout-mode=original] .tk-segment-nav .VPNav .VPNavBar.has-sidebar:not(.home) .container>.content .content-body .VPNavBarSearch{padding-left:0}html[layout-mode=original] .tk-card-nav .VPNav .VPNavBar:not(.has-sidebar) .container,html[layout-mode=original] .tk-segment-nav .VPNav .VPNavBar:not(.has-sidebar) .container{margin:0;max-width:100%}}html[layout-mode=original] .tk-card-nav.Layout .VPNav .VPNavBar:not(.home),html[layout-mode=original] .tk-card.Layout .VPNav .VPNavBar:not(.home),html[layout-mode=original] .tk-segment-nav.Layout .VPNav .VPNavBar:not(.home),html[layout-mode=original] .tk-segment.Layout .VPNav .VPNavBar:not(.home){background-color:var(--tk-bg-color)}@media(min-width:1440px){html[layout-mode=original] .tk-card-nav.Layout .VPNav .VPNavBar:not(.home),html[layout-mode=original] .tk-card.Layout .VPNav .VPNavBar:not(.home),html[layout-mode=original] .tk-segment-nav.Layout .VPNav .VPNavBar:not(.home),html[layout-mode=original] .tk-segment.Layout .VPNav .VPNavBar:not(.home){background-color:var(--tk-nav-color-dilute)}}html[layout-mode=original] .tk-card .VPContent:not(.is-home) .VPDoc,html[layout-mode=original] .tk-card-nav .VPContent:not(.is-home) .VPDoc,html[layout-mode=original] .tk-segment .VPContent:not(.is-home) .VPDoc,html[layout-mode=original] .tk-segment-nav .VPContent:not(.is-home) .VPDoc{position:relative}html[layout-mode=original] .tk-card .VPContent:not(.is-home) .VPDoc .container>.content,html[layout-mode=original] .tk-card-nav .VPContent:not(.is-home) .VPDoc .container>.content,html[layout-mode=original] .tk-segment .VPContent:not(.is-home) .VPDoc .container>.content,html[layout-mode=original] .tk-segment-nav .VPContent:not(.is-home) .VPDoc .container>.content{border-radius:4px;padding-top:20px}html[layout-mode=original] .tk-card .VPContent:not(.is-home) .VPDoc .container>.content main>div,html[layout-mode=original] .tk-card-nav .VPContent:not(.is-home) .VPDoc .container>.content main>div,html[layout-mode=original] .tk-segment .VPContent:not(.is-home) .VPDoc .container>.content main>div,html[layout-mode=original] .tk-segment-nav .VPContent:not(.is-home) .VPDoc .container>.content main>div{z-index:1}html[layout-mode=original] .tk-card .VPNav .VPNavBar.has-sidebar .divider,html[layout-mode=original] .tk-card-nav .VPNav .VPNavBar.has-sidebar .divider,html[layout-mode=original] .tk-segment .VPNav .VPNavBar.has-sidebar .divider,html[layout-mode=original] .tk-segment-nav .VPNav .VPNavBar.has-sidebar .divider{padding:0}html[layout-mode=original] .tk-card .VPNav .VPNavBar.has-sidebar .VPNavBarTitle.has-sidebar .title,html[layout-mode=original] .tk-card-nav .VPNav .VPNavBar.has-sidebar .VPNavBarTitle.has-sidebar .title,html[layout-mode=original] .tk-segment .VPNav .VPNavBar.has-sidebar .VPNavBarTitle.has-sidebar .title,html[layout-mode=original] .tk-segment-nav .VPNav .VPNavBar.has-sidebar .VPNavBarTitle.has-sidebar .title{border:none}@media(min-width:1440px){html[layout-mode=original] .tk-card .VPSidebar,html[layout-mode=original] .tk-card-nav .VPSidebar,html[layout-mode=original] .tk-segment .VPSidebar,html[layout-mode=original] .tk-segment-nav .VPSidebar{background-color:var(--tk-sidebar-color-dilute);padding:0;top:var(--vp-nav-height);width:var(--vp-sidebar-width)}html[layout-mode=original] .tk-card .VPSidebar .nav,html[layout-mode=original] .tk-card-nav .VPSidebar .nav,html[layout-mode=original] .tk-segment .VPSidebar .nav,html[layout-mode=original] .tk-segment-nav .VPSidebar .nav{margin-top:10px}html[layout-mode=original] .tk-card .VPSidebar .nav .group,html[layout-mode=original] .tk-card-nav .VPSidebar .nav .group,html[layout-mode=original] .tk-segment .VPSidebar .nav .group,html[layout-mode=original] .tk-segment-nav .VPSidebar .nav .group{width:245px}html[layout-mode=original] .tk-card .VPSidebar .nav .VPSidebarItem.level-0,html[layout-mode=original] .tk-card-nav .VPSidebar .nav .VPSidebarItem.level-0,html[layout-mode=original] .tk-segment .VPSidebar .nav .VPSidebarItem.level-0,html[layout-mode=original] .tk-segment-nav .VPSidebar .nav .VPSidebarItem.level-0{padding-left:18px}html[layout-mode=original] .tk-card .VPSidebar .nav .VPSidebarItem.level-0 .items,html[layout-mode=original] .tk-card-nav .VPSidebar .nav .VPSidebarItem.level-0 .items,html[layout-mode=original] .tk-segment .VPSidebar .nav .VPSidebarItem.level-0 .items,html[layout-mode=original] .tk-segment-nav .VPSidebar .nav .VPSidebarItem.level-0 .items{padding-left:16px}}@media(min-width:1280px){html[layout-mode=original] .tk-card .VPContent:not(.is-home) .VPDoc,html[layout-mode=original] .tk-card-nav .VPContent:not(.is-home) .VPDoc,html[layout-mode=original] .tk-segment .VPContent:not(.is-home) .VPDoc,html[layout-mode=original] .tk-segment-nav .VPContent:not(.is-home) .VPDoc{margin:20px}html[layout-mode=original] .tk-card .VPContent:not(.is-home) .VPDoc .container>.content .content-container,html[layout-mode=original] .tk-card-nav .VPContent:not(.is-home) .VPDoc .container>.content .content-container,html[layout-mode=original] .tk-segment .VPContent:not(.is-home) .VPDoc .container>.content .content-container,html[layout-mode=original] .tk-segment-nav .VPContent:not(.is-home) .VPDoc .container>.content .content-container{max-width:100%}}.tk-article-share{padding:14px 0}.tk-article-share__button{background-color:var(--vp-c-bg-alt);border:1px solid transparent;border-radius:14px;color:var(--tk-theme-color);cursor:pointer;font-size:14px;font-weight:500;overflow:hidden;padding:7px 14px;position:relative;transition:all var(--tk-transition-duration-slow) cubic-bezier(.25,.8,.25,1);width:100%;z-index:1}.tk-article-share__button:before{background-color:var(--vp-c-brand-soft);content:"";height:100%;left:-100%;position:absolute;top:0;transition:left var(--tk-transition-duration-slow-plus) ease;width:100%;z-index:-1}.tk-article-share__button:hover{background-color:var(--vp-c-brand-soft);border-color:var(--vp-c-brand-soft);transform:translateY(-1px)}.tk-article-share__button:active{transform:scale(.9)}.tk-article-share__button.copied{background-color:var(--vp-c-brand-soft);color:var(--tk-theme-color)}.tk-article-share__button.copied:before{background-color:var(--vp-c-brand-soft);left:0}.tk-article-title .VPBadge.left{margin-right:5px}.tk-article-title .VPBadge.right{margin-left:5px}:root{--tk-article-update-num-color:var(--tk-theme-color);--tk-article-update-more-color:var(--vp-c-brand-2)}.tk-article-update{border:1px solid var(--vp-c-divider);border-radius:8px;margin:16px 0}.tk-article-update__title{border-bottom:1px solid var(--vp-c-divider);font-size:18px;padding:16px}.tk-article-update__title .edit-icon{margin-right:5px}.tk-article-update>ul{overflow:hidden}.tk-article-update>ul>li{border-bottom:1px dotted var(--vp-c-divider);height:50px;padding:8px 0;width:100%}.tk-article-update>ul>li:last-child{color:var(--tk-article-update-more-color)}.tk-article-update>ul>li:last-child:hover{color:var(--tk-theme-color)}.tk-article-update--num{color:var(--tk-article-update-num-color);font-size:17px;margin:0;text-align:center;width:50px}.tk-article-update__content{display:flex;flex:1}.tk-article-update__content a{padding-right:10px;width:180px}.tk-article-update__content a:hover{text-decoration:underline;text-decoration-color:var(--tk-theme-color)}.tk-article-update__content--date{color:var(--vp-c-text-3);font-size:14px;margin-right:15px;max-width:160px}:root{--tk-body-bg-img-nav-color:hsla(0,0%,100%,.9);--tk-body-bg-img-sidebar-color:hsla(0,0%,100%,.85)}:root.dark{--tk-body-bg-img-nav-color:rgba(27,27,31,.9);--tk-body-bg-img-sidebar-color:rgba(27,27,31,.85)}.tk-body-bg-image{background:var(--tk-body-bg-img);height:100vh;left:0;opacity:var(--tk-body-bg-img-opacity);position:fixed;top:0;transition:background-image 1s;width:100vw;z-index:-999999}.tk-body-bg-image .mask{background-color:var(--tk-body-mask-bg-color);height:100%;width:100%}.tk-body-bg-image~.tk-layout.Layout .VPContent:not(.is-home){background-color:var(--tk-bg-color)}@media(min-width:1280px){.tk-body-bg-image~.tk-layout.Layout header.VPNav .VPNavBar:not(.full-img-nav-bar).home,.tk-body-bg-image~.tk-layout.Layout header.VPNav .VPNavBar:not(.full-img-nav-bar):not(.home){background-color:var(--tk-body-bg-img-nav-color)}.tk-body-bg-image~.tk-layout.Layout.tk-card .VPNav .VPNavBar:not(.home) .content-body,.tk-body-bg-image~.tk-layout.Layout.tk-card-nav .VPNav .VPNavBar:not(.home) .content-body,.tk-body-bg-image~.tk-layout.Layout.tk-segment .VPNav .VPNavBar:not(.home) .content-body,.tk-body-bg-image~.tk-layout.Layout.tk-segment-nav .VPNav .VPNavBar:not(.home) .content-body{background-color:transparent}.tk-body-bg-image~.tk-layout.Layout.tk-card .VPSidebar,.tk-body-bg-image~.tk-layout.Layout.tk-card-nav .VPSidebar,.tk-body-bg-image~.tk-layout.Layout.tk-segment .VPSidebar,.tk-body-bg-image~.tk-layout.Layout.tk-segment-nav .VPSidebar{background-color:var(--tk-body-bg-img-sidebar-color)}.tk-body-bg-image~.tk-layout.Layout.tk-card .VPSidebar .curtain,.tk-body-bg-image~.tk-layout.Layout.tk-card-nav .VPSidebar .curtain,.tk-body-bg-image~.tk-layout.Layout.tk-segment .VPSidebar .curtain,.tk-body-bg-image~.tk-layout.Layout.tk-segment-nav .VPSidebar .curtain{background-color:transparent}}.tk-body-bg-image~.tk-layout.Layout .VPContent.is-home .vp-doc>div{background-color:var(--tk-bg-color);border-radius:4px;padding:0 32px 1px;width:calc(var(--tk-home-max-width) - var(--tk-home-card-width))}.tk-body-bg-image~.tk-layout.Layout .VPNavBar.home .divider{display:none}html[layout-mode=original] .tk-body-bg-image~.tk-layout.Layout.tk-card .VPContent:not(.is-home),html[layout-mode=original] .tk-body-bg-image~.tk-layout.Layout.tk-card-nav .VPContent:not(.is-home),html[layout-mode=original] .tk-body-bg-image~.tk-layout.Layout.tk-segment .VPContent:not(.is-home),html[layout-mode=original] .tk-body-bg-image~.tk-layout.Layout.tk-segment-nav .VPContent:not(.is-home){background-color:transparent}.tk-border-highlight{border-radius:6px;outline-color:transparent;outline-offset:4px;outline-style:dashed;outline-width:2px;transition:outline var(--tk-transition-duration-fast) cubic-bezier(.4,0,.2,1)}.tk-border-highlight.is-active{outline-color:var(--vp-c-brand-1)}.tk-sub-catalogue{margin-bottom:28px;margin-top:16px;width:100%}.tk-sub-catalogue__title .anchor{color:var(--tk-theme-color);font-size:.85em;margin-left:-1em;opacity:0;padding-right:.38em}.tk-sub-catalogue__title .anchor:hover{text-decoration:underline}.tk-sub-catalogue__title span{font-size:17.6px}.tk-sub-catalogue__title:hover .anchor{opacity:1}.tk-sub-catalogue__inline{margin-left:16px;margin-top:11px}.tk-sub-catalogue__inline .tk-sub-catalogue{margin-bottom:0}.tk-catalogue-item{margin-bottom:8px;width:48%}.tk-catalogue-item a,.tk-catalogue-item a:hover{color:var(--tk-theme-color)}@media(max-width:768px){.tk-catalogue-item{width:100%}}.tk-catalogue__header{border-bottom:1px solid var(--tk-line-color);margin-top:16px;padding-bottom:19px}.tk-catalogue__header .description{margin-top:10px}.tk-catalogue__wrapper .title{font-size:23px;margin:32px 0 16px}.tk-catalogue__wrapper .post{display:inline-block;margin-bottom:16px;width:50%}:root{--tk-code-block-fold-height:40px;--tk-code-block-lang-transform:uppercase}html[code-block=tk]:root{--vp-icon-copy:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='rgba(60,60,67,1)' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Crect width='8' height='4' x='8' y='2' rx='1' ry='1'/%3E%3Cpath d='M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2'/%3E%3C/svg%3E");--vp-icon-copied:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='rgba(60,60,67,1)' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Crect width='8' height='4' x='8' y='2' rx='1' ry='1'/%3E%3Cpath d='M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2'/%3E%3Cpath d='m9 14 2 2 4-4'/%3E%3C/svg%3E")}html[code-block=tk]:root.dark{--vp-icon-copy:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='rgba(223,223,214,1)' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Crect width='8' height='4' x='8' y='2' rx='1' ry='1'/%3E%3Cpath d='M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2'/%3E%3C/svg%3E");--vp-icon-copied:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='rgba(223,223,214,1)' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Crect width='8' height='4' x='8' y='2' rx='1' ry='1'/%3E%3Cpath d='M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2'/%3E%3Cpath d='m9 14 2 2 4-4'/%3E%3C/svg%3E")}html[code-block=tk] .tk-postItem__info__left__excerpt div[class*=language-],html[code-block=tk] .vp-doc :not(.tk-vp-code)>div[class*=language-]{overflow:hidden;transition:height var(--tk-transition-duration) ease-in-out}html[code-block=tk] .tk-postItem__info__left__excerpt div[class*=language-] .vp-code,html[code-block=tk] .vp-doc :not(.tk-vp-code)>div[class*=language-] .vp-code{padding-top:var(--tk-code-block-fold-height)}html[code-block=tk] .tk-postItem__info__left__excerpt div[class*=language-] .line-numbers-wrapper,html[code-block=tk] .vp-doc :not(.tk-vp-code)>div[class*=language-] .line-numbers-wrapper{margin-top:var(--tk-code-block-fold-height);padding-top:0}html[code-block=tk] .tk-postItem__info__left__excerpt div[class*=language-]:before,html[code-block=tk] .vp-doc :not(.tk-vp-code)>div[class*=language-]:before{background:#fc625d;border-radius:50%;box-shadow:20px 0 #fdbc40,40px 0 #35cd4b;content:"";display:block;height:12px;left:14px;position:absolute;top:calc(var(--tk-code-block-fold-height)/2);transform:translateY(-50%);width:12px}html[code-block=tk] .tk-postItem__info__left__excerpt div[class*=language-] span.lang,html[code-block=tk] .vp-doc :not(.tk-vp-code)>div[class*=language-] span.lang{color:var(--vp-c-text-1);font-size:18px;font-weight:700;left:75px;position:absolute;text-transform:var(--tk-code-block-lang-transform);top:calc(var(--tk-code-block-fold-height)/2);transform:translateY(-50%);width:-moz-fit-content;width:fit-content;z-index:3}html[code-block=tk] .tk-postItem__info__left__excerpt div[class*=language-] button.copy,html[code-block=tk] .vp-doc :not(.tk-vp-code)>div[class*=language-] button.copy{background-color:transparent;background-size:14px;border:none;height:18px;opacity:1;position:absolute;right:36px;top:calc(var(--tk-code-block-fold-height)/2);transform:translateY(-50%);width:18px}html[code-block=tk] .tk-postItem__info__left__excerpt div[class*=language-] button.copy:focus,html[code-block=tk] .tk-postItem__info__left__excerpt div[class*=language-] button.copy:focus+span.lang,html[code-block=tk] .tk-postItem__info__left__excerpt div[class*=language-]:hover button.copy+span.lang,html[code-block=tk] .tk-postItem__info__left__excerpt div[class*=language-]:hover>button.copy,html[code-block=tk] .vp-doc :not(.tk-vp-code)>div[class*=language-] button.copy:focus,html[code-block=tk] .vp-doc :not(.tk-vp-code)>div[class*=language-] button.copy:focus+span.lang,html[code-block=tk] .vp-doc :not(.tk-vp-code)>div[class*=language-]:hover button.copy+span.lang,html[code-block=tk] .vp-doc :not(.tk-vp-code)>div[class*=language-]:hover>button.copy{opacity:1}html[code-block=tk] .tk-postItem__info__left__excerpt div[class*=language-] .code-arrow,html[code-block=tk] .vp-doc :not(.tk-vp-code)>div[class*=language-] .code-arrow{color:var(--vp-c-text-2);cursor:pointer;position:absolute;right:14px;top:calc(var(--tk-code-block-fold-height)/2);transform:translateY(-50%);transition:all var(--tk-transition-duration);-webkit-user-select:none;-moz-user-select:none;user-select:none;z-index:3}html[code-block=tk] .tk-postItem__info__left__excerpt div[class*=language-] .code-arrow:hover,html[code-block=tk] .vp-doc :not(.tk-vp-code)>div[class*=language-] .code-arrow:hover{color:var(--vp-c-text-1)}html[code-block=tk] .tk-postItem__info__left__excerpt div[class*=language-] .code-arrow svg,html[code-block=tk] .vp-doc :not(.tk-vp-code)>div[class*=language-] .code-arrow svg{height:16px;width:16px;fill:var(--vp-c-text-1)}html[code-block=tk] .tk-postItem__info__left__excerpt div[class*=language-] .code-arrow.fold,html[code-block=tk] .vp-doc :not(.tk-vp-code)>div[class*=language-] .code-arrow.fold{transform:rotate(90deg) translate(-50%)}html[code-block=tk] .tk-postItem__info__left__excerpt div[class*=language-] .code-block-overlay,html[code-block=tk] .vp-doc :not(.tk-vp-code)>div[class*=language-] .code-block-overlay{align-items:center;background:linear-gradient(#0a0a0a00,#0a0a0af2);bottom:0;color:#ffffffe6;cursor:pointer;display:flex;font-size:20px;height:70px;justify-content:center;left:0;padding:0 24px;position:absolute;right:0;transition:opacity var(--tk-transition-duration) ease,color var(--tk-transition-duration) ease;z-index:10}html[code-block=tk] .tk-postItem__info__left__excerpt div[class*=language-] .code-block-overlay:hover,html[code-block=tk] .vp-doc :not(.tk-vp-code)>div[class*=language-] .code-block-overlay:hover{color:#fff;opacity:.8}html[code-block=tk] .tk-postItem__info__left__excerpt div[class*=language-] .code-block-overlay .overlay-icon,html[code-block=tk] .vp-doc :not(.tk-vp-code)>div[class*=language-] .code-block-overlay .overlay-icon{font-size:18px;margin-left:6px}.tk-artalk{--at-color-main:var(--vp-c-brand-2)}.tk-demo-code-description{font-size:14px;line-height:20px;margin-bottom:16px;margin-top:16px}.tk-demo-code{border:1px solid var(--vp-c-divider);border-radius:4px 4px 0 0}.tk-demo-code__effect{margin:.5px;overflow-y:auto;padding:24px}.tk-demo-code__button-group{align-items:center;border-top:1px solid var(--vp-c-divider);display:flex;height:40px;justify-content:flex-end;padding:8px}.tk-demo-code__button-group .tk-icon{color:var(--vp-c-text-1);cursor:pointer;margin:0 8px;opacity:.5;transition:opacity var(--tk-transition-duration);-webkit-user-select:none;-moz-user-select:none;user-select:none}.tk-demo-code__button-group .tk-icon:hover{opacity:1}.tk-demo-code .language-vue{border-radius:0!important;margin:0!important}.tk-demo-code__float-control{align-items:center;background-color:var(--tk-bg-color);border-bottom-left-radius:4px;border-bottom-right-radius:4px;border-left:1px solid var(--vp-c-divider);border-top:1px solid var(--vp-c-divider);bottom:0;color:var(--vp-c-text-1);cursor:pointer;display:flex;height:40px;justify-content:center;left:0;margin-top:-1px;position:sticky;right:0;z-index:10}.tk-demo-code__float-control span{font-size:14px;margin-left:10px}.tk-demo-code__float-control:hover{color:var(--tk-theme-color)}.tk-footer-group{display:grid;gap:20px 16px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));margin:20px auto;max-width:var(--tk-home-footer-group-width);padding-bottom:20px;width:100%}.tk-footer-group>div{padding-left:25%}.tk-footer-group__title{display:inline-flex;font-size:16px;font-weight:700;margin-bottom:14px;opacity:.9}.tk-footer-group__link{color:var(--vp-c-text-1);font-size:14px}.tk-footer-group__link a{align-items:center;border-radius:12px;display:inline-flex;margin-left:-10px;max-width:120px;padding:8px 10px;transition:color var(--tk-transition-duration) ease,background-color var(--tk-transition-duration) ease;width:-moz-max-content;width:max-content}.tk-footer-group__link a:hover{background-color:var(--tk-fill-color-light)}.tk-footer-group__link__external-icon{margin-left:4px}@media(max-width:640px){.tk-footer-group{grid-template-columns:repeat(2,1fr)}}:root{--tk-footer-gap:var(--tk-gap2)}.tk-footer-info{padding:0 20px 12px;text-align:center;width:100%}.tk-footer-info__icons{gap:var(--tk-footer-gap)}.tk-footer-info p{color:var(--vp-c-text-2);font-size:14px;font-weight:500;line-height:24px}.tk-footer-info__list{color:var(--vp-c-text-2);font-size:14px;gap:15px}.tk-footer-info__list__item{gap:5px}.tk-footer-info__list__item a:hover{color:var(--tk-theme-color);text-decoration:underline;text-decoration-color:var(--tk-theme-color);text-decoration-style:dashed}@media(max-width:719px){.tk-footer-info__list{align-items:center;flex-direction:column;gap:0}}.tk-banner-content{color:var(--tk-banner-text-color);padding-top:48px;text-align:center;width:100%}.tk-banner-content__title{font-size:var(--tk-banner-title-text);font-weight:600;line-height:1.25}.tk-banner-content__desc{font-size:var(--tk-banner-desc-text);line-height:1.3;margin:24px auto;max-width:800px;min-height:32px}@media(max-width:640px){.tk-banner-content__desc{margin:24px 10px}}.tk-banner-content__desc .switch{cursor:pointer}.tk-banner-content__desc .typed{opacity:1}.tk-banner-content__desc .typed.is-animation{animation:fade-out 1s infinite}@keyframes fade-out{0%{opacity:1}to{opacity:0}}:root{--tk-home-banner-feature-row-gap:var(--tk-gap2)}.tk-banner-feature{margin:40px auto 0;max-width:1100px;overflow:hidden;padding:32px 0;position:relative;row-gap:var(--tk-home-banner-feature-row-gap);width:100%}.tk-banner-feature__feature__item{color:var(--tk-banner-text-color);text-align:center;width:30%}.tk-banner-feature__feature__item .feature-img{animation:heart 1.2s ease-in-out 0s infinite alternate;animation-play-state:paused;height:160px;width:160px}.tk-banner-feature__feature__item .feature-img:hover{animation-play-state:running}.tk-banner-feature__feature__item .feature-title{font-size:21px;font-weight:500;margin-top:16px}.tk-banner-feature__feature__item .feature-details{margin:16px;opacity:.8}.tk-banner-feature__feature__item.tk-slide-next-enter-from{opacity:0!important;transform:translate(100%)!important}@media(max-width:719px){.tk-banner-feature__feature__item{width:100%}}@keyframes heart{0%{transform:translate(0)}to{transform:translateY(8px)}}.tk-banner-bg-image.part{min-height:var(--tk-home-banner-part-min-height)}.tk-banner-bg-image.full{height:100vh;left:0;position:absolute;top:0;width:100%}.tk-banner-bg-image.full,.tk-banner-bg-image.part{background:var(--tk-banner-img-bg) fixed;transition:background 1s}.tk-banner-bg-image.full .mask,.tk-banner-bg-image.part .mask{background-color:var(--tk-banner-mask-bg-color);height:100%;position:absolute;width:100%}.tk-banner-bg-pure{min-height:var(--tk-home-banner-part-min-height)}:root{--tk-waves-fill-color-1:hsla(0,0%,99%,.7);--tk-waves-fill-color-2:hsla(0,0%,99%,.5);--tk-waves-fill-color-3:hsla(0,0%,99%,.3);--tk-waves-fill-color-4:var(--tk-bg-color-elm)}:root.dark{--tk-waves-fill-color-1:rgba(34,34,34,.7);--tk-waves-fill-color-2:rgba(34,34,34,.5);--tk-waves-fill-color-3:rgba(34,34,34,.3)}.tk-banner-waves{height:12vh;margin-top:-11vh;max-height:150px;min-height:50px;position:relative;width:100%;z-index:10}.tk-banner-waves .parallax .use{animation:move-forever 25s cubic-bezier(.55,.5,.45,.5) infinite}.tk-banner-waves .parallax .use:first-child{animation-delay:-2s;animation-duration:7s;fill:var(--tk-waves-fill-color-1)}.tk-banner-waves .parallax .use:first-child :is(.dark .dark\:fill-black){fill:#000!important}.tk-banner-waves .parallax .use:nth-child(2){animation-delay:-3s;animation-duration:10s;fill:var(--tk-waves-fill-color-2)}.tk-banner-waves .parallax .use:nth-child(2) :is(.dark .dark\:fill-black){fill:#000}.tk-banner-waves .parallax .use:nth-child(3){animation-delay:-4s;animation-duration:13s;fill:var(--tk-waves-fill-color-3)}.tk-banner-waves .parallax .use:nth-child(4){animation-delay:-5s;animation-duration:20s;fill:var(--tk-waves-fill-color-4)}@keyframes move-forever{0%{transform:translate3d(-90px,0,0)}to{transform:translate3d(85px,0,0)}}:root{--tk-home-banner-part-min-height:450px;--tk-bg-img-default:#28282d url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACMAAAAjCAYAAAAe2bNZAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAABOSURBVFhH7c6xCQAgDAVRR9A6E4hLu4uLiWJ7tSnuQcIvr2TRYsw3/zOGGEOMIcYQY4gxxBhiDDGGGEOMIcYQY4gxxBhiDLkx52W4Gn1tuslCtHJvL54AAAAASUVORK5CYII=)}.tk-banner{position:relative}.tk-banner.is-full-img{margin-top:calc(var(--vp-nav-height)*-1)}.tk-banner.is-full-img .tk-banner__content{height:100vh}.tk-banner.is-full-img .tk-banner__content.no-feature{padding-bottom:15vh}.tk-banner__content{display:flex;flex-direction:column;justify-content:center;min-height:var(--tk-home-banner-part-min-height);position:relative}.tk-banner__content.no-feature{padding-bottom:10vh}.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open){background-color:transparent;color:var(--vp-c-white)}.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPNavBarMenuGroup .text,.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPNavBarMenuLink,.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPNavBarTitle .title,.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPSocialLink{color:var(--vp-c-white)}.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPNavBarMenuGroup .text.active,.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPNavBarMenuGroup .text:hover,.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPNavBarMenuLink.active,.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPNavBarMenuLink:hover,.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPNavBarTitle .title.active,.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPNavBarTitle .title:hover,.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPSocialLink.active,.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPSocialLink:hover{color:var(--tk-theme-color)}.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .divider{display:none}.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPNavBarSearch .DocSearch-Button{background-color:transparent}.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPNavBarSearch .DocSearch-Button .DocSearch-Button-Placeholder,.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPNavBarSearch .DocSearch-Button .tk-icon,.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPNavBarSearch .DocSearch-Button .vp-icon{color:var(--vp-c-white)}.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPNavBarSearch .DocSearch-Button .DocSearch-Button-Key{border:none;color:var(--vp-c-white)}.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPNavBarSearch .DocSearch-Button .DocSearch-Button-Key:after,.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPNavBarTranslations .text{color:var(--vp-c-white)}.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPNavBarHamburger .bottom,.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPNavBarHamburger .middle,.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPNavBarHamburger .top{background-color:var(--vp-c-white)}.tk-layout .VPNavBar.home.full-img-nav-bar:not(.screen-open) .VPNavBarExtra .button{color:var(--vp-c-white)}:root{--tk-home-info-gap:var(--tk-gap1)}.tk-home-card-list{gap:var(--tk-home-info-gap)}.tk-category.is-page{max-height:calc(100vh - 160px);min-height:67px;overflow-y:auto;position:sticky;top:72px}.tk-category__list{margin-top:5px;position:relative}.tk-category__list a{border-left:2px solid transparent;display:flex;font-size:var(--tk-home-font-size-middle);justify-content:space-between;margin-top:-1px;padding:2px 5px;transition:background-color var(--tk-transition-duration-fast),border-color var(--tk-transition-duration-fast),color var(--tk-transition-duration-fast),opacity var(--tk-transition-duration-slow) ease,transform var(--tk-transition-duration-slow) ease;width:100%}.tk-category__list a:hover{background-color:var(--tk-fill-color-light);border-color:var(--tk-theme-color)}.tk-category__list a.active{background:var(--tk-theme-color);border-color:transparent;border-radius:1px;color:var(--tk-bg-color);padding-left:13px}.tk-category--empty{font-size:var(--tk-home-font-size-middle);padding:6px;text-align:center}.tk-doc-analysis__item{display:flex;font-size:var(--tk-home-font-size-middle);justify-content:space-between;padding:1px 2px}.tk-home-features{margin:auto;max-width:1280px}@media(min-width:960px){.tk-home-features{padding:0 64px;width:100%}}@media(min-width:640px){.tk-home-features{padding:0 48px}}.tk-home-features .header h2{border-top:none;font-size:48px;font-weight:400;letter-spacing:0;line-height:48px;margin-bottom:32px;padding-top:12px}.tk-home-features .header p{font-size:18px;margin:18px 0}.tk-home-features .item{border-radius:8px;overflow:hidden;padding:16px;transition:background .3s cubic-bezier(.4,0,.2,1),box-shadow .3s cubic-bezier(.4,0,.2,1),transform .3s cubic-bezier(.4,0,.2,1);width:100%}.tk-home-features .item:hover{background-color:transparent;box-shadow:var(--tk-hover-shadow);transform:scale(1.05)}.tk-home-features .item .feature-icon{font-size:inherit;margin-right:6px}.tk-home-features a{color:inherit;text-decoration:none}.tk-home-features a:hover{color:inherit}.tk-home-features__feature-wrapper{padding-top:24px;position:relative;text-align:center}.tk-home-features__feature__content .image{height:160px;margin:0 auto}.tk-home-features__feature__content .features{align-content:stretch;align-items:stretch;display:flex;flex-wrap:wrap;justify-content:space-around;margin-top:16px;text-align:start}@media(max-width:719px){.tk-home-features__feature__content .features{gap:10px}}@media(max-width:640px){.tk-home-features__feature__content .features{padding-inline-end:24px;padding-inline-start:24px}}.tk-home-features__feature__content .features__item{flex-basis:calc(33% - 48px);margin:8px}.tk-home-features__feature__content .features__item:first-child:nth-last-child(2),.tk-home-features__feature__content .features__item:nth-child(2):last-child{flex-basis:calc(50% - 3rem)}@media(min-width:1440px){.tk-home-features__feature__content .features__item{flex-basis:calc(25% - 48px)}}@media(max-width:719px){.tk-home-features__feature__content .features__item{flex-basis:100%;font-size:15.2px;padding:0 16px}}.tk-home-features__feature__content .features__item h3{font-size:20.8px;font-weight:700;margin:4px 0 8px}.tk-home-features__feature__content .features__item p{margin:0}.tk-home-features__highlight-wrapper{position:relative}.tk-home-features__highlight-wrapper:nth-child(2n) .tk-home-features__highlight{flex-flow:row-reverse}.tk-home-features__highlight{align-items:center;display:flex;flex:1;justify-content:flex-end;padding:40px}@media(max-width:719px){.tk-home-features__highlight{display:block;padding-inline-end:24px;padding-inline-start:24px}}.tk-home-features__highlight .image{margin:32px 64px;width:192px}@media(max-width:959px){.tk-home-features__highlight .image{width:160px}}@media(max-width:719px){.tk-home-features__highlight .image{margin:0 auto;width:128px}}.tk-home-features__highlight__content{display:flex;flex:1;flex-direction:column;gap:5px;text-align:start}.tk-home-features__highlight__content .highlights__item{display:block}.tk-home-features__highlight__content .highlights__item.no-details:hover{box-shadow:none;transform:none}.tk-home-features__highlight__content .highlights__item h3{font-size:18px;font-weight:600;margin-top:0}.tk-home-features__highlight__content .highlights__item p{margin:0}.tk-home-features__highlight__header{padding-left:3ch}:root{--tk-home-friend-link-gap:var(--tk-gap2)}.tk-friend-link__list{gap:var(--tk-home-friend-link-gap);padding-right:5px;position:relative}.tk-friend-link__list__item{padding:0 5px}.tk-friend-link__list__item a{gap:15px}.tk-friend-link__list__item a .friend-avatar{border-radius:50%;height:50px;min-width:50px;overflow:hidden;transition:all .6s;width:50px}.tk-friend-link__list__item a .friend-avatar .avatar{height:100%;width:100%}.tk-friend-link__list__item__info{min-width:0}.tk-friend-link__list__item__info .friend-name{font-size:var(--tk-home-font-size-middle);font-weight:450}.tk-friend-link__list__item__info .friend-desc{color:var(--vp-c-text-2);font-size:var(--tk-home-font-size-middle)}.tk-friend-link--empty{font-size:var(--tk-"" home-font-size-middle);padding:6px;text-align:center}html.tk-fullscreen-wallpaper{overflow:hidden}html.tk-fullscreen-wallpaper .VPNav,html.tk-fullscreen-wallpaper .tk-wallpaper-outside{display:none}.tk-my-screen{border-bottom:1px solid var(--vp-c-divider);display:flex;gap:16px;margin-bottom:15px;padding-bottom:10px}.tk-my-screen__avatar{border-radius:5px;height:60px;width:60px}.tk-my-screen__blogger{flex:1}.tk-my-screen__blogger .name{font-size:18px;font-weight:600;margin-bottom:6px}.tk-my-screen__blogger .slogan{font-size:15px}.tk-my{position:relative}.tk-my.is-circle-bg{background-color:transparent}.tk-my__avatar{margin-bottom:10px;width:100%}.tk-my__avatar.circle-rotate img{transition:var(--tk-transition-duration-slow-plus) ease}.tk-my__avatar.circle-rotate img:hover{transform:rotate(1turn) scale(1.1)}.tk-my__avatar.circle-rotate-last img:hover{transform:rotate(666turn);transition-duration:59s;transition-timing-function:cubic-bezier(.34,0,.84,1)}.tk-my__avatar.square{margin:calc(var(--tk-home-card-padding)*-1) calc(var(--tk-home-card-padding)*-1) 10px;width:var(--tk-home-card-width)}@media(max-width:768px){.tk-my__avatar.square>span img{width:240px}}.tk-my__avatar>div{position:relative}.tk-my__avatar>div .avatar-sticker{align-items:center;border-radius:50%;bottom:3px;display:flex;justify-content:center;position:absolute;right:3px;transform:scale(1);transition:.3s ease-out .2s;z-index:0}.tk-my__avatar__circle--bg{background-position:50%;background-repeat:no-repeat;background-size:cover;height:100%;left:0;position:absolute;right:0;top:0;z-index:-1}.tk-my__avatar__circle--bg.is-mask:after{background:linear-gradient(to bottom,rgba(0,0,0,.3) 0,var(--tk-bg-color-elm) 100%);bottom:0;content:"";height:100%;left:0;opacity:.5;position:absolute;right:0}.tk-my__icons{margin-bottom:5px}.tk-my__blogger{padding:5px 5px 0;text-align:left}.tk-my__blogger .name{display:block;font-size:21px;margin-bottom:6px;text-align:center}.tk-my__blogger .slogan{display:-webkit-box;overflow:hidden;text-overflow:ellipsis;-webkit-box-orient:vertical;line-clamp:3;-webkit-line-clamp:3}@media(max-width:768px){.tk-my{text-align:center}}.tk-post-item{background-color:var(--tk-bg-color-elm);border-radius:8px;box-shadow:var(--tk-card-shadow);margin-bottom:14px;overflow:hidden;position:relative;transition:box-shadow var(--tk-transition-duration-slow) cubic-bezier(.4,0,.2,1),transform var(--tk-transition-duration-slow) cubic-bezier(.4,0,.2,1);width:100%}.tk-post-item:hover{box-shadow:var(--tk-hover-shadow);transform:scale(1.01)}.tk-post-item .pin{height:30px;left:-4px;opacity:.5;overflow:hidden;position:absolute;top:-4px;width:30px;z-index:9}.tk-post-item .pin:before{background-image:linear-gradient(45deg,var(--tk-theme-color),var(--tk-theme-color));box-shadow:0 5px 10px #0000003b;content:"";height:30px;position:absolute;transform:rotate(-45deg) translateY(-20px);width:120%}.tk-post-item__left{flex:1;padding:16px 24px;width:100%}.tk-post-item__left__title{cursor:pointer;display:block;font-size:20px;font-weight:600}.tk-post-item__left__footer{margin-top:8px}.tk-post-item__left__excerpt{margin:8px 0}.tk-post-item__left__excerpt.bottom{border-top:1px solid var(--tk-line-color)}.tk-post-item__left__excerpt.bottom .excerpt{display:-webkit-box;margin:8px 0;overflow:hidden;text-overflow:ellipsis;-webkit-box-orient:vertical;line-clamp:var(--tk-home-post-line-clamp);-webkit-line-clamp:var(--tk-home-post-line-clamp)}.tk-post-item__left__excerpt .excerpt{color:var(--tk-text-color-secondary);font-size:14px}.tk-post-item__left__excerpt .excerpt h1,.tk-post-item__left__excerpt .excerpt h2,.tk-post-item__left__excerpt .excerpt h3{display:none}.tk-post-item__left__excerpt .excerpt img{margin:0 auto;max-height:280px;max-width:100%}.tk-post-item__left__excerpt .more{color:var(--vp-c-brand-2);float:right;line-height:16px;margin-right:16px}.tk-post-item__left__excerpt .more:hover{color:var(--tk-theme-color)}.tk-post-item__right .cover{cursor:pointer}.tk-post-item__right .cover.default .cover-img{background-position:50%;background-repeat:no-repeat;background-size:contain;border-radius:2px;height:var(--tk-home-post-simple-img-height);margin-right:24px;width:var(--tk-home-post-simple-img-width)}.tk-post-item__right .cover.full{height:100%}.tk-post-item__right .cover.full .cover-img{clip-path:polygon(0 0,100% 0,100% 100%,8% 100%);height:var(--tk-home-post-full-img-height);max-width:var(--tk-home-post-full-img-width);transition:transform var(--tk-transition-duration) linear}.tk-post-item__right .cover.full .cover-img:hover{transform:scale(1.1)}@media(max-width:640px){.tk-post-item__right{display:none}}.tk-post-item-card{background-color:var(--tk-bg-color-elm);border-radius:8px;box-shadow:var(--tk-card-shadow);height:100%;overflow:hidden;position:relative;transition:box-shadow var(--tk-transition-duration-slow) cubic-bezier(.4,0,.2,1),transform var(--tk-transition-duration-slow) cubic-bezier(.4,0,.2,1)}.tk-post-item-card:hover{box-shadow:var(--tk-hover-shadow);transform:scale(1.01)}.tk-post-item-card .top{color:var(--tk-top-color,var(--tk-theme-color));opacity:.8;position:absolute;right:-4px;top:-5px;z-index:9}.tk-post-item-card__cover-img{overflow:hidden}.tk-post-item-card__cover-img .cover-img{cursor:pointer;height:100%;-o-object-fit:cover;object-fit:cover;transition:transform var(--tk-transition-duration) linear;width:100%}.tk-post-item-card__cover-img .cover-img:hover{transform:scale(1.2)}.tk-post-item-card__info{margin-bottom:10px;padding:10px 15px}.tk-post-item-card__info .title{cursor:pointer;display:block;font-size:18px;font-weight:600;margin-bottom:10px}.tk-post-item-card__info .excerpt{color:var(--tk-text-color-secondary);font-size:12px;margin-bottom:10px}.tk-post-item-card__info .tk-article-info__item:not(.split):not(:last-child){margin-right:10px}.tk-post-list.is-card>ul{-moz-column-gap:1.1rem;column-gap:1.1rem;display:grid;grid-auto-flow:row dense;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));row-gap:1.1rem}.tk-post-list__empty{margin:.5px;padding:24px}.tk-post-list__empty__title{margin-top:20px}.tk-post-list .tk-pagination{padding:15px 2px 0}.tk-post-list li.full-img:nth-child(2n) .list{flex-direction:row-reverse}.tk-post-list li.full-img:nth-child(2n) .list .full .cover-img{clip-path:polygon(0 0,92% 0,100% 100%,0 100%)}.tk-tag.is-page{max-height:calc(100vh - 160px);min-height:67px;overflow-y:auto;position:sticky;top:72px}.tk-tag__list{margin-top:5px;position:relative}.tk-tag__list a{border-radius:3px;display:inline-block;font-size:var(--tk-home-font-size-small);height:24px;line-height:24px;margin:0 5px 6px;padding:0 7px;text-align:center;transition:transform var(--tk-transition-duration) cubic-bezier(.4,0,.2,1)}.tk-tag__list a:hover{transform:translateY(-2px) scale(1.05)}.tk-tag__list a.active{box-shadow:0 5px 10px -5px var(--tk-home-tag-bg-color);transform:scale(1.15)}.tk-tag__list a.active:hover{text-decoration:none}.tk-tag__list a .num{font-size:12px;position:relative;right:-3px;top:-8px}.tk-tag__list .more{color:var(--vp-c-text-1);font-size:var(--tk-home-font-size-middle);line-height:var(--tk-home-font-size-middle)}.tk-tag__list .more:hover{color:var(--tk-theme-color);transform:none}.tk-tag--empty{font-size:var(--tk-home-font-size-middle);padding:6px;text-align:center}:root{--tk-home-top-article-gap:var(--tk-gap1)}.tk-top-article__list{gap:var(--tk-home-top-article-gap);padding-right:5px;position:relative}.tk-top-article__list__item{display:flex;gap:10px}.tk-top-article__list__item .num{border-radius:8px 0;color:var(--tk-text-color-secondary);font-size:var(--tk-home-font-size-middle);font-style:italic;font-weight:600;height:18px;line-height:18px;margin-top:4px;padding:0 6px}.tk-top-article__list__item .num.sticky{background-color:var(--tk-num-bg-color);border-radius:8px 0;color:var(--vp-c-white);font-size:var(--tk-home-font-size-small)}.tk-top-article__list__item__info{min-width:0}.tk-top-article__list__item__info .title{font-size:var(--tk-home-font-size-middle);font-weight:450}.tk-top-article__list__item__info .date{color:var(--vp-c-text-2);font-size:var(--tk-home-font-size-small)}.tk-top-article--empty{font-size:var(--tk-home-font-size-middle);padding:6px;text-align:center}.tk-home__content{gap:var(--tk-home-gap);margin:48px auto 0;max-width:var(--tk-home-max-width)}.tk-home__content__post{flex:1;min-width:400px}.tk-home__content__info{position:sticky;top:calc(var(--vp-nav-height) + 10px)}.tk-home__content__info.is-left{order:-1}@media(max-width:768px){.tk-home__content__info.is-left{order:1}}@media(max-width:1280px){.tk-home__content{padding:0 10px}}@media(max-width:768px){.tk-home__content{flex-wrap:wrap}.tk-home__content__post{min-width:100%;width:100%}.tk-home__content__info{flex:1;width:100%}}:root{--tk-full-width-max-width:100%;--tk-page-max-width:100%;--tk-doc-max-width:100%}@media(min-width:1280px){html[layout-mode=fullWidth] .VPNavBar.has-sidebar>.wrapper>.container>.title{padding-left:max(32px,(100% - (var(--tk-full-width-max-width) - 64px))/2)!important;width:calc(50% - var(--tk-full-width-max-width)/2 + var(--vp-sidebar-width))!important}html[layout-mode=fullWidth] .VPNavBar.has-sidebar>.wrapper>.container,html[layout-mode=fullWidth] .VPNavBar>.wrapper>.container{max-width:var(--tk-full-width-max-width)!important}html[layout-mode=fullWidth] .VPNavBar.has-sidebar>.wrapper>.container>.content{padding-left:max(32px,var(--vp-sidebar-width))!important;padding-right:32px!important;width:100%!important}html[layout-mode=fullWidth] .VPSidebar{padding-left:max(32px,(100% - (var(--tk-full-width-max-width) - 64px))/2)!important;width:calc(50% - var(--tk-full-width-max-width)/2 + var(--vp-sidebar-width))!important}html[layout-mode=fullWidth] .VPContent.has-sidebar{padding-left:calc((100vw - var(--tk-full-width-max-width))/2 + var(--vp-sidebar-width) - var(--tk-sidebar-trigger-doc-offset, 0px))!important;padding-right:calc((100vw - var(--tk-full-width-max-width))/2)!important}html[layout-mode=fullWidth] .VPDoc.has-aside div.content-container,html[layout-mode=fullWidth] .VPDoc:not(.has-sidebar) .container,html[layout-mode=fullWidth] .VPDoc:not(.has-sidebar) .container>.content{max-width:var(--tk-full-width-max-width)}}@media(min-width:1440px){html[layout-mode=fullWidth] .VPNavBar>.wrapper>.container{max-width:var(--tk-full-width-max-width)}html[layout-mode=fullWidth] .VPNavBar.has-sidebar>.divider{padding-left:calc((100vw - var(--tk-full-width-max-width))/2 + var(--vp-sidebar-width))!important}}@media(min-width:1536px){html[layout-mode=fullWidth] .VPDoc .container,html[layout-mode=fullWidth] .VPNavBar>.wrapper>.container{max-width:var(--tk-full-width-max-width)}}@media(min-width:1280px){html[layout-mode=sidebarWidthAdjustableOnly] .VPNavBar.has-sidebar>.wrapper>.container>.title{padding-left:max(32px,(100% - (var(--tk-page-max-width) - 64px))/2)!important;width:calc(50% - var(--tk-page-max-width)/2 + var(--vp-sidebar-width))!important}html[layout-mode=sidebarWidthAdjustableOnly] .VPNavBar.has-sidebar>.wrapper>.container,html[layout-mode=sidebarWidthAdjustableOnly] .VPNavBar>.wrapper>.container{max-width:var(--tk-page-max-width)!important}html[layout-mode=sidebarWidthAdjustableOnly] .VPNavBar.has-sidebar>.wrapper>.container>.content{padding-left:max(32px,(var(--vp-sidebar-width)))!important;padding-right:32px!important;width:100%!important}html[layout-mode=sidebarWidthAdjustableOnly] .VPSidebar{padding-left:max(32px,(100% - (var(--tk-page-max-width) - 64px))/2)!important;width:calc(50% - var(--tk-page-max-width)/2 + var(--vp-sidebar-width))!important}}@media(min-width:1440px){html[layout-mode=sidebarWidthAdjustableOnly] .VPNavBar.has-sidebar>.wrapper>.container,html[layout-mode=sidebarWidthAdjustableOnly] .VPNavBar>.wrapper>.container{max-width:var(--tk-page-max-width)!important}html[layout-mode=sidebarWidthAdjustableOnly] .VPNavBar.has-sidebar>.divider{padding-left:calc((100vw - var(--tk-page-max-width))/2 + var(--vp-sidebar-width))!important}html[layout-mode=sidebarWidthAdjustableOnly] .VPContent.has-sidebar{padding-left:calc((100vw - var(--tk-doc-max-width))/2 + var(--vp-sidebar-width) - var(--tk-sidebar-trigger-doc-offset, 0px))!important;padding-right:calc((100vw - var(--tk-doc-max-width))/2)!important}}@media(min-width:1280px){html[layout-mode=bothWidthAdjustable] .VPNavBar.has-sidebar>.wrapper>.container>.title{padding-left:max(32px,(100% - (var(--tk-page-max-width) - 64px))/2)!important;width:calc(50% - var(--tk-page-max-width)/2 + var(--vp-sidebar-width))!important}html[layout-mode=bothWidthAdjustable] .VPNavBar.has-sidebar>.wrapper>.container,html[layout-mode=bothWidthAdjustable] .VPNavBar>.wrapper>.container{max-width:var(--tk-page-max-width)!important}html[layout-mode=bothWidthAdjustable] .VPNavBar.has-sidebar>.wrapper>.container>.content{padding-left:max(32px,var(--vp-sidebar-width))!important;padding-right:32px!important;width:100%!important}html[layout-mode=bothWidthAdjustable] .VPSidebar{padding-left:max(32px,(100% - (var(--tk-page-max-width) - 64px))/2)!important;width:calc(50% - var(--tk-page-max-width)/2 + var(--vp-sidebar-width))!important}html[layout-mode=bothWidthAdjustable] .VPDoc.has-aside .content-container,html[layout-mode=bothWidthAdjustable] .VPDoc:not(.has-sidebar) .container,html[layout-mode=bothWidthAdjustable] .VPDoc:not(.has-sidebar) .container>.content{max-width:var(--tk-doc-max-width)}}@media(min-width:1440px){html[layout-mode=bothWidthAdjustable] .VPNavBar.has-sidebar>.wrapper>.container,html[layout-mode=bothWidthAdjustable] .VPNavBar>.wrapper>.container{max-width:var(--tk-page-max-width)!important}html[layout-mode=bothWidthAdjustable] .VPNavBar.has-sidebar>.divider{padding-left:calc((100vw - var(--tk-page-max-width))/2 + var(--vp-sidebar-width))!important}html[layout-mode=bothWidthAdjustable] .VPContent.has-sidebar{padding-left:calc((100vw - var(--tk-doc-max-width))/2 + var(--vp-sidebar-width) - var(--tk-sidebar-trigger-doc-offset, 0px))!important;padding-right:calc((100vw - var(--tk-doc-max-width))/2)!important}}@media(min-width:1536px){html[layout-mode=bothWidthAdjustable] .VPNavBar.has-sidebar>.wrapper>.container,html[layout-mode=bothWidthAdjustable] .VPNavBar>.wrapper>.container{max-width:var(--tk-page-max-width)!important}html[layout-mode=bothWidthAdjustable] .VPDoc .container{max-width:var(--tk-doc-max-width)}}html[layout-mode-animated=true] .VPNavBar.has-sidebar>.wrapper>.container>.title,html[layout-mode-animated=true] .VPNavBar>.wrapper>.container>.title{transition:width var(--tk-transition-duration-slow) ease-in-out,padding-left var(--tk-transition-duration-slow) ease-in-out}html[layout-mode-animated=true] .VPNavBar>.wrapper>.container{transition:width var(--tk-transition-duration-slow) ease-in-out,max-width var(--tk-transition-duration-slow) ease-in-out}html[layout-mode-animated=true] .VPNavBar.has-sidebar>.wrapper>.container>.content,html[layout-mode-animated=true] .VPNavBar>.wrapper>.container>.content{transition:padding-right var(--tk-transition-duration-slow) ease-in-out,padding-left var(--tk-transition-duration-slow) ease-in-out}html[layout-mode-animated=true] .VPNavBar.has-sidebar>.divider{transition:padding-left var(--tk-transition-duration-slow) ease-in-out,width var(--tk-transition-duration-slow) ease-in-out}html[layout-mode-animated=true] .VPSidebar{transition:width var(--tk-transition-duration-slow) ease-in-out,padding-left var(--tk-transition-duration-slow) ease-in-out}html[layout-mode-animated=true] .VPContent.has-sidebar{transition:width var(--tk-transition-duration-slow) ease-in-out,padding-left var(--tk-transition-duration-slow) ease-in-out,padding-right var(--tk-transition-duration-slow) ease-in-out}html[layout-mode-animated=true] .VPDoc .container,html[layout-mode-animated=true] .VPDoc.has-aside .content-container,html[layout-mode-animated=true] .VPDoc:not(.has-sidebar) .container,html[layout-mode-animated=true] .VPDoc:not(.has-sidebar) .container>.content{transition:width var(--tk-transition-duration-slow) ease-in-out,max-width var(--tk-transition-duration-slow) ease-in-out}.tk-layout--hide-vp-home .VPHomeFeatures,.tk-layout--hide-vp-home .VPHomeHero{display:none}.tk-layout__comment{margin-top:20px}:root{--tk-login-bg-color:#eee;--tk-login-mask-bg-color:hsla(0,0%,100%,.8);--tk-login-bg-img:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' baseProfile='full' viewBox='0 0 1400 800'%3E%3Crect width='150' height='150' x='1300' y='400' fill='%2381C995' stroke='%2381C995' rx='40' ry='40'%3E%3CanimateTransform attributeName='transform' attributeType='XML' begin='0s' dur='35s' from='0 1450 550' repeatCount='indefinite' to='360 1450 550' type='rotate'/%3E%3C/rect%3E%3Cpath fill='%23a2b3ff' d='M100 350a150 150 0 1 1 300 0q0 20-20 20H120q-20 0-20-20'%3E%3CanimateMotion begin='0s' dur='20s' path='M 800 -200 L 800 -300 L 800 -200' repeatCount='indefinite'/%3E%3CanimateTransform attributeName='transform' attributeType='XML' begin='0s' dur='30s' keyTimes='0 ; 0.5 ; 1' repeatCount='indefinite' type='rotate' values='0 210 530 ; -30 210 530 ; 0 210 530'/%3E%3C/path%3E%3Ccircle cx='150' cy='150' r='180' fill='%2385FFBD' stroke='%2385FFBD'%3E%3CanimateMotion dur='5s' path='M 0 0 L 40 20 Z' repeatCount='indefinite'/%3E%3C/circle%3E%3Cpath fill='%23a2b3ff' d='M165 580h105q5-2 0-10l-47-87q-3-3-6 0l-52 87q-5 8 0 10'%3E%3CanimateTransform attributeName='transform' attributeType='XML' begin='0s' dur='35s' from='0 210 530' repeatCount='indefinite' to='360 210 530' type='rotate'/%3E%3C/path%3E%3Cpath fill='%233054EB' d='M100 350a40 40 0 1 1 80 0v80a40 40 0 1 1-80 0Z'%3E%3CanimateMotion begin='0s' dur='20s' path='M 140 390 L 180 360 L 140 390' repeatCount='indefinite'/%3E%3CanimateTransform attributeName='transform' attributeType='XML' begin='0s' dur='30s' keyTimes='0 ; 0.5 ; 1' repeatCount='indefinite' type='rotate' values='0 140 390; -60 140 390; 0 140 390'/%3E%3C/path%3E%3Crect width='100' height='100' x='400' y='600' fill='%233054EB' stroke='%2381C995' rx='40' ry='40'%3E%3CanimateTransform attributeName='transform' attributeType='XML' begin='0s' dur='35s' from='-30 550 750' repeatCount='indefinite' to='330 550 750' type='rotate'/%3E%3C/rect%3E%3C/svg%3E")}:root.dark{--tk-login-bg-color:#191919;--tk-login-mask-bg-color:rgba(0,0,0,.8)}.tk-login{background-color:var(--tk-login-bg-color);background-image:var(--tk-login-bg-img);background-size:cover;height:100vh;min-height:550px;padding:30px;position:relative}.tk-login__wrapper{align-items:center;background-color:var(--tk-login-mask-bg-color);border-radius:10px;display:flex;height:100%;justify-content:space-around;padding:0 50px;width:100%}@media(max-width:640px){.tk-login__wrapper{background-color:transparent;padding:0}}.tk-login__left{width:900px}.tk-login__left img{height:100%;width:100%}.tk-login__right{background-color:var(--tk-bg-color);border-radius:10px;box-shadow:var(--tk-card-shadow);min-width:450px;overflow:hidden;padding:50px 40px 45px}.tk-login__right .cursor-pointer{width:30%}@media(max-width:640px){.tk-login__right{min-width:100%}}.tk-login__right__header{flex-wrap:wrap;gap:15px;margin-bottom:45px}.tk-login__right__header img{width:60px}.tk-login__right__header .title{color:var(--vp-c-text-1);font-size:42px;font-weight:700;line-height:1;margin:0;white-space:wrap}@media(max-width:640px){.tk-login__right__header .title{font-size:24px;text-align:center}}.tk-login__right__form{align-items:center;border:1px solid var(--vp-c-divider);border-radius:4px;display:inline-flex;flex-grow:1;justify-content:center;padding:1px 15px;transition:border .2s ease;transition:border-color .3s;width:100%}.tk-login__right__form .sr-only{height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;clip:rect(0,0,0,0);border-width:0;white-space:nowrap}.tk-login__right__form:hover{border-color:var(--vp-c-border)}.tk-login__right__form .tk-icon{color:var(--vp-c-text-3);margin-right:8px;pointer-events:none}.tk-login__right__form.is-focus{border-color:var(--tk-theme-color)}.tk-login__right__form.is-error{border-color:var(--vp-c-danger-1)}.tk-login__right__form.is-error input::-moz-placeholder{color:var(--vp-c-danger-1)}.tk-login__right__form.is-error .tk-icon,.tk-login__right__form.is-error input::placeholder{color:var(--vp-c-danger-1)}.tk-login__right__form--control{height:36px;outline:none;width:100%}.tk-login__right__form__btn{display:flex;flex-wrap:wrap;gap:20px;justify-content:space-between;width:100%}@media(max-width:640px){.tk-login__right__form__btn{justify-content:center}}.tk-login__right__form__btn button{border:1px solid var(--vp-c-divider);border-radius:20px;font-size:14px;height:40px;padding:12px 19px;width:185px}@media(max-width:640px){.tk-login__right__form__btn button{width:100%}}.tk-login__right__form__btn button .tk-icon{margin-right:8px;pointer-events:none}.tk-login__right__form__btn button:hover{background-color:var(--tk-fill-color-light)}.tk-login__right__form__btn button.primary{background-color:var(--tk-theme-color);border:none;color:var(--vp-c-white)}.tk-login__right__form__btn button.primary .tk-icon{color:var(--vp-c-white)}.tk-login__right__form__btn button.primary:hover{background-color:var(--vp-c-brand-3)}.tk-login~div{display:none}.VPContent .tk-login{height:calc(100vh - var(--vp-nav-height))}.tk-notice__icon{background-color:var(--vp-c-brand-3);border-radius:50%;cursor:pointer;font-size:12px;opacity:.6;padding:8px;position:fixed;right:10px;top:80px;z-index:20}.tk-notice__icon.twinkle{animation:twinkle 1.5s ease-in-out infinite}@media(max-width:1280px){.tk-notice__icon{top:115px}}.tk-notice__popover{background-color:var(--tk-bg-color);border:1px solid var(--vp-c-brand-3);border-radius:6px;box-shadow:var(--vp-shadow-2);max-width:400px;min-width:260px;position:fixed;right:20px;top:80px;z-index:110}.tk-notice__popover.is-top{right:20px;top:80px}.tk-notice__popover.is-center{left:50%;top:50%;transform:translate(-50%,-50%)}.tk-notice__popover__header{background-color:var(--vp-c-brand-3);color:var(--vp-c-white);padding:6px 4px}.tk-notice__popover__header>div{overflow:hidden}.tk-notice__popover__header .title{font-size:14px;padding-left:6px}.tk-notice__popover__content{padding:10px}.tk-notice__mask{background-color:#00000080;bottom:0;height:100%;left:0;overflow:auto;position:fixed;top:0;width:100%;z-index:109}@keyframes twinkle{0%{opacity:.5}50%{opacity:0}to{opacity:.5}}html.disable-scroll{overflow:hidden}.tk-right-bottom-button{bottom:40px;gap:16px;position:fixed;right:32px;z-index:99}.tk-right-bottom-button__button{align-items:center;background:var(--tk-bg-color);border-radius:50%;box-shadow:var(--tk-card-shadow);cursor:pointer;display:flex;height:37px;justify-content:center;position:relative;text-align:center;transition:all var(--tk-transition-duration) ease;width:37px}.tk-right-bottom-button__button .content{-webkit-user-select:none;-moz-user-select:none;user-select:none}.tk-right-bottom-button__button:hover{background-color:var(--tk-theme-color);box-shadow:0 0 15px var(--tk-theme-color)}.tk-right-bottom-button__button:hover .content,.tk-right-bottom-button__button:hover .tk-icon{color:var(--vp-c-white)}.tk-right-bottom-button__button.back-top:before{background:radial-gradient(farthest-side,var(--tk-theme-color) 98%,transparent) top/3.7px 3.7px no-repeat,conic-gradient(var(--tk-theme-color) calc(var(--tk-progress)*1%),transparent 0);border-radius:50%;content:"";inset:0;-webkit-mask:radial-gradient(farthest-side,transparent calc(99% - 3.7px),#000 calc(100% - 3.7px));mask:radial-gradient(farthest-side,transparent calc(99% - 3.7px),#000 calc(100% - 3.7px));position:absolute}.tk-right-bottom-button__button.back-top:after{background-color:var(--tk-theme-color);border-radius:50%;content:"";inset:calc(50% - 1.85px);position:absolute;transform:rotate(calc(var(--tk-progress)*3.6deg - 90deg)) translate(calc(18.5px - 50%))}.tk-right-bottom-button__dropdown{border-radius:6px;line-height:25.6px;padding:6px 0 8px;text-align:left}.tk-right-bottom-button__dropdown .dropdown-item{cursor:pointer;font-size:14px;padding:0 10px 0 15px}.tk-right-bottom-button__dropdown .dropdown-item:hover{background-color:var(--tk-fill-color-light);color:var(--tk-theme-color)}.tk-right-bottom-button__dropdown .dropdown-item.active{background-color:var(--tk-theme-color);color:var(--tk-bg-color)}.tk-right-bottom-button__dropdown__title{color:var(--tk-el-color-info);font-size:12px;padding:0 10px}@media(max-width:719px){.tk-right-bottom-button{bottom:24px;right:16px}}@media(max-width:960px){.tk-right-bottom-button .size-change{display:none}}.tk-risk-link{background-color:var(--tk-bg-color-elm);border-radius:10px;box-shadow:var(--tk-card-shadow);max-width:620px;min-width:350px;padding:20px;top:40%}@media(max-width:640px){.tk-risk-link{width:calc(100% - 60px)}}.tk-risk-link__header{flex-wrap:wrap;gap:15px}.tk-risk-link__header img{width:40px}.tk-risk-link__title{font-size:18px;font-weight:600;line-height:24px}.tk-risk-link__link{color:var(--vp-c-text-3);font-size:16px}.tk-risk-link button{background-color:var(--tk-theme-color);background-image:none;border:1px solid transparent;border-radius:6px;color:#fff;cursor:pointer;display:inline-block;font-size:14px;font-weight:400;height:32px;line-height:1.5;outline:none;padding:4px 15px;position:relative;text-align:center;touch-action:manipulation;transition:all var(--tk-transition-duration-fast) cubic-bezier(.645,.045,.355,1);-webkit-user-select:none;-moz-user-select:none;user-select:none;white-space:nowrap}.tk-risk-link button:hover{background-color:var(--vp-c-brand-3)}.tk-risk-link button.btn{float:right}.tk-risk-link~div{display:none}.tk-route-loading__mask{background:var(--vp-c-bg);left:0;position:fixed;top:0;width:100%;z-index:9999}.tk-route-loading__loader,.tk-route-loading__mask{align-items:center;display:flex;height:100%;justify-content:center}.tk-route-loading__loader{flex-direction:column}.tk-route-loading__spinner{animation:spin 1s linear infinite;border:4px solid #f1f1f1;border-radius:50%;border-top:4px solid var(--vp-c-brand-1);height:40px;margin:0 auto 10px;width:40px}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(1turn)}}:root{--tk-sidebar-trigger-top-offset:10px;--tk-sidebar-trigger-left-offset:10px;--tk-sidebar-trigger-collapse-doc-offset:160px}.tk-layout.has-sidebar-trigger .VPSidebar{transition:width var(--tk-transition-duration-slow) ease-in-out,padding-left var(--tk-transition-duration-slow) ease-in-out,padding-right var(--tk-transition-duration-slow) ease-in-out,opacity var(--tk-transition-duration-slow),transform var(--tk-transition-duration)}.tk-layout.has-sidebar-trigger .VPContent.has-sidebar.sidebar-trigger-transition{transition:padding-left var(--tk-transition-duration-slow) ease-in-out}.tk-layout.has-sidebar-trigger .VPDoc:not(.has-sidebar) .tk-sidebar-trigger{display:none}.tk-layout.has-sidebar-trigger.is-sidebar-collapse{--tk-sidebar-trigger-doc-offset:var(--tk-sidebar-trigger-collapse-doc-offset)}.tk-layout.has-sidebar-trigger.is-sidebar-collapse .VPSidebar{padding-left:0!important;padding-right:0!important;width:0!important}.tk-layout.has-sidebar-trigger.is-sidebar-collapse .VPNav{border:1px solid var(--vp-c-divider)}.tk-layout.has-sidebar-trigger.is-sidebar-collapse .VPNav .VPNavBar.has-sidebar{background-color:var(--vp-nav-bg-color)}.tk-layout.has-sidebar-trigger.is-sidebar-collapse .VPNav .VPNavBar.has-sidebar .divider{display:none}.tk-layout.has-sidebar-trigger.is-sidebar-collapse .VPNavBarTitle.has-sidebar>.title{border:none}.tk-layout.has-sidebar-trigger.is-sidebar-collapse .VPContent.has-sidebar{padding-left:calc((100vw - var(--vp-layout-max-width))/2 + var(--vp-sidebar-width) - var(--tk-sidebar-trigger-doc-offset, 0px))}.tk-layout.has-sidebar-trigger.is-sidebar-collapse .tk-sidebar-trigger{left:var(--tk-sidebar-trigger-left-offset)!important}.tk-layout.has-sidebar-trigger .tk-sidebar-trigger{left:calc(50% - var(--vp-layout-max-width)/2 + var(--vp-sidebar-width) + var(--tk-sidebar-trigger-left-offset));position:fixed;top:calc(var(--vp-nav-height) + var(--tk-sidebar-trigger-top-offset));transition:left var(--tk-transition-duration-slow) ease-in-out;z-index:20px}.tk-layout.has-sidebar-trigger .tk-sidebar-trigger>div{box-shadow:none}.tk-layout.has-sidebar-trigger .tk-sidebar-trigger.is-active{transition-duration:var(--tk-transition-duration-slow)}@media(max-width:1440px){.tk-layout.has-sidebar-trigger .tk-sidebar-trigger{left:calc(var(--vp-sidebar-width) + var(--tk-sidebar-trigger-left-offset))!important}}@media(max-width:1280px){.tk-layout.has-sidebar-trigger .tk-sidebar-trigger{top:calc(var(--vp-nav-height) + var(--tk-sidebar-trigger-top-offset) + 47px)}}.tk-card-nav.Layout.has-sidebar-trigger .tk-sidebar-trigger,.tk-card.Layout.has-sidebar-trigger .tk-sidebar-trigger,.tk-segment-nav.Layout.has-sidebar-trigger .tk-sidebar-trigger,.tk-segment.Layout.has-sidebar-trigger .tk-sidebar-trigger{left:calc(var(--vp-sidebar-width) + var(--tk-sidebar-trigger-left-offset))}.tk-card-nav.Layout.has-sidebar-trigger.is-sidebar-collapse .tk-sidebar-trigger,.tk-card.Layout.has-sidebar-trigger.is-sidebar-collapse .tk-sidebar-trigger,.tk-segment-nav.Layout.has-sidebar-trigger.is-sidebar-collapse .tk-sidebar-trigger,.tk-segment.Layout.has-sidebar-trigger.is-sidebar-collapse .tk-sidebar-trigger{left:var(--tk-sidebar-trigger-left-offset)}html[layout-mode=original] .tk-layout .tk-sidebar-trigger{left:calc(50% - var(--vp-layout-max-width)/2 + var(--vp-sidebar-width) + var(--tk-sidebar-trigger-left-offset));transition-duration:var(--tk-transition-duration-slow)}html[layout-mode=bothWidthAdjustable] .tk-layout .tk-sidebar-trigger,html[layout-mode=sidebarWidthAdjustableOnly] .tk-layout .tk-sidebar-trigger{left:calc(50% - var(--tk-page-max-width)/2 + var(--vp-sidebar-width) + var(--tk-sidebar-trigger-left-offset));transition-duration:var(--tk-transition-duration-slow)}html[layout-mode=fullWidth] .tk-layout .tk-sidebar-trigger{left:calc(50% - var(--tk-full-width-max-width)/2 + var(--vp-sidebar-width) + var(--tk-sidebar-trigger-left-offset));transition-duration:var(--tk-transition-duration-slow)}:root{--tk-spotlight-under-bg-color:var(--vp-c-brand-soft)}.tk-spotlight-hover{pointer-events:none;position:fixed}.tk-spotlight-hover__aside:before{background-color:var(--vp-c-brand);border-radius:4px;content:"";display:block;height:100%;left:-24px;position:absolute;width:4px}.tk-spotlight-hover__under{background-color:var(--tk-spotlight-under-bg-color);z-index:-1}:root{--tk-theme-enhance-text-color:var(--vp-c-text-1);--tk-theme-enhance-inner-bg-color:var(--tk-fill-color-dark)}.tk-segmented{background-color:var(--tk-theme-enhance-inner-bg-color);color:var(--tk-theme-enhance-text-color)}.tk-theme-enhance{height:100%}.tk-theme-enhance:before{background-color:var(--vp-c-divider);content:"";height:24px;margin-left:16px;margin-right:16px;width:1px}.tk-theme-enhance .tk-icon{cursor:pointer}@media(max-width:768px){.tk-theme-enhance{display:none!important}}.tk-theme-enhance__popover{border-radius:12px;padding:20px;width:340px}.tk-theme-enhance__content>*{margin-bottom:10px}.tk-theme-enhance__content>:last-child{margin-bottom:0}.tk-theme-enhance__theme-color .label{margin-right:10px}.tk-theme-enhance__theme-color h3{display:inline-block;font-size:12px;margin-bottom:6px;opacity:.8}.tk-theme-enhance__theme-color .color-list{gap:10px}.tk-theme-enhance__theme-color .color-wrapper{border-radius:6px;cursor:pointer;outline:1px solid var(--vp-c-divider);padding:4px;transition:outline-color .2s ease-in-out}.tk-theme-enhance__theme-color .color-wrapper.is-active,.tk-theme-enhance__theme-color .color-wrapper:hover{outline:2px solid var(--tk-theme-color)}.tk-theme-enhance__theme-color .color-wrapper .color-bg{border-radius:6px;height:24px;margin:6px 12px;width:24px}.tk-theme-enhance__title{align-items:center;color:var(--tk-theme-enhance-text-color);display:inline-flex;flex:1 1 0%;font-size:14px;font-weight:500;gap:4px;padding-right:16px;-webkit-user-select:none;-moz-user-select:none;user-select:none}.tk-theme-enhance__title.is-disabled{opacity:.5}.tk-theme-enhance__helper{color:var(--tk-theme-enhance-text-color);cursor:help;opacity:.5;transition:all var(--tk-transition-duration-fast) cubic-bezier(.4,0,.2,1)}.tk-theme-enhance__helper:hover{opacity:1}.tk-theme-enhance__helper--title{font-weight:600;margin-bottom:4px}.tk-theme-enhance__helper--desc{font-size:14px;line-height:20px;margin-bottom:8px}.tk-theme-enhance__helper__popup{color:var(--tk-theme-enhance-text-color)}.tk-theme-enhance__helper__body{max-width:400px}.tk-theme-enhance__helper__body__tip{background-color:var(--tk-theme-enhance-inner-bg-color);border-radius:12px;font-size:14px;line-height:20px;margin-bottom:10px;padding:12px}.tk-theme-enhance__helper__body__tip:last-child{margin-bottom:0}.tk-theme-enhance__slide{background-color:var(--tk-theme-enhance-inner-bg-color);color:var(--tk-theme-enhance-text-color)}.tk-theme-enhance__switch{align-items:center;background:#dcdfe6;border:1px solid #dcdfe6;border-radius:10px;box-sizing:border-box;cursor:pointer;display:inline-flex;height:20px;min-width:40px;outline:none;position:relative;transition:border-color var(--tk-transition-duration),background-color var(--tk-transition-duration)}.tk-theme-enhance__switch .action{align-items:center;background-color:var(--vp-c-white);border-radius:100%;color:#dcdfe6;display:flex;height:16px;justify-content:center;left:1px;position:absolute;transition:all var(--tk-transition-duration);width:16px}.tk-theme-enhance__switch.is-checked{background-color:var(--vp-c-brand-1);border-color:var(--vp-c-brand-1)}.tk-theme-enhance__switch.is-checked .action{color:var(--vp-c-brand-1);left:calc(100% - 17px)}.tk-theme-enhance .tk-theme-enhance-slide-enter-active,.tk-theme-enhance .tk-theme-enhance-slide-leave-active,.tk-theme-enhance .tk-theme-enhance-slide-move{transition:all var(--tk-transition-duration-fast) ease-in-out}.tk-theme-enhance .tk-theme-enhance-slide-enter-from,.tk-theme-enhance .tk-theme-enhance-slide-leave-to{opacity:0;transform:translateY(-15px)}@font-face{font-family:iconfont;src:url(iconfont.woff2?t=1755181778742) format("woff2"),url(iconfont.woff?t=1755181778742) format("woff"),url(iconfont.ttf?t=1755181778742) format("truetype")}.iconfont{font-family:iconfont!important;font-size:16px;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon-douban:before{content:""}.icon-xiangce:before{content:""}.icon-telegram:before{content:""}.icon-rss:before{content:""}.icon-weixin:before{content:""}.icon-Youtube:before{content:""}.icon-QQ:before{content:""}.icon-weibo:before{content:""}.icon-yuque:before{content:""}.icon-vex:before{content:""}.icon-csdn:before{content:""}.icon-facebook:before{content:""}.icon-youjian:before{content:""}.icon-sf:before{content:""}.icon-juejin:before{content:""}.icon-douyin:before{content:""}.icon-cnblogs-grey:before{content:""}.icon-github:before{content:""}.icon-jianshu:before{content:""}.icon-npm:before{content:""}.icon-bilibili:before{content:""}.icon-zhihu:before{content:""}.icon-tuite:before{content:""}.icon-gitee:before{content:""}.vp-code{outline:none}@media(max-width:640px){.vp-block,.vp-code-group .tabs,.vp-doc div[class*=language-]{margin-left:0;margin-right:0}}.VPSidebar .nav .item h2.text{font-size:18px}.VPSidebar .nav .item p.text{font-size:15px;transition:transform var(--tk-transition-duration) ease-in-out}.VPSidebar .nav .item p.text:hover{transform:translate(4px)}.VPSidebar .nav .VPSidebarItem.level-0>.items{padding-left:10px}.DocSearch-Button{background-color:transparent}.Layout .VPNavBar .VPSwitchAppearance{width:22px!important}.Layout .VPNavBar .VPSwitchAppearance .check{transform:none}.VPNav .VPNavBarTranslations .VPMenu .title{color:var(--tk-theme-color)}.VPDoc .aside .aside-container .outline-link{transition:color var(--tk-transition-duration),transform var(--tk-transition-duration)}.VPDoc .aside .aside-container .outline-link:hover{transform:translate(4px)}.VPDoc .aside .aside-container .outline-link.active{color:var(--tk-theme-color)}.VPDoc h1{background:-webkit-linear-gradient(10deg,#bd34fe 5%,#e43498 15%);-webkit-background-clip:text;background-clip:text;color:transparent}.vp-doc table{display:table;width:100%}.vp-doc td,.vp-doc th{border:0;min-width:92px}.vp-doc tr:nth-child(2n){background-color:unset}.vp-doc tr:last-child{border-bottom:1px solid var(--vp-c-divider)}:root{--tk-mark-color:#d63200}:root.dark{--tk-mark-color:#b160ea}.vp-doc mark{background-color:transparent;border:1px solid var(--tk-mark-color);border-radius:32px;color:var(--tk-mark-color);font-size:15px;margin:0 3px;padding:1px 8px}.vp-doc blockquote{background-color:var(--vp-c-gray-soft);border-radius:10px;opacity:.9;padding:10px 16px}@keyframes rainbow{0%{--rainbow-prev:#009ff7;--rainbow-next:#c76dd1}1.25%{--rainbow-prev:#009dfa;--rainbow-next:#cf69c9}2.5%{--rainbow-prev:#009bfc;--rainbow-next:#d566c2}3.75%{--rainbow-prev:#0098fd;--rainbow-next:#dc63ba}5%{--rainbow-prev:#0096fd;--rainbow-next:#e160b3}6.25%{--rainbow-prev:#0093fd;--rainbow-next:#e65eab}7.5%{--rainbow-prev:#2e90fc;--rainbow-next:#e95ca2}8.75%{--rainbow-prev:#4d8dfa;--rainbow-next:#ed5a9a}10%{--rainbow-prev:#638af8;--rainbow-next:#ef5992}11.25%{--rainbow-prev:#7587f5;--rainbow-next:#f15989}12.5%{--rainbow-prev:#8583f1;--rainbow-next:#f25981}13.75%{--rainbow-prev:#9280ed;--rainbow-next:#f25a79}15%{--rainbow-prev:#9f7ce9;--rainbow-next:#f25c71}16.25%{--rainbow-prev:#aa78e3;--rainbow-next:#f15e69}17.5%{--rainbow-prev:#b574dd;--rainbow-next:#ef6061}18.75%{--rainbow-prev:#be71d7;--rainbow-next:#ed635a}20%{--rainbow-prev:#c76dd1;--rainbow-next:#eb6552}21.25%{--rainbow-prev:#cf69c9;--rainbow-next:#e8694b}22.5%{--rainbow-prev:#d566c2;--rainbow-next:#e46c44}23.75%{--rainbow-prev:#dc63ba;--rainbow-next:#e06f3d}25%{--rainbow-prev:#e160b3;--rainbow-next:#db7336}26.25%{--rainbow-prev:#e65eab;--rainbow-next:#d77630}27.5%{--rainbow-prev:#e95ca2;--rainbow-next:#d17a2a}28.75%{--rainbow-prev:#ed5a9a;--rainbow-next:#cc7d24}30%{--rainbow-prev:#ef5992;--rainbow-next:#c6811e}31.25%{--rainbow-prev:#f15989;--rainbow-next:#bf8418}32.5%{--rainbow-prev:#f25981;--rainbow-next:#b98713}33.75%{--rainbow-prev:#f25a79;--rainbow-next:#b28a0f}35%{--rainbow-prev:#f25c71;--rainbow-next:#ab8d0c}36.25%{--rainbow-prev:#f15e69;--rainbow-next:#a3900b}37.5%{--rainbow-prev:#ef6061;--rainbow-next:#9c920d}38.75%{--rainbow-prev:#ed635a;--rainbow-next:#949510}40%{--rainbow-prev:#eb6552;--rainbow-next:#8b9715}41.25%{--rainbow-prev:#e8694b;--rainbow-next:#83991b}42.5%{--rainbow-prev:#e46c44;--rainbow-next:#7a9b21}43.75%{--rainbow-prev:#e06f3d;--rainbow-next:#719d27}45%{--rainbow-prev:#db7336;--rainbow-next:#679e2e}46.25%{--rainbow-prev:#d77630;--rainbow-next:#5da035}47.5%{--rainbow-prev:#d17a2a;--rainbow-next:#51a13c}48.75%{--rainbow-prev:#cc7d24;--rainbow-next:#44a244}50%{--rainbow-prev:#c6811e;--rainbow-next:#34a44b}51.25%{--rainbow-prev:#bf8418;--rainbow-next:#1ba553}52.5%{--rainbow-prev:#b98713;--rainbow-next:#00a65b}53.75%{--rainbow-prev:#b28a0f;--rainbow-next:#00a663}55%{--rainbow-prev:#ab8d0c;--rainbow-next:#00a76c}56.25%{--rainbow-prev:#a3900b;--rainbow-next:#00a874}57.5%{--rainbow-prev:#9c920d;--rainbow-next:#00a87d}58.75%{--rainbow-prev:#949510;--rainbow-next:#00a985}60%{--rainbow-prev:#8b9715;--rainbow-next:#00a98e}61.25%{--rainbow-prev:#83991b;--rainbow-next:#00a996}62.5%{--rainbow-prev:#7a9b21;--rainbow-next:#00a99f}63.75%{--rainbow-prev:#719d27;--rainbow-next:#00a9a7}65%{--rainbow-prev:#679e2e;--rainbow-next:#00a9b0}66.25%{--rainbow-prev:#5da035;--rainbow-next:#00a9b8}67.5%{--rainbow-prev:#51a13c;--rainbow-next:#00a9c0}68.75%{--rainbow-prev:#44a244;--rainbow-next:#00a8c7}70%{--rainbow-prev:#34a44b;--rainbow-next:#00a8cf}71.25%{--rainbow-prev:#1ba553;--rainbow-next:#00a7d5}72.5%{--rainbow-prev:#00a65b;--rainbow-next:#00a6dc}73.75%{--rainbow-prev:#00a663;--rainbow-next:#00a6e2}75%{--rainbow-prev:#00a76c;--rainbow-next:#00a4e7}76.25%{--rainbow-prev:#00a874;--rainbow-next:#00a3ec}77.5%{--rainbow-prev:#00a87d;--rainbow-next:#00a2f1}78.75%{--rainbow-prev:#00a985;--rainbow-next:#00a0f4}80%{--rainbow-prev:#00a98e;--rainbow-next:#009ff7}81.25%{--rainbow-prev:#00a996;--rainbow-next:#009dfa}82.5%{--rainbow-prev:#00a99f;--rainbow-next:#009bfc}83.75%{--rainbow-prev:#00a9a7;--rainbow-next:#0098fd}85%{--rainbow-prev:#00a9b0;--rainbow-next:#0096fd}86.25%{--rainbow-prev:#00a9b8;--rainbow-next:#0093fd}87.5%{--rainbow-prev:#00a9c0;--rainbow-next:#2e90fc}88.75%{--rainbow-prev:#00a8c7;--rainbow-next:#4d8dfa}90%{--rainbow-prev:#00a8cf;--rainbow-next:#638af8}91.25%{--rainbow-prev:#00a7d5;--rainbow-next:#7587f5}92.5%{--rainbow-prev:#00a6dc;--rainbow-next:#8583f1}93.75%{--rainbow-prev:#00a6e2;--rainbow-next:#9280ed}95%{--rainbow-prev:#00a4e7;--rainbow-next:#9f7ce9}96.25%{--rainbow-prev:#00a3ec;--rainbow-next:#aa78e3}97.5%{--rainbow-prev:#00a2f1;--rainbow-next:#b574dd}98.75%{--rainbow-prev:#00a0f4;--rainbow-next:#be71d7}to{--rainbow-prev:#009ff7;--rainbow-next:#c76dd1}}:root{--rainbow-prev:#009ff7;--rainbow-next:#c76dd1;--vp-home-hero-name-color:transparent;--vp-home-hero-name-background:-webkit-linear-gradient(120deg,var(--rainbow-prev) 30%,var(--rainbow-next));--vp-home-hero-image-background-image:linear-gradient(-45deg,var(--rainbow-prev) 30%,var(--rainbow-next));--vp-home-hero-image-filter:blur(80px)}.tk-banner-content__desc{-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);background-color:#fff6;border-radius:8px;display:inline-block;padding:8px}.tk-banner-content__desc span{background:linear-gradient(90deg,#f37055,#ef4e7b,#a166ab,#5073b8,#1098ad,#07b39b,#6fba82);-webkit-background-clip:text;background-clip:text;color:transparent;font-weight:700;letter-spacing:.1em}.tk-post-item{border-radius:10px}.tk-post-item:hover{box-shadow:0 8px 32px var(--vp-c-brand-1);transform:scale(1.02)}.tk-page-card{border-radius:10px}.tk-page-card:hover{box-shadow:0 8px 32px var(--vp-c-brand-1);transform:scale(1.02)}.tk-post-item-card{border-radius:10px}.tk-post-item-card:hover{box-shadow:0 8px 32px var(--vp-c-brand-1);transform:scale(1.02)}.tk-archives,.tk-article-banner__info,.tk-article-page .tk-aside-outline,.tk-article-page .tk-doc>div,.tk-banner__content,.tk-footer-group,.tk-home-card-list,.tk-home-feature,.tk-login,.tk-post-list,.tk-risk-link>*{animation:fade-up .6s .1s backwards}.VPDoc .VPDocAsideOutline,.VPDoc .vp-doc>div,.VPSidebar .group{animation:fade-up-slide .7s ease-out forwards}@keyframes fade-up{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}@keyframes fade-up-slide{0%{opacity:0;transform:translateY(40px)}30%{animation-timing-function:ease-out}to{opacity:1;transform:translateY(0)}}:root{--vp-code-block-bg: var(--tk-fill-color-light)}.tk-iframe .tk-article-page__aside{display:block}.tk-home .tk-banner-bg-pure{background:linear-gradient(180deg,#f7f5fa,#fff)}.tk-home .tk-banner-feature__feature__item{color:#000;letter-spacing:.3px;font-weight:600}.katex-display{margin:2em auto!important;text-align:center!important;display:flex!important;justify-content:center!important;align-items:center!important;width:100%!important;max-width:100%!important}.katex-display .katex{font-family:Kalam,Comic Sans MS,Marker Felt,Bradley Hand,cursive!important;font-size:1.5em!important;font-weight:700!important;padding:1.2em 1.8em;display:inline-flex!important;align-items:center!important;position:relative;margin:0 auto!important;vertical-align:middle!important;line-height:normal!important}.katex-display .katex>*{vertical-align:middle!important}.katex-display .katex .katex-html{display:inline-flex!important;align-items:center!important;vertical-align:middle!important}.katex-display .katex .katex-html>*{display:inline-flex!important;align-items:center!important;vertical-align:middle!important}.katex-display .katex .katex-mathml{display:inline-flex!important;align-items:center!important;vertical-align:middle!important}.katex-display .katex .frac{display:inline-flex!important;flex-direction:column!important;align-items:center!important;vertical-align:middle!important;justify-content:center!important;margin:0!important}.katex-display .katex .mrel,.katex-display .katex .mbin,.katex-display .katex .mop,.katex-display .katex .mord{display:inline-flex!important;align-items:center!important;vertical-align:middle!important}.katex-display .katex .mrel{align-self:center!important}.katex-display .katex{border:3px solid #ff6b6b;border-radius:12px;box-shadow:0 4px 6px #0000001a,0 2px 4px #0000000f,inset 0 1px #fffc;background:linear-gradient(135deg,#fff8f0f2,#ffefd5f2,#fff8f0f2);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}.katex-display .katex:before{content:"";position:absolute;inset:-2px;border:2px solid rgba(255,107,107,.3);border-radius:14px;z-index:-1;background:linear-gradient(135deg,#ffb6c14d,#ffdab94d)}.katex-display .katex{color:#2c3e50;letter-spacing:.03em}.katex-display .katex .katex-mathml .base,.katex-display .katex .katex-html .base{font-weight:700!important}.katex-display .katex .katex-mathml .mbin,.katex-display .katex .katex-mathml .mrel,.katex-display .katex .katex-html .mbin,.katex-display .katex .katex-html .mrel{margin:0 .4em!important}.katex-display .katex .katex-mathml .mopen,.katex-display .katex .katex-mathml .mclose,.katex-display .katex .katex-html .mopen,.katex-display .katex .katex-html .mclose{margin:0 .2em!important}.katex-display .katex *{letter-spacing:.03em}.katex-display .katex .mbin,.katex-display .katex .mrel,.katex-display .katex .mopen,.katex-display .katex .mclose{letter-spacing:.05em}.dark .katex-display .katex{border-color:#ff8787;background:linear-gradient(135deg,#2d3440f2,#3c4655f2,#2d3440f2);color:#e8e8e8;box-shadow:0 4px 6px #0000004d,0 2px 4px #0003,inset 0 1px #ffffff1a}.dark .katex-display .katex:before{border-color:#ff878766;background:linear-gradient(135deg,#ff6b6b33,#ffa50033)}@media(max-width:768px){.katex-display .katex{font-size:1.2em!important;padding:1em 1.2em}}.katex:not(.katex-display .katex){font-weight:600;font-family:Kalam,Comic Sans MS,cursive}.vp-doc table{display:table;border-collapse:collapse;border-spacing:0;width:100%;margin:1.5em 0;box-shadow:0 0 0 1px var(--vp-c-divider);border-radius:8px;overflow:hidden}.vp-doc table thead{background:linear-gradient(135deg,#3b82f61a,#8b5cf61a)}.vp-doc table thead tr{border-bottom:2px solid var(--vp-c-divider)}.vp-doc table thead th{padding:.75em 1em;text-align:left;font-weight:600;color:var(--vp-c-text-1);border-right:1px solid var(--vp-c-divider)}.vp-doc table thead th:last-child{border-right:none}.vp-doc table tbody tr{border-bottom:1px solid var(--vp-c-divider);transition:background-color .2s}.vp-doc table tbody tr:hover{background-color:var(--vp-c-bg-soft)}.vp-doc table tbody tr:last-child{border-bottom:none}.vp-doc table tbody td{padding:.75em 1em;border-right:1px solid var(--vp-c-divider);vertical-align:top}.vp-doc table tbody td:last-child{border-right:none}.vp-doc table tbody tr td:first-child{font-weight:600;color:var(--vp-c-text-1)}.dark .vp-doc table thead{background:linear-gradient(135deg,#3b82f626,#8b5cf626)}.dark .vp-doc table tbody tr:hover{background-color:var(--vp-c-bg-soft)}@media(max-width:768px){.vp-doc table{font-size:.875em}.vp-doc table thead th,.vp-doc table tbody td{padding:.5em .75em}}.tk-home-card-list .scroll__animate:has(.tk-page-card.tk-my){display:none!important}.tk-home-card-list .scroll__animate:not(:has(*)){display:none}.nav-card-container .nav-card__item__img img{margin:0}.article-card-list[data-v-d45a9e33]{margin:2rem 0}.category-section[data-v-d45a9e33]{margin-bottom:2.5rem}.category-header[data-v-d45a9e33]{display:flex;align-items:center;gap:1rem;margin-bottom:1.25rem;position:relative}.category-icon-wrap[data-v-d45a9e33]{width:48px;height:48px;border-radius:14px;display:flex;align-items:center;justify-content:center;flex-shrink:0;box-shadow:0 4px 12px #00000014}.category-icon[data-v-d45a9e33]{font-size:22px;display:flex;align-items:center;justify-content:center}.category-info[data-v-d45a9e33]{display:flex;align-items:baseline;gap:.5rem}.category-index[data-v-d45a9e33]{font-size:.75rem;font-weight:700;font-family:SF Mono,Monaco,monospace;opacity:.8}.category-title[data-v-d45a9e33]{font-size:1.125rem;font-weight:600;color:var(--vp-c-text-1);margin:0;letter-spacing:-.01em}.category-line[data-v-d45a9e33]{flex:1;height:2px;border-radius:1px;margin-left:.5rem}.article-grid[data-v-d45a9e33]{display:grid;gap:.875rem}.article-card[data-v-d45a9e33]{display:flex;align-items:stretch;background:var(--vp-c-bg);border:1px solid var(--vp-c-divider);border-radius:14px;text-decoration:none;overflow:hidden;transition:all .25s cubic-bezier(.4,0,.2,1);position:relative}.article-card[data-v-d45a9e33]:before{content:"";position:absolute;inset:0;background:linear-gradient(135deg,var(--vp-c-brand-3) 0%,transparent 60%);opacity:0;transition:opacity .25s ease}.article-card[data-v-d45a9e33]:hover{border-color:var(--vp-c-brand-2);transform:translateY(-2px);box-shadow:0 8px 24px #0000001a,0 2px 8px #0000000f}.article-card[data-v-d45a9e33]:hover:before{opacity:.03}.card-indicator[data-v-d45a9e33]{width:4px;flex-shrink:0;opacity:.7;transition:all .25s ease}.article-card:hover .card-indicator[data-v-d45a9e33]{opacity:1;box-shadow:0 0 12px currentColor}.card-body[data-v-d45a9e33]{flex:1;padding:1rem 1.25rem;min-width:0}.article-meta[data-v-d45a9e33]{display:flex;align-items:center;gap:.5rem;margin-bottom:.375rem}.article-index[data-v-d45a9e33]{font-size:.6875rem;font-weight:700;font-family:SF Mono,Monaco,monospace;opacity:.7}.article-tag[data-v-d45a9e33]{font-size:.625rem;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--vp-c-text-3);background:var(--vp-c-bg-soft);padding:.125rem .5rem;border-radius:4px}.article-title[data-v-d45a9e33]{font-size:.9375rem;font-weight:600;color:var(--vp-c-text-1);margin:0 0 .375rem;line-height:1.45;letter-spacing:-.01em;transition:color .2s ease}.article-card:hover .article-title[data-v-d45a9e33]{color:var(--vp-c-brand-1)}.article-desc[data-v-d45a9e33]{font-size:.8125rem;color:var(--vp-c-text-2);margin:0;line-height:1.5;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.card-action[data-v-d45a9e33]{display:flex;align-items:center;gap:.375rem;padding:0 1.25rem;color:var(--vp-c-text-3);transition:all .25s ease;flex-shrink:0}.article-card:hover .card-action[data-v-d45a9e33]{color:var(--vp-c-brand-1)}.action-text[data-v-d45a9e33]{font-size:.75rem;font-weight:600;opacity:0;transform:translate(-8px);transition:all .25s ease}.action-icon[data-v-d45a9e33]{transition:transform .25s ease}.article-card:hover .action-text[data-v-d45a9e33]{opacity:1;transform:translate(0)}.article-card:hover .action-icon[data-v-d45a9e33]{transform:translate(4px)}@media(max-width:640px){.category-icon-wrap[data-v-d45a9e33]{width:42px;height:42px;border-radius:12px}.category-icon[data-v-d45a9e33]{font-size:18px}.category-title[data-v-d45a9e33]{font-size:1rem}.article-grid[data-v-d45a9e33]{gap:.75rem}.card-body[data-v-d45a9e33]{padding:.875rem 1rem}.article-title[data-v-d45a9e33]{font-size:.875rem}.card-action[data-v-d45a9e33]{padding:0 .875rem}.action-text[data-v-d45a9e33]{display:none}}.highlight-text[data-v-f601581b]{--hl-bg-color: var(--highlight-text-warning-bg, #fff3cd);--hl-text-color: var(--highlight-text-warning-text, #856404);display:inline;padding:var(--hl-padding);border-radius:var(--hl-border-radius);background-color:var(--hl-bg-color);color:var(--hl-text-color);line-height:1.4}.highlight-text--warning[data-v-f601581b]{--hl-bg-color: var(--highlight-text-warning-bg, #fff3cd);--hl-text-color: var(--highlight-text-warning-text, #856404)}.highlight-text--info[data-v-f601581b]{--hl-bg-color: var(--highlight-text-info-bg, #d1ecf1);--hl-text-color: var(--highlight-text-info-text, #0c5460)}.highlight-text--success[data-v-f601581b]{--hl-bg-color: var(--highlight-text-success-bg, #d4edda);--hl-text-color: var(--highlight-text-success-text, #155724)}.highlight-text--danger[data-v-f601581b]{--hl-bg-color: var(--highlight-text-danger-bg, #f8d7da);--hl-text-color: var(--highlight-text-danger-text, #721c24)}.highlight-text--note[data-v-f601581b]{--hl-bg-color: var(--highlight-text-note-bg, #e7d5f1);--hl-text-color: var(--highlight-text-note-text, #492866)}.highlight-text--custom[data-v-f601581b]{--hl-bg-color: var(--hl-custom-bg, #fff3cd);--hl-text-color: var(--hl-custom-text, #856404);background-color:var(--hl-bg-color);color:var(--hl-text-color)}:root{--highlight-text-warning-bg: #fff3cd;--highlight-text-warning-text: #856404;--highlight-text-info-bg: #d1ecf1;--highlight-text-info-text: #0c5460;--highlight-text-success-bg: #d4edda;--highlight-text-success-text: #155724;--highlight-text-danger-bg: #f8d7da;--highlight-text-danger-text: #721c24;--highlight-text-note-bg: #e7d5f1;--highlight-text-note-text: #492866}html.dark{--highlight-text-warning-bg: #3e331b;--highlight-text-warning-text: #ffd78a;--highlight-text-info-bg: #163a42;--highlight-text-info-text: #8edce6;--highlight-text-success-bg: #163c20;--highlight-text-success-text: #98e8a7;--highlight-text-danger-bg: #3d1b1e;--highlight-text-danger-text: #f5a3a9;--highlight-text-note-bg: #2a1d36;--highlight-text-note-text: #c9a7e0}.two-column-image[data-v-1bf3bb09]{display:flex;justify-content:space-between;align-items:flex-end}.image-column[data-v-1bf3bb09]{width:49%;text-align:center}.image[data-v-1bf3bb09]{width:100%;border-radius:8px}.caption[data-v-1bf3bb09]{font-size:14px;color:#666;margin-top:8px}.book-panel[data-v-1ddfc013]{position:fixed;inset:0;z-index:1000;display:flex;justify-content:flex-end;align-items:stretch}.book-panel__overlay[data-v-1ddfc013]{position:absolute;inset:0;background:#0006;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px)}.book-panel__drawer[data-v-1ddfc013]{position:relative;z-index:1;width:45%;max-width:92vw;height:100%;background:#fff;box-shadow:-12px 0 48px #00000024;display:flex;flex-direction:column;overflow-y:auto;overscroll-behavior:contain;--panel-leave-transform: translateX(100%)}.book-panel__header[data-v-1ddfc013]{position:relative;padding:52px 28px 28px;flex-shrink:0}.book-panel__close[data-v-1ddfc013]{position:absolute;top:14px;right:16px;width:30px;height:30px;border-radius:50%;border:none;background:#ffffffbf;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);display:flex;align-items:center;justify-content:center;cursor:pointer;color:#444;transition:background .2s,transform .15s;flex-shrink:0;z-index:2}.book-panel__close[data-v-1ddfc013]:hover{background:#fff;transform:rotate(90deg)}.book-panel__header-meta[data-v-1ddfc013]{display:flex;flex-direction:column;gap:6px}.book-panel__header-label[data-v-1ddfc013]{font-size:11px;font-weight:600;letter-spacing:1.2px;text-transform:uppercase;color:#00000073;margin:0}.book-panel__title[data-v-1ddfc013]{font-size:22px;font-weight:800;color:#1a1a1a;margin:0;line-height:1.35;display:-webkit-box;-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.book-panel__author[data-v-1ddfc013]{font-size:13px;color:#00000080;margin:0}.book-panel__body[data-v-1ddfc013]{padding:22px 28px 36px;display:flex;flex-direction:column;gap:16px;flex:1}.book-panel__top-bar[data-v-1ddfc013]{display:flex;justify-content:space-between;align-items:flex-start;gap:16px}.book-panel__top-left[data-v-1ddfc013]{display:flex;flex-direction:column;gap:10px;flex:1;min-width:0}.book-panel__links[data-v-1ddfc013]{display:flex;gap:8px;flex-shrink:0}.book-panel__link-btn[data-v-1ddfc013]{display:inline-flex;align-items:center;gap:5px;padding:7px 13px;border-radius:20px;background:#ffffffe6;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);color:#333;font-size:12px;font-weight:500;text-decoration:none;transition:background .2s,transform .2s,box-shadow .2s;box-shadow:0 1px 4px #0000000f;border:1px solid rgba(0,0,0,.05)}.book-panel__link-btn[data-v-1ddfc013]:hover{background:#fff;transform:translateY(-1px);box-shadow:0 3px 10px #0000001a}.book-panel__tags[data-v-1ddfc013]{display:flex;flex-wrap:wrap;gap:7px}.book-panel__tag[data-v-1ddfc013]{display:inline-block;padding:4px 13px;border-radius:20px;font-size:12px;font-weight:500;line-height:1.6;white-space:nowrap}.book-panel__rating[data-v-1ddfc013]{display:flex;align-items:center;gap:8px}.book-panel__rating .stars[data-v-1ddfc013]{display:flex;gap:2px}.book-panel__rating .star[data-v-1ddfc013]{width:18px;height:18px;color:#fbbf24}.book-panel__rating .star svg[data-v-1ddfc013]{width:100%;height:100%}.book-panel__rating .rating-label[data-v-1ddfc013]{font-size:13px;font-weight:500;color:#6b7280}.book-panel__rating .rating-text[data-v-1ddfc013]{font-size:14px;font-weight:600;color:#f59e0b}.book-panel__divider[data-v-1ddfc013]{height:1px;background:#00000012}.book-panel__section[data-v-1ddfc013]{display:flex;flex-direction:column;gap:10px}.book-panel__section-title[data-v-1ddfc013]{font-size:14px;font-weight:600;color:#aaa;margin:0;letter-spacing:.4px;line-height:1;display:flex;align-items:center;gap:6px}.book-panel__section-icon[data-v-1ddfc013]{font-style:normal;font-size:14px}.book-panel__desc[data-v-1ddfc013]{font-size:14px;color:#444;line-height:1.85;margin:0}.book-panel__highlights[data-v-1ddfc013]{list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:8px}.book-panel__highlight-item[data-v-1ddfc013]{font-size:14px;font-weight:500;color:#444;line-height:1.7;padding:10px 14px;background:linear-gradient(135deg,#fef9c3,#fef3c7);border-radius:8px;border-left:3px solid #f59e0b}.book-panel__highlight-item[data-v-1ddfc013]:before{content:"✓ ";color:#f59e0b;font-weight:700;margin-right:4px}.panel-slide-enter-active[data-v-1ddfc013],.panel-slide-leave-active[data-v-1ddfc013]{transition:opacity .28s ease}.panel-slide-enter-active .book-panel__drawer[data-v-1ddfc013],.panel-slide-leave-active .book-panel__drawer[data-v-1ddfc013]{transition:transform .3s cubic-bezier(.4,0,.2,1)}.panel-slide-enter-from[data-v-1ddfc013],.panel-slide-leave-to[data-v-1ddfc013]{opacity:0}.panel-slide-enter-from .book-panel__drawer[data-v-1ddfc013]{transform:translate(100%)}.panel-slide-leave-to .book-panel__drawer[data-v-1ddfc013]{transform:var(--panel-leave-transform, translateX(100%))}@media(max-width:640px){.book-panel[data-v-1ddfc013]{align-items:flex-end;justify-content:center}.book-panel__drawer[data-v-1ddfc013]{width:100%;max-width:100%;height:82vh;border-radius:20px 20px 0 0;box-shadow:0 -8px 40px #0000002e;--panel-leave-transform: translateY(100%)}.book-panel__drawer[data-v-1ddfc013]:before{content:"";display:block;width:36px;height:4px;border-radius:2px;background:#00000026;margin:10px auto 0;flex-shrink:0}.book-panel__header[data-v-1ddfc013]{padding:20px 22px 24px}.book-panel__title[data-v-1ddfc013]{font-size:19px}.book-panel__body[data-v-1ddfc013]{padding:18px 22px 40px}.book-panel__close[data-v-1ddfc013]{top:16px;right:16px}.book-panel__top-bar[data-v-1ddfc013]{flex-direction:column;align-items:stretch;gap:14px}.book-panel__links[data-v-1ddfc013]{justify-content:flex-start}.book-panel__link-btn[data-v-1ddfc013]{padding:6px 11px;font-size:11px}.panel-slide-enter-from .book-panel__drawer[data-v-1ddfc013]{transform:translateY(100%)}}.dark{background:var(--vp-c-bg, #1a1a2e)}.dark{color:#fff6}.dark{color:#e8e8e8}.dark{color:#b8b8c8}.dark{background:#ffffff14}.dark{color:#ffffff59}.dark{background:#ffffff26;color:#ccc}.dark{background:#ffffff40}.dark{color:#ffffff73}.dark{background:#ffffff26}.dark{background:linear-gradient(135deg,#fbbf2426,#f59e0b1a);border-left-color:#f59e0b;color:#e8e8e8}.dark{background:#28283ce6;color:#e8e8e8;box-shadow:0 1px 4px #0003;border-color:#ffffff14}.dark{background:#373750fa}.book-list[data-v-fd79cd55]{margin-top:16px;display:grid;grid-template-columns:repeat(3,1fr);gap:20px;padding:4px 0 28px}@media(max-width:768px){.book-list[data-v-fd79cd55]{grid-template-columns:repeat(2,1fr)}}@media(max-width:480px){.book-list[data-v-fd79cd55]{grid-template-columns:1fr}}.book-card[data-v-fd79cd55]{display:flex;flex-direction:column;border-radius:14px;overflow:hidden;box-shadow:0 2px 10px #00000012;border:1px solid rgba(0,0,0,.05);transition:transform .25s ease,box-shadow .25s ease;cursor:pointer;background:#fff;text-decoration:none;color:inherit}.book-card[data-v-fd79cd55]:hover{transform:translateY(-5px);box-shadow:0 10px 28px #0000001f}.book-card--active[data-v-fd79cd55]{box-shadow:0 0 0 2px var(--vp-c-brand, #3b82f6),0 10px 28px #0000001f;transform:translateY(-5px)}.book-cover[data-v-fd79cd55]{position:relative;width:100%;aspect-ratio:16 / 9;overflow:hidden}.book-cover__img[data-v-fd79cd55]{width:100%;height:100%;object-fit:cover;display:block;transition:transform .3s ease}.book-card:hover .book-cover__img[data-v-fd79cd55]{transform:scale(1.04)}.book-cover__overlay[data-v-fd79cd55]{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:#0000;transition:background .25s ease}.book-card:hover .book-cover__overlay[data-v-fd79cd55]{background:#00000052}.book-cover__hint[data-v-fd79cd55]{color:#fff;font-size:13px;font-weight:500;letter-spacing:.5px;opacity:0;transform:translateY(6px);transition:opacity .25s ease,transform .25s ease;text-decoration:none;padding:6px 14px;border:1px solid rgba(255,255,255,.7);border-radius:20px;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.book-card:hover .book-cover__hint[data-v-fd79cd55]{opacity:1;transform:translateY(0)}.book-info[data-v-fd79cd55]{padding:14px 16px 16px;display:flex;flex-direction:column;gap:7px;flex:1;background:#fff}.book-info__title[data-v-fd79cd55]{font-size:14px;font-weight:700;line-height:1.4;color:#1a1a1a;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.book-info__author[data-v-fd79cd55]{font-size:12px;color:#888}.book-info__rating[data-v-fd79cd55]{display:flex;align-items:center;gap:6px}.book-info__rating .stars[data-v-fd79cd55]{display:flex;gap:1px}.book-info__rating .star[data-v-fd79cd55]{width:14px;height:14px;color:#fbbf24}.book-info__rating .star svg[data-v-fd79cd55]{width:100%;height:100%}.book-info__rating .rating-label[data-v-fd79cd55]{font-size:11px;font-weight:500;color:#6b7280}.book-info__rating .rating-text[data-v-fd79cd55]{font-size:12px;font-weight:600;color:#f59e0b}.book-info__tags[data-v-fd79cd55]{display:flex;flex-wrap:wrap;gap:5px}.book-info__desc[data-v-fd79cd55]{font-size:12px;color:#666;line-height:1.7;margin:0;display:-webkit-box;-webkit-line-clamp:3;line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}.tag[data-v-fd79cd55]{display:inline-block;padding:2px 8px;border-radius:20px;font-size:11px;font-weight:500;line-height:1.6;white-space:nowrap}.dark .book-card[data-v-fd79cd55]{background:var(--vp-c-bg-soft, #1e1e2e);border-color:#ffffff14}.dark .book-info[data-v-fd79cd55]{background:var(--vp-c-bg-soft, #1e1e2e)}.dark .book-info__title[data-v-fd79cd55]{color:#e8e8e8}.dark .book-info__desc[data-v-fd79cd55]{color:#aaa}:root{animation:rainbow 12s linear infinite}.tk-avatar{height:var(--tk-avatar-size)!important;width:var(--tk-avatar-size)!important}.tk-avatar--circle{border-radius:50%!important}.vp-doc #hero-text{display:none!important}@media(min-width:640px){:root{--vp-home-hero-image-filter: blur(56px)}}@media(min-width:960px){:root{--vp-home-hero-image-filter: blur(68px)}}.VPLocalSearchBox[data-v-400916ea]{position:fixed;z-index:100;inset:0;display:flex}.backdrop[data-v-400916ea]{position:absolute;inset:0;background:var(--vp-backdrop-bg-color);transition:opacity .5s}.shell[data-v-400916ea]{position:relative;padding:12px;margin:64px auto;display:flex;flex-direction:column;gap:16px;background:var(--vp-local-search-bg);width:min(100vw - 60px,900px);height:min-content;max-height:min(100vh - 128px,900px);border-radius:6px}@media(max-width:767px){.shell[data-v-400916ea]{margin:0;width:100vw;height:100vh;max-height:none;border-radius:0}}.search-bar[data-v-400916ea]{border:1px solid var(--vp-c-divider);border-radius:4px;display:flex;align-items:center;padding:0 12px;cursor:text}@media(max-width:767px){.search-bar[data-v-400916ea]{padding:0 8px}}.search-bar[data-v-400916ea]:focus-within{border-color:var(--vp-c-brand-1)}.local-search-icon[data-v-400916ea]{display:block;font-size:18px}.navigate-icon[data-v-400916ea]{display:block;font-size:14px}.search-icon[data-v-400916ea]{margin:8px}@media(max-width:767px){.search-icon[data-v-400916ea]{display:none}}.search-input[data-v-400916ea]{padding:6px 12px;font-size:inherit;width:100%}.search-input[data-v-400916ea]::-webkit-search-cancel-button{display:none}@media(max-width:767px){.search-input[data-v-400916ea]{padding:6px 4px}}.search-actions[data-v-400916ea]{display:flex;gap:4px}@media(any-pointer:coarse){.search-actions[data-v-400916ea]{gap:8px}}@media(min-width:769px){.search-actions.before[data-v-400916ea]{display:none}}.search-actions button[data-v-400916ea]{padding:8px}.search-actions button[data-v-400916ea]:not([disabled]):hover,.toggle-layout-button.detailed-list[data-v-400916ea]{color:var(--vp-c-brand-1)}.search-actions button.clear-button[data-v-400916ea]:disabled{opacity:.37}.search-keyboard-shortcuts[data-v-400916ea]{font-size:.8rem;opacity:75%;display:flex;flex-wrap:wrap;gap:16px;line-height:14px}.search-keyboard-shortcuts span[data-v-400916ea]{display:flex;align-items:center;gap:4px}@media(max-width:767px){.search-keyboard-shortcuts[data-v-400916ea]{display:none}}.search-keyboard-shortcuts kbd[data-v-400916ea]{background:#8080801a;border-radius:4px;padding:3px 6px;min-width:24px;display:inline-block;text-align:center;vertical-align:middle;border:1px solid rgba(128,128,128,.15);box-shadow:0 2px 2px #0000001a}.results[data-v-400916ea]{display:flex;flex-direction:column;gap:6px;overflow-x:hidden;overflow-y:auto;overscroll-behavior:contain}.result[data-v-400916ea]{display:flex;align-items:center;gap:8px;border-radius:4px;transition:none;line-height:1rem;border:solid 2px var(--vp-local-search-result-border);outline:none}.result>div[data-v-400916ea]{margin:12px;width:100%;overflow:hidden}@media(max-width:767px){.result>div[data-v-400916ea]{margin:8px}}.titles[data-v-400916ea]{display:flex;flex-wrap:wrap;gap:4px;position:relative;z-index:1001;padding:2px 0}.title[data-v-400916ea]{display:flex;align-items:center;gap:4px}.title.main[data-v-400916ea]{font-weight:500}.title-icon[data-v-400916ea]{opacity:.5;font-weight:500;color:var(--vp-c-brand-1)}.title svg[data-v-400916ea]{opacity:.5}.result.selected[data-v-400916ea]{--vp-local-search-result-bg: var(--vp-local-search-result-selected-bg);border-color:var(--vp-local-search-result-selected-border)}.excerpt-wrapper[data-v-400916ea]{position:relative}.excerpt[data-v-400916ea]{opacity:50%;pointer-events:none;max-height:140px;overflow:hidden;position:relative;margin-top:4px}.result.selected .excerpt[data-v-400916ea]{opacity:1}.excerpt[data-v-400916ea] *{font-size:.8rem!important;line-height:130%!important}.titles[data-v-400916ea] mark,.excerpt[data-v-400916ea] mark{background-color:var(--vp-local-search-highlight-bg);color:var(--vp-local-search-highlight-text);border-radius:2px;padding:0 2px}.excerpt[data-v-400916ea] .vp-code-group .tabs{display:none}.excerpt[data-v-400916ea] .vp-code-group div[class*=language-]{border-radius:8px!important}.excerpt-gradient-bottom[data-v-400916ea]{position:absolute;bottom:-1px;left:0;width:100%;height:8px;background:linear-gradient(transparent,var(--vp-local-search-result-bg));z-index:1000}.excerpt-gradient-top[data-v-400916ea]{position:absolute;top:-1px;left:0;width:100%;height:8px;background:linear-gradient(var(--vp-local-search-result-bg),transparent);z-index:1000}.result.selected .titles[data-v-400916ea],.result.selected .title-icon[data-v-400916ea]{color:var(--vp-c-brand-1)!important}.no-results[data-v-400916ea]{font-size:.9rem;text-align:center;padding:12px}svg[data-v-400916ea]{flex:none} diff --git a/assets/tags.md.DelZTtSB.js b/assets/tags.md.DelZTtSB.js new file mode 100644 index 00000000..22416c79 --- /dev/null +++ b/assets/tags.md.DelZTtSB.js @@ -0,0 +1 @@ +import{_ as e,g as t,h as a}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const m=JSON.parse('{"title":"标签","description":"","frontmatter":{"title":"标签","permalink":"/tags","tagsPage":true,"article":false,"layout":"home"},"headers":[],"relativePath":"tags.md","filePath":"@pages/tagsPage.md"}'),s={name:"tags.md"};function r(o,n,c,i,p,g){return a(),t("div")}const _=e(s,[["render",r]]);export{m as __pageData,_ as default}; diff --git a/assets/tags.md.DelZTtSB.lean.js b/assets/tags.md.DelZTtSB.lean.js new file mode 100644 index 00000000..22416c79 --- /dev/null +++ b/assets/tags.md.DelZTtSB.lean.js @@ -0,0 +1 @@ +import{_ as e,g as t,h as a}from"./chunks/vitepress-theme-teek.BIbhbr3v.js";const m=JSON.parse('{"title":"标签","description":"","frontmatter":{"title":"标签","permalink":"/tags","tagsPage":true,"article":false,"layout":"home"},"headers":[],"relativePath":"tags.md","filePath":"@pages/tagsPage.md"}'),s={name:"tags.md"};function r(o,n,c,i,p,g){return a(),t("div")}const _=e(s,[["render",r]]);export{m as __pageData,_ as default}; diff --git a/@pages/categoriesPage.html b/categories.html similarity index 89% rename from @pages/categoriesPage.html rename to categories.html index 46b7413a..b0af8a80 100644 --- a/@pages/categoriesPage.html +++ b/categories.html @@ -6,12 +6,12 @@ 分类 | Insight Stack - + - - - - + + + + @@ -30,7 +30,7 @@ - + +
      diff --git a/fullstack/ai-change-work-workflow.html b/fullstack/ai-change-work-workflow.html new file mode 100644 index 00000000..897ed51a --- /dev/null +++ b/fullstack/ai-change-work-workflow.html @@ -0,0 +1,178 @@ + + + + + + 读 Anthropic 研究报告,探寻 AI 时代的工程范式重塑 | Insight Stack + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      Skip to content
      4407
      + + + + 15.2m

      读 Anthropic 研究报告,探寻 AI 时代的工程范式重塑

      摘要总结:软件工程正经历从“手写逻辑”向“意图调度”的范式迁徙。Anthropic 的研究揭示了 AI 并非简单的提效工具,而是通过释放 27% 曾经“不划算”的工程任务,重塑了软件质量的密度。在自然语言即编程语言的时代,我们需要通过规格驱动(SDD)与多智能体编排,破解“监督悖论”带来的技能平庸化危机,将 AI 的概率性生成驯化为确定性的工程交付。当编码成本趋于零,工程师的终极壁垒将是定义完美的品味,以及在 AI 迷雾中识破平庸的洞察力。

      博客原文

      地址How AI is transforming work at Anthropic

      核心标签AI辅助编程 工程 范式转移 工作转型 生产力提升 技能发展 人机协作

      一句话介绍:Anthropic 不仅仅是 AI 工具的生产者,更是第一个进入“未来实验室”的深度观察者。他们通过内部数月的实验数据告诉我们:大模型对软件工程的改造,绝非简单的“提效”,而是一场关于工程范式与职业认同的重塑。

      延伸思考工程团队要用多少年,才会把现在的'人+AI 协作方式',沉淀为一个稳定的工程范式?

      1. 引言

      软件工程的历史,本质上是一部不断通过“抽象”来对抗“复杂度”的进化史。从汇编语言到高级语言,从手动内存管理到垃圾回收,每一次抽象层的上移,都会让一部分曾经引以为傲的手艺淡出舞台,同时释放出更宏大的创造力。

      2025 年底,Anthropic 发布了一份具有里程碑意义的研究报告:《AI 如何改变 Anthropic 的工作方式》。作为大模型的缔造者,Anthropic 将自己变成了一个“AI 时代工作范式的实验室”。他们不仅向外输出模型,更在内部深度观测:当工程师拥有了像 Claude 这样具备自主能力的“AI 同事”后,代码的生产流程、团队的协作边界、甚至是“工程师”这一职业的底层逻辑,究竟发生了怎样的质变?

      这份报告揭示了一组迷人且令人警醒的数据:在 AI 辅助下,工程师们不仅在提速,更在处理那 27% 曾经“不划算”或“超出能力边界”的任务。然而,光鲜的数据背后,是“编程技能萎缩”的隐忧和“监督悖论”的挑战。

      站在产品与应用工程师的角度看,我最关心的不仅是“AI 能写多快”,而是如何将这种碎片化的、依赖“灵感”的 AI 协作,沉淀为一套稳定的工程范式

      本文将基于 Anthropic 的这份深度观测,结合我们在 AI Native 应用架构、以及“规格驱动开发(SDD)”中的一些实践,探讨三个核心命题:

      • 任务重构:当编码成本趋于零时,哪些被长期忽视的“工程债务”将变成核心资产?

      • 能力重塑:在“英语/中文即编程语言”的时代,如何保持技术尖锐度并构建新的“工程 Sense”?

      • 范式落地:我们该如何设计一套人机协作的链路,让 AI 的产出从“不确定的随机性”走向“可交付的工程化”?

      2. 盯准任务构成,而非单一速度,重获“工程尊严”的 27%

      一句话总结:

      AI 对工程团队的真正馈赠,是让我们从繁琐的、“不得不做”的苦力活中抽身,去夺回对软件质量的掌控力。速度是副产品,质量的密度才是衡量 AI 协作水平的终极标准。

      在讨论 AI 提效时,我们很容易掉入的陷阱就是 “速度幻觉”。如果单纯观察代码产出行数(LOC)或需求交付周期,我们可能会得出“工程师变快了”的浅层结论,但 Anthropic 的研究给出了一个更具洞察力的视角:AI 带来的最大变量,不是让既有任务变快了,而是改变了“任务的构成比例”

      报告中提到的那个关键数字——27%,代表了那些如果没有 AI 辅助,工程师根本不会去碰的任务。这 27% 并非边缘工作,而是软件工程中长期被牺牲掉的“工程尊严”。

      2.1 从"技术债务"到"系统韧性"

      在传统开发模式下,那些遗留的烂代码、缺失的测试覆盖、疏于维护的内部工具——这些"技术债务"虽不至于让系统立刻崩溃,却如同慢性毒药,持续侵蚀团队的认知资源与开发效率。

      Anthropic 的观察揭示了一个关键转折点:当 AI 介入后,清偿这些"技术债务"的成本首次降到了可接受的阈值之下。

      • 重构民主化:曾经需要资深工程师耗费数小时、如履薄冰的手动重构,如今在 AI 辅助下几分钟即可完成初稿并通过基础验证,重构从"高风险操作"变成了"日常习惯"。
      • 测试与文档的范式转移:最令人抵触的单元测试编写和技术文档维护,正逐渐演变为 AI 擅长的"结构化填空"——工程师定义意图与边界,AI 负责填充实现细节,人类则专注于验收与精炼。
      • 可视化与工具的自动化:随着 AI 能力的提升,可视化工具、内部工具等也开始被自动化,工程师可以更专注于业务逻辑的实现,而不是手动维护这些工具。

      2.2 从"不划算"到"高价值":任务优先级的重新洗牌

      作为产品工程师,我们每天都在做取舍:哪些任务值得投入时间,哪些只能往后放?过去,很多工程改进任务——比如增加可观测性的埋点、搭建内部性能看板——虽然对系统长期健康很重要,但因为做起来太费功夫,往往被无限期搁置。我们心里都明白这些任务有价值,但"性价比"太低,排不上优先级。

      AI 的出现改变了这个算式。它像一根杠杆,把那些原本需要花费大量时间的繁琐工作,变成了可以快速完成的"轻量级任务"。过去可能要花一整天写的监控脚本,现在几分钟就能让 AI 生成初稿;以前需要专门排期的重构工作,现在可以随手完成。

      这意味着什么?那些曾经因为"太麻烦"而被忽视的任务,现在突然变得"很划算"了。团队不再只是追求开发速度,而是有能力把系统打磨得更健壮、更可维护。我们不再只是跑得更快,而是能跑得更稳、更远。

      2.3 跨领域能力的“无痛溢出”

      研究还揭示了一个引人注目的现象:工程师的角色边界正在变得愈发模糊,"全栈化"趋势日益明显。

      • 后端工程师借助 AI 轻松涉足复杂的数据可视化前端开发。
      • 研究员也能独立搭建用于实验的内部管理后台。

      这种能力的自然延伸并非意味着人人都成为通才,而是 AI 将跨领域协作的摩擦成本大幅降低。当技术壁垒被削平,原本需要数周协调的跨职能配合,如今可在数小时内完成闭环验证——反馈周期实现了量级压缩。

      3. 对抗“平庸化” —— 在自然语言编程时代重塑工程 Sense

      一句话总结:

      抽象层的上移并不意味着底层知识的贬值,反而意味着识别平庸的能力变得空前昂贵。当每个人都有一个能写代码的 AI 同事时,你对“完美工程”的定义能力,决定了你在这个时代的价值上限。

      当编程的门槛降低到“只要会说话就能写代码”时,软件工程正经历一场权力的交接:自然语言(英语/中文)正在成为最高级的编程语言。

      这种转变带来了一种极其诱人的“Vibe Coding(凭感觉编程)”体验。然而,Anthropic 的研究揭示了一个冷酷的现实:AI 往往表现得像一个“极其聪明但缺乏责任感的初级工程师”。如果我们全盘接受这种便利,而不去有意识地重构自身的职业能力,我们可能会陷入一种“监督悖论(Supervision Paradox)”——即当你失去了手动解决问题的能力时,你也失去了监督 AI 的资格。

      3.1 警惕“监督悖论”与能力的平庸化

      Anthropic 的报告中提到,有效使用 AI 需要极强的“监督力”,而这种能力恰恰源于那些正在被 AI 取代的底层编码实践。这种转变催生了一个深刻的监督悖论:

      • 技能萎缩的风险:长期依赖 AI 生成代码,会导致开发者对内存管理、并发模型、边界条件等底层细节的敏感度下降。

      (附带学习)的丧失: 过去我们在翻阅文档、调试 Bug 的痛苦过程中,会意外学到系统的运行机理。AI 直接给出答案,切断了这种深度学习的路径。

      AI Free 的刻意练习:每周或每个迭代,挑选一个核心逻辑块,尝试在完全不求助 AI 的情况下,手写实现并进行性能调优。这就像飞行员必须定期进行手动起降练习一样,是保持底层“肌肉记忆”的唯一方式。

      3.2 从 Vibe Coding 进化到规范驱动(SDD)

      为了不让工程质量滑向“随机性”的深渊,我们需要将“凭感觉”转化为 “定规范”。在“英语即编程语言”的时代,工程师的独特价值不再是实现细节,而是对约束条件的定义。

      • 定义验收标准:我们需要比以前更清晰地告诉 AI,什么是“正确”。这就要求具备极强的系统架构思维和对业务逻辑的深度拆解能力。
      • 引入工程语义:模糊的指令只会带来模糊的结果。正如近期在实践中推崇的 Specification Driven Development (SDD),我们需要在自然语言与 AI 执行之间,建立一套严谨的语义层。这套语义标准如同工程契约,确保 AI 生成的代码不是随机"发散"的,而是始终锚定于可预期的工程范式之内。

      3.3. 构建新型“工程 Sense”:从手艺人到导演

      未来的高级工程师,其核心竞争力将体现在对品味与评判权的掌控上。

      • 批判性审美:AI 给出三个方案,你为什么选这一个?是因为它的扩展性更好,还是因为它在特定高并发场景下更稳健?这种基于经验的“选择权”就是新的工程 Sense。
      • 逆向工程能力:能够快速读懂 AI 生成的大体量代码,并在其中精准定位“聪明但危险”的逻辑缺陷。这要求我们必须保持对新技术的“深度阅读”习惯,而非仅仅停留在“调用”层面。

      4. 范式落地——在随机性之上,构建确定性的工程基座

      一句话总结:

      范式的落地不是一蹴而就的规则设定,而是一场伴随模型能力进化的动态博弈。我们要构建的是一套 “宽容输入、严格输出” 的链路:给 AI 足够的空间去创造和提效,但在交付的最后一公里,用最传统的工程理性进行最严苛的审判。

      如果说 AI 是一台拥有无限爆发力的引擎,那么软件工程范式就是承载它的底盘。当前最核心的矛盾在于:大模型本质上是概率性的,而工程交付要求的却是确定性的。

      如何让"不确定的生成"进化为"可交付的代码"?这不只是技术层面的挑战,更是一个关于全链路治理的系统性命题。我们不能以静态的视角审视现有工具,而需要动态地观察 LLM 能力演进、Agent 架构革新与传统工程设施的深度融合与协同演化。

      4.1 从“单点指令”转向“多智能体编排(Multi-Agent Orchestration)”

      正如 Anthropic 内部使用 Claude Code 处理日益复杂的任务,未来的落地范式绝非"人与单一窗口的对话",而是一个闭环的多智能体协作流水线。

      • 角色专业化分工:将复杂任务拆解并委派给不同的"专家智能体"。一个 Agent 专注于需求理解与方案设计,另一个负责代码实现,第三个则扮演"红队审查者"的角色,进行自动化的对抗性测试与漏洞挖掘。

      • 迭代式错误收敛:工程确定性不源于单次生成的完美,而来自 "生成-验证-诊断-修复-再验证" 的自动化闭环。在代码合并入主分支之前,它应当已在隔离的沙盒环境中,历经多轮 Agent 驱动的自我修正与质量收敛。

      4.2 构建"上下文护城河":从 Prompt 到知识图谱

      AI 输出的质量,本质上取决于它对业务语境的理解深度。当前最大的工程化障碍,正是模型面对团队私有知识时的"冷启动"困境——它缺乏对特定代码规范、架构决策和历史演进的隐性认知。

      • 动态上下文注入: 超越传统的 RAG(检索增强生成),将代码库、架构文档乃至团队的代码评审偏好,实时编织为 AI 的"工作记忆"。这不再是简单的信息检索,而是让 AI 真正"融入"团队的工程文化。

      • 工程语义翻译层: 在人类的模糊意图与机器的结构化理解之间,我们需要一座桥梁。这座桥梁将自然语言需求转化为 AI 可精确解析的语义图谱——基于 Graph 的代码索引、依赖关系网络与领域知识建模,共同构成这一翻译层的核心骨架。

      4.3 "可观测性":让 AI 的决策过程透明可见

      传统 DevOps 关注的是服务器负载、响应时间等机器指标;而在 AI 工程时代,我们需要追踪的是 AI 的"思考过程"。

      • 记录 AI 的决策链路:当 AI 修改代码时,我们不仅要看到"改了什么",更要理解"为什么这么改"——完整还原它的推理链条,让每一次变更都可追溯、可解释。

      • 建立分级信任机制:不是所有任务都需要人工逐一审核。对于 AI 表现稳定的标准化工作(如调整样式、生成单元测试),可以自动放行;一旦发现 AI 在推理过程中反复纠结、多次修正或出现异常,立即触发人工深度审查,形成人机协同的质量把关。

      4.4 拥抱"不确定性",但守住"质量底线"

      我们需要认清一个现实:未来的软件开发将是人与 AI 协作的过渡态,不会是非黑即白的完全自动化。与其追求每一步都人工可控,不如确保最终结果可验证、可信赖

      这意味着工程团队的核心能力要从"亲自写代码"转向 "搭建完善的评估体系"。只要你的测试、监控、回滚机制足够健壮,即使 AI 的输出带有一定随机性,也能被牢牢限制在安全的边界之内。

      5. 结语

      Anthropic 的这份报告,本质上是为我们展现了一个软件工程的“后工业时代”。在这个时代,AI 不是取代你的收割机,而是给了你“一百万匹马”的爆发力。

      正如报告中所揭示的那样:我们不应再纠结于单应仰望更高应仰望更高维度的景观。当写代码变得不再昂贵,对“什么是好代码”的定义权,以及对“系统为何而存在”的理解力,便成了这个行业最后的稀缺品

      未来,最优秀的工程师或许不再是那个能手写极致算法的人,而是那个能在随机生成的迷雾中,凭借深厚的底层功底,一眼识破平庸与风险,并为 AI 指明方向的人。

      范式的沉淀或许仍需时间,请务必在享受 AI 提效的同时,刻意保持你的技术尖锐度。因为 在“机器执行”的洪流下,人类的品位与责任感,依然是软件工程中那道最坚固、也最温暖的防御线

      + + + + \ No newline at end of file diff --git a/fullstack/ai-coding/resources.html b/fullstack/ai-coding/resources.html new file mode 100644 index 00000000..3c487155 --- /dev/null +++ b/fullstack/ai-coding/resources.html @@ -0,0 +1,177 @@ + + + + + + AI 编程工具与资源推荐 | Insight Stack + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      Skip to content
      3472
      + + + + 13.3m

      AI 编程工具与资源推荐

      摘要总结:本文深度解析了 AI 驱动编程的三大演进范式:Vibe Coding(自然语言零门槛构建)、AI IDE(编辑器深度辅助提效)及 Agentic Engineering(自主工程师执行任务)。通过横向对比 Bolt.new、Cursor、Claude Code 等前沿工具,文章勾勒出一条从“快速原型”到“高效协同”再到“自主交付”的进阶路径。核心旨在指导用户利用 AI 工具矩阵打破技术边界,实现从创意描述到工业级交付的生产力飞跃,重塑软件开发全生命周期。

      1. 三种编程范式速览

      范式一句话描述你的角色
      Vibe Coding用自然语言描述需求,AI 直接生成可运行的完整项目描述需求,让 AI 写代码(新手友好)
      AI IDE在编辑器里引入 AI 辅助,边写边补全、边问边改主导开发,让 AI 做副驾驶(更多控制)
      Agentic EngineeringAI 作为"自主工程师",接收任务后自动规划并执行全套代码工作流提任务、审结果,让 AI 执行(极致提效)

      新手路线建议:先用 Bolt.new 或 v0.dev 体验 Vibe Coding 零门槛出产品的感觉 → 再切换到 Cursor 做日常编码提效 → 最后尝试 Claude Code/opencode 体验 AI 自主完成工程任务,三步感受"AI 如何重塑编程工作流"。

      注意:使用 Claude Code 等 CLI Agent 工具,需要订阅官方模型服务(Claude Pro / API)。若暂无订阅,可通过配置自定义模型服务,支持对接兼容 第三方服务(如 GLM、DeepSeek、通义千问),实现低成本上手。

      2. Vibe Coding — 用自然语言"说"出一个应用

      2.1 关键点说明

      适合人群:产品经理、设计师、创业者,或想快速验证想法的非专业开发者。

      核心价值:从一段文字描述到可运行的 Web 应用,无需搭建开发环境;天生适合 MVP 原型验证UI 快速迭代

      如何上手:打开网站 → 在输入框描述你的应用(如"做一个番茄钟 App,有开始暂停按钮,完成后有提示音")→ AI 生成代码并实时预览 → 继续对话迭代功能。

      2.2 六款工具横向对比

      💡 快速选择建议

      • 要做完整全栈 Web 并直接上线Bolt.new(成熟度最高)
      • 只需前端 UI 组件嵌入现有项目 → v0
      • 非技术背景想独立做出有数据库的产品 → Lovable
      • 在线学编程或使用 Python / Go 等非 React 语言 → Replit Agent
      • 手头有参考网站想直接还原其界面 → Same.dev
      • 中文用户或目标平台是微信小程序秒哒 Miaoda
      工具核心定位输出形态技术栈最适场景上手门槛
      Bolt.new应用生成完整 Web 应用React快速生成可部署全栈 Demo
      v0UI 组件生成React 组件代码片段React + Tailwind + shadcn/ui前端界面快速出图,嵌入 Next.js 项目
      Lovable零代码全栈建站含数据库的完整 Web 产品前端 + Supabase 后端非技术人员独立做出可上线产品
      Replit Agent云端多语言全栈多语言完整项目Python / JS / Go 等多语言在线学编程、非 React 技术栈原型⭐⭐
      Same.dev网站 UI 克隆前端页面还原代码前端(URL → 代码)参考竞品设计、快速获取建站初始模板
      秒哒 Miaoda无代码应用搭建Web 应用 / 微信小程序Web + 小程序双端中文一句话出原型,尤其适合小程序

      3. AI IDE — 与代码编辑器深度融合

      3.1 关键点说明

      适合人群:有一定编程基础、追求研发效率的开发者。

      核心价值:上下文感知补全 + 自然语言对话改代码 + Agent 自主多文件重构,让"写代码"变成"描述 + 确认"。

      如何上手:安装对应工具 → 打开项目 → 用快捷键呼出 AI 对话框(如 Cursor 的 Cmd+K)→ 用自然语言描述要改什么 → 确认差异后应用。

      3.2 三款工具横向对比

      💡 选择建议

      • 追求口碑最佳 + 生态最成熟的 AI IDE → Cursor(社区资源最丰富)
      • 数据安全 / 合规要求,或想要免费的国产方案 → Trae IDE
      • 喜欢 AI 自动串联多步任务,享受不中断的"心流"编程体验 → Windsurf
      • 三款均基于 VS Code 改造,现有 VS Code 插件和快捷键习惯均可无缝迁移
      工具核心特色Agent 能力数据安全费用最适场景
      Cursor多文件上下文感知补全 + Cmd+K 行内生成强 — 多文件规划 + 终端执行一般(代码发往云端)免费额度 + 订阅日常功能开发、多文件重构、代码 Review
      Trae IDE国产免费 + 本地优先数据安全强 — 对标 Cursor,含在线 SOLO 版本地优先 + 隐私模式免费有合规需求的国内团队、个人日常开发
      WindsurfCascade 前瞻规划 + Tab 一键心流强 — 前瞻 10 步、自动串联多步任务一般(代码发往云端)免费额度 + 订阅复杂多步任务自动执行、追求"心流"开发体验

      4. Agentic Engineering — AI 自主完成工程任务

      4.1 关键点说明

      适合人群:希望将完整工程任务交给 AI 自主处理的资深开发者或团队。

      核心价值:AI 不再只是"副驾驶",而是能自主读取代码库、运行测试、修复 Bug、甚至提交 PR 的"自主工程师",适合 Bug 修复、功能迭代、代码重构等完整工程周期。

      如何上手(以 Claude Code 为例)npm install -g @anthropic-ai/claude-code → 在项目根目录执行 claude → 输入任务(如"帮我找出 #123 这个 Bug 的根因,写好测试后提交")→ Claude Code 自主读取代码库、执行命令并逐步反馈,审查后确认提交。

      4.2 五款 Agentic 工具横向对比

      选型建议

      • 个人 / 小项目:优先 Claude Code(体验最流畅),无订阅则用 opencode 接入低成本模型平替。
      • 团队 / 私有部署:用 OpenHands 自托管,统一管控模型与 API Key,保障数据不出域。
      • Issue 驱动的研发流:接入 Devin,让 AI 全程完成 Issue → 代码 → PR 闭环,人工只做 Review。
      • 大型存量代码库:优先 Augment Code,深度索引能力是 CLI Agent 难以替代的。
      工具交互方式核心优势适场景典型任务示例费用
      Claude Code终端 CLI与本地代码库深度结合,可执行 Shell / Git,多文件读写全自动个人或小团队的重构、批量 Bug 修复、自动提交等完整工程周期claude → "重构 auth 模块,保持接口不变,补齐单测后提交"Claude Pro / API 按量计费
      opencode终端 CLI完全开源,内置免费模型,支持接入任意 LLM(含国内模型)无官方订阅、希望接入 DeepSeek / 通义等低成本模型的场景opencode → 配置自定义模型 → 同上工程任务取决于所接模型
      DevinWeb 界面高度自主,可持续跟进 GitHub Issue,全链路无人值守有明确 Issue 驱动的团队研发流,AI 自动完成功能开发并提 PR粘贴 Issue URL → 指定验收标准 → 审查 PR付费(企业为主)
      OpenHandsWeb / API开源自托管,支持多 LLM,可定制扩展 Agentic 流程企业私有化部署,团队共享 AI 工程师能力,保障数据安全Docker 启动 → 接入 DeepSeek → 批量分配修复任务开源免费,按模型计费
      Augment CodeIDE 插件深度索引百万行级代码库,上下文感知精准大型企业存量代码库的日常开发、重构与工程管理圈选模块 → "梳理调用链并生成文档"免费额度 + 订阅
      + + + + \ No newline at end of file diff --git a/fullstack/ai-engineer-capability.html b/fullstack/ai-engineer-capability.html new file mode 100644 index 00000000..c35aef2f --- /dev/null +++ b/fullstack/ai-engineer-capability.html @@ -0,0 +1,178 @@ + + + + + + 重构开发者:AI 时代下的工程师能力图谱与演进指南 | Insight Stack + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      Skip to content
      3614
      + + + + 12.9m

      重构开发者:AI 时代下的工程师能力图谱与演进指南

      摘要总结:当 AI 极速降低代码编写门槛,单纯的“业务代码翻译器”角色正加速贬值。本文从技术演进与产品思考的交汇点出发,将 AI 时代的开发者能力图谱重新划分为三大核心圈层:产品应用层(Insight Stack)、Agent 开发层与 AI 基础设施层。无论你是深耕视图层交互、精通 Node.js 等服务端架构的开发者,还是致力于技术落地的探索者,都能在这份演进指南中找到打破能力边界、向“超级个体”与“AI 智能体指挥官”跃迁的破局之道。

      about site background

      如果你对近两年的技术浪潮保持敏感,大概会得出一个有些残酷但无比真实的结论:代码正在发生“通货膨胀”。随着大模型编程能力的指数级跃升,纯粹的“将业务逻辑翻译成代码”这项技能的溢价正在快速衰减。当 AI 能在几秒钟内吐出包含完整类型定义、错误处理和测试用例的后端接口或是 React 组件时,软件工程师的护城河究竟在哪里?

      行业的演进给出了答案:开发者的角色正在经历一次彻底的重构。我们正在从“代码的编写者”转变为“系统的架构者”与“AI 智能体的指挥官”。结合当下的工业界实践,我们可以将 AI 时代的工程师图谱清晰地划分为三大核心圈层:产品应用层、Agent 开发层与 AI 基础设施层

      1. 产品应用层(Insight Stack):走向“超级个体”的 AI 原生全栈

      核心壁垒:技术视野 + 产品敏锐度 + 极速的架构组装能力,能够单枪匹马或带领极小团队,将一个灵感迅速转化为高可用产品。

      在 AI 极大地降低了代码编写门槛的今天,“决定做什么”和“如何利用 AI 构建系统”的价值,已经逐渐超越了“纯手工敲击代码”的价值。这或许是传统前端、后端开发者转型最顺滑、也最能释放巨大商业价值的一层。

      在这一层,“全栈工程师”的定义被重新改写为“产品工程师(Product Engineer)”。技术栈不再仅仅是前端框架和数据库,而是包含了“产品 Sense”与“商业洞察”的 Insight Stack。全栈工程师也正在进化为“超级个体”或“产品工程师(Product Engineer)”。问题发现 -> 创意沉淀 -> AI 辅助技术方案 -> AI 驱动代码生成 这一闭环,正是当前最高效的独立开发或小团队敏捷开发范式。

      1.1 产品 Sense 与业务洞察

      过去,工程师往往是被动接收 PRD。而在 AI 时代,技术门槛的降低意味着工程师可以随时将生活和工作中的“灵感碎片”与“痛点捕获”转化为产品创意。我们需要具备极其敏锐的 AI 边界认知,明确知道哪些场景适合用传统的 CRUD 解决,哪些必须交由 LLM 去处理模糊与非确定性。

      在产品应用层,我们还需要具备数据飞轮意识,注重在应用层设计埋点,收集用户的交互与纠错数据,为后续的 Agentic workflow 优化或模型微调提供高质量数据源。

      1.2 Agentic Engineering(智能体工程)

      这是一种全新的开发范式,开发者不再逐行手敲代码,而是通过撰写严谨的 Spec、利用 TDD(测试驱动开发)和 Lint 强约束,去“驱动”和“管理” AI 编程助手(如 Claude Code、Cursor),全栈基础设施的范畴也扩展到了跨端轻量化应用(例如利用前端技术栈快速构建高价值的浏览器插件)。

      能力维度具体要求
      规划、设计与迭代能力• 能够快速响应业务需求,规划产品功能,完成技术架构的调研、选型与整体设计。
      • 能借助 AI 进行前端视图层、Node.js 后端核心数据流、业务流程的顶层设计。
      • 不但能单枪匹马或带领极小团队中的人,还懂得领导、管理 AI 数字员工。
      AI 驱动编程基于 Spec、TDD、Hooks(Lint 检查)等强约束机制,驱动 Claude Code / Copilot 等工具生成高规范度代码。
      全栈基础设施熟练掌握传统架构体系(数据库选型、Redis、微服务、消息队列),以及跨端/轻量化形态(如 Chrome 插件生态)的工程搭建。
      DevOps现代化的自动化部署、CI/CD 流水线搭建与运维。

      1.3 AI-First 的交互哲学

      AI 应用的体验与传统软件截然不同。为了对抗大模型的延迟与幻觉,工程师必须掌握流式渲染(Streaming UI)、生成式 UI(Generative UI)等新一代交互模式,用优雅的工程设计兜底 AI 的不确定性。

      • 流式渲染(Streaming UI):优化大模型响应的等待体验。
      • 生成式交互(Generative UI):在前端框架(如 React / Next.js)中,根据 AI 返回的结构化状态实时渲染出最合适的交互组件,而非死板的对话框。
      • 容错与兜底机制:优雅处理大模型幻觉(Hallucination),降低用户的挫败感。

      2. Agent 开发层:构建连接物理世界的数字中枢

      核心壁垒:标准化模块组装 + 复杂 Agentic Workflow 编排 + 严谨的评测体系,这一层负责为 AI 赋予记忆、手脚和专业领域的知识,是连接“底层模型大脑”与“上层应用交互”的核心枢纽。

      如果说大模型是大脑,那么 Agent 工程师就是为这个大脑装上“四肢”、“记忆”和“专业工具”的人,这是一个正在爆发的新兴领域,也是实现 AI 业务落地的核心枢纽

      2.1 Agentic Workflow 设计

      能力维度具体要求
      任务拆解与路由基于 CoT(思维链)等技术工程的任务拆解与路由机制,针对不同复杂度的工作流设计稳健的多 Agent 协作与分发机制。
      设计模式与编排熟练应用 ReAct、Plan-and-Execute 等智能体设计模式,针对不同的业务场景(如信息爬取、长文总结过滤等自动化处理),设计稳健的多 Agent 协作与路由流。
      主流 Agent 框架的核心机制与实战落地熟悉并掌握如 Claude Agent SDK、LangChain、AutoGen 等主流 Agent 框架的核心机制,能够在实际项目中灵活应用,解决复杂的业务场景。

      2.2 记忆机制(Memory Management)

      要让 Agent 变得“好用”,必须解决上下文遗忘和知识幻觉的问题。这就要求工程师深谙长期记忆/短期记忆的协同管理,以及复杂文档的切块(Chunking)、向量化(Embedding)和混合检索(Hybrid Search)技术。

      • 短期记忆:精准控制 Context Window,进行 Prompt 截断与摘要,即上下文工程能力。
      • 长期记忆:基于图数据库或向量库,持久化存储用户画像与历史交互状态。

      2.3 技能的插件化(Agent Skill)

      Agent Skill 是由 Anthropic 提出并推动的一种开放式标准,旨在将特定领域的知识、工作流、指令和脚本打包封装成的标准化、模块化资源包,让 AI Agent 按需动态加载这些技能,实现从通用助手向特定任务专家(如代码审计、法律文件分析)的无缝转变。

      • 结构化封装:以目录形式组织(如含 SKILL.md 的文件夹),包含详细的执行规则。
      • 渐进披露 & 按需调用:Agent 仅在处理相关任务时动态激活这些能力,无需每次提示都包含所有技能。
      • 可重用与组合:技能可多次重复使用,或多个技能组合处理复杂流程。

      无论是长文抓取、摘要提取还是打标签,都可以被封装为独立的 Skill,在复杂的 Workflow 中被 Agent 动态挂载,即插即用,在构建特定场景的 Agent(例如专注于技术资讯处理的知识管理助手)时,能够像搭积木一样,根据当前任务的上下文动态加载所需的 Skills,从而大幅提升 Agent 的泛化能力和开发效率。

      2.4 从硬编码到标准协议与上下文连接

      随着 MCP(Model Context Protocol)等标准化协议的成熟,Agent 开发正在摆脱杂乱的胶水代码。我们可以利用熟悉的后端生态(如 Node.js)构建 MCP Server,让 AI 安全、统一地读取外部 API 或是企业内部知识库,打破信息孤岛。

      • 统一数据接入层:不再需要为每一个数据源(如 Notion、本地文件系统、特定的研发工具或外部 API)手写杂乱的胶水代码。通过实现和接入 MCP Server,为大模型提供一套标准化的双向通信协议。
      • 跨生态与端侧集成:能够利用 Node.js 等熟悉的后端生态快速构建 MCP 服务,让大模型统一、安全地读取多源上下文。这对于开发跨端的 AI 应用(如在浏览器插件中打破沙盒限制,直接与本地或云端知识库联动)至关重要。

      2.5 模型选型、路由与可观测性

      • 动态 API 路由:在成本与性能之间取舍,灵活调度国内外大模型(Claude、Gemini、GPT-4,以及国内的 DeepSeek、GLM、MiniMax、Qwen等)。
      • Agent 监控:构建测试集(Eval),监控链路执行过程(Tracing),分析 Token 消耗与步骤延迟。

      2.6 EDD(评估驱动开发)重塑工程质量

      在 Agent 开发中,大模型的输出具有非确定性,如果说开发 Agent 只是完成了从 0 到 1 的“能用”,那么构建完善的评测体系,就是解决从 1 到 100 的“好用”与“敢用”的核心壁垒。成熟的 Agent 工程师必须建立系统的评测与监控体系(Observability),通过构建黄金测试集(Golden Dataset)、引入 LLM-as-a-Judge,以及精确到 Token 级的链路追踪(Tracing),将“感觉不错”的玄学转化为可量化的工程指标。

      能力维度具体要求
      自动化评测驱动 (EDD)摒弃"肉眼看效果"的游击战,建立特定场景的 Golden Dataset(基准测试集),熟练引入 Promptfoo、Ragas 等评估框架,将评测无缝融入 CI/CD 流水线。
      多维指标体系设计针对具体任务(如长文总结、内容归类),设计并量化诸如事实一致性 (Faithfulness)、答案相关性 (Answer Relevance)、幻觉率 (Hallucination Rate) 等核心指标。
      LLM-as-a-Judge 与人工对齐使用强模型(如 Claude 4.6/GPT)来批量自动评测弱模型或 Agent 的输出质量,并在关键节点结合 HITL(Human-in-the-loop,人机协同)进行人工微调与对齐。
      链路追踪与归因 (Tracing)面对多 Agent 协作或复杂的 RAG 链路,熟练使用 LangSmith、Langfuse 等可观测性工具,记录每一次工具调用、Prompt 组装耗时和 Token 消耗,精准定位 Bad Case 的根因。

      3. AI 基础设施层:算力与模型的重工业底座

      核心壁垒:深厚的底层算法素养 + 极致的性能压榨 + 大规模分布式系统经验。这一层是 AI 时代的“重工业”底座,负责打造和打磨基础模型,并提供极致性价比的算力支撑。

      技术工程背景的工程师可暂时只关注于模型预备训练、后训练、推理等放面的原理与流程,以及如何在大规模分布式系统上高效部署和运行这些模型,而无需深入理解底层的分布式系统和计算架构。

      如果前两层是造车和开车的,这一层就是修路和提炼石油的。这属于 AI 的“重工业”,门槛极高,主要由具备深厚算法背景和底层工程能力的顶级大厂或 AI Native 独角兽主导。

      能力维度具体要求
      模型精炼与对齐随着开源基座模型的强大,预训练已不再是唯一解。后训练(Post-training)阶段的变得至关重要,通过 RL(强化学习)、SFT(监督微调)、RLHF/DPO(人类偏好对齐),将通用模型打磨成特定领域(如代码生成、逻辑推理)的专家。
      极致的推理优化随着模型越大,成本越高。熟练掌握 vLLM 等高性能推理框架,运用量化技术(如 FP8/INT4)、KV Cache 优化(如 PagedAttention),在不牺牲精度的前提下榨干每一滴 GPU 算力。
      LLMOps 与算力调度在万卡级别的 GPU 集群上,处理节点故障、实现资源负载均衡和容灾恢复,保障极其昂贵的算力资源不被浪费。

      4. 找准自己的生态位

      面对这股重塑整个行业的洪流,焦虑是本能,但进阶才是解药。

      对于绝大多数有着丰富 Web 开发经验(无论是精通前端交互,还是深谙 Node.js/Golang/Java 等后端架构)的工程师而言,“产品应用层”和“Agent 开发层”不仅是最具性价比的切入点,更是能够最大化杠杆原有技能的沃土

      我们不应该将自己局限在“写代码的机器”这一狭窄定义中。尝试用产品 Sense 发现问题,用 AI 编程工具快速实现 MVP,用标准的 Agent skills、MCP 协议和高阶 Agentic workflow 设计赋予应用专业深度。

      AI 不会淘汰开发者,只会淘汰那些拒绝使用 AI 来放大自身产品价值的开发者。在技术通缩的时代,唯有洞察力和对业务流的把控力,才能迎来真正的价值膨胀。

      + + + + \ No newline at end of file diff --git a/fullstack/ai-native.html b/fullstack/ai-native.html new file mode 100644 index 00000000..9e26ce35 --- /dev/null +++ b/fullstack/ai-native.html @@ -0,0 +1,178 @@ + + + + + + 不止于代码:构建 AI 时代全栈工程师的“认知三层塔” | Insight Stack + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      Skip to content
      2017
      + + + + 7.2m

      不止于代码:构建 AI 时代全栈工程师的“认知三层塔”

      摘要总结:在 AI 重塑软件工程的今天,全栈不再是技术的线性叠加,正在从“技术栈堆砌”转向“认知栈重构”。本文提出 “(工程 + 产品) × AI” 的新公式,助力开发者构建“洞察-架构-杠杆”认知三层塔,利用 AI 杠杆让自己进化为价值创造者。

      1. 引言

      在很长一段时间里,当我们谈论“全栈工程师”时,脑海中浮现的往往是一张冗长且令人疲惫的技术工序清单

      就像我曾经以为的那样,全栈就是线性的技能叠加与物理式的技术拼接,是一种依靠人力去填补技术鸿沟的“西西弗斯式”努力:

      • 线性的技能叠加:我们被迫成为“全能手”,左手用 React/Vue 构建精美的 UI,右手用 Node/Go 编写高并发 API,中间还要处理数据库的 ACID 事务(整个链路基本是这样的:构建前端 UI 交互 -> 编写后端业务API -> 维护底层数据存储与服务稳定)。
      • 物理式的拼接:我们试图用人力去掩盖技术栈之间的裂痕——用各种 Shell 脚本、Docker 配置、Nginx 转发规则,去粘合一个支离破碎的系统。

      那个时候,我认为全栈的护城河在于“掌握编程语言的数量”。只要我能写前端、能写后端、偶尔还能写点 Python 爬虫,我就是全栈。我们都在拼命地做加法,试图把自己打磨成一把无所不能的瑞士军刀。

      但在 AI 彻底重构代码生产方式的今天,这个定义显得过时且狭隘。当 GPT5/Claude Code/Cursor 等能够在一分钟内生成高质量的 CRUD 代码,甚至自动完成单元测试时,我们掌握语言、语法的价值又还剩多少?如果一个人就能通过 AI 完成一支团队的工作,那么“全栈”的边界到底在哪里?

      真正的全栈,已经从“技能的物理叠加” 进化到了 “价值的化学闭环”。如果一个人通过 AI 就能完成过去一支团队的交付量,那么“全栈”的边界就不再是技术栈(Tech Stack),而是认知栈(Insight Stack)。

      维度旧全栈 (Legacy Full Stack)新全栈 (AI-Native Full Stack)
      关注点语言、框架、语法 (Tools)问题、场景、价值 (Value)
      核心能力纯手工编码 (Coding)架构设计、Prompt 工程、代码审查 (Architecting)
      交付边界前端页面 + 后端接口需求洞察 \rightarrow 产品设计 \rightarrow 落地运营
      AI 的角色辅助工具 (Copilot)核心引擎与分身 (Co-founder)

      2. AI 时代的全栈新公式

      在重新思考技术演进的逻辑后,笔者思考出了一个更具现代感的全栈价值公式。这不仅仅是技能的组合,更是思维模型的重构:

      Full Stack=(Engineering+Product)×AI\mathbf{Full\ Stack} \; = \; (\mathbf{Engineering} \; + \; \mathbf{Product}) \; \times \; \mathbf{AI}

      这个公式告诉我们:不要再执着于手里有多少把锤子,而要关注你能构建出怎样的建筑,AI 是那个能够让工程能力和产品思维产生指数级爆炸的乘数。

      2.1. Engineering (工程力):从“困于实现”到“敢于设计”

      新旧模式对比:

      旧模式:熟练记忆 API,手写大量样板代码,关注具体的语言和语法细节。

      新模式具备系统级视野,关注架构的健壮性、可维护性以及自动化交付体系。

      在 AI 时代,工程力的内核发生了迁移,AI 在逐渐接管 How(怎么写代码),人类必须专注于 What(做什么系统)和 Why(为什么这样设计)。

      能力维度核心要点
      架构决策当代码生成变得廉价,架构决策变得昂贵。是选择单体还是微服务?是 SQL 还是 NoSQL?这些决定了系统的上限。
      代码审计与验收你从"写作者"变成了"编辑"和"审计员",当 AI 帮你写完 80% 的代码后,你是否有能力调试剩下那 20% 最隐蔽的逻辑漏洞?
      DevOps 与交付工程力不再止步于 localhost,它意味着你能利用 Docker、K8s、CI/CD 乃至 Serverless,将代码安全、稳定地送达线上,并将产品交付到用户手中。

      2.2. Product (产品力):从“需求翻译机”到“价值定义者”

      新旧模式对比:

      旧模式:被动接收需求文档,关注功能的按时上线。

      新模式理解商业模式与用户痛点,能判断“做什么”比“怎么做”更重要。

      产品力是技术人员最容易忽视,但在公式中权重极高的变量,它与工程力是相加关系——没有产品力的工程师,只是 AI 的操作员。

      维度核心要点
      同理心 (Empathy)脱离"技术自嗨",回归"用户感知"。工程师常沉迷于后端架构的完美重构(High Effort),却忽略前端模糊的报错提示(Low Effort)正让用户抓狂。
      具备同理心的全栈懂得计算体验 ROI:优先解决阻碍用户达成目标的"可见障碍",而非盲目追求技术实现的"隐性完美"。
      MVP 思维 (ROI 意识)精准识别"低成本高价值"的功能。在 AI 辅助下,快速构建最小可行性产品(MVP)验证假设,而非陷入过度设计的泥潭。
      业务闭环不仅把功能做出来,还要考虑数据如何回流、用户如何增长。

      2.3. AI (AI 杠杆):指数级倍增器

      NOTE

      旧模式:将 AI 视为搜索引擎的替代品或简单的代码补全工具。

      新模式:AI 是你的数字员工、技能分身,是让个人产出这种线性增长变成指数增长的关键变量。

      为什么 AI 处于乘数的位置?因为它是对上述两种能力的全方位放大

      能力维度核心要点
      技能树的补全利用 Cursor/Claude Code 等 AI 编程与 Agentic 工具,后端工程师可以写出像素级完美的前端 CSS,前端工程师可以编写复杂的 SQL 分析语句。AI 抹平了技术栈之间的专业门槛
      上下文工程学会如何向 AI 提供高质量的上下文(Context),让 AI 理解你的项目结构、业务逻辑和编码规范,从而生成生产级代码。
      时间压缩将从"Idea"到"Demo"的时间从数周压缩到数小时。这让"超级个体(Solo Maker)"成为可能——一个人就是一支队伍。

      3. 从 Tech Stack 到 Insight Stack:进阶之路

      全栈新时代架构图

      过去的“全栈”是指 Tech Stack(技术栈) —— 我们在简历上堆砌的 React、Vue、NestJS、Python、Rust 等名词。

      现在的“全栈”是指 Insight Stack(认知栈) —— 我们构建的是一套解决复杂问题的思维模型。

      在新的范式下,我们的核心竞争力不再是精通具体的语言特性或掌握庞杂的框架细节——因为 AI 已是最好的“百科全书”与“熟练工”——而是转变为构建以下三层认知模型:

      1. 洞察层:具备 Product Sense,能够发现真实世界中值得解决的问题,并定义清楚需求的边界。
      2. 架构层:具备 Engineering Logic,能够设计出高可用、可扩展的技术方案,并指挥 AI 完成具体的模块实现。
      3. 杠杆层:具备 AI Quotient (AI商),熟练运用 LLM、RAG、Agents 等工具,将上述两层能力指数级放大。

      AI 并没有以此消灭全栈工程师,它只是消灭了“平庸的搬运工”。它正在邀请我们,从“代码工人”进化为真正的“价值创造者”。

      + + + + \ No newline at end of file diff --git "a/01.\345\205\250\346\240\210/40.\345\211\215\347\253\257\345\267\245\347\250\213/02.CSS\345\267\245\347\250\213\345\214\226.html" b/fullstack/css-engineering.html similarity index 85% rename from "01.\345\205\250\346\240\210/40.\345\211\215\347\253\257\345\267\245\347\250\213/02.CSS\345\267\245\347\250\213\345\214\226.html" rename to fullstack/css-engineering.html index cf064d61..ac40ebaf 100644 --- "a/01.\345\205\250\346\240\210/40.\345\211\215\347\253\257\345\267\245\347\250\213/02.CSS\345\267\245\347\250\213\345\214\226.html" +++ b/fullstack/css-engineering.html @@ -6,12 +6,12 @@ 从原子化到变体驱动:现代 CSS 工程化的架构演进与混合实践指南 | Insight Stack - + - - - - + + + + @@ -30,7 +30,7 @@ - +
      Skip to content

      从原子化到变体驱动:现代 CSS 工程化的架构演进与混合实践指南

      摘要总结:在前端生态日新月异的今天,CSS 工程化早已超越了“如何写样式”的范畴,演变为一场关于开发效率(Velocity)与系统韧性(Resilience)的深度博弈。本文将系统梳理从预处理器、CSS-in-JS、Scoped CSS 到原子化 CSS 的演进脉络,并首次引入 “样式资产 ROI” 模型,深入剖析为何 Tailwind 已成为 AI 时代的基石架构。针对 Vue 与 React 的不同哲学,我们总结出了一套 “原子化为主,工程化局部兜底” 的企业级混合架构方案。无论你是深耕 React 生态、追求全链路类型安全的“变体驱动”先行者,还是在 Vue 生态中寻找极致心智负担平衡的实践者,本文都将为你提供一份清晰的架构决策树,助你规避工程红线,构建真正面向未来的样式资产。

      1. 引言:主流 CSS 工程化方案有哪些?

      在现代前端开发中,随着项目复杂度的急剧提升,原生 CSS 常常面临全局污染、复用困难、层级嵌套过深以及维护成本极高等问题。为了解决这些痛点,社区多年来不断探索,沉淀出了多种主流的 CSS 工程化方案。

      除原生 CSS 之外,主流方案还包括预处理器、CSS-in-JS、CSS Module、Scoped CSS、原子化 CSS 等。BEM 作为一种基于命名约定来规避命名冲突的早期方案,在现代前端工程中已基本不再使用,因此本文不再对其展开详细分析。

      CSS 命名规范(BEM):通过严格的命名约定(如 Block__Element--Modifier)来约束作用域,增强代码的可读性和可维护性。BEM 本身是一个优秀的规范,但它高度依赖开发者的自觉性,且会导致类名冗长,难以管理。

      2. CSS 预处理器

      CSS 预处理器是一种扩展了 CSS 功能的脚本语言,通过添加变量、嵌套、混入(Mixins)和函数等编程特性,让 CSS 更具结构化、可读性和可维护性。它允许开发者用特殊语法编写样式,然后编译成浏览器可读的普通 CSS 文件。 它也是最早也是最基础的工程化方案,核心思想是通过扩展原生 CSS 的语法,赋予其“编程”能力。

      维度说明
      核心思想增强版 CSS 使用变量统一管理设计令牌(Design Tokens),用嵌套减少重复选择器。
      代表技术Sass (SCSS), Less, Stylus
      核心特点提供了变量(Variables)、嵌套(Nesting)、混合(Mixins)、继承、函数等功能。
      适用场景几乎所有项目。现阶段它通常不作为独立的解决方案,而是与其他方案(如 CSS Modules)结合使用。
      局限性编译后的产物依然是普通 CSS,无法从根本上解决全局命名冲突的问题(通常需要配合 BEM 命名规范来缓解)

      以 SCSS 为例,示意如下:

      scss
      /* Button.scss */
      +  

      从原子化到变体驱动:现代 CSS 工程化的架构演进与混合实践指南

      摘要总结:在前端生态日新月异的今天,CSS 工程化早已超越了“如何写样式”的范畴,演变为一场关于开发效率(Velocity)与系统韧性(Resilience)的深度博弈。本文将系统梳理从预处理器、CSS-in-JS、Scoped CSS 到原子化 CSS 的演进脉络,并首次引入 “样式资产 ROI” 模型,深入剖析为何 Tailwind 已成为 AI 时代的基石架构。针对 Vue 与 React 的不同哲学,我们总结出了一套 “原子化为主,工程化局部兜底” 的企业级混合架构方案。无论你是深耕 React 生态、追求全链路类型安全的“变体驱动”先行者,还是在 Vue 生态中寻找极致心智负担平衡的实践者,本文都将为你提供一份清晰的架构决策树,助你规避工程红线,构建真正面向未来的样式资产。

      1. 引言:主流 CSS 工程化方案有哪些?

      在现代前端开发中,随着项目复杂度的急剧提升,原生 CSS 常常面临全局污染、复用困难、层级嵌套过深以及维护成本极高等问题。为了解决这些痛点,社区多年来不断探索,沉淀出了多种主流的 CSS 工程化方案。

      除原生 CSS 之外,主流方案还包括预处理器、CSS-in-JS、CSS Module、Scoped CSS、原子化 CSS 等。BEM 作为一种基于命名约定来规避命名冲突的早期方案,在现代前端工程中已基本不再使用,因此本文不再对其展开详细分析。

      CSS 命名规范(BEM):通过严格的命名约定(如 Block__Element--Modifier)来约束作用域,增强代码的可读性和可维护性。BEM 本身是一个优秀的规范,但它高度依赖开发者的自觉性,且会导致类名冗长,难以管理。

      2. CSS 预处理器

      CSS 预处理器是一种扩展了 CSS 功能的脚本语言,通过添加变量、嵌套、混入(Mixins)和函数等编程特性,让 CSS 更具结构化、可读性和可维护性。它允许开发者用特殊语法编写样式,然后编译成浏览器可读的普通 CSS 文件。 它也是最早也是最基础的工程化方案,核心思想是通过扩展原生 CSS 的语法,赋予其“编程”能力。

      维度说明
      核心思想增强版 CSS 使用变量统一管理设计令牌(Design Tokens),用嵌套减少重复选择器。
      代表技术Sass (SCSS), Less, Stylus
      核心特点提供了变量(Variables)、嵌套(Nesting)、混合(Mixins)、继承、函数等功能。
      适用场景几乎所有项目。现阶段它通常不作为独立的解决方案,而是与其他方案(如 CSS Modules)结合使用。
      局限性编译后的产物依然是普通 CSS,无法从根本上解决全局命名冲突的问题(通常需要配合 BEM 命名规范来缓解)

      以 SCSS 为例,示意如下:

      scss
      /* Button.scss */
       
       /* 1. 定义变量 */
       $primary-color: #3b82f6;
      @@ -506,7 +506,7 @@
          职责定位:
             - 整个架构的发动机。负责将非标准 CSS 转换为浏览器安全代码,并执行 Tailwind。
             - 将一切非标准语法转化为浏览器可识别的 CSS,是智能化 UI 生成与工程构建的底层基建。
      -===================================================================================

      8.1 第一层:架构的根基 —— CSS 变量、设计规范与 Design Token

      无论上层使用什么技术栈,坚决消灭硬编码(Hardcode)是现代前端架构的第一铁律:

      • 核心策略:将设计规范抽象为 CSS 变量(Custom Properties),以此作为全项目的 Design Token 唯一真理来源。这不仅能够确保设计的一致性,还能在代码中直接引用变量,避免在多个地方重复定义相同的颜色值。
      • 价值:它是实现暗黑模式、SaaS 多租户一键换肤的绝对基石,能完美兼容上层的所有开发模式,还能将研发团队与设计团队的协作效率提升到一个新的水平。
      • 最佳实践
        • 分层定义: 将变量分为“基础令牌 (Primitive)”(如 --blue-500: 221 83% 53%)和“语义令牌 (Semantic)”(如 --color-primary: var(--blue-500))。
        • 拥抱 HSL/RGB 通道: 变量只存数字通道,不存色值格式。
        • 桥接 Tailwind: 在 tailwind.config.js 中使用 <alpha-value> 将语义变量映射给 Tailwind,赋予其透明度计算能力。

      8.2 第二层:生产力基石与标准协议 —— 占比 90% 的主力构建层

      在日常业务开发中,我们必须将思维从“写自定义 CSS”转变为“用标准化工具类拼装 UI”。这一层是整个工程提效的核心发动机。

      • 核心策略:全面拥抱 Utility-first(实用优先)理念,将绝大部分(约 90%)的布局、间距、字体排版和基础色彩交给 Tailwind CSS 等原子化 CSS 引擎来处理。

      • 价值

        • 极速交付与零膨胀:免去了在 HTML 和 CSS 文件间反复横跳的低效,且得益于 JIT 引擎,无论项目多大,CSS 产物体积始终保持极小。
        • 强力约束与 AI 友好:通过类名强制约束团队遵循第一层定义的 Design Token,避免“自由发挥”导致的样式碎片化;同时,这种高度内聚在 HTML/JSX 中的范式,对 AI Coding Agent 等大模型辅助生成代码极度友好。
      • 最佳实践

        • 拥抱长类名,抽离组件而非样式:不要害怕 HTML 类名过长,坚决抵制为了“看起来干净”而滥用 @apply 重新创建 .card、.btn 的反模式。复用的单位应该是 Vue/React 组件。
        • 引入 CVA (变体驱动原子化):针对 React 团队或复杂自研 UI 组件库,彻底抛弃外部 CSS 文件,使用 cva 配合 TypeScript 构建强类型的枚举接口,将 UI 的不同状态完美映射为 Tailwind 类名组合。

      8.3 第三层:兜底封装与高级逻辑 —— 占比 10% 的边界“逃生舱”

      原子化并非万能,剩下的 10% 业务边界和极端场景,需要用更具工程表达能力的预处理器(如 SCSS 等)结合框架原生的隔离机制来解决。

      • 核心策略:将 CSS 预处理器从“全局样式管理器”降级为“局部增强利器”。针对原子类难以描述的复杂场景,在安全的局部作用域内进行逻辑封装与样式覆写。
      • 价值:弥补 Tailwind 在处理复杂 CSS 动效、伪元素组合以及第三方黑盒组件时的短板,为开发者提供一个安全、可控的“逃生舱”,且保证不污染全局环境。
      • 最佳实践
        • 因地制宜的隔离方案
          • Vue 生态:毫不犹豫地使用 <style scoped lang="scss"> 。这是心智负担最低的方案,坚决避开在 Vue 中使用 CSS Modules 带来的语法噪音。
          • React 生态:使用 CSS Modules (.module.scss),通过 clsx 工具库在 JSX 中将 Tailwind 基础类与 Module 兜底类优雅拼装。
        • 深度覆写第三方库:当需要修改 Element Plus 或 Ant Design 内部样式时,结合 SCSS 的嵌套语法(&),在 Vue 中使用 :deep(),在 React (Modules) 中使用 :global() 进行穿透定位。
        • 扁平化原则:即使在隔离环境中,SCSS 的嵌套也不应超过 3 层,避免选择器权重过高导致后期的维护灾难。

      8.4 底部构建环境:PostCSS 编译管道 (Pipeline)

      这是整个样式架构“看不见”但至关重要的基石。它将我们在上面三层编写的所有代码,统一转化为浏览器能够安全、高效运行的最终产物。

      • 核心策略:将 CSS 视为数据(抽象语法树 AST),通过标准化的插件流水线对其进行转化、加工和压缩。
      • 价值:它是实现 Tailwind 实时编译(JIT)、自动化处理浏览器兼容性、以及未来对接智能化 UI 代码生成(D2C)等高阶工程化链路的唯一底层载体。
      • 最佳实践
        • 严格的执行秩序:在 postcss.config.js 中,插件顺序决定了编译结果。必须确保工作流为:构建原子层 (tailwindcss) -> 处理兼容前缀 (autoprefixer) -> 极限压缩树结构 (cssnano)。
        • 区分预处理与后处理的边界:切忌混淆两者的定位。SCSS(预处理)只负责提供更爽的编写体验(如嵌套、混入);PostCSS(后处理)则全权负责产物加工与工程化转化。团队不应在构建管道中添加过多臃肿的自定义插件,保持流水线的纯粹与高效。

      8.5 架构红线 —— 一些必须规避的反模式

      CSS 工程化解决方案和工具繁多,在将这些工具组合时,稍有不慎就会导致项目变得比原来更难维护。以下是实战中必须拉响警报的红线:

      红线症状诊断
      红线一:在 Vue 中强行使用 CSS Modules + Tailwind模板中充斥着 :class="[$style.card, 'flex p-4 mt-2']" 这种视觉噪音极大的代码。框架自带的 Scoped 已经实现了优雅的隔离,引入 Modules 纯属“过度设计”,不仅剥夺了 Tailwind 的书写快感,还增加了运行时的解析成本。
      红线二:滥用 @apply 将 Tailwind 退化为预处理器.btn { @apply px-4 py-2 bg-blue-500 rounded; } 满天飞。这是新手转型 Tailwind 时最容易犯的错。它会导致 CSS 产物体积爆炸,失去了 Utility-First 的核心优势。正确做法是抽离 Framework 框架层面的组件 (如 React/Vue Component),而不是抽离 CSS 类。
      红线三:在 CSS 变量中硬编码 HEX/RGB 格式:root { --primary: #ff0000; }这会彻底干掉 Tailwind 非常实用的透明度修饰符(如 bg-primary/50)。必须严格遵循“只存通道值,配合 <alpha-value>”的规范。
      红线四:CSS Modules 中嵌套层级过深 (Nesting Hell)SCSS Module 中嵌套了 5 层以上的选择器。即使是 Modules,过深的嵌套也会导致 CSS 产物体积变大,且覆盖优先级极难控制。应保持扁平化,最多不超过 3 层。

      9. 结语:从手工精雕到 AI 增强的架构跃迁

      CSS 工程化早已超越了单纯的“页面美化”,它本质上是一场对抗系统熵增的架构实践。我们在评估各种眼花缭乱的方案时,其底层逻辑无非是在做一道关于产品感的算术题:用架构引入的合理复杂度,去换取前端资产的长期可维护性与业务交付的极速 ROI。

      纵观前文,在应对复杂业务的挑战时,单一方案往往独木难支。基于不同生态的特性,我们沉淀出了三种走向成熟的混合架构范式,前两种是 Vue 生态和 React 生态中常用且成熟的实践模式:

      模式架构分工AI 友好度
      Vue 生态:Scoped + SCSS + TailwindCSS90% (TailwindCSS): 负责页面布局、间距、字体、颜色排布。极大提升复用率和开发速度。
      10% (Scoped + SCSS): 作为“逃生舱”。负责覆写 Element/AntD 等第三方 UI 库(借助 :deep())、编写极其复杂的关键帧动画(@keyframes)、以及处理 Tailwind 难以描述的极端伪元素逻辑。
      极高,可以直接把大模型生成的 Tailwind HTML 片段丢进 Vue 的 <template> 中无缝运行,遇到复杂的业务定制样式,再让大模型输出一段 Scoped SCSS 补充在底部。
      React 生态:CSS Modules + SCSS + TailwindCSS90% (TailwindCSS): 同上,处理所有标准化 UI 搭建。
      10% (Modules + SCSS): 由于 React 没有 Scoped,通过引入 xxx.module.scss 配合 clsx 库来实现第三方样式覆盖和复杂逻辑的物理隔离。
      ,虽然 JSX 中混写 Module 变量(styles.wrapper)和 Tailwind 字符串需要用到 clsx 拼接,但目前的主流代码模型已经能非常熟练地处理这种拼接范式。

      第三种最佳实践模式是前沿的组件化范式 —— 变体驱动 (CVA + TailwindCSS)。它是 React 生态下更完美的实践模式,因为它将 CSS 视作组件的状态函数,通过 TypeScript 强类型定义 UI 的 Variants(变体),从而实现高度的可维护性和可扩展性。它不仅是值得探索的领域,还已经成为目前顶级 React 开发者(特别是 Next.js 生态)的事实标准:

      维度说明
      架构思想彻底干掉 CSS 文件,将 CSS 视作组件的 “状态函数”。通过 TypeScript 强类型定义 UI 的 Variants(变体)。
      对 AI 的友好度评估极其完美(史诗级增强),传统 CSS 对 AI 是一个“开放的无限空间”,容易出现幻觉。而 CVA 结合 TypeScript,给大模型提供了一个“封闭的枚举上下文”
      实战场景当 AI 生成 UI 组件时,它需要根据你的 CVA 接口定义,自动推导出必须输出的组件。
      例如,当你让 AI “生成一个警告按钮”时,AI 不需要去猜应该用什么 Tailwind 颜色,它只要看一眼你的 CVA 接口定义,就会自动推导出必须输出 <Button variant="destructive" />。诸如 v0.dev 这样的 AI 生成神器,其底层输出的完全就是这一套架构,它让 AI 产出的代码具备了企业级的稳定性。

      在这个从“纯手工编码”全面迈向“AI 增强构建”的转折点上,我们需要的不再是花哨的样式技巧,而是具备高度确定性的工程基建。希望这份 CSS 工程化指南,能成为你知识体系中一块有价值的拼图,在下一次重构或开启新项目时,帮你找到开发效率与架构韧性之间的最佳杠杆。

      +===================================================================================

      8.1 第一层:架构的根基 —— CSS 变量、设计规范与 Design Token

      无论上层使用什么技术栈,坚决消灭硬编码(Hardcode)是现代前端架构的第一铁律:

      • 核心策略:将设计规范抽象为 CSS 变量(Custom Properties),以此作为全项目的 Design Token 唯一真理来源。这不仅能够确保设计的一致性,还能在代码中直接引用变量,避免在多个地方重复定义相同的颜色值。
      • 价值:它是实现暗黑模式、SaaS 多租户一键换肤的绝对基石,能完美兼容上层的所有开发模式,还能将研发团队与设计团队的协作效率提升到一个新的水平。
      • 最佳实践
        • 分层定义: 将变量分为“基础令牌 (Primitive)”(如 --blue-500: 221 83% 53%)和“语义令牌 (Semantic)”(如 --color-primary: var(--blue-500))。
        • 拥抱 HSL/RGB 通道: 变量只存数字通道,不存色值格式。
        • 桥接 Tailwind: 在 tailwind.config.js 中使用 <alpha-value> 将语义变量映射给 Tailwind,赋予其透明度计算能力。

      8.2 第二层:生产力基石与标准协议 —— 占比 90% 的主力构建层

      在日常业务开发中,我们必须将思维从“写自定义 CSS”转变为“用标准化工具类拼装 UI”。这一层是整个工程提效的核心发动机。

      • 核心策略:全面拥抱 Utility-first(实用优先)理念,将绝大部分(约 90%)的布局、间距、字体排版和基础色彩交给 Tailwind CSS 等原子化 CSS 引擎来处理。

      • 价值

        • 极速交付与零膨胀:免去了在 HTML 和 CSS 文件间反复横跳的低效,且得益于 JIT 引擎,无论项目多大,CSS 产物体积始终保持极小。
        • 强力约束与 AI 友好:通过类名强制约束团队遵循第一层定义的 Design Token,避免“自由发挥”导致的样式碎片化;同时,这种高度内聚在 HTML/JSX 中的范式,对 AI Coding Agent 等大模型辅助生成代码极度友好。
      • 最佳实践

        • 拥抱长类名,抽离组件而非样式:不要害怕 HTML 类名过长,坚决抵制为了“看起来干净”而滥用 @apply 重新创建 .card、.btn 的反模式。复用的单位应该是 Vue/React 组件。
        • 引入 CVA (变体驱动原子化):针对 React 团队或复杂自研 UI 组件库,彻底抛弃外部 CSS 文件,使用 cva 配合 TypeScript 构建强类型的枚举接口,将 UI 的不同状态完美映射为 Tailwind 类名组合。

      8.3 第三层:兜底封装与高级逻辑 —— 占比 10% 的边界“逃生舱”

      原子化并非万能,剩下的 10% 业务边界和极端场景,需要用更具工程表达能力的预处理器(如 SCSS 等)结合框架原生的隔离机制来解决。

      • 核心策略:将 CSS 预处理器从“全局样式管理器”降级为“局部增强利器”。针对原子类难以描述的复杂场景,在安全的局部作用域内进行逻辑封装与样式覆写。
      • 价值:弥补 Tailwind 在处理复杂 CSS 动效、伪元素组合以及第三方黑盒组件时的短板,为开发者提供一个安全、可控的“逃生舱”,且保证不污染全局环境。
      • 最佳实践
        • 因地制宜的隔离方案
          • Vue 生态:毫不犹豫地使用 <style scoped lang="scss"> 。这是心智负担最低的方案,坚决避开在 Vue 中使用 CSS Modules 带来的语法噪音。
          • React 生态:使用 CSS Modules (.module.scss),通过 clsx 工具库在 JSX 中将 Tailwind 基础类与 Module 兜底类优雅拼装。
        • 深度覆写第三方库:当需要修改 Element Plus 或 Ant Design 内部样式时,结合 SCSS 的嵌套语法(&),在 Vue 中使用 :deep(),在 React (Modules) 中使用 :global() 进行穿透定位。
        • 扁平化原则:即使在隔离环境中,SCSS 的嵌套也不应超过 3 层,避免选择器权重过高导致后期的维护灾难。

      8.4 底部构建环境:PostCSS 编译管道 (Pipeline)

      这是整个样式架构“看不见”但至关重要的基石。它将我们在上面三层编写的所有代码,统一转化为浏览器能够安全、高效运行的最终产物。

      • 核心策略:将 CSS 视为数据(抽象语法树 AST),通过标准化的插件流水线对其进行转化、加工和压缩。
      • 价值:它是实现 Tailwind 实时编译(JIT)、自动化处理浏览器兼容性、以及未来对接智能化 UI 代码生成(D2C)等高阶工程化链路的唯一底层载体。
      • 最佳实践
        • 严格的执行秩序:在 postcss.config.js 中,插件顺序决定了编译结果。必须确保工作流为:构建原子层 (tailwindcss) -> 处理兼容前缀 (autoprefixer) -> 极限压缩树结构 (cssnano)。
        • 区分预处理与后处理的边界:切忌混淆两者的定位。SCSS(预处理)只负责提供更爽的编写体验(如嵌套、混入);PostCSS(后处理)则全权负责产物加工与工程化转化。团队不应在构建管道中添加过多臃肿的自定义插件,保持流水线的纯粹与高效。

      8.5 架构红线 —— 一些必须规避的反模式

      CSS 工程化解决方案和工具繁多,在将这些工具组合时,稍有不慎就会导致项目变得比原来更难维护。以下是实战中必须拉响警报的红线:

      红线症状诊断
      红线一:在 Vue 中强行使用 CSS Modules + Tailwind模板中充斥着 :class="[$style.card, 'flex p-4 mt-2']" 这种视觉噪音极大的代码。框架自带的 Scoped 已经实现了优雅的隔离,引入 Modules 纯属“过度设计”,不仅剥夺了 Tailwind 的书写快感,还增加了运行时的解析成本。
      红线二:滥用 @apply 将 Tailwind 退化为预处理器.btn { @apply px-4 py-2 bg-blue-500 rounded; } 满天飞。这是新手转型 Tailwind 时最容易犯的错。它会导致 CSS 产物体积爆炸,失去了 Utility-First 的核心优势。正确做法是抽离 Framework 框架层面的组件 (如 React/Vue Component),而不是抽离 CSS 类。
      红线三:在 CSS 变量中硬编码 HEX/RGB 格式:root { --primary: #ff0000; }这会彻底干掉 Tailwind 非常实用的透明度修饰符(如 bg-primary/50)。必须严格遵循“只存通道值,配合 <alpha-value>”的规范。
      红线四:CSS Modules 中嵌套层级过深 (Nesting Hell)SCSS Module 中嵌套了 5 层以上的选择器。即使是 Modules,过深的嵌套也会导致 CSS 产物体积变大,且覆盖优先级极难控制。应保持扁平化,最多不超过 3 层。

      9. 结语:从手工精雕到 AI 增强的架构跃迁

      CSS 工程化早已超越了单纯的“页面美化”,它本质上是一场对抗系统熵增的架构实践。我们在评估各种眼花缭乱的方案时,其底层逻辑无非是在做一道关于产品感的算术题:用架构引入的合理复杂度,去换取前端资产的长期可维护性与业务交付的极速 ROI。

      纵观前文,在应对复杂业务的挑战时,单一方案往往独木难支。基于不同生态的特性,我们沉淀出了三种走向成熟的混合架构范式,前两种是 Vue 生态和 React 生态中常用且成熟的实践模式:

      模式架构分工AI 友好度
      Vue 生态:Scoped + SCSS + TailwindCSS90% (TailwindCSS): 负责页面布局、间距、字体、颜色排布。极大提升复用率和开发速度。
      10% (Scoped + SCSS): 作为“逃生舱”。负责覆写 Element/AntD 等第三方 UI 库(借助 :deep())、编写极其复杂的关键帧动画(@keyframes)、以及处理 Tailwind 难以描述的极端伪元素逻辑。
      极高,可以直接把大模型生成的 Tailwind HTML 片段丢进 Vue 的 <template> 中无缝运行,遇到复杂的业务定制样式,再让大模型输出一段 Scoped SCSS 补充在底部。
      React 生态:CSS Modules + SCSS + TailwindCSS90% (TailwindCSS): 同上,处理所有标准化 UI 搭建。
      10% (Modules + SCSS): 由于 React 没有 Scoped,通过引入 xxx.module.scss 配合 clsx 库来实现第三方样式覆盖和复杂逻辑的物理隔离。
      ,虽然 JSX 中混写 Module 变量(styles.wrapper)和 Tailwind 字符串需要用到 clsx 拼接,但目前的主流代码模型已经能非常熟练地处理这种拼接范式。

      第三种最佳实践模式是前沿的组件化范式 —— 变体驱动 (CVA + TailwindCSS)。它是 React 生态下更完美的实践模式,因为它将 CSS 视作组件的状态函数,通过 TypeScript 强类型定义 UI 的 Variants(变体),从而实现高度的可维护性和可扩展性。它不仅是值得探索的领域,还已经成为目前顶级 React 开发者(特别是 Next.js 生态)的事实标准:

      维度说明
      架构思想彻底干掉 CSS 文件,将 CSS 视作组件的 “状态函数”。通过 TypeScript 强类型定义 UI 的 Variants(变体)。
      对 AI 的友好度评估极其完美(史诗级增强),传统 CSS 对 AI 是一个“开放的无限空间”,容易出现幻觉。而 CVA 结合 TypeScript,给大模型提供了一个“封闭的枚举上下文”
      实战场景当 AI 生成 UI 组件时,它需要根据你的 CVA 接口定义,自动推导出必须输出的组件。
      例如,当你让 AI “生成一个警告按钮”时,AI 不需要去猜应该用什么 Tailwind 颜色,它只要看一眼你的 CVA 接口定义,就会自动推导出必须输出 <Button variant="destructive" />。诸如 v0.dev 这样的 AI 生成神器,其底层输出的完全就是这一套架构,它让 AI 产出的代码具备了企业级的稳定性。

      在这个从“纯手工编码”全面迈向“AI 增强构建”的转折点上,我们需要的不再是花哨的样式技巧,而是具备高度确定性的工程基建。希望这份 CSS 工程化指南,能成为你知识体系中一块有价值的拼图,在下一次重构或开启新项目时,帮你找到开发效率与架构韧性之间的最佳杠杆。

      diff --git "a/01.\345\205\250\346\240\210/80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273/20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227/3.ES Modules \346\240\270\345\277\203\350\247\204\350\214\203\344\270\216\345\256\236\350\267\265\350\247\243\346\236\220.html" b/fullstack/decode-es-modules.html similarity index 80% rename from "01.\345\205\250\346\240\210/80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273/20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227/3.ES Modules \346\240\270\345\277\203\350\247\204\350\214\203\344\270\216\345\256\236\350\267\265\350\247\243\346\236\220.html" rename to fullstack/decode-es-modules.html index df561694..e96c2b66 100644 --- "a/01.\345\205\250\346\240\210/80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273/20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227/3.ES Modules \346\240\270\345\277\203\350\247\204\350\214\203\344\270\216\345\256\236\350\267\265\350\247\243\346\236\220.html" +++ b/fullstack/decode-es-modules.html @@ -6,12 +6,12 @@ 回归标准,拥抱原生:ES Modules 核心规范与实践解析 | Insight Stack - + - - - - + + + + @@ -30,7 +30,7 @@ - +
      Skip to content

      回归标准,拥抱原生:ES Modules 核心规范与实践解析

      如果说 CommonJS 是“草根英雄”,那么 ES Modules 就是“名门正派”。它是 ECMAScript 官方定义的模块系统,旨在为所有 JavaScript 环境提供统一、高效、且可静态分析的模块化方案。

      理解 ESM,不仅仅是学会 import 和 export,更重要的是理解它如何通过编译时优化彻底改变了前端构建的效率。

      1. 命名导出与导入:精准的代码引用

      命名导出(Named Exports)是 ESM 最常用的形式,它允许一个模块暴露多个成员。其核心优势在于:导入方可以按需引入,且 IDE 能提供精准的补全。

      语法实践:

      javascript
      // math.js - 命名导出
      +  

      回归标准,拥抱原生:ES Modules 核心规范与实践解析

      如果说 CommonJS 是“草根英雄”,那么 ES Modules 就是“名门正派”。它是 ECMAScript 官方定义的模块系统,旨在为所有 JavaScript 环境提供统一、高效、且可静态分析的模块化方案。

      理解 ESM,不仅仅是学会 import 和 export,更重要的是理解它如何通过编译时优化彻底改变了前端构建的效率。

      1. 命名导出与导入:精准的代码引用

      命名导出(Named Exports)是 ESM 最常用的形式,它允许一个模块暴露多个成员。其核心优势在于:导入方可以按需引入,且 IDE 能提供精准的补全。

      语法实践:

      javascript
      // math.js - 命名导出
       // 行内导出
       export const PI = 3.14159;
       
      @@ -347,7 +347,7 @@
         console.log('b.js received a:', a);
       });
       
      -eventBus.emit('b-ready', 'b');

      7. 结语:在标准规范中寻求最优解

      从 ESM 的核心语法我们可以看到,它不仅解决了“代码怎么写”的问题,更通过静态性为现代前端工程化铺平了道路。没有 ESM,就没有如此高效的 HMR(热更新),也没有精准的 Tree Shaking。

      ESM 不再仅仅是一个模块协议,它已成为 JavaScript 生态的通用标准,让全栈代码同构变得轻而易举,也让复杂的依赖治理变得有迹可循。

      掌握 ESM,本质上是在掌握一种确定性**——无论是在浏览器端、服务端,还是日益兴起的 AI-native 场景中,这种标准化都是构建大规模复杂系统应用的基础。

      +eventBus.emit('b-ready', 'b');

      7. 结语:在标准规范中寻求最优解

      从 ESM 的核心语法我们可以看到,它不仅解决了“代码怎么写”的问题,更通过静态性为现代前端工程化铺平了道路。没有 ESM,就没有如此高效的 HMR(热更新),也没有精准的 Tree Shaking。

      ESM 不再仅仅是一个模块协议,它已成为 JavaScript 生态的通用标准,让全栈代码同构变得轻而易举,也让复杂的依赖治理变得有迹可循。

      掌握 ESM,本质上是在掌握一种确定性**——无论是在浏览器端、服务端,还是日益兴起的 AI-native 场景中,这种标准化都是构建大规模复杂系统应用的基础。

      diff --git "a/01.\345\205\250\346\240\210/80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273/20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227/2.\344\270\215\345\220\214\346\250\241\345\235\227\345\214\226\350\247\204\350\214\203\346\242\263\347\220\206.html" b/fullstack/different-module-programming-specifications.html similarity index 72% rename from "01.\345\205\250\346\240\210/80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273/20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227/2.\344\270\215\345\220\214\346\250\241\345\235\227\345\214\226\350\247\204\350\214\203\346\242\263\347\220\206.html" rename to fullstack/different-module-programming-specifications.html index e729d907..d7704787 100644 --- "a/01.\345\205\250\346\240\210/80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273/20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227/2.\344\270\215\345\220\214\346\250\241\345\235\227\345\214\226\350\247\204\350\214\203\346\242\263\347\220\206.html" +++ b/fullstack/different-module-programming-specifications.html @@ -6,12 +6,12 @@ JavaScript 模块化规范全景图:从 CJS 到 ESM | Insight Stack - + - - - - + + + + @@ -30,7 +30,7 @@ - +
      Skip to content

      JavaScript 模块化规范全景图:从 CJS 到 ESM

      摘要总结: 本文横向对比 JavaScript 四大模块化规范:CommonJS、AMD、UMD、ES Modules。通过代码示例展示各规范的核心语法,并提供从 CommonJS 迁移到 ESM 的具体步骤,以及从 AMD 向 ESM 迁移的构建工具策略。最后以对比表格收尾,阐明 ESM 作为现代开发唯一推荐标准的地位。

      在 JavaScript 进化史上,“模块化”始终是一个核心命题。从早期 script 标签满天飞的“混沌时代”,到各路规范群雄逐鹿的“战国时代”,再到如今 ES Modules 定于一尊,开发者们在解决依赖管理、作用域污染和异步加载等问题上付出了巨大的努力。

      本文将带你梳理 JavaScript 历史上最重要的几种模块化规范,便于构建起全栈开发的底层知识图谱。

      1. CommonJS 规范:Node.js 生态的基石

      CommonJS 是伴随 Node.js 诞生的规范,由 Kevin Dangoor 提出,初衷是让 JavaScript 脱离浏览器也能构建复杂的系统应用。它是 Node.js 成功的关键因素之一,在它出现之前,JavaScript 缺乏在服务器端运行所需的组织结构。它规定每个文件都是一个独立的模块,拥有私有的作用域,不会污染全局空间。

      核心逻辑:

      • 导出:通过 module.exportsexports 对象暴露成员。
      • 导入:使用同步的 require() 函数加载模块。

      示例代码:

      javascript
      // 导出模块(module.exports)
      +  

      JavaScript 模块化规范全景图:从 CJS 到 ESM

      摘要总结: 本文横向对比 JavaScript 四大模块化规范:CommonJS、AMD、UMD、ES Modules。通过代码示例展示各规范的核心语法,并提供从 CommonJS 迁移到 ESM 的具体步骤,以及从 AMD 向 ESM 迁移的构建工具策略。最后以对比表格收尾,阐明 ESM 作为现代开发唯一推荐标准的地位。

      在 JavaScript 进化史上,“模块化”始终是一个核心命题。从早期 script 标签满天飞的“混沌时代”,到各路规范群雄逐鹿的“战国时代”,再到如今 ES Modules 定于一尊,开发者们在解决依赖管理、作用域污染和异步加载等问题上付出了巨大的努力。

      本文将带你梳理 JavaScript 历史上最重要的几种模块化规范,便于构建起全栈开发的底层知识图谱。

      1. CommonJS 规范:Node.js 生态的基石

      CommonJS 是伴随 Node.js 诞生的规范,由 Kevin Dangoor 提出,初衷是让 JavaScript 脱离浏览器也能构建复杂的系统应用。它是 Node.js 成功的关键因素之一,在它出现之前,JavaScript 缺乏在服务器端运行所需的组织结构。它规定每个文件都是一个独立的模块,拥有私有的作用域,不会污染全局空间。

      核心逻辑:

      • 导出:通过 module.exportsexports 对象暴露成员。
      • 导入:使用同步的 require() 函数加载模块。

      示例代码:

      javascript
      // 导出模块(module.exports)
       const add = (a, b) => a + b;
       const subtract = (a, b) => a - b;
       
      @@ -221,7 +221,7 @@
       // 导入模块
       import mathDefault, { add, subtract } from './math.js';
       console.log(add(1, 2)); // 输出:3
      -console.log(mathDefault.multiply(2, 3)); // 输出:6
      关键特性说明
      静态分析与 CommonJS 的运行时加载不同,ESM 在代码编译阶段就能确定依赖关系。这使得 Tree Shaking(剔除未使用的代码)成为可能。
      异步加载支持天然适配浏览器。
      官方标准现代浏览器及 Node.js(v12+)均已原生支持。

      5. 规范对比与现代迁移指南

      为了更直观地理解,我们将四种规范进行横向对比:

      规范主要环境加载方式核心优势现状
      CommonJSNode.js同步简单高效,生态极其丰富存量项目主流,正向 ESM 转型
      AMD浏览器异步解决浏览器阻塞问题已淡出历史舞台
      UMD跨平台兼容一份代码,到处运行仅在需要兼容老旧环境时使用
      ES Modules全栈静态语言标准,支持 Tree Shaking现代开发的唯一推荐标准

      迁移策略建议

      1. 全面拥抱 ESM:新项目应直接在 package.json 中设置 "type": "module"。
      2. 从 CommonJS 迁移到 ES Modules:可以将 .js 逐步重命名为 .mjs,或利用 esbuild 等工具进行平滑转译。
        • 使用 .mjs 扩展名或在 package.json 中设置 "type": "module"
        • require() 替换为 import
        • module.exports 替换为 exportexport default
      3. 从 AMD 迁移到 ES Modules
        • 使用现代构建工具(如 Webpack、Vite)处理模块加载
        • define() 替换为 ES Modules 语法
        • 利用构建工具的代码分割功能实现按需加载
        • 移除对 RequireJS 的依赖
      4. 构建工具的妙用:利用 ViteTurbopack,我们完全可以用 ESM 编写代码,由工具链自动处理老旧环境的兼容。

      6. 结语:在标准之上构建未来

      从 CommonJS 的探索到 ESM 的大一统,模块化规范的演进本质上是 JavaScript 从一种“脚本语言”向“工业级编程语言”蜕变的过程

      理解这些规范不仅是为了应付面试或处理老旧代码,更是为了让我们在面对复杂的全栈架构时,能对代码的加载、执行和构建有更深层的掌控力。在 AI 辅助编程普及的今天,清晰的模块化思维更是构建可靠 Prompt 和 Agentic 流程的基石,希望这篇梳理能为你夯实全栈基础。

      +console.log(mathDefault.multiply(2, 3)); // 输出:6
      关键特性说明
      静态分析与 CommonJS 的运行时加载不同,ESM 在代码编译阶段就能确定依赖关系。这使得 Tree Shaking(剔除未使用的代码)成为可能。
      异步加载支持天然适配浏览器。
      官方标准现代浏览器及 Node.js(v12+)均已原生支持。

      5. 规范对比与现代迁移指南

      为了更直观地理解,我们将四种规范进行横向对比:

      规范主要环境加载方式核心优势现状
      CommonJSNode.js同步简单高效,生态极其丰富存量项目主流,正向 ESM 转型
      AMD浏览器异步解决浏览器阻塞问题已淡出历史舞台
      UMD跨平台兼容一份代码,到处运行仅在需要兼容老旧环境时使用
      ES Modules全栈静态语言标准,支持 Tree Shaking现代开发的唯一推荐标准

      迁移策略建议

      1. 全面拥抱 ESM:新项目应直接在 package.json 中设置 "type": "module"。
      2. 从 CommonJS 迁移到 ES Modules:可以将 .js 逐步重命名为 .mjs,或利用 esbuild 等工具进行平滑转译。
        • 使用 .mjs 扩展名或在 package.json 中设置 "type": "module"
        • require() 替换为 import
        • module.exports 替换为 exportexport default
      3. 从 AMD 迁移到 ES Modules
        • 使用现代构建工具(如 Webpack、Vite)处理模块加载
        • define() 替换为 ES Modules 语法
        • 利用构建工具的代码分割功能实现按需加载
        • 移除对 RequireJS 的依赖
      4. 构建工具的妙用:利用 ViteTurbopack,我们完全可以用 ESM 编写代码,由工具链自动处理老旧环境的兼容。

      6. 结语:在标准之上构建未来

      从 CommonJS 的探索到 ESM 的大一统,模块化规范的演进本质上是 JavaScript 从一种“脚本语言”向“工业级编程语言”蜕变的过程

      理解这些规范不仅是为了应付面试或处理老旧代码,更是为了让我们在面对复杂的全栈架构时,能对代码的加载、执行和构建有更深层的掌控力。在 AI 辅助编程普及的今天,清晰的模块化思维更是构建可靠 Prompt 和 Agentic 流程的基石,希望这篇梳理能为你夯实全栈基础。

      diff --git "a/01.\345\205\250\346\240\210/80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273/20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227/1.\345\211\215\347\253\257\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\237\272\347\241\200.html" b/fullstack/frontend-module-programming-basic.html similarity index 74% rename from "01.\345\205\250\346\240\210/80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273/20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227/1.\345\211\215\347\253\257\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\237\272\347\241\200.html" rename to fullstack/frontend-module-programming-basic.html index a2a95802..9b843530 100644 --- "a/01.\345\205\250\346\240\210/80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273/20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227/1.\345\211\215\347\253\257\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\237\272\347\241\200.html" +++ b/fullstack/frontend-module-programming-basic.html @@ -6,12 +6,12 @@ 模块化编程初体验:概念、演进与设计模式 | Insight Stack - + - - - - + + + + @@ -30,7 +30,7 @@ - +
      Skip to content

      模块化编程初体验:概念、演进与设计模式

      摘要总结: 本文系统讲解 JavaScript 模块化编程基础,涵盖 IIFE、CommonJS、ES Modules 规范演进,以及工厂、单例、观察者等设计模式与模块化的结合。从模块化的核心痛点出发——全局变量污染、依赖关系混乱、加载性能瓶颈——逐步展开模块化编程的知识图谱。实践层面结合工厂模式(批量创建相似对象)、单例模式(全局唯一实例,如数据库连接)、观察者/发布订阅模式(模块间松耦合通信)三种经典设计模式,展示模块化与设计模式的有机结合。

      1. 引言

      随着项目规模日益膨胀,代码量从几千行迅速增长到数万甚至数十万行,将所有逻辑塞进少数几个文件的做法早已难以为继。在这样的背景下,模块化编程应运而生,成为现代前端开发的标配。

      它的核心理念简洁而优雅:像搭积木一样,将庞大复杂的系统拆解为一个个独立、功能单一且可复用的模块,让每个模块各司其职,再通过标准接口灵活组合。

      2. 模块化编程初体验

      在深入理论之前,让我们先通过一个简单的 JavaScript 示例,直观地感受一下什么是模块化。假设我们需要处理一些数学运算,我们可以将其封装成一个独立的工具模块:

      javascript
      // math.js - 定义一个数学工具模块
      +  

      模块化编程初体验:概念、演进与设计模式

      摘要总结: 本文系统讲解 JavaScript 模块化编程基础,涵盖 IIFE、CommonJS、ES Modules 规范演进,以及工厂、单例、观察者等设计模式与模块化的结合。从模块化的核心痛点出发——全局变量污染、依赖关系混乱、加载性能瓶颈——逐步展开模块化编程的知识图谱。实践层面结合工厂模式(批量创建相似对象)、单例模式(全局唯一实例,如数据库连接)、观察者/发布订阅模式(模块间松耦合通信)三种经典设计模式,展示模块化与设计模式的有机结合。

      1. 引言

      随着项目规模日益膨胀,代码量从几千行迅速增长到数万甚至数十万行,将所有逻辑塞进少数几个文件的做法早已难以为继。在这样的背景下,模块化编程应运而生,成为现代前端开发的标配。

      它的核心理念简洁而优雅:像搭积木一样,将庞大复杂的系统拆解为一个个独立、功能单一且可复用的模块,让每个模块各司其职,再通过标准接口灵活组合。

      2. 模块化编程初体验

      在深入理论之前,让我们先通过一个简单的 JavaScript 示例,直观地感受一下什么是模块化。假设我们需要处理一些数学运算,我们可以将其封装成一个独立的工具模块:

      javascript
      // math.js - 定义一个数学工具模块
       export const PI = 3.14159;
       
       export function add(a, b) {
      @@ -243,7 +243,7 @@
       import { EventEmitter } from './observer.js';
       const emitter = new EventEmitter();
       emitter.on('message', (data) => console.log('Received:', data));
      -emitter.emit('message', 'Hello Observer!');

      4. 结语:在秩序与复杂中寻找平衡

      至此,我们已经推开了模块化编程的大门。从最直观的代码抽离切入,你会发现,模块化从来不仅仅是 import 和 export 的语法糖,它更像是一种对抗软件生命周期中“熵增”的工程哲学。

      前端生态历经十余年,从早期 IIFE 的暗夜摸索,到 CommonJS 与 AMD 的百家争鸣,再到如今 ES Modules 的一统江湖,这条演进之路的背后,本质上是整个工程界对于“如何驾驭日益庞大的系统复杂度”这一命题的持续作答。它不仅抹平了命名冲突、依赖混乱的深坑,更为现代团队的高效协作铺设了最底层的基建。

      当你开始熟练地运用“高内聚、低耦合”的思维边界,并将工厂、单例、观察者等经典设计模式自然地融入日常开发时,你就不再只是一个单纯的“代码编写者”,而是进阶为了一名掌控全局的“系统构建者”。

      代码的物理边界终会在打包工具的运转下被抹平或重组,但留在你脑海中那道划分模块职责的逻辑边界,才是决定一个项目能走多远、多稳的真正基石。希望这次的模块化初体验,能为你未来的工程实践铺垫好最坚实的底色。

      +emitter.emit('message', 'Hello Observer!');

      4. 结语:在秩序与复杂中寻找平衡

      至此,我们已经推开了模块化编程的大门。从最直观的代码抽离切入,你会发现,模块化从来不仅仅是 import 和 export 的语法糖,它更像是一种对抗软件生命周期中“熵增”的工程哲学。

      前端生态历经十余年,从早期 IIFE 的暗夜摸索,到 CommonJS 与 AMD 的百家争鸣,再到如今 ES Modules 的一统江湖,这条演进之路的背后,本质上是整个工程界对于“如何驾驭日益庞大的系统复杂度”这一命题的持续作答。它不仅抹平了命名冲突、依赖混乱的深坑,更为现代团队的高效协作铺设了最底层的基建。

      当你开始熟练地运用“高内聚、低耦合”的思维边界,并将工厂、单例、观察者等经典设计模式自然地融入日常开发时,你就不再只是一个单纯的“代码编写者”,而是进阶为了一名掌控全局的“系统构建者”。

      代码的物理边界终会在打包工具的运转下被抹平或重组,但留在你脑海中那道划分模块职责的逻辑边界,才是决定一个项目能走多远、多稳的真正基石。希望这次的模块化初体验,能为你未来的工程实践铺垫好最坚实的底色。

      diff --git a/fullstack/full-stack-resources.html b/fullstack/full-stack-resources.html new file mode 100644 index 00000000..648cfa81 --- /dev/null +++ b/fullstack/full-stack-resources.html @@ -0,0 +1,177 @@ + + + + + + 全栈技术资源推荐 | Insight Stack + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      Skip to content
      7425
      + + + + 30.1m

      全栈技术资源推荐

      摘要总结:本文系统梳理了现代全栈开发的完整技术图谱与演进范式,不仅是一份全栈工具检索目录,更是一份指导开发者从全局视角构建高性能、类型安全、且极具工程化思维的现代 Web 应用的最佳实践指南。

      • 文章从基石出发,覆盖 Web 核心语言(JS/TS) 与 主流 UI 框架(React/Vue/Svelte),并推荐以 Tailwind CSS 和 shadcn/ui 为代表的现代样式与组件原语。
      • 在核心业务逻辑层,深度对比了轻量化状态管理方案(首推 Zustand/Jotai),并重点解析了数据交互的三大现代架构范式:从基础 Axios 到 React Query 状态调度,再到 tRPC 和 GraphQL 带来的全栈类型安全与多端聚合。
      • 在工程化与服务端模块,文章全面拥抱 Vite、Rsbuild 等极速构建工具,并剖析了 Next.js/Nuxt 同构元框架与 NestJS 企业级 Node 服务的最佳适用场景。最后,辅以 Vercel 等现代边缘部署平台及丰富的开源社区学习资源。

      1. 基本语言与环境

      2. 核心 UI 框架

      3. 样式与 UI 组件库 (Styling & Component Libraries)

      4. 路由与状态管理

      React 状态管理库横向对比分析:

      特性/库Zustand 大部分项目的首选Jotai 编辑比较频繁的建议使用Redux 不再推荐
      核心思想自上而下的全局状态管理自下而上的原子化状态管理单向数据流、集中式全局状态
      适用场景中大型应用全局状态、偏好轻量方案组件间状态共享、细粒度更新、贴近React思维超大型复杂应用、强可预测性需求
      学习曲线平缓,API 简洁平缓,原子概念容易理解陡峭,需理解中间件、Redux Toolkit 等
      代码风格简洁,类似轻量版 Redux原子化,分散定义状态相对冗长,需定义 Action、Reducer
      性能优化支持组件精准订阅状态天然细粒度更新,避免不必要重渲染需配合 Reselect 等工具优化
      社区生态生态稳定,常用插件完善生态活跃,适合实验性场景生态庞大,工具链成熟

      5. 数据获取与 API 集成 (Data Fetching & API)

      技术/工具核心定位与特征核心优势 (能解决什么痛点)局限性与妥协最佳实践与适用场景
      Fetch API 通信基建浏览器原生标准协议无需安装第三方包、天然融入现代 Web 标准。在 Edge Runtime 环境下表现最佳。默认不抛出 HTTP 错误状态码(需手动拦截);处理 JSON 和参数拼接繁琐、缺少请求取消机制。极简场景/底层封装:不需要复杂拦截器的轻量级页面;作为更高级架构的底层引擎,如 Next.js 内部的 fetch 扩展。
      Axios
      通信基建
      全能型同构请求体API 极其友好、请求/响应拦截器(处理全局 Token、统一错误提示的利器)、自动转换 JSON 数据。增加了一定的打包体积;基于 XHR(尽管现代版本已支持 fetch 底层),在某些最新的服务端边缘计算环境中可能受限。重度依赖 RESTful 的项目:需要精细化控制请求头、进行全局鉴权拦截、处理复杂文件上传的传统全栈或中后台系统。
      SWR
      状态调度
      按需验证的轻量级缓存极致的轻量与简单;焦点聚焦时自动刷新、网络恢复时重试;带来极佳的“UI 瞬间响应”体验。面对极其复杂的异步状态流转(如互相依赖的串行请求、精细的离线修改回滚)时,显得心有余而力不足。内容驱动型应用:注重阅读体验的博客站点、数据实时性要求中等的数据看板。配置极简,非常适合快速迭代的产品。
      React Query
      状态调度
      大而全的异步状态接管强大的缓存生命周期管理;优雅的 Mutations(数据变更)处理与乐观更新;极好的开发调试工具。学习曲线较陡峭;默认配置下有时会导致意料之外的组件重渲染;体积相对较大。复杂交互型 SaaS / 强业务逻辑系统:需要处理大量表单提交、列表无限滚动、精细化缓存控制的重型单页应用(SPA)。
      GraphQL 协议契约声明式的图谱查询彻底解决 Over-fetching;前端拥有极高的数据按需组合自由度;自带强类型的 Schema 文档。后端开发成本极高(需编写大量 Resolver 函数);容易产生 N+1 查询性能问题;HTTP 缓存机制难以直接利用。多端复用型大中型产品:后端需要同时服务于 Web、iOS、Android 甚至第三方开发者;业务实体关系高度复杂的系统。
      tRPC
      协议契约
      端到端的全栈类型推导前后端类型零成本共享;重构时的代码安全性极高;完全不需要手写接口文档或 Schema。强绑定 Node.js/TypeScript 技术栈;如果前端项目和后端代码没有在一个 Monorepo 中,威力大打折扣。敏捷全栈/单人作战团队:采用 Node.js + 前端框架(React/Vue)构建的全栈项目。极度追求开发效率和产品迭代速度的团队。

      现代 Web 数据流架构范式:

      1、标准前后端分离架构:Axios + React Query(或 SWR)

      • 适用场景: 异构系统(如前端使用 React/Vue,后端使用 Java/Go/Python 等非 JS 语言);高度依赖传统 RESTful API 规范、需要精细化控制网络请求拦截器的中大型企业级项目。
      • 架构机制:将网络请求的“底层通道”与“上层状态”严格解耦。Axios 专注于基础通信层的治理,负责全局请求头注入(如 Bearer Token)、统一的 HTTP 状态码拦截与静默错误上报;React Query / SWR 则专注于表现层的状态调度,接管数据的缓存生命周期、请求去重(Deduplication)以及乐观更新(Optimistic UI)。
      • 工程价值:具备极高的稳健性与技术栈包容性。前后端边界清晰,互不干扰。

      2、全栈类型安全架构:tRPC + React Query

      • 适用场景: 采用 Monorepo 架构管理的纯 TypeScript/Node.js 全栈项目;追求敏捷开发、极速交付以及需要频繁进行业务重构的 SaaS 产品或内部系统。
      • 架构机制:基于 TypeScript 的强类型推导系统,打通前后端数据流。tRPC 官方深度集成了 React Query(@trpc/react-query),在保留了完整的现代前端缓存调度能力的同时,彻底免去了手动维护 API 接口文档和 Schema 编译生成的中间环节。后端的类型变更会即刻反映为前端编译期的静态类型检查报错。
      • 工程价值:极致的研发效能与结构安全性。对于专注于产品迭代与业务增长的 Node.js 全栈开发者而言,这种组合完美契合了“以更少投入获得更大收益”的工程哲学。它直接消灭了“接口联调”这一无效耗时环节,让开发者能将核心精力聚焦于产品逻辑本身。

      3、多端数据聚合 BFF 架构:GraphQL + Apollo Client

      • 适用场景: 数据来源庞杂且分散的大型业务系统;需要同时为多种不同客户端提供高灵活性 API,且前后端团队规模较大、需要高度并行的项目。
      • 架构机制:引入 BFF(Backend For Frontend,服务于前端的后端)理念。GraphQL 作为中间件层,负责将底层分散的微服务、数据库或第三方 API 进行聚合与编排(Data Orchestration)。前端通过 Apollo Client 发起声明式查询,精准获取 UI 组件所需的数据切片,并利用 Apollo 强大的标准化缓存(Normalized Cache)管理复杂实体关系。
      • 工程价值:彻底解决多端设备(Web、iOS、Android)面临的过度获取(Over-fetching)与碎片化接口治理问题,实现了数据消费端的高度自治。

      6. 构建工具与工作流 (Build Tools & Workflow)

      7. 全栈框架

      同构元框架:Next.js、Nuxt,现代全栈开发倾向于使用“元框架”,它们模糊了客户端和服务器的界限,提供一体化的开发体验。

      企业级 Node 服务端框架:NestJS,一个用于构建高效、可扩展的 Node.js 服务器端应用程序的框架,它采用现代 TypeScript 编写,并完全支持它(同时也支持纯 JavaScript)。它融合了 OOP(面向对象编程)、FP(函数式编程)和 FRP(函数响应式编程)的理念。其设计深受 Angular 启发,内置了依赖注入(DI)、模块化和分层架构等强主张特性,被称为 Node.js 版的 Spring 框架。

      对比维度Next.jsNuxtNestJS
      框架定位React 全栈框架
      (Isomorphic Meta-framework)
      Vue 全栈框架
      (Isomorphic Meta-framework)
      企业级 Node.js 服务端框架
      (Backend Framework)
      底层驱动Webpack / Turbopack
      React Server Components
      Vite / Nitro 引擎
      Vue3
      Express / Fastify (底层可插拔)
      纯 TypeScript
      核心工程特性混合渲染 (SSR/SSG/ISR)
      Server Actions (无缝 RPC)
      边缘计算路由
      混合渲染与预渲染
      极致的自动导入 (Auto-imports)
      开箱即用的模块化生态
      依赖注入 (DI) / 控制反转 (IoC)
      面向切面编程 (AOP)
      强主张的模块化目录
      数据流职责视图层渲染、BFF (服务于前端的后端)、轻量级聚合 API。视图层渲染、BFF (服务于前端的后端)、轻量级聚合 API。纯后端业务逻辑处理、微服务通信与编排、统一 API 供应。
      最佳业务场景重 SEO 的 C 端产品 (电商、内容站); 敏捷迭代的 SaaS; 单仓库极速交付。重交互体验的 Web 应用; Vue 技术团队的全栈转型; 独立开发者建站。复杂领域驱动设计 (DDD) 系统; 多端复用的 API 中台; 庞大的微服务集群。
      需规避的反模式承载高并发 CPU 密集型计算; 极其复杂的跨服务分布式事务。承载高并发 CPU 密集型计算; 极其复杂的跨服务分布式事务。仅需极简 CRUD 的小型外包项目; 强依赖首屏 HTML 直出的纯展示网页。
      团队协作模型前端主导的敏捷全栈小队, 或追求“单兵作战”的极客团队。前端主导的敏捷全栈小队, 或 Vue 生态重度依赖团队。后端主导的中大型团队, 前后端物理分离的标准化开发流水线。

      8. 部署与托管 (Deployment & Hosting)

      9. 学习资源与社区 (Learning & Community)

      + + + + \ No newline at end of file diff --git "a/01.\345\205\250\346\240\210/40.\345\211\215\347\253\257\345\267\245\347\250\213/03.JAMStack \346\242\263\347\220\206\344\270\216\345\256\236\350\267\265\346\214\207\345\215\227.html" b/fullstack/jamstack.html similarity index 78% rename from "01.\345\205\250\346\240\210/40.\345\211\215\347\253\257\345\267\245\347\250\213/03.JAMStack \346\242\263\347\220\206\344\270\216\345\256\236\350\267\265\346\214\207\345\215\227.html" rename to fullstack/jamstack.html index 75269d4f..23dfa6aa 100644 --- "a/01.\345\205\250\346\240\210/40.\345\211\215\347\253\257\345\267\245\347\250\213/03.JAMStack \346\242\263\347\220\206\344\270\216\345\256\236\350\267\265\346\214\207\345\215\227.html" +++ b/fullstack/jamstack.html @@ -6,12 +6,12 @@ JAMStack 梳理与实践指南 | Insight Stack - + - - - - + + + + @@ -30,7 +30,7 @@ - +
      Skip to content

      JAMStack 梳理与实践指南

      摘要总结:JAMStack 是一种以"预构建静态资产 + 客户端动态交互 + API 数据集成"为核心的 web 开发范式,名称源自 JavaScript、APIs、Markup 三个核心技术缩写。

      其核心机制是在构建时将页面预渲染为静态 HTML/CSS/JS,部署至 CDN 供用户就近加载,仅在需要动态数据时通过 JavaScript 调用 API 获取。相较于传统动态网站,JAMStack 在性能、可靠性、扩展性、安全性及运维成本上具有显著优势。

      本文梳理了主流构建工具(Gatsby、Next.js、Nuxt.js、11ty)、静态托管平台(Vercel、Netlify、Cloudflare Pages)、API/BaaS 服务(Supabase、Firebase、Auth0)及无头 CMS(Contentful、Sanity、Strapi)的选型策略,并通过 Next.js + Vercel + Supabase + Contentful 的实战案例,完整演示了从项目初始化、内容配置、SSG 预渲染、动态评论集成到自动化部署的全流程。

      JAMStack 是近几年前端领域备受关注的架构理念,它并非单一技术,而是一套以“高性能、高可靠、易扩展”为核心的开发范式。其名称源于三个核心技术的缩写:JavaScript(客户端交互逻辑)、APIs(通过第三方/自建接口获取数据)、Markup(预渲染的静态标记,如 HTML)。本质是“预渲染静态页面 + 客户端动态交互 + 接口数据集成”的架构模式,彻底改变了传统动态网站的部署与运行方式。

      1. JAMStack 核心概念与核心特性

      1.1 核心定义

      JAMStack 的核心是“预构建静态资产”——网站部署前,所有页面已通过构建工具(如 Gatsby、Next.js)渲染为静态 HTML、CSS、JS 文件,部署时仅需将这些静态文件托管到 CDN 即可。用户访问时,直接从 CDN 加载静态资源,无需后端服务器动态生成页面,仅在需要时通过 API 调用获取动态数据(如用户信息、实时数据)。

      1.2 核心特性(与传统动态网站对比)

      特性JAMStack传统动态网站(如 PHP/Java 后端渲染)
      页面生成时机构建时预渲染(部署前完成)请求时动态生成(用户访问时后端计算)
      服务器依赖无(仅需 CDN 托管静态资源)强依赖后端服务器(需运行应用服务)
      性能极高(CDN 全球分发,就近加载)中等(受服务器性能、网络延迟影响)
      可靠性极高(静态资源无单点故障)中等(依赖后端服务器稳定性)
      扩展性天然支持(CDN 弹性扩容)需配置服务器集群、负载均衡,成本高
      安全性高(无服务器端代码,攻击面极小)较低(需防护 SQL 注入、XSS 等攻击)
      开发/部署成本低(静态托管免费/低成本,无需运维服务器)高(需服务器运维、扩容、安全防护)

      1.3 关键误区澄清

      • ❌ 误区1:JAMStack = 纯静态网站(无动态交互)

        ✅ 正解:JAMStack 支持动态交互,只是“页面骨架”预渲染为静态,动态数据通过 JavaScript 调用 API 实现(如登录、评论、实时数据展示)。

      • ❌ 误区2:JAMStack 只能做博客/文档类网站

        ✅ 正解:可覆盖绝大多数场景,包括电商网站、管理后台、SaaS 应用(如 Netlify、Vercel 本身就是基于 JAMStack 构建的)。

      • ❌ 误区3:JAMStack 不需要后端

        ✅ 正解:需要后端,但后端仅提供 API 接口(无页面渲染逻辑),可使用第三方 BaaS 服务(如 Firebase、Supabase)替代自建后端,降低开发成本。

      2. JAMStack 核心技术栈(工具链选型)

      JAMStack 的实现依赖“构建工具 + 静态托管 + API/BaaS + 可选的无头 CMS”,以下是主流工具选型推荐:

      2.1 核心构建工具(静态站点生成器 SSG)

      负责将源码(Markdown、组件、数据)预渲染为静态 HTML,是 JAMStack 的核心工具:

      工具核心优势适用场景技术栈依赖
      Next.js支持 SSG/SSR/ISR 混合渲染,React 生态,灵活度高复杂应用(电商、SaaS、管理后台)React
      GatsbyGraphQL 数据层,插件生态丰富,优化极致博客、文档、营销网站React
      Nuxt.jsVue 生态,支持 SSG/SSR,易用性强全场景 Vue 项目Vue
      11ty(Eleventy)轻量无依赖,原生支持 Markdown,配置简单小型博客、静态文档原生 JS/模板引擎

      2.2 静态资源托管(部署平台)

      无需自建服务器,直接托管预构建的静态文件,提供全球 CDN 分发:

      • 主流平台:Vercel(Next.js 官方推荐,免费入门,一键部署)、Netlify(JAMStack 先驱,功能全面,支持表单/无服务器函数)、Cloudflare Pages(免费、CDN 速度快)、GitHub Pages(适合小型项目,免费无广告)。
      • 自建方案:将静态文件上传到阿里云 OSS + CDN、腾讯云 COS + CDN,适合需要私有化部署的场景。

      2.3 API/BaaS 服务(后端能力补充)

      JAMStack 无自建后端,需通过 API 获取动态能力(如数据库操作、用户认证):

      • 用户认证:Auth0、NextAuth.js(Next.js 专属)、Firebase Auth。
      • 数据库/存储:Supabase(开源 Firebase 替代方案,支持 PostgreSQL + 存储 + 认证)、Firebase Firestore、MongoDB Atlas。
      • 无服务器函数(Serverless Functions):Vercel Functions、Netlify Functions(无需部署独立 API 服务,在静态项目中直接编写 Node.js 函数,处理后端逻辑)。
      • 第三方 API:支付(Stripe)、邮件(SendGrid)、地图(高德/谷歌地图 API)等。

      2.4 无头 CMS(内容管理)

      适合非技术人员维护内容(如博客文章、产品信息),提供 API 供构建工具拉取数据:

      • 主流选择:Contentful、Sanity、Strapi(开源,可自建)、Ghost(专注博客)。
      • 核心作用:内容与代码分离,编辑者在 CMS 中修改内容后,触发构建工具重新预渲染静态页面(或通过 ISR 增量更新)。

      3. JAMStack 项目实践:从 0 到 1 搭建博客网站

      以“Next.js + Vercel + Supabase + Contentful”为例,搭建一个支持内容管理、用户评论的博客网站,步骤如下:

      3.1 技术栈选型

      • 构建工具:Next.js(支持 SSG 预渲染,方便后续扩展动态功能)。
      • 托管平台:Vercel(一键部署,自动构建,全球 CDN)。
      • 内容管理:Contentful(免费版足够个人博客使用,API 友好)。
      • 动态功能:Supabase(提供 PostgreSQL 数据库,存储用户评论;Auth 功能实现评论登录)。
      • 样式方案:Tailwind CSS(快速开发,响应式设计)。

      3.2 具体实施步骤

      步骤 1:初始化 Next.js 项目(SSG 模式)

      首先创建 Next.js 项目,开启 SSG 预渲染模式(Next.js 13+ 推荐 App Router):

      bash
      # 1. 创建项目
      +  

      JAMStack 梳理与实践指南

      摘要总结:JAMStack 是一种以"预构建静态资产 + 客户端动态交互 + API 数据集成"为核心的 web 开发范式,名称源自 JavaScript、APIs、Markup 三个核心技术缩写。

      其核心机制是在构建时将页面预渲染为静态 HTML/CSS/JS,部署至 CDN 供用户就近加载,仅在需要动态数据时通过 JavaScript 调用 API 获取。相较于传统动态网站,JAMStack 在性能、可靠性、扩展性、安全性及运维成本上具有显著优势。

      本文梳理了主流构建工具(Gatsby、Next.js、Nuxt.js、11ty)、静态托管平台(Vercel、Netlify、Cloudflare Pages)、API/BaaS 服务(Supabase、Firebase、Auth0)及无头 CMS(Contentful、Sanity、Strapi)的选型策略,并通过 Next.js + Vercel + Supabase + Contentful 的实战案例,完整演示了从项目初始化、内容配置、SSG 预渲染、动态评论集成到自动化部署的全流程。

      JAMStack 是近几年前端领域备受关注的架构理念,它并非单一技术,而是一套以“高性能、高可靠、易扩展”为核心的开发范式。其名称源于三个核心技术的缩写:JavaScript(客户端交互逻辑)、APIs(通过第三方/自建接口获取数据)、Markup(预渲染的静态标记,如 HTML)。本质是“预渲染静态页面 + 客户端动态交互 + 接口数据集成”的架构模式,彻底改变了传统动态网站的部署与运行方式。

      1. JAMStack 核心概念与核心特性

      1.1 核心定义

      JAMStack 的核心是“预构建静态资产”——网站部署前,所有页面已通过构建工具(如 Gatsby、Next.js)渲染为静态 HTML、CSS、JS 文件,部署时仅需将这些静态文件托管到 CDN 即可。用户访问时,直接从 CDN 加载静态资源,无需后端服务器动态生成页面,仅在需要时通过 API 调用获取动态数据(如用户信息、实时数据)。

      1.2 核心特性(与传统动态网站对比)

      特性JAMStack传统动态网站(如 PHP/Java 后端渲染)
      页面生成时机构建时预渲染(部署前完成)请求时动态生成(用户访问时后端计算)
      服务器依赖无(仅需 CDN 托管静态资源)强依赖后端服务器(需运行应用服务)
      性能极高(CDN 全球分发,就近加载)中等(受服务器性能、网络延迟影响)
      可靠性极高(静态资源无单点故障)中等(依赖后端服务器稳定性)
      扩展性天然支持(CDN 弹性扩容)需配置服务器集群、负载均衡,成本高
      安全性高(无服务器端代码,攻击面极小)较低(需防护 SQL 注入、XSS 等攻击)
      开发/部署成本低(静态托管免费/低成本,无需运维服务器)高(需服务器运维、扩容、安全防护)

      1.3 关键误区澄清

      • ❌ 误区1:JAMStack = 纯静态网站(无动态交互)

        ✅ 正解:JAMStack 支持动态交互,只是“页面骨架”预渲染为静态,动态数据通过 JavaScript 调用 API 实现(如登录、评论、实时数据展示)。

      • ❌ 误区2:JAMStack 只能做博客/文档类网站

        ✅ 正解:可覆盖绝大多数场景,包括电商网站、管理后台、SaaS 应用(如 Netlify、Vercel 本身就是基于 JAMStack 构建的)。

      • ❌ 误区3:JAMStack 不需要后端

        ✅ 正解:需要后端,但后端仅提供 API 接口(无页面渲染逻辑),可使用第三方 BaaS 服务(如 Firebase、Supabase)替代自建后端,降低开发成本。

      2. JAMStack 核心技术栈(工具链选型)

      JAMStack 的实现依赖“构建工具 + 静态托管 + API/BaaS + 可选的无头 CMS”,以下是主流工具选型推荐:

      2.1 核心构建工具(静态站点生成器 SSG)

      负责将源码(Markdown、组件、数据)预渲染为静态 HTML,是 JAMStack 的核心工具:

      工具核心优势适用场景技术栈依赖
      Next.js支持 SSG/SSR/ISR 混合渲染,React 生态,灵活度高复杂应用(电商、SaaS、管理后台)React
      GatsbyGraphQL 数据层,插件生态丰富,优化极致博客、文档、营销网站React
      Nuxt.jsVue 生态,支持 SSG/SSR,易用性强全场景 Vue 项目Vue
      11ty(Eleventy)轻量无依赖,原生支持 Markdown,配置简单小型博客、静态文档原生 JS/模板引擎

      2.2 静态资源托管(部署平台)

      无需自建服务器,直接托管预构建的静态文件,提供全球 CDN 分发:

      • 主流平台:Vercel(Next.js 官方推荐,免费入门,一键部署)、Netlify(JAMStack 先驱,功能全面,支持表单/无服务器函数)、Cloudflare Pages(免费、CDN 速度快)、GitHub Pages(适合小型项目,免费无广告)。
      • 自建方案:将静态文件上传到阿里云 OSS + CDN、腾讯云 COS + CDN,适合需要私有化部署的场景。

      2.3 API/BaaS 服务(后端能力补充)

      JAMStack 无自建后端,需通过 API 获取动态能力(如数据库操作、用户认证):

      • 用户认证:Auth0、NextAuth.js(Next.js 专属)、Firebase Auth。
      • 数据库/存储:Supabase(开源 Firebase 替代方案,支持 PostgreSQL + 存储 + 认证)、Firebase Firestore、MongoDB Atlas。
      • 无服务器函数(Serverless Functions):Vercel Functions、Netlify Functions(无需部署独立 API 服务,在静态项目中直接编写 Node.js 函数,处理后端逻辑)。
      • 第三方 API:支付(Stripe)、邮件(SendGrid)、地图(高德/谷歌地图 API)等。

      2.4 无头 CMS(内容管理)

      适合非技术人员维护内容(如博客文章、产品信息),提供 API 供构建工具拉取数据:

      • 主流选择:Contentful、Sanity、Strapi(开源,可自建)、Ghost(专注博客)。
      • 核心作用:内容与代码分离,编辑者在 CMS 中修改内容后,触发构建工具重新预渲染静态页面(或通过 ISR 增量更新)。

      3. JAMStack 项目实践:从 0 到 1 搭建博客网站

      以“Next.js + Vercel + Supabase + Contentful”为例,搭建一个支持内容管理、用户评论的博客网站,步骤如下:

      3.1 技术栈选型

      • 构建工具:Next.js(支持 SSG 预渲染,方便后续扩展动态功能)。
      • 托管平台:Vercel(一键部署,自动构建,全球 CDN)。
      • 内容管理:Contentful(免费版足够个人博客使用,API 友好)。
      • 动态功能:Supabase(提供 PostgreSQL 数据库,存储用户评论;Auth 功能实现评论登录)。
      • 样式方案:Tailwind CSS(快速开发,响应式设计)。

      3.2 具体实施步骤

      步骤 1:初始化 Next.js 项目(SSG 模式)

      首先创建 Next.js 项目,开启 SSG 预渲染模式(Next.js 13+ 推荐 App Router):

      bash
      # 1. 创建项目
       npx create-next-app@latest jamstack-blog --typescript --tailwind --eslint
       cd jamstack-blog
       
      @@ -358,7 +358,7 @@
       git add .
       git commit -m "initial jamstack blog"
       git remote add origin https://github.com/你的用户名/jamstack-blog.git
      -git push -u origin main
    • 部署到 Vercel:

      • 访问 Vercel 官网,登录 GitHub 账号,导入上述仓库。
      • Vercel 会自动识别 Next.js 项目,无需额外配置,直接点击“Deploy”。
      • 部署完成后,Vercel 会生成一个免费域名(如 jamstack-blog-xxx.vercel.app),访问即可看到预渲染的博客网站。
    • 配置自动构建(内容更新后自动部署):

      • 在 Contentful 控制台中,添加“Webhook”:触发事件选择“Entry published”,URL 填写 Vercel 项目的“Deploy Hook”(在 Vercel 项目设置 → Git → Deploy Hooks 中生成)。
      • 此后,在 Contentful 中修改/新增文章并发布后,会自动触发 Vercel 重新构建项目,更新静态页面。
    • 3.3 项目扩展:从博客到电商(JAMStack 场景延伸)

      若需将博客扩展为电商网站,仅需补充以下步骤:

      1. 内容管理:在 Contentful 中添加 Product 内容模型(名称、价格、库存、图片等)。
      2. 购物车:使用 localStorage 存储购物车数据(静态场景),或 Supabase 存储用户购物车(登录后同步)。
      3. 支付集成:接入 Stripe API,通过 Vercel Functions 编写支付回调函数(避免前端暴露支付密钥)。
      4. 订单管理:在 Supabase 中创建 orders 表,存储订单信息,通过 API 实现订单查询。

      4. JAMStack 适用场景与不适用场景

      场景类型说明
      适用场景(优先选择 JAMStack)• 博客、文档、营销网站(内容更新不频繁,对性能要求高)。
      • 电商网站(商品页面预渲染,购物车/支付通过 API 实现)。
      • 管理后台(静态页面 + 接口调用,无需后端渲染)。
      • 个人/小型团队项目(降低开发、运维成本)。
      不适用场景(谨慎选择)• 实时性极高的应用(如聊天软件、股票交易平台):虽然可通过 SSE/WebSocket 弥补,但复杂度高于传统架构。
      • 内容频繁更新的网站(如新闻网站,每分钟更新数百篇文章):频繁触发重新构建,可能影响性能(可通过 ISR 增量渲染缓解)。
      • 重度依赖服务器端计算的应用(如复杂数据分析、视频处理):需额外集成 Serverless 函数或后端服务,架构复杂度上升。

      5. 总结

      JAMStack 的核心价值是“用静态资源的高性能 + API 的灵活性,替代传统动态网站的复杂架构”,其优势在于:开发效率高(无需关心后端运维)、性能极致(CDN 全球分发)、成本低(免费托管方案丰富)。

      对于开发者而言,实践 JAMStack 的关键步骤是:

      1. 选型:根据项目复杂度选择构建工具(Next.js 万能,11ty 轻量)。
      2. 开发:用 SSG 预渲染静态页面,动态功能通过 API/BaaS 实现。
      3. 部署:托管到 Vercel/Netlify 等平台,配置自动构建。
      4. 迭代:通过 Webhook 实现内容更新自动部署,通过 ISR 平衡静态性能与实时性。

      无论是个人博客、企业官网还是中小型电商,JAMStack 都是值得尝试的架构方案——它能让你专注于产品本身,而非基础设施的维护。

      +git push -u origin main
    • 部署到 Vercel:

      • 访问 Vercel 官网,登录 GitHub 账号,导入上述仓库。
      • Vercel 会自动识别 Next.js 项目,无需额外配置,直接点击“Deploy”。
      • 部署完成后,Vercel 会生成一个免费域名(如 jamstack-blog-xxx.vercel.app),访问即可看到预渲染的博客网站。
    • 配置自动构建(内容更新后自动部署):

      • 在 Contentful 控制台中,添加“Webhook”:触发事件选择“Entry published”,URL 填写 Vercel 项目的“Deploy Hook”(在 Vercel 项目设置 → Git → Deploy Hooks 中生成)。
      • 此后,在 Contentful 中修改/新增文章并发布后,会自动触发 Vercel 重新构建项目,更新静态页面。
    • 3.3 项目扩展:从博客到电商(JAMStack 场景延伸)

      若需将博客扩展为电商网站,仅需补充以下步骤:

      1. 内容管理:在 Contentful 中添加 Product 内容模型(名称、价格、库存、图片等)。
      2. 购物车:使用 localStorage 存储购物车数据(静态场景),或 Supabase 存储用户购物车(登录后同步)。
      3. 支付集成:接入 Stripe API,通过 Vercel Functions 编写支付回调函数(避免前端暴露支付密钥)。
      4. 订单管理:在 Supabase 中创建 orders 表,存储订单信息,通过 API 实现订单查询。

      4. JAMStack 适用场景与不适用场景

      场景类型说明
      适用场景(优先选择 JAMStack)• 博客、文档、营销网站(内容更新不频繁,对性能要求高)。
      • 电商网站(商品页面预渲染,购物车/支付通过 API 实现)。
      • 管理后台(静态页面 + 接口调用,无需后端渲染)。
      • 个人/小型团队项目(降低开发、运维成本)。
      不适用场景(谨慎选择)• 实时性极高的应用(如聊天软件、股票交易平台):虽然可通过 SSE/WebSocket 弥补,但复杂度高于传统架构。
      • 内容频繁更新的网站(如新闻网站,每分钟更新数百篇文章):频繁触发重新构建,可能影响性能(可通过 ISR 增量渲染缓解)。
      • 重度依赖服务器端计算的应用(如复杂数据分析、视频处理):需额外集成 Serverless 函数或后端服务,架构复杂度上升。

      5. 总结

      JAMStack 的核心价值是“用静态资源的高性能 + API 的灵活性,替代传统动态网站的复杂架构”,其优势在于:开发效率高(无需关心后端运维)、性能极致(CDN 全球分发)、成本低(免费托管方案丰富)。

      对于开发者而言,实践 JAMStack 的关键步骤是:

      1. 选型:根据项目复杂度选择构建工具(Next.js 万能,11ty 轻量)。
      2. 开发:用 SSG 预渲染静态页面,动态功能通过 API/BaaS 实现。
      3. 部署:托管到 Vercel/Netlify 等平台,配置自动构建。
      4. 迭代:通过 Webhook 实现内容更新自动部署,通过 ISR 平衡静态性能与实时性。

      无论是个人博客、企业官网还是中小型电商,JAMStack 都是值得尝试的架构方案——它能让你专注于产品本身,而非基础设施的维护。

      diff --git "a/01.\345\205\250\346\240\210/80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273/20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227/0.overview.html" b/fullstack/module-programming-practice-guide.html similarity index 93% rename from "01.\345\205\250\346\240\210/80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273/20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227/0.overview.html" rename to fullstack/module-programming-practice-guide.html index d163689a..c9a970f9 100644 --- "a/01.\345\205\250\346\240\210/80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273/20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227/0.overview.html" +++ b/fullstack/module-programming-practice-guide.html @@ -6,12 +6,12 @@ 模块化编程实践指南 | Insight Stack - + - - - - + + + + @@ -30,7 +30,7 @@ - +
      Skip to content

      模块化编程实践指南

      作为模块化编程系列的总览文章,本文系统梳理了从基础概念到大型项目架构设计的全栈知识体系。首先介绍分层架构设计,包括前端 React 分层与后端 NestJS 分层,以及 DDD 四层架构。随后探讨微前端架构,解析 iframe、Web Components、single-spa、qiankun、模块联邦等方案的优劣势,并提供模块联邦的完整实战配置。系列文章涵盖 CommonJS、AMD、UMD、ES Modules 等规范演进,以及 TypeScript 模块增强、工程化实践与 Node.js 模块化。

      1. 引言

      模块化编程是现代 JavaScript/TypeScript 开发的核心原则,它通过将复杂系统拆分为独立可复用的模块,降低系统复杂性并提高可维护性与可复用性。因此,我们通过系列文章详细介绍了模块化的基础概念、演进历程、不同规范的深度解析、TypeScript模块化增强、ES Modules 核心语法与实践、模块化编程原则与最佳实践、前端工程化中的模块化、Node.js中的模块化实践、大型项目中的模块化设计、模块化与代码维护以及未来发展趋势。

      前面的系列文章主要有:

      本文将重点介绍大型项目中的模块化设计。

      2.分层架构设计

      分层架构是大型项目中常用的模块化设计模式,它将系统分为多个层次,每层负责特定的功能。

      2.1 前端分层架构

      以 React 技术栈为例,一个典型的前端分层架构通常包含以下核心层次:

      层级说明
      表现层负责 UI 渲染,包含组件与页面,遵循原子设计(Atomic Design)方法论
      业务逻辑层封装业务规则与流程,通过自定义 Hooks 和服务实现
      数据访问层处理与后端的通信,包括 API 请求、数据缓存与同步策略
      状态管理层管理全局与局部状态,确保数据流的可预测性
      路由层定义导航结构与路由守卫,处理权限控制与代码分割
      基础设施层提供横切关注点支持,包括工具函数、常量定义与配置管理

      以下是一个基于 React + TypeScript 的现代项目目录结构示例:

      shell
      src/
      +  

      模块化编程实践指南

      作为模块化编程系列的总览文章,本文系统梳理了从基础概念到大型项目架构设计的全栈知识体系。首先介绍分层架构设计,包括前端 React 分层与后端 NestJS 分层,以及 DDD 四层架构。随后探讨微前端架构,解析 iframe、Web Components、single-spa、qiankun、模块联邦等方案的优劣势,并提供模块联邦的完整实战配置。系列文章涵盖 CommonJS、AMD、UMD、ES Modules 等规范演进,以及 TypeScript 模块增强、工程化实践与 Node.js 模块化。

      1. 引言

      模块化编程是现代 JavaScript/TypeScript 开发的核心原则,它通过将复杂系统拆分为独立可复用的模块,降低系统复杂性并提高可维护性与可复用性。因此,我们通过系列文章详细介绍了模块化的基础概念、演进历程、不同规范的深度解析、TypeScript模块化增强、ES Modules 核心语法与实践、模块化编程原则与最佳实践、前端工程化中的模块化、Node.js中的模块化实践、大型项目中的模块化设计、模块化与代码维护以及未来发展趋势。

      前面的系列文章主要有:

      本文将重点介绍大型项目中的模块化设计。

      2.分层架构设计

      分层架构是大型项目中常用的模块化设计模式,它将系统分为多个层次,每层负责特定的功能。

      2.1 前端分层架构

      以 React 技术栈为例,一个典型的前端分层架构通常包含以下核心层次:

      层级说明
      表现层负责 UI 渲染,包含组件与页面,遵循原子设计(Atomic Design)方法论
      业务逻辑层封装业务规则与流程,通过自定义 Hooks 和服务实现
      数据访问层处理与后端的通信,包括 API 请求、数据缓存与同步策略
      状态管理层管理全局与局部状态,确保数据流的可预测性
      路由层定义导航结构与路由守卫,处理权限控制与代码分割
      基础设施层提供横切关注点支持,包括工具函数、常量定义与配置管理

      以下是一个基于 React + TypeScript 的现代项目目录结构示例:

      shell
      src/
       ├── app/                    # 应用层:应用配置和入口
          ├── App.tsx             # 应用根组件
          ├── Router.tsx          # 路由配置
      @@ -1053,7 +1053,7 @@
          └── docker-compose.yml
       
       ├── package.json                 # 根 package.json
      -└── README.md

      2.4.7 微前端最佳实践

      在实际项目中应用微前端架构,建议遵循以下最佳实践:

      策略要点具体措施
      合理划分子应用边界• 按业务领域划分:用户、商品、订单、支付等
      • 按团队职责划分:每个团队负责一个或多个子应用
      • 避免过度拆分:子应用数量不宜过多,建议 3-10 个
      统一技术规范• 制定统一的编码规范和目录结构
      • 统一 UI 组件库和设计系统
      • 统一 API 接口规范和数据格式
      共享依赖管理• 使用模块联邦的 shared 配置共享基础库
      • 避免版本冲突,统一管理依赖版本
      • 共享的依赖应该保持向后兼容
      样式隔离策略• 使用 CSS Modules 或 CSS-in-JS
      • 使用命名空间前缀(如 product-app__button
      • 使用 Shadow DOM 实现完全隔离
      性能优化• 使用懒加载和预加载策略
      • 合理配置共享依赖的加载时机
      • 监控子应用的加载性能
      错误处理• 子应用加载失败时的降级策略
      • 全局错误捕获和上报
      • 子应用之间的错误隔离

      2.4.8 微前端小结

      微前端架构是前端模块化发展的必然产物,它通过将大型前端应用拆分为多个独立的子应用,解决了以下核心问题:

      1. 复杂度控制:将复杂的单体应用拆分为多个简单的子应用,每个子应用专注于特定的业务领域,降低了系统的整体复杂度。

      2. 团队协作:不同团队可以独立开发和部署自己的子应用,互不影响,大大提高了开发效率和团队协作能力。

      3. 技术演进:子应用可以使用不同的技术栈,支持渐进式升级和技术迁移,避免了技术债务的积累。

      4. 可维护性:每个子应用都是独立的模块,可以独立测试、调试和维护,提高了代码的可维护性。

      5. 扩展性:新增业务功能时,只需添加新的子应用,无需修改现有代码,支持业务的快速扩展。

      然而,微前端架构也带来了一些挑战:

      • 架构复杂度:需要处理子应用的加载、通信、路由等问题
      • 调试困难:跨子应用的调试和问题定位更加复杂
      • 性能开销:多个子应用的加载可能影响首屏性能
      • 团队要求:需要团队具备较强的架构能力和协作能力

      因此,在决定采用微前端架构时,需要权衡项目的规模、团队的规模和技术能力。对于中小型项目,传统的单体应用可能更加合适;对于大型企业级应用,微前端架构则能够带来显著的收益。

      核心建议:微前端不是目的,而是手段。在采用微前端架构之前,务必评估项目的实际需求,避免为了微前端而微前端。只有在真正需要解决复杂度、团队协作和技术演进问题时,微前端架构才能发挥其最大的价值。

      结语

      通过梳理一系列模块化编程的核心概念和实践技巧,我们旨在理解不同模块化规范的特点与适用场景,熟练掌握 ES Modules 的核心语法和最佳实践,并能够在前端和 Node.js 项目中灵活应用模块化设计。

      模块化设计是构建大型、复杂应用的关键,它可以帮助开发者应对不断增长的应用复杂度,提高开发效率和代码质量。随着Web技术的不断发展,模块化设计将继续演进,与新兴技术深度融合,成为构建现代应用的核心原则。

      希望本系列文章能够帮助读者理解模块化编程的重要性,掌握一些模块化设计的原则和实践技巧,构建出更健壮、更可维护的大型应用。

      +└── README.md

      2.4.7 微前端最佳实践

      在实际项目中应用微前端架构,建议遵循以下最佳实践:

      策略要点具体措施
      合理划分子应用边界• 按业务领域划分:用户、商品、订单、支付等
      • 按团队职责划分:每个团队负责一个或多个子应用
      • 避免过度拆分:子应用数量不宜过多,建议 3-10 个
      统一技术规范• 制定统一的编码规范和目录结构
      • 统一 UI 组件库和设计系统
      • 统一 API 接口规范和数据格式
      共享依赖管理• 使用模块联邦的 shared 配置共享基础库
      • 避免版本冲突,统一管理依赖版本
      • 共享的依赖应该保持向后兼容
      样式隔离策略• 使用 CSS Modules 或 CSS-in-JS
      • 使用命名空间前缀(如 product-app__button
      • 使用 Shadow DOM 实现完全隔离
      性能优化• 使用懒加载和预加载策略
      • 合理配置共享依赖的加载时机
      • 监控子应用的加载性能
      错误处理• 子应用加载失败时的降级策略
      • 全局错误捕获和上报
      • 子应用之间的错误隔离

      2.4.8 微前端小结

      微前端架构是前端模块化发展的必然产物,它通过将大型前端应用拆分为多个独立的子应用,解决了以下核心问题:

      1. 复杂度控制:将复杂的单体应用拆分为多个简单的子应用,每个子应用专注于特定的业务领域,降低了系统的整体复杂度。

      2. 团队协作:不同团队可以独立开发和部署自己的子应用,互不影响,大大提高了开发效率和团队协作能力。

      3. 技术演进:子应用可以使用不同的技术栈,支持渐进式升级和技术迁移,避免了技术债务的积累。

      4. 可维护性:每个子应用都是独立的模块,可以独立测试、调试和维护,提高了代码的可维护性。

      5. 扩展性:新增业务功能时,只需添加新的子应用,无需修改现有代码,支持业务的快速扩展。

      然而,微前端架构也带来了一些挑战:

      • 架构复杂度:需要处理子应用的加载、通信、路由等问题
      • 调试困难:跨子应用的调试和问题定位更加复杂
      • 性能开销:多个子应用的加载可能影响首屏性能
      • 团队要求:需要团队具备较强的架构能力和协作能力

      因此,在决定采用微前端架构时,需要权衡项目的规模、团队的规模和技术能力。对于中小型项目,传统的单体应用可能更加合适;对于大型企业级应用,微前端架构则能够带来显著的收益。

      核心建议:微前端不是目的,而是手段。在采用微前端架构之前,务必评估项目的实际需求,避免为了微前端而微前端。只有在真正需要解决复杂度、团队协作和技术演进问题时,微前端架构才能发挥其最大的价值。

      结语

      通过梳理一系列模块化编程的核心概念和实践技巧,我们旨在理解不同模块化规范的特点与适用场景,熟练掌握 ES Modules 的核心语法和最佳实践,并能够在前端和 Node.js 项目中灵活应用模块化设计。

      模块化设计是构建大型、复杂应用的关键,它可以帮助开发者应对不断增长的应用复杂度,提高开发效率和代码质量。随着Web技术的不断发展,模块化设计将继续演进,与新兴技术深度融合,成为构建现代应用的核心原则。

      希望本系列文章能够帮助读者理解模块化编程的重要性,掌握一些模块化设计的原则和实践技巧,构建出更健壮、更可维护的大型应用。

      diff --git "a/01.\345\205\250\346\240\210/80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273/20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227/5.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\216\237\345\210\231\344\270\216\346\234\200\344\275\263\345\256\236\350\267\265.html" b/fullstack/module-programming-principles-best-practices.html similarity index 71% rename from "01.\345\205\250\346\240\210/80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273/20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227/5.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\216\237\345\210\231\344\270\216\346\234\200\344\275\263\345\256\236\350\267\265.html" rename to fullstack/module-programming-principles-best-practices.html index 87a34b6b..5f7075ac 100644 --- "a/01.\345\205\250\346\240\210/80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273/20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227/5.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\216\237\345\210\231\344\270\216\346\234\200\344\275\263\345\256\236\350\267\265.html" +++ b/fullstack/module-programming-principles-best-practices.html @@ -6,12 +6,12 @@ 模块化编程原则梳理与总结 | Insight Stack - + - - - - + + + + @@ -30,7 +30,7 @@ - +
      Skip to content

      模块化编程原则梳理与总结

      如果说掌握模块化语法是“术”,那么理解其背后的设计原则就是“道”。在大型前端工程中,乱用模块化往往比不用更糟糕。为了构建出既健壮又易于扩展的系统,我们需要遵循一套行之有效的工程准则。

      1. 单一职责原则

      核心思想:一个模块应当有且只有一个被改变的原因。

      模块不应成为功能的“杂货铺”。当一个模块承担了太多不相关的业务逻辑时,它的复杂度会呈指数级上升,任何微小的改动都可能引发意想不到的连锁反应。

      代码演示:

      javascript
      // ✅ 推荐:职责拆分明确
      +  

      模块化编程原则梳理与总结

      如果说掌握模块化语法是“术”,那么理解其背后的设计原则就是“道”。在大型前端工程中,乱用模块化往往比不用更糟糕。为了构建出既健壮又易于扩展的系统,我们需要遵循一套行之有效的工程准则。

      1. 单一职责原则

      核心思想:一个模块应当有且只有一个被改变的原因。

      模块不应成为功能的“杂货铺”。当一个模块承担了太多不相关的业务逻辑时,它的复杂度会呈指数级上升,任何微小的改动都可能引发意想不到的连锁反应。

      代码演示:

      javascript
      // ✅ 推荐:职责拆分明确
       // user-service.js - 仅处理用户数据的 CRUD
       export const getUser = async (id) => { /* ... */ };
       
      @@ -236,7 +236,7 @@
       
       ## 1.0.0 (2022-11-01)
       - 初始版本发布
      -- 支持 `createUser``getUser` 方法

      6. 结语:构建可预测的秩序

      模块化编程的终点,不是将代码拆得零散,而是要在混沌的业务逻辑之上,构建出一套清晰、稳定、可预测的秩序。

      从单一职责的约束,到高内聚低耦合的权衡,再到对循环依赖的警惕,这些原则本质上都在做同一件事:降低心智负担。优秀的模块化设计应当让开发者在进入代码库时,能够迅速建立“地图感”——知道每一块拼图的位置,也清楚拿掉一块拼图后会产生的波纹。

      在 AI 辅助编程日益普及的今天,清晰的模块边界更是 AI 能够准确理解并生成高质量代码的前提。愿你不仅能写出跑得通的模块,更能设计出经得起时间推敲的工程结构。

      +- 支持 `createUser``getUser` 方法

      6. 结语:构建可预测的秩序

      模块化编程的终点,不是将代码拆得零散,而是要在混沌的业务逻辑之上,构建出一套清晰、稳定、可预测的秩序。

      从单一职责的约束,到高内聚低耦合的权衡,再到对循环依赖的警惕,这些原则本质上都在做同一件事:降低心智负担。优秀的模块化设计应当让开发者在进入代码库时,能够迅速建立“地图感”——知道每一块拼图的位置,也清楚拿掉一块拼图后会产生的波纹。

      在 AI 辅助编程日益普及的今天,清晰的模块边界更是 AI 能够准确理解并生成高质量代码的前提。愿你不仅能写出跑得通的模块,更能设计出经得起时间推敲的工程结构。

      diff --git "a/01.\345\205\250\346\240\210/60.\347\275\221\347\273\234\344\270\216\351\200\232\344\277\241/03.\351\200\200\351\201\277\350\275\256\350\257\242\344\270\216\351\225\277\350\275\256\350\257\242\347\232\204\345\216\237\347\220\206\343\200\201\345\256\236\346\210\230\344\270\216\351\200\211\345\236\213\345\206\263\347\255\226.html" b/fullstack/networking-polling-optimization.html similarity index 75% rename from "01.\345\205\250\346\240\210/60.\347\275\221\347\273\234\344\270\216\351\200\232\344\277\241/03.\351\200\200\351\201\277\350\275\256\350\257\242\344\270\216\351\225\277\350\275\256\350\257\242\347\232\204\345\216\237\347\220\206\343\200\201\345\256\236\346\210\230\344\270\216\351\200\211\345\236\213\345\206\263\347\255\226.html" rename to fullstack/networking-polling-optimization.html index 1a124383..586769dd 100644 --- "a/01.\345\205\250\346\240\210/60.\347\275\221\347\273\234\344\270\216\351\200\232\344\277\241/03.\351\200\200\351\201\277\350\275\256\350\257\242\344\270\216\351\225\277\350\275\256\350\257\242\347\232\204\345\216\237\347\220\206\343\200\201\345\256\236\346\210\230\344\270\216\351\200\211\345\236\213\345\206\263\347\255\226.html" +++ b/fullstack/networking-polling-optimization.html @@ -6,12 +6,12 @@ HTTP 轮询优化指南:退避轮询与长轮询的原理、实战与选型决策 | Insight Stack - + - - - - + + + + @@ -30,7 +30,7 @@ - +
      Skip to content

      HTTP 轮询优化指南:退避轮询与长轮询的原理、实战与选型决策

      摘要总结: 针对传统固定频率轮询的服务器资源浪费问题,系统分析退避轮询与长轮询两种优化策略的核心原理与运行机制。通过 TypeScript 客户端与 NestJS 服务端的完整实现示例,对比两种方案在实时性、资源占用、复杂度等维度的差异。构建包含任务耗时、并发规模、基础设施约束的技术选型决策树,并提出退避+长轮询级联、按业务分级等混合策略建议。结论表明,低实时要求高并发场景选退避轮询,高实时要求中低并发场景选长轮询,复杂场景可两者结合。

      1. 引言

      在现代 Web 开发中,WebSocket 和 Server-Sent Events (SSE) 常常被视为实时通信的银弹。然而,HTTP 轮询(Polling)作为最朴素的实时通信方案,非但没有退出历史舞台,反而在特定的复杂业务场景中大放异彩。

      📖 如果你对 HTTP 轮询在整个 Web 通信协议体系中的定位尚不清晰,推荐先阅读 Web 通信协议全景:从 HTTP 到 WebSocket 的技术选型指南,了解轮询与短连接、长连接、WebSocket、SSE 等方案的演进关系与适用边界,再结合本文深入实践。

      在当前众多顶级的 AI AIGC 应用(如 Midjourney 类的第三方集成应用、Stable Diffusion 商业平台、长视频生成等)中,任务处理往往需要数十秒甚至数分钟。在面对海量并发和复杂的网关负载均衡时,HTTP 轮询因其无状态、易扩展、断连恢复成本极低的特性,成为了架构师经过深思熟虑后的首选方案。

      然而,传统的固定频率轮询(如每秒请求一次)对服务器极不友好。为了兼顾用户体验与服务器的稳定性,本文将深入探讨两种常用的 HTTP 轮询优化策略:退避轮询(Backoff Polling) 与 长轮询(Long Polling)。

      2. 退避轮询

      退避轮询是一种在计算机网络和分布式系统中常用的网络请求或重试策略。它的核心思想是:当服务端任务未完成时,客户端下一次查询的等待时间并非固定,而是随着查询次数的增加而递增。

      2.1 为什么需要退避轮询?

      在服务器过载、网络故障或由于短时间高频请求触发限流(如 HTTP 429 错误)时,如果客户端仍以固定高频重试,会引发严重的灾难:

      • 惊群效应:大量客户端同时高频重试,导致服务器压力倍增,进而彻底崩溃。
      • 资源浪费:服务端在执行耗时任务(如 AI 渲染)时,初期的频繁查询注定是无效的,这不仅浪费了服务器带宽,也消耗了客户端的设备电量与性能。

      2.2 核心机制与运行规则

      退避轮询通过不断拉大两次请求之间的延迟时间,巧妙地实现了请求分流。其典型规则如下:

      • 服务端:保持“极轻”的逻辑,收到请求后立刻查询状态并返回(完成、失败或处理中),不做任何阻塞。

      • 客户端:收到“处理中”状态时,按策略进入等待。例如:

        • 第一次等待:2 秒

        • 第二次等待:5 秒

        • 第三次等待:10 秒

        • 第 N 次等待:最大上限(如 15 秒,避免等待过久导致体验断层)

      设置最大值是为了避免等待时间变得不可接受(如几个小时),通常会设置一个最大等待时间(Max Delay)和最大重试次数。

      2.3 客户端实现示例

      在客户端中,我们可以通过简单的 while 循环和 setTimeout 挂起机制来实现:

      typescript
      
      +  

      HTTP 轮询优化指南:退避轮询与长轮询的原理、实战与选型决策

      摘要总结: 针对传统固定频率轮询的服务器资源浪费问题,系统分析退避轮询与长轮询两种优化策略的核心原理与运行机制。通过 TypeScript 客户端与 NestJS 服务端的完整实现示例,对比两种方案在实时性、资源占用、复杂度等维度的差异。构建包含任务耗时、并发规模、基础设施约束的技术选型决策树,并提出退避+长轮询级联、按业务分级等混合策略建议。结论表明,低实时要求高并发场景选退避轮询,高实时要求中低并发场景选长轮询,复杂场景可两者结合。

      1. 引言

      在现代 Web 开发中,WebSocket 和 Server-Sent Events (SSE) 常常被视为实时通信的银弹。然而,HTTP 轮询(Polling)作为最朴素的实时通信方案,非但没有退出历史舞台,反而在特定的复杂业务场景中大放异彩。

      📖 如果你对 HTTP 轮询在整个 Web 通信协议体系中的定位尚不清晰,推荐先阅读 Web 通信协议全景:从 HTTP 到 WebSocket 的技术选型指南,了解轮询与短连接、长连接、WebSocket、SSE 等方案的演进关系与适用边界,再结合本文深入实践。

      在当前众多顶级的 AI AIGC 应用(如 Midjourney 类的第三方集成应用、Stable Diffusion 商业平台、长视频生成等)中,任务处理往往需要数十秒甚至数分钟。在面对海量并发和复杂的网关负载均衡时,HTTP 轮询因其无状态、易扩展、断连恢复成本极低的特性,成为了架构师经过深思熟虑后的首选方案。

      然而,传统的固定频率轮询(如每秒请求一次)对服务器极不友好。为了兼顾用户体验与服务器的稳定性,本文将深入探讨两种常用的 HTTP 轮询优化策略:退避轮询(Backoff Polling) 与 长轮询(Long Polling)。

      2. 退避轮询

      退避轮询是一种在计算机网络和分布式系统中常用的网络请求或重试策略。它的核心思想是:当服务端任务未完成时,客户端下一次查询的等待时间并非固定,而是随着查询次数的增加而递增。

      2.1 为什么需要退避轮询?

      在服务器过载、网络故障或由于短时间高频请求触发限流(如 HTTP 429 错误)时,如果客户端仍以固定高频重试,会引发严重的灾难:

      • 惊群效应:大量客户端同时高频重试,导致服务器压力倍增,进而彻底崩溃。
      • 资源浪费:服务端在执行耗时任务(如 AI 渲染)时,初期的频繁查询注定是无效的,这不仅浪费了服务器带宽,也消耗了客户端的设备电量与性能。

      2.2 核心机制与运行规则

      退避轮询通过不断拉大两次请求之间的延迟时间,巧妙地实现了请求分流。其典型规则如下:

      • 服务端:保持“极轻”的逻辑,收到请求后立刻查询状态并返回(完成、失败或处理中),不做任何阻塞。

      • 客户端:收到“处理中”状态时,按策略进入等待。例如:

        • 第一次等待:2 秒

        • 第二次等待:5 秒

        • 第三次等待:10 秒

        • 第 N 次等待:最大上限(如 15 秒,避免等待过久导致体验断层)

      设置最大值是为了避免等待时间变得不可接受(如几个小时),通常会设置一个最大等待时间(Max Delay)和最大重试次数。

      2.3 客户端实现示例

      在客户端中,我们可以通过简单的 while 循环和 setTimeout 挂起机制来实现:

      typescript
      
       interface TaskResponse {
         status: 'processing' | 'completed' | 'failed';
         result?: string;
      @@ -315,7 +315,7 @@
       
       └─ 是否有事件驱动基础设施(Redis/消息队列)?
           ├─ 是 → 长轮询可发挥最佳性能
      -    └─ 否 → 退避轮询实现更简单,无需额外组件

      4.2 适用场景速查

      优先选择退避轮询

      • 任务耗时较长(数十秒到分钟级),对实时性要求不高
      • 海量并发场景,服务器资源敏感
      • 无需 WebSocket/SSE 环境(如某些 API 第三方集成)
      • 需要简洁的客户端实现,不希望引入长连接管理复杂度
      • 示例:AI 生图进度查询、视频渲染任务状态、批量数据导出进度

      优先选择长轮询

      • 需要在秒级获得任务完成反馈,用户体验要求较高
      • 服务器连接池资源相对充裕,可以承受一定数量的挂起连接
      • 任务完成时间方差较大(可能几秒也可能几十秒)
      • 已有事件驱动基础设施(Redis Pub/Sub、消息队列)可复用
      • 示例:即时通讯未读数刷新、协同文档状态同步、在线游戏状态同步

      4.3 混合策略建议

      在实际生产环境中,并不局限于二选一,我们可以考虑以下混合思路:

      1. 退避 + 长轮询级联:任务初期使用长轮询追求实时性,经历过若干轮后降级为退避轮询,避免长时间占用连接资源。
      2. 按业务分级:核心业务流程使用长轮询,次要或后台任务使用退避轮询。
      3. 按客户端分级:PC 端浏览器使用长轮询,移动端或低功耗设备使用退避轮询节省电量。
      + └─ 否 → 退避轮询实现更简单,无需额外组件

      4.2 适用场景速查

      优先选择退避轮询

      • 任务耗时较长(数十秒到分钟级),对实时性要求不高
      • 海量并发场景,服务器资源敏感
      • 无需 WebSocket/SSE 环境(如某些 API 第三方集成)
      • 需要简洁的客户端实现,不希望引入长连接管理复杂度
      • 示例:AI 生图进度查询、视频渲染任务状态、批量数据导出进度

      优先选择长轮询

      • 需要在秒级获得任务完成反馈,用户体验要求较高
      • 服务器连接池资源相对充裕,可以承受一定数量的挂起连接
      • 任务完成时间方差较大(可能几秒也可能几十秒)
      • 已有事件驱动基础设施(Redis Pub/Sub、消息队列)可复用
      • 示例:即时通讯未读数刷新、协同文档状态同步、在线游戏状态同步

      4.3 混合策略建议

      在实际生产环境中,并不局限于二选一,我们可以考虑以下混合思路:

      1. 退避 + 长轮询级联:任务初期使用长轮询追求实时性,经历过若干轮后降级为退避轮询,避免长时间占用连接资源。
      2. 按业务分级:核心业务流程使用长轮询,次要或后台任务使用退避轮询。
      3. 按客户端分级:PC 端浏览器使用长轮询,移动端或低功耗设备使用退避轮询节省电量。
      diff --git a/fullstack/networking-protocol-selection-guide.html b/fullstack/networking-protocol-selection-guide.html new file mode 100644 index 00000000..a10ebb7c --- /dev/null +++ b/fullstack/networking-protocol-selection-guide.html @@ -0,0 +1,177 @@ + + + + + + Web 通信协议全景:从 HTTP 到 WebSocket 的技术选型指南 | Insight Stack + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      Skip to content
      6770
      + + + + 23.9m

      Web 通信协议全景:从 HTTP 到 WebSocket 的技术选型指南

      摘要总结:本文针对传统 HTTP 在实时通信场景的局限,系统分析流式 HTTP、SSE、WebSocket、Webhooks、HTTP 轮询五种技术的核心原理、网络机制与适用边界。通过对比各方案在单向/双向推送、实时性、资源开销等维度的差异,结合 AI 文本对话、生图生视频等典型场景,构建技术选型决策矩阵。结论表明,不存在最优技术,需根据任务耗时特征、并发规模、基础设施约束等因素选择最适配方案。

      1. 引言

      HTTP 是一种基于文本的通信协议,主要用于 Web 浏览器、移动应用、桌面应用等客户端和 Web 服务器之间的数据传输。传统 HTTP 采用同步的请求-响应模式:请求 -> 等待 -> 完整响应。这种方式虽能满足大多数场景,但在实时性要求较高的领域——如游戏、聊天、视频会议,以及 AI 时代的对话式应用——却显得力不从心。

      为解决这一问题,业界发展出了多种实时 Web 通信方案。本文将围绕 流式 HTTP、SSE、WebSocket、Webhooks、HTTP 轮询 这五种主流技术,从原理、特性、适用场景出发,探讨它们在现代分布式架构中的选型策略与工程实践。

      2. 传统 HTTP——Web 通信的基石

      自 1991 年诞生以来,HTTP(超文本传输协议)便成为了互联网运行的“通用语言”。作为一种无状态、基于“请求-响应”模式的应用层协议,它构筑了现代 Web 通信的稳固基石。

      在核心运作机制上,传统 HTTP 遵循着严谨的单向驱动逻辑:通信必须由客户端发起请求(Request),服务器在处理完成后返回完整的响应(Response)。一旦数据传输完成,连接在逻辑上即告结束。

      维度说明
      网络特征HTTP 构建于 TCP 协议之上。尽管从 HTTP/1.1 开始,协议默认开启了 Connection: keep-alive 机制以复用底层 TCP 连接,减少了频繁三次握手的开销,但在应用层层面,它依然维持着半双工通信的本质——在同一时刻,数据只能单向流动,且服务器永远处于"被动应答"状态
      典型应用这种模式完美契合了绝大多数非即时性的资源获取场景,如加载网页 HTML、调用标准 RESTful API(获取用户信息、提交表单)以及加载静态图片等。

      随着 Web 应用向“实时化”与“高互动”演进,传统 HTTP 的固有特性逐渐演变为开发的痛点:

      痛点说明
      无法主动推送服务器如同一个被动的仓库管理员,即便仓库内的数据发生了更新,只要客户端不主动询问,服务器也无法将新信息触达用户。
      头部开销沉重在 HTTP/1.x 中,每次请求都必须携带完整的 Header 信息(包括 Cookie、User-Agent 等)。对于实时性要求高、但单次数据包极小的场景(如传感器数值同步),这些重复的头部数据往往比有效载荷还要大,造成了带宽的极大浪费。
      实时性的"伪实现"在 WebSocket 等原生实时技术成熟前,为了模拟实时效果,开发者通常被迫采用轮询(Polling)技术。无论是频繁发起连接的短轮询,还是长时间挂起请求的长轮询(Long Polling),都会产生大量冗余请求,对服务器并发处理能力提出了严峻挑战。

      3. 流式 HTTP(Streamable HTTP)

      如果说传统 HTTP 是严谨的“一问一答”,那么流式 HTTP(Streamable HTTP)则更像是一次“未完待续”的深度交流。它通过对响应机制的巧妙“变异”,打破了“服务端必须积攒全部结果才能返回”的物理限制,实现了数据的边计算、边传输。

      3.1 核心原理:分块传输的艺术

      流式 HTTP 的精髓在于它不再追求一次性交付,而是通过特定的协议头,将数据化整为零:

      • 传输机制:在 HTTP 响应头中声明 Transfer-Encoding: chunked(分块传输编码)或 Content-Type: text/event-stream。这告诉客户端:服务器目前尚不清楚响应的总长度(Content-Length),但会将数据切分成一个个逻辑块(Chunks)依次下发。

      • 网络特征:客户端在接收到 200 OK 状态码后,底层 TCP 连接并不会立即关闭。借助现代浏览器的 Fetch API 及其 ReadableStream 特性,前端可以像接水管一样,实时读取并处理源源不断传来的数据块,直到服务器发送一个长度为 0 的终止信号。

      3.2 应用场景:从大文件到 AI 时代

      这种“边读边播”的特性,使其在以下场景中无可替代:

      • AI 大模型“打字机”效果:这是当前最火热的应用。ChatGPT、Claude 等模型生成的长文本,正是通过流式 HTTP 将响应数据实时推送到前端,显著降低了用户的首字感知延迟(TTFT)。

      • 大容量资源下发:如超大文件或视频流的段落化加载,避免了内存爆仓,提升了系统吞吐量。

      • SSE 的灵活替代方案:配合 fetch-event-source 等库,它能完美模拟 SSE 的长连接功能,同时规避了标准 SSE 在请求方式(仅限 GET)和自定义 Header 上的限制。

      3.3 隐藏的坑:代理与缓冲

      虽然流式传输在逻辑上很美好,但在工程落地时必须关注“链路通畅”问题:

      局限说明
      单向传输局限它本质上仍是 Server-to-Client 的单向流。如果业务需要客户端也实时回传数据,则需要考虑其他双向通信协议。
      代理服务这是最常见的坑。一些旧版 Nginx、防火墙或负载均衡器默认开启了强缓冲(Buffering)机制。它们会试图"积攒"足够多的流式数据再统一发给客户端。这对于实时 AI 对话是致命的,开发者必须确保代理层配置了 X-Accel-Buffering: no 等指令来禁用缓冲,确保数据的"直达性"。

      4. SSE (Server-Sent Events):规范化的单向推送协议

      如果说 流式 HTTP 是一种底层的“传输机制”,那么 SSE 则是基于此机制建立的一套标准化应用层协议。它专门为“服务器向客户端推送事件”而生,在逻辑上比纯粹的流式传输更具约束力,也更便于浏览器集成

      4.1 核心原理:严格的文本契约

      SSE 不允许像普通流那样随心所欲地传输字符,它要求响应头强制设定为 Content-Type: text/event-stream,且数据格式必须遵循一套严密的“报文规范”:

      • 结构化字段:每条消息由 id:(事件 ID)、event:(事件类型)、data:(业务数据)和 retry:(重连间隔)等字段组成。

      • 消息边界:必须以双换行符 \n\n 作为一条独立消息的终点。这种协议级的约定,使得客户端能够精准地拆分出每一条业务事件,而无需开发者手动处理流的切片逻辑。

      4.2 网络机制:原生浏览器的“自动驾驶”

      SSE 的一大优势在于其深度集成了浏览器原生的 EventSource API。这赋予了它许多开箱即用的高级特性:

      • 自动重连:当网络波动导致连接中断时,EventSource 会自动发起重连尝试。

      • 状态追踪:利用 Last-Event-ID 机制,客户端在重连时会自动携带最后一次收到的 ID,服务端据此可以实现数据的“断点续传”,确保消息不丢失。

      4.3 典型场景:轻量级的实时感知

      SSE 极其适合那些“高频下发、低频上报”的业务场景:

      场景说明
      金融/行情股票价格、加密货币的实时波动。
      状态监控系统资源占用大盘、CI/CD 构建进度条。
      社交提醒站内信通知、点赞互动的实时更新。

      4.4 工程避坑指南:不可忽视的约束

      尽管 SSE 足够轻巧,但在实际架构设计中,必须正视其局限性:

      局限说明
      文本编码限制SSE 仅支持 UTF-8 文本流。如果需要传输二进制文件(如实时生成的缩略图),必须先转码为 Base64,这会带来约 33% 的体积开销。
      浏览器"单行道"限制原生的 EventSource 仅支持 GET 请求。在需要传递复杂查询参数(如超长的 JSON 过滤器)时,这一限制显得非常局促。这也是为什么许多现代项目(如 AI 聊天应用)宁愿使用 Fetch 模拟 SSE 的原因
      连接数水位线在 HTTP/1.1 环境下,浏览器对同一域名的并发长连接限制通常只有 6 个。这意味着如果你在浏览器中多开了几个监控标签页,很可能会耗尽连接池,导致页面其他请求完全阻塞。(注:在 HTTP/2 及以上版本中,由于多路复用特性的存在,这一限制已基本消除)。

      5. WebSocket:全双工通信

      WebSocket 不同于 流式 HTTP 和 SSE 这种在传统 HTTP 框架下的“精雕细琢”,而是一次彻底的“范式革命”。它不仅仅是一个简单的 API,而是一个独立的、与 HTTP 平级的应用层协议。

      它是一种基于 TCP 协议的全双工通信协议,真正的全双工持久连接方案,通过一次 HTTP 握手完成协议升级后,客户端与服务器可双向、实时、低延迟地传输数据,连接全程保持开放。旨在打破“请求-响应”的束缚,建立起真正意义上的“零延迟”双向通道。

      5.1 核心原理

      WebSocket 的建立遵循一个标准化的协议升级流程:

      • 协议升级握手:连接初始化阶段采用标准 HTTP 请求。客户端在请求头中声明 Upgrade: websocketConnection: Upgrade,表明协议升级意图。

      • 连接状态转换:服务器确认支持 WebSocket 协议后,返回 101 Switching Protocols 状态码。至此,底层 TCP 连接完成协议切换,后续通信采用 WebSocket 帧格式进行数据传输,不再承载 HTTP 协议开销。

      5.2 网络机制

      在 WebSocket 连接建立后,通信双方会进入全双工对等传输状态:

      • 全双工数据传输:客户端与服务器可随时、独立地向对端发送数据,无需等待对方请求或确认。这种双向并发通信机制彻底摆脱了 HTTP 协议"请求-响应"的串行约束,实现低延迟的实时数据交换。

      • 轻量级帧结构:相较于 HTTP 协议数百字节的首部开销,WebSocket 数据帧首部极为紧凑,固定部分仅 2 字节,带掩码时最大 14 字节。对于高频、小数据包传输场景(如实时游戏状态同步、传感器数据采集),显著降低网络带宽占用与传输延迟。

      • 原生二进制支持:WebSocket 协议原生支持文本(UTF-8)与二进制数据帧,无需像 SSE 那样进行 Base64 编码转换。该特性使其在实时音视频流传输、二进制协议封装等多媒体场景中具有显著的性能优势。

      5.3 应用场景:高互动的终极方案

      凡是需要“毫秒级同步”的场景,WebSocket 都是不二之选:

      场景典型应用
      即时通讯微信网页版、飞书聊天
      协同办公Google Docs、Figma 的多人在同步编辑
      竞技游戏实时同步玩家坐标与指令的 MMO 或 MOBA 游戏
      金融博弈极速波动的量化交易终端

      5.4 工程落地的“重装”代价

      作为一种"有状态"的协议,WebSocket 在带来极致性能的同时,也给后端架构带来了沉重的复杂性:

      • 状态维护与内存开销
        不同于 HTTP 的"阅后即焚"模式,服务器必须为每一个 WebSocket 连接维持一个持久的 Session 状态。当并发量攀升至十万甚至百万级时,内存占用与长连接管理压力将呈几何级数增长,对服务器的资源调度能力提出严峻考验。

      • 分布式系统的挑战
        在水平扩容场景下,WebSocket 堪称负载均衡器的"噩梦"。由于连接具有状态属性,若用户 A 连接至机器 1,用户 B 连接至机器 2,二者间的通信便无法直接完成。此时后端必须引入 Redis Pub/Sub、消息队列(Message Queue)或专用网关等中间件,以实现跨节点的"消息对齐"与状态同步。

      • 原始协议的局限
        WebSocket 协议本身设计得极为精简,并未内置自动重连、心跳保活或消息确认等机制。为保障连接在生产环境中的鲁棒性,开发者必须在应用层自行实现 Ping/Pong 心跳检测、断线感知以及带退避策略的重连逻辑,这无疑增加了工程实现的复杂度。

      6. Webhooks:事件驱动的反向回调

      如果说 SSE 是服务器"主动推送给浏览器",那么 Webhooks 则是服务器"主动推送给服务端"——它是一种基于 HTTP 的事件触发机制,专为服务端向服务端单向推送而设计。

      6.1 核心原理:回调的自动化

      Webhooks 的工作模式非常清晰:

      • 事件注册:客户端(通常是第三方应用)预先在服务端注册一个回调 URL,并指定关注的事件类型(如"订单完成"、"用户注册"、"文件上传"等)。

      • 事件触发:当服务端发生指定事件时,它会主动向客户端注册的 URL 发送一个 HTTP POST 请求,将事件详情封装在请求体中。

      • 即时响应:客户端收到回调后,执行相应业务逻辑(如更新本地数据、发送通知等),并返回一个确认响应。

      整个过程完全基于标准 HTTP,无需维护持久连接,也无需客户端持续轮询。

      6.2 典型场景:跨系统的松耦合集成

      场景说明
      支付回调当用户在第三方支付平台(如 Stripe、支付宝)完成付款后,支付平台会向商户服务器发送 Webhook 回调,通知交易结果。
      版本控制系统GitHub、GitLab 等平台通过 Webhooks 在代码提交、PR 创建时通知外部 CI/CD 系统。
      电商订单同步订单状态变更、用户注册等事件触发后,同步至 ERP、CRM 等内部系统。
      消息推送集成将消息平台的事件(如用户发送消息)推送至自有的聊天机器人或客服系统。

      6.3 工程考量:可靠投递与安全防护

      虽然 Webhooks 概念简单,但在生产环境中需要关注几个关键问题:

      考量点说明
      可靠投递保障HTTP 请求可能因网络问题投递失败,因此主流平台通常支持失败重试机制,并要求回调端点返回 2xx 状态码才视为成功。
      幂等性设计由于重试机制的存在,同一个事件可能被多次投递。客户端应当具备幂等处理能力,避免重复业务操作。
      安全验证为了防止恶意伪造回调,服务端通常会在请求中加入签名(如 HMAC 签名),客户端通过验证签名来确认请求的真实性。

      6.4 与 SSE 的本质区别

      维度WebhooksSSE
      推送对象服务端 → 服务端服务端 → 浏览器
      连接方向由接收方预先暴露 URL由发送方建立并维持连接
      适用场景跨系统事件同步浏览器端实时更新
      协议基础标准 HTTP POST长连接 + EventSource API

      7. 关于 HTTP 轮询的讨论

      HTTP 轮询是一种最朴素的实时通信方案,是实现实时性的基础方案,核心逻辑是客户端定时向服务器发起请求,主动拉取最新数据。

      不少人在学习了 流式 HTTP、SSE 和 WebSocket 后,会产生一种“技术洁癖”,觉得 HTTP 轮询是上古时代的落后技术,应当被彻底淘汰。但现实是,在当前很多顶级的 AI 生图(如 Midjourney 类的第三方集成应用、部分 Stable Diffusion 商业平台)甚至部分长视频生成应用中,HTTP 轮询不仅没有消失,反而是架构师经过深思熟虑后的首选方案。

      7.1 任务特性的本质差异:流式输出 vs 异步大任务

      AI 应用的交互模式决定了通信协议的选型:

      应用类型场景特征解释说明
      文本大模型(如 ChatGPT)流式持续输出模型在极短时间内(首个 Token 约 200ms 即可生成)就开始返回数据,随后持续"吐字"。若采用传统同步 HTTP,用户将面对长达数秒的白屏等待,体验极差。SSE/流式 HTTP 正是为此类场景量身打造。
      AI 生图/生视频重计算异步任务一张高质量图片的生成可能需要 GPU 满载运算 10~30 秒,甚至在高峰期需要排队数分钟。任务执行期间,除了偶尔的进度更新(10%、50%),并没有持续的数据流可供传输。让客户端和网关之间维持一条长达数十秒的"闲置长连接",仅用于等待最终一个图片 URL 的返回,在系统设计上是一笔不小的开销。

      7.2 基础设施的残酷现实:连接池枯竭与网关超时

      如果 AI 生图使用 WebSocket 或保持长达 30 秒的 HTTP 连接,会遇到严峻的基础设施挑战:

      挑战说明
      网关/负载均衡的超时限制大多数云厂商的负载均衡器(如 AWS ALB、Nginx 默认配置)和 CDN 对 HTTP 连接都有严格超时限制(通常为 30s 至 60s)。当 AI 任务耗时过长时,网关会主动切断连接并返回 504 Gateway Timeout。
      并发连接数瓶颈服务器的并发连接池是有限的。假设 1 万名用户同时排队等图片:使用 WebSocket 需要维持 1 万个长连接;而使用轮询,每位用户每 3 秒发起一个极轻量的 GET 请求,查询完毕立即释放连接。无状态的短连接模式能让服务器吞吐量提升数个量级。

      7.3 后端架构的天然要求:解耦与消息队列

      现代高并发 AI 生图平台的后端架构通常是彻底解耦的:

      1. 提交任务 (Client):客户端 POST 请求 /api/generate

      2. 下发队列 (API Server):API 服务器将任务投入 Kafka/RabbitMQ 队列中,生成唯一 task_id 并立即返回给客户端(耗时约 50ms)。

      3. 异步消费 (GPU Worker):后端 GPU 节点从队列中取出任务,执行计算。生成完毕后,将图片上传至 OSS/S3 并将结果写入数据库。

      4. 获取结果 (Client):客户端持有 task_id,每隔数秒轮询一次 /api/task/{task_id} 查询任务状态。

      在这个经典的生产者-消费者模型中,处理 HTTP 请求的 Web 服务器与真正执行计算的 GPU 服务器在物理上彼此隔离。若强行使用 WebSocket 或 SSE 将二者串联,不仅违背了解耦原则,还会使 Web 服务器与 GPU 节点间的状态同步变得极为复杂。

      7.4 移动端弱网环境下的"绝对鲁棒性"

      试想这样一个场景:用户在地铁中使用手机生图,刚提交任务便遭遇了 5 秒的网络中断。

      • 使用 WebSocket:连接断开后,重连时如何恢复先前的"会话状态"?服务器如何识别并继续向重连后的客户端推送结果?这需要一套复杂的重传与会话恢复机制。

      • 使用轮询 (Polling):则极为简洁。客户端持有 task_id。网络恢复后,继续发送 GET /api/task/{task_id} 即可获取结果。无状态特性带来了卓越的抗干扰能力。

      7.5 小结

      综上所述,轮询凭借其无状态、低连接开销、高吞吐量的特性,成为 AI 生图场景下更具性价比的通信方案

      当然,如果决定使用轮询,为了兼顾体验和服务器压力,业界通常会采用退避轮询策略——即随着任务等待时间延长,逐步降低查询频率。例如前 30 秒每 2 秒查询一次,30 秒后改为每 5 秒查询一次,到后期甚至可以降至每 10 秒一次。这种策略能在保证及时获取结果的同时,有效减少不必要的请求开销。

      8. 实践选型指南:不买最贵的,只选最对的

      在实际应用中,脱离业务场景谈协议与通信方案的优劣是毫无意义的。WebSocket 虽强,但并非银弹;标准 HTTP 虽“老”,但在大规模分布式系统中依然是最稳健的选择。

      8.1 决策矩阵:AI 与实时业务场景选型

      业务场景任务耗时特征推荐通信协议决策依据与变通方案
      AI 文本对话 (LLM)快速响应,持续文本流 (几秒~几十秒)流式 HTTP (Fetch / SSE)需提供“打字机”反馈以维持用户注意力。相比 WS,HTTP 更易穿透防火墙与网关。
      AI 实时语音/视觉助手极低延迟,双向高频互动 (<500ms)WebSocket / WebRTC必须消除 HTTP 握手与头部延迟,实现真正的全双工流式交互。
      AI 快速生图 (SDXL Turbo)耗时极短(<3s),无排队压力标准 HTTP (Request-Response)简单的挂起等待即可。无需引入长连接复杂度,保持架构简洁。
      高精生图/视频/长文生成耗时长且需排队(10s ~ 数分钟)异步提交 + HTTP 轮询保护网关的核心手段。解耦 GPU 计算节点与 Web 节点,客户端持 TaskID 定时查询状态。
      跨系统事件同步事件驱动,无固定耗时Webhooks适用于服务端间的异步事件通知(如支付回调、订单同步、Git 钩子触发 CI/CD)。接收方需预先暴露回调 URL,并确保幂等处理与签名验证。

      8.2 深度决策逻辑:工程选型的五条金律

      1、高频双向:WebSocket 的主场

      核心逻辑:HTTP 及其衍生品在双向交互下,重复的头部开销会吞噬大量带宽,且无法实现真正的全双工并发。

      若业务需要客户端与服务端互发高频消息(如多人竞技游戏、协作编辑、实时双向聊天),WebSocket 是唯一选择

      2、单向推送:SSE 的轻量优势

      若业务场景仅需服务端向客户端单向高频推送(如股票行情大盘、服务器实时日志、监控预警):

      首选方案是 SSE。它完全复用现有的 HTTP 基础设施(负载均衡、WAF、鉴权逻辑),无需额外配置 WebSocket 网关。同时,其原生的断线重连机制极大降低了前端的开发心智负担。

      3、流式响应:Streamable HTTP 的主场,AI 时代的主流选择

      这是目前 LLM 文本对话中最主流的"事实标准"

      痛点:原生 SSE 受限于浏览器实现,通常只能发起 GET 请求。但在 AI 场景下,我们需要发送庞大的 system_prompt 或上下文历史(Context),GET 的 URL 长度限制成为了瓶颈。

      变通方案使用 Fetch API 结合 POST 请求,通过 ReadableStream 接收流式响应。既能突破 GET 的长度限制,又避免了 WebSocket 在维持长连接、处理心跳保活方面的额外资源损耗。这正是 fetch-event-source 这类库在 AI 社区盛行的底层逻辑。

      4、异步任务:轮询的主场

      对于 AI 生图、生视频等耗时较长(10s ~ 数分钟)的重计算任务,其特点是计算期间无持续数据流,仅在完成后返回结果。

      此时若强行使用 WebSocket 或 SSE 维持长连接,不仅会遭遇网关超时限制(通常 30s~60s),还会造成并发连接数瓶颈。异步提交 + 轮询查询是更合理的架构:客户端提交任务后获得 TaskID,定期轮询查询状态。这种方式解耦了 Web 节点与 GPU 节点,无状态的短连接模式让服务器能够承载更高的吞吐量。

      5、跨系统回调:Webhooks 的主场

      若业务涉及跨服务的事件通知(如支付平台回调、订单状态变更通知、Git 仓库事件触发 CI/CD),且接收方是服务端而非浏览器:

      首选方案是 Webhooks。它完全基于标准 HTTP POST 请求,无需维护持久连接,由接收方预先暴露回调 URL 即可实现事件驱动推送。这种模式天然适合服务间的松耦合集成,但需注意幂等性处理与签名验证以确保安全。

      9. 结语

      回望这场从 HTTP 到 WebSocket 的技术演进,我们或许能提炼出一个更普适的架构哲学:没有"最好"的技术,只有"最合适"的技术

      技术的演进从来不是"长江后浪推前浪"的简单替代,而是一种"分工细化"的自然结果。传统 HTTP 依然是 Web 的基石,流式 HTTP 让它焕发新生;SSE 在单向推送场景轻量而优雅;WebSocket 为真正的实时双向交互打开了大门;轮询在 AI 时代的大模型洪流中,依然默默支撑着无数生图、生视频应用的正常运行;而 Webhooks 则在跨系统的服务端间编织出一张事件驱动的网络。

      真正成熟的架构师,不会执着于"最新"或"最复杂"的方案,而是深入理解每种技术的边界与代价,在业务场景的约束下做出最优雅的取舍。毕竟,最好的架构不是用技术堆砌出来的,而是让技术各归其位的顺势而为

      + + + + \ No newline at end of file diff --git "a/01.\345\205\250\346\240\210/60.\347\275\221\347\273\234\344\270\216\351\200\232\344\277\241/02.\346\265\201\345\274\217 HTTP \344\270\216 SSE \345\215\217\350\256\256\357\274\232\344\273\216\346\246\202\345\277\265\350\276\250\346\236\220\345\210\260\347\224\237\344\272\247\345\256\236\350\267\265.html" b/fullstack/networking-sse-practice.html similarity index 88% rename from "01.\345\205\250\346\240\210/60.\347\275\221\347\273\234\344\270\216\351\200\232\344\277\241/02.\346\265\201\345\274\217 HTTP \344\270\216 SSE \345\215\217\350\256\256\357\274\232\344\273\216\346\246\202\345\277\265\350\276\250\346\236\220\345\210\260\347\224\237\344\272\247\345\256\236\350\267\265.html" rename to fullstack/networking-sse-practice.html index 8abf6581..06a3cb18 100644 --- "a/01.\345\205\250\346\240\210/60.\347\275\221\347\273\234\344\270\216\351\200\232\344\277\241/02.\346\265\201\345\274\217 HTTP \344\270\216 SSE \345\215\217\350\256\256\357\274\232\344\273\216\346\246\202\345\277\265\350\276\250\346\236\220\345\210\260\347\224\237\344\272\247\345\256\236\350\267\265.html" +++ b/fullstack/networking-sse-practice.html @@ -6,13 +6,13 @@ 流式 HTTP 与 SSE 协议:从概念辨析到生产实践 | Insight Stack - + - - - - - + + + + + @@ -31,7 +31,7 @@ - +
      Skip to content

      流式 HTTP 与 SSE 协议:从概念辨析到生产实践

      摘要总结: 针对开发者容易混淆流式 HTTP 与 SSE 协议的问题,从概念层次出发厘清二者本质区别与协作关系,指出流式 HTTP 是底层传输机制而 SSE 是应用层数据格式约定。文章依次介绍原生 EventSource API、fetch + ReadableStream 进阶方案、@microsoft/fetch-event-source 工业级实现等三种客户端方案,并以 NestJS 为例展示服务端 SSE 响应的标准实现与 POST 请求扩展,最后涵盖指数退避重试、事件分类处理、连接状态追踪、资源清理等生产实践要点,为 AI 时代的流式响应场景提供完整技术方案。

      1. 引言

      Web 通信协议全景:从 HTTP 到 WebSocket 的技术选型指南中,我们对比分析了多种通信技术。在本文我们将重点探讨 SSE(Server-Sent Events)流式 HTTP(HTTP Streaming) 的实践。

      1.1 概念澄清:两种技术,两个层次

      很多开发者容易将 SSE 与流式 HTTP 混为一谈,实际上它们处于不同的技术层次:

      维度流式 HTTPSSE
      定位底层传输机制应用层协议
      核心原理HTTP Chunked Transfer Encoding,数据分块连续传输基于 HTTP 的事件流协议,定义了标准化的数据格式
      浏览器原生支持无,需自行解析数据流有,EventSource API
      协议规范无标准格式约定W3C 标准(text/event-stream

      简而言之,流式 HTTP 是一种“传输手段”,而 SSE 是一种“数据格式约定”流式 HTTP 关注的是如何把数据“边发边传”,而 SSE 关注的是如何让数据“按照固定格式组织”,便于客户端解析处理

      1.2 关联与协作

      尽管处于不同层次,但二者完全可以协同工作:

      • SSE 必须基于流式 HTTP:SSE 的标准格式需要通过 HTTP 流式传输来实现,因此 SSE 协议的数据流底层必然依赖流式 HTTP
      • 流式 HTTP 不必局限于 SSE:纯流式 HTTP 可以自定义数据格式(如 JSON Lines、NDJSON),不一定要遵循 SSE 的 event:id:data: 等字段约定

      正是由于这种关系,我们可以利用 fetch + ReadableStream 突破 SSE 的一些局限

      1. 请求方式受限:原生 SSE 仅支持 GET 请求,当需要携带较大 body 数据(如文件上传上下文、复杂查询参数)时会受到限制,而 fetch API 不受此约束。
      2. 身份验证不便:原生 SSE 无法灵活地在请求头中添加 Authorization: Bearer <token> 等认证信息,fetch API 则可以像调用普通接口一样自定义 Header。

      因此,基于流式 HTTP,采用 fetch + ReadableStream 的方案,不仅保留了 fetch 的全部能力(POST 方法、自定义 Headers、超时控制等),同时具备了流式传输的实时性,并且在数据格式层面依然遵循 SSE 协议,保持良好的可解析性和通用性。相比原生 SSE,使用 Fetch API + ReadableStream 能突破 GET 请求限制,可携带任意大小的 body 数据,同时支持灵活的身份验证方式;相比 WebSocket,则避免了维护长连接和心跳保活的额外资源损耗。

      这种“取两家之长”的方案,正是 @microsoft/fetch-event-source 这类库在 AI 社区盛行的底层逻辑:既能像调用普通接口一样编写业务逻辑,又能享受流式传输的实时性,数据格式依然遵循 SSE 协议,客户端解析毫无额外成本

      特性标准 EventSource (SSE)Fetch + Stream
      HTTP 方法仅限 GET支持 POST、PUT 等所有方法
      自定义 Header不支持(无法传 Token 等)完全支持
      **请求体 **(Body)不支持支持发送 JSON Payload
      重连机制浏览器内置,难以精细控制插件实现,支持高度自定义重连策略
      跨域 (CORS)比较死板,需特定配置遵循标准的 Fetch CORS 规则
      底层 API浏览器原生 EventSource 对象基于 fetch 和 ReadableStream

      1.3 SSE 协议数据格式

      SSE 协议对数据流格式有明确规定,服务器返回的响应头和数据体需遵循以下规范:

      markdown
      Content-Type: text/event-stream
      +  

      流式 HTTP 与 SSE 协议:从概念辨析到生产实践

      摘要总结: 针对开发者容易混淆流式 HTTP 与 SSE 协议的问题,从概念层次出发厘清二者本质区别与协作关系,指出流式 HTTP 是底层传输机制而 SSE 是应用层数据格式约定。文章依次介绍原生 EventSource API、fetch + ReadableStream 进阶方案、@microsoft/fetch-event-source 工业级实现等三种客户端方案,并以 NestJS 为例展示服务端 SSE 响应的标准实现与 POST 请求扩展,最后涵盖指数退避重试、事件分类处理、连接状态追踪、资源清理等生产实践要点,为 AI 时代的流式响应场景提供完整技术方案。

      1. 引言

      Web 通信协议全景:从 HTTP 到 WebSocket 的技术选型指南中,我们对比分析了多种通信技术。在本文我们将重点探讨 SSE(Server-Sent Events)流式 HTTP(HTTP Streaming) 的实践。

      1.1 概念澄清:两种技术,两个层次

      很多开发者容易将 SSE 与流式 HTTP 混为一谈,实际上它们处于不同的技术层次:

      维度流式 HTTPSSE
      定位底层传输机制应用层协议
      核心原理HTTP Chunked Transfer Encoding,数据分块连续传输基于 HTTP 的事件流协议,定义了标准化的数据格式
      浏览器原生支持无,需自行解析数据流有,EventSource API
      协议规范无标准格式约定W3C 标准(text/event-stream

      简而言之,流式 HTTP 是一种“传输手段”,而 SSE 是一种“数据格式约定”流式 HTTP 关注的是如何把数据“边发边传”,而 SSE 关注的是如何让数据“按照固定格式组织”,便于客户端解析处理

      1.2 关联与协作

      尽管处于不同层次,但二者完全可以协同工作:

      • SSE 必须基于流式 HTTP:SSE 的标准格式需要通过 HTTP 流式传输来实现,因此 SSE 协议的数据流底层必然依赖流式 HTTP
      • 流式 HTTP 不必局限于 SSE:纯流式 HTTP 可以自定义数据格式(如 JSON Lines、NDJSON),不一定要遵循 SSE 的 event:id:data: 等字段约定

      正是由于这种关系,我们可以利用 fetch + ReadableStream 突破 SSE 的一些局限

      1. 请求方式受限:原生 SSE 仅支持 GET 请求,当需要携带较大 body 数据(如文件上传上下文、复杂查询参数)时会受到限制,而 fetch API 不受此约束。
      2. 身份验证不便:原生 SSE 无法灵活地在请求头中添加 Authorization: Bearer <token> 等认证信息,fetch API 则可以像调用普通接口一样自定义 Header。

      因此,基于流式 HTTP,采用 fetch + ReadableStream 的方案,不仅保留了 fetch 的全部能力(POST 方法、自定义 Headers、超时控制等),同时具备了流式传输的实时性,并且在数据格式层面依然遵循 SSE 协议,保持良好的可解析性和通用性。相比原生 SSE,使用 Fetch API + ReadableStream 能突破 GET 请求限制,可携带任意大小的 body 数据,同时支持灵活的身份验证方式;相比 WebSocket,则避免了维护长连接和心跳保活的额外资源损耗。

      这种“取两家之长”的方案,正是 @microsoft/fetch-event-source 这类库在 AI 社区盛行的底层逻辑:既能像调用普通接口一样编写业务逻辑,又能享受流式传输的实时性,数据格式依然遵循 SSE 协议,客户端解析毫无额外成本

      特性标准 EventSource (SSE)Fetch + Stream
      HTTP 方法仅限 GET支持 POST、PUT 等所有方法
      自定义 Header不支持(无法传 Token 等)完全支持
      **请求体 **(Body)不支持支持发送 JSON Payload
      重连机制浏览器内置,难以精细控制插件实现,支持高度自定义重连策略
      跨域 (CORS)比较死板,需特定配置遵循标准的 Fetch CORS 规则
      底层 API浏览器原生 EventSource 对象基于 fetch 和 ReadableStream

      1.3 SSE 协议数据格式

      SSE 协议对数据流格式有明确规定,服务器返回的响应头和数据体需遵循以下规范:

      markdown
      Content-Type: text/event-stream
       Cache-Control: no-cache
       Connection: keep-alive
       
      @@ -740,7 +740,7 @@
           }
           return count;
         }
      -}

      6. 结语

      回顾全文,我们从概念辨析出发,历经客户端到服务端的完整技术链条:

      • 概念层:厘清了流式 HTTP(传输机制)与 SSE(数据格式)的本质区别与协作关系
      • 客户端层:从原生 EventSource API,到 fetch + ReadableStream 的进阶方案,再到 @microsoft/fetch-event-source 的工业级实现
      • 服务端层:以 NestJS 为例,展示了 SSE 响应的标准实现与 POST 请求扩展

      或许在阅读之前,你对 SSE 的认知还停留在"浏览器原生的 EventSource"。但现在你应该已经掌握了一套完整的解决方案:既能像调用普通接口一样携带请求体、自定义 Header,又能享受流式传输的实时性;数据格式依然遵循 SSE 协议,客户端解析零成本。

      这套方案并非银弹——它本质上仍是单向通信。如果你的业务需要双向实时交互,WebSocket 仍是更合适的选择。但在 AI 时代,大量"请求-流式响应"的场景(如 LLM 对话、任务进度推送、实时日志等),fetch + SSE 的组合已经足够强大且优雅。下次遇到需要实时数据推送的场景时,不妨先问自己:真的需要 WebSocket 吗?

      +}

      6. 结语

      回顾全文,我们从概念辨析出发,历经客户端到服务端的完整技术链条:

      • 概念层:厘清了流式 HTTP(传输机制)与 SSE(数据格式)的本质区别与协作关系
      • 客户端层:从原生 EventSource API,到 fetch + ReadableStream 的进阶方案,再到 @microsoft/fetch-event-source 的工业级实现
      • 服务端层:以 NestJS 为例,展示了 SSE 响应的标准实现与 POST 请求扩展

      或许在阅读之前,你对 SSE 的认知还停留在"浏览器原生的 EventSource"。但现在你应该已经掌握了一套完整的解决方案:既能像调用普通接口一样携带请求体、自定义 Header,又能享受流式传输的实时性;数据格式依然遵循 SSE 协议,客户端解析零成本。

      这套方案并非银弹——它本质上仍是单向通信。如果你的业务需要双向实时交互,WebSocket 仍是更合适的选择。但在 AI 时代,大量"请求-流式响应"的场景(如 LLM 对话、任务进度推送、实时日志等),fetch + SSE 的组合已经足够强大且优雅。下次遇到需要实时数据推送的场景时,不妨先问自己:真的需要 WebSocket 吗?

      diff --git "a/01.\345\205\250\346\240\210/80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273/20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227/6.\350\247\243\346\236\220 NodeJS \344\270\255\347\232\204\346\250\241\345\235\227\345\214\226.html" b/fullstack/nodejs-module-programming-summary.html similarity index 64% rename from "01.\345\205\250\346\240\210/80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273/20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227/6.\350\247\243\346\236\220 NodeJS \344\270\255\347\232\204\346\250\241\345\235\227\345\214\226.html" rename to fullstack/nodejs-module-programming-summary.html index f45f2693..ce6e7b1f 100644 --- "a/01.\345\205\250\346\240\210/80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273/20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227/6.\350\247\243\346\236\220 NodeJS \344\270\255\347\232\204\346\250\241\345\235\227\345\214\226.html" +++ b/fullstack/nodejs-module-programming-summary.html @@ -6,12 +6,12 @@ Node.js 模块化编程梳理与总结 | Insight Stack - + - - - - + + + + @@ -30,7 +30,7 @@ - +
      Skip to content

      Node.js 模块化编程梳理与总结

      如果说浏览器端的模块化是为了"按需加载",那么 Node.js 的模块化则是为了"代码组织"。作为将 JavaScript 带入服务器端的先驱,Node.js 经历了从 CommonJS (CJS) 独霸天下到 ES Modules (ESM) 全面接入的范式转移。

      在服务器端,模块化不仅仅是为了拆分代码,更是为了构建清晰的项目结构、管理依赖关系,以及实现代码的复用与维护。

      1. CommonJS 与 ES Modules 双模共存

      在现代 Node.js 开发中,我们经常面临两种规范交织的情况。这不仅是文件后缀的改变,更是同步与异步加载逻辑的博弈。

      共存策略:

      1. 后缀决定论.mjs 始终被视为 ESM,.cjs 始终被视为 CJS。
      2. 包定义导向:在 package.json 中设置 "type": "module",则目录下所有 .js 均视为 ESM,反之默认为 CJS。
      3. 互操作性(Interop)
        • ESM 引用 CJS:直接 import 即可,Node 会将 module.exports 包装为默认导出。
        • CJS 引用 ESM:由于 ESM 是异步加载的,CJS 无法使用 require,必须使用 动态 import:const module = await import('./es-module.mjs')

      代码示例

      javascript
      // package.json
      +  

      Node.js 模块化编程梳理与总结

      如果说浏览器端的模块化是为了"按需加载",那么 Node.js 的模块化则是为了"代码组织"。作为将 JavaScript 带入服务器端的先驱,Node.js 经历了从 CommonJS (CJS) 独霸天下到 ES Modules (ESM) 全面接入的范式转移。

      在服务器端,模块化不仅仅是为了拆分代码,更是为了构建清晰的项目结构、管理依赖关系,以及实现代码的复用与维护。

      1. CommonJS 与 ES Modules 双模共存

      在现代 Node.js 开发中,我们经常面临两种规范交织的情况。这不仅是文件后缀的改变,更是同步与异步加载逻辑的博弈。

      共存策略:

      1. 后缀决定论.mjs 始终被视为 ESM,.cjs 始终被视为 CJS。
      2. 包定义导向:在 package.json 中设置 "type": "module",则目录下所有 .js 均视为 ESM,反之默认为 CJS。
      3. 互操作性(Interop)
        • ESM 引用 CJS:直接 import 即可,Node 会将 module.exports 包装为默认导出。
        • CJS 引用 ESM:由于 ESM 是异步加载的,CJS 无法使用 require,必须使用 动态 import:const module = await import('./es-module.mjs')

      代码示例

      javascript
      // package.json
       {
         "type": "module"
       }
      @@ -193,7 +193,7 @@
       }

      Monorepo 选型: 虽然 Lerna 曾是标配,但在现代工作流中,pnpm workspaces 凭借其极速的硬链接机制和简洁的配置,已成为 AI 时代开发者(AI-Augmented Builders)的首选。

      yaml
      # pnpm-workspace.yaml
       packages:
         - 'packages/*'
      -  - 'apps/*'

      通过 Monorepo,你可以轻松地在 apps/web 中引用 packages/shared-utils,而无需频繁发布 npm 包。

      4. 模块化架构:分层设计与关注点分离

      随着后端逻辑变厚,单纯的模块拆分已不够,我们需要引入分层架构(Layered Architecture)。

      • API / Controller 层:负责解析请求、参数校验,不触及核心业务。
      • Service 层:系统的灵魂。存放纯粹的业务逻辑,可被多个接口复用。
      • Repository / DAO 层:负责与数据库或外部 API 通信,将数据操作抽象化。
      • Constants, / Types 层:定义全域共用的常量与 TypeScript 契约。

      这种设计的精髓在于:哪怕你从 MySQL 换到了 MongoDB,理论上你只需要修改 Repository 层,而 Service 层的业务代码纹丝不动。

      5. 结语

      Node.js 的模块化实践,是一场从“能跑就行”到“优雅治理”的进化。我们从 CJS 与 ESM 的混战中学会了兼容的艺术,从加载机制中理解了性能的边界,又从 Monorepo 和分层架构中习得了掌控复杂系统的能力。

      模块化不应是开发的负担,而应是你的“工程外骨骼”。一个设计良好的 Node.js 架构,应当像是一组排列整齐、接口严密的精密齿轮——每一个模块都深藏功与名,只通过最精简的接口与外界对话。

      在编写下一行 import 之前,不妨停顿一秒:这个模块的边界清晰吗?它是否承担了不该属于它的因果?当你开始思考这些问题时,你已经从一个“写 Node.js 的人”,进化成为了一个真正的“后端架构守望者”。

      + - 'apps/*'

      通过 Monorepo,你可以轻松地在 apps/web 中引用 packages/shared-utils,而无需频繁发布 npm 包。

      4. 模块化架构:分层设计与关注点分离

      随着后端逻辑变厚,单纯的模块拆分已不够,我们需要引入分层架构(Layered Architecture)。

      • API / Controller 层:负责解析请求、参数校验,不触及核心业务。
      • Service 层:系统的灵魂。存放纯粹的业务逻辑,可被多个接口复用。
      • Repository / DAO 层:负责与数据库或外部 API 通信,将数据操作抽象化。
      • Constants, / Types 层:定义全域共用的常量与 TypeScript 契约。

      这种设计的精髓在于:哪怕你从 MySQL 换到了 MongoDB,理论上你只需要修改 Repository 层,而 Service 层的业务代码纹丝不动。

      5. 结语

      Node.js 的模块化实践,是一场从“能跑就行”到“优雅治理”的进化。我们从 CJS 与 ESM 的混战中学会了兼容的艺术,从加载机制中理解了性能的边界,又从 Monorepo 和分层架构中习得了掌控复杂系统的能力。

      模块化不应是开发的负担,而应是你的“工程外骨骼”。一个设计良好的 Node.js 架构,应当像是一组排列整齐、接口严密的精密齿轮——每一个模块都深藏功与名,只通过最精简的接口与外界对话。

      在编写下一行 import 之前,不妨停顿一秒:这个模块的边界清晰吗?它是否承担了不该属于它的因果?当你开始思考这些问题时,你已经从一个“写 Node.js 的人”,进化成为了一个真正的“后端架构守望者”。

      diff --git "a/01.\345\205\250\346\240\210/80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273/00.\345\245\245\345\215\241\345\247\206\345\211\203\345\210\200\345\216\237\345\210\231\357\274\232\344\273\216\347\220\206\350\256\272\345\210\260\347\274\226\347\250\213\350\256\276\350\256\241\347\232\204\345\256\236\350\267\265\346\214\207\345\215\227.html" b/fullstack/occams-razor-software-design.html similarity index 72% rename from "01.\345\205\250\346\240\210/80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273/00.\345\245\245\345\215\241\345\247\206\345\211\203\345\210\200\345\216\237\345\210\231\357\274\232\344\273\216\347\220\206\350\256\272\345\210\260\347\274\226\347\250\213\350\256\276\350\256\241\347\232\204\345\256\236\350\267\265\346\214\207\345\215\227.html" rename to fullstack/occams-razor-software-design.html index 052fd286..81404fd6 100644 --- "a/01.\345\205\250\346\240\210/80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273/00.\345\245\245\345\215\241\345\247\206\345\211\203\345\210\200\345\216\237\345\210\231\357\274\232\344\273\216\347\220\206\350\256\272\345\210\260\347\274\226\347\250\213\350\256\276\350\256\241\347\232\204\345\256\236\350\267\265\346\214\207\345\215\227.html" +++ b/fullstack/occams-razor-software-design.html @@ -6,13 +6,13 @@ 奥卡姆剃刀原则:从理论到编程设计的实践指南 | Insight Stack - + - - - - - + + + + + @@ -31,7 +31,7 @@ - +
      Skip to content

      奥卡姆剃刀原则:从理论到编程设计的实践指南

      摘要总结:奥卡姆剃刀原则由 14 世纪逻辑学家威廉·奥卡姆提出,其核心为"如无必要,勿增实体"——在多个同等有效的方案中,选择假设最少、最简洁的那个。该原则并非否定复杂性,而是避免无意义的过度设计。文章从编程与设计实践出发,依次探讨了需求实现、代码实现、架构设计、依赖管理、接口设计、调试优化六大场景的反例与正例,并明确指出三个关键边界:不可牺牲可维护性、可扩展性、安全性换取简洁。

      1. 奥卡姆剃刀原则的核心内涵

      "奥卡姆剃刀" 是哲学与科学研究中经典的思维工具,其核心思想可概括为"如无必要,勿增实体"。这一原则由 14 世纪逻辑学家、圣方济各会修士威廉·奥卡姆(William of Ockham)提出,本质是在多个能同等解释现象的理论中,选择假设最少、最简洁的那个——并非否定复杂的可能性,而是优先用简单方案解决问题,避免无意义的"过度设计"。

      要正确应用奥卡姆剃刀,需先理解其三个关键前提:

      关键前提说明
      "同等有效"是前提仅当多个方案能实现相同的功能、满足相同的需求时,才用"简洁性"作为筛选标准;若简单方案无法覆盖需求(如安全性、可扩展性),则必须引入复杂设计,不可为了"简"而"简"。
      "实体"指"不必要的假设/组件"例如解释"手机没电","电池耗尽"比"电池故障+系统休眠+充电器接触不良"更简洁,后者多了两个无证据的"实体",应优先排除。
      "简洁"≠"简陋"简洁是"去除冗余",而非"省略必要环节"。比如设计登录功能,"账号+密码"是简洁,"仅靠手机号(无验证)"是简陋,后者牺牲了安全性,不符合原则。

      2. 编程与设计中应用奥卡姆剃刀的核心场景

      在编程(代码实现)和设计(架构、接口、模块)中,"奥卡姆剃刀"的本质是减少"无价值的复杂性"——包括冗余代码、过度抽象、多余依赖、未使用的功能等。以下从六个核心场景展开,结合"反例"与"正例"说明实践方法:

      2.1 场景1:需求实现,拒绝"提前设计未来功能"

      开发中最常见的误区是"过度预判需求":为了"可能用得上"的功能,提前加入复杂逻辑,导致代码臃肿、维护成本升高。奥卡姆剃刀的要求是:只实现"当前明确需要"的功能,未来需求留待未来迭代

      反例(过度设计)

      开发一个"用户个人资料页"时,需求仅要求"展示姓名、手机号、邮箱",但开发者预判"未来可能要加地址、生日、社交账号",于是:

      java
      // 提前定义了大量未使用的字段和方法
      +  

      奥卡姆剃刀原则:从理论到编程设计的实践指南

      摘要总结:奥卡姆剃刀原则由 14 世纪逻辑学家威廉·奥卡姆提出,其核心为"如无必要,勿增实体"——在多个同等有效的方案中,选择假设最少、最简洁的那个。该原则并非否定复杂性,而是避免无意义的过度设计。文章从编程与设计实践出发,依次探讨了需求实现、代码实现、架构设计、依赖管理、接口设计、调试优化六大场景的反例与正例,并明确指出三个关键边界:不可牺牲可维护性、可扩展性、安全性换取简洁。

      1. 奥卡姆剃刀原则的核心内涵

      "奥卡姆剃刀" 是哲学与科学研究中经典的思维工具,其核心思想可概括为"如无必要,勿增实体"。这一原则由 14 世纪逻辑学家、圣方济各会修士威廉·奥卡姆(William of Ockham)提出,本质是在多个能同等解释现象的理论中,选择假设最少、最简洁的那个——并非否定复杂的可能性,而是优先用简单方案解决问题,避免无意义的"过度设计"。

      要正确应用奥卡姆剃刀,需先理解其三个关键前提:

      关键前提说明
      "同等有效"是前提仅当多个方案能实现相同的功能、满足相同的需求时,才用"简洁性"作为筛选标准;若简单方案无法覆盖需求(如安全性、可扩展性),则必须引入复杂设计,不可为了"简"而"简"。
      "实体"指"不必要的假设/组件"例如解释"手机没电","电池耗尽"比"电池故障+系统休眠+充电器接触不良"更简洁,后者多了两个无证据的"实体",应优先排除。
      "简洁"≠"简陋"简洁是"去除冗余",而非"省略必要环节"。比如设计登录功能,"账号+密码"是简洁,"仅靠手机号(无验证)"是简陋,后者牺牲了安全性,不符合原则。

      2. 编程与设计中应用奥卡姆剃刀的核心场景

      在编程(代码实现)和设计(架构、接口、模块)中,"奥卡姆剃刀"的本质是减少"无价值的复杂性"——包括冗余代码、过度抽象、多余依赖、未使用的功能等。以下从六个核心场景展开,结合"反例"与"正例"说明实践方法:

      2.1 场景1:需求实现,拒绝"提前设计未来功能"

      开发中最常见的误区是"过度预判需求":为了"可能用得上"的功能,提前加入复杂逻辑,导致代码臃肿、维护成本升高。奥卡姆剃刀的要求是:只实现"当前明确需要"的功能,未来需求留待未来迭代

      反例(过度设计)

      开发一个"用户个人资料页"时,需求仅要求"展示姓名、手机号、邮箱",但开发者预判"未来可能要加地址、生日、社交账号",于是:

      java
      // 提前定义了大量未使用的字段和方法
       public class UserProfile {
           private String name;       // 必用
           private String phone;      // 必用
      @@ -242,7 +242,7 @@
         "data": {
           "userId": "123456" // 仅暴露调用者需使用的用户ID
         }
      -}

      2.6 场景6:调试与优化,优先排查"简单原因"

      定位 bug 或性能问题时,开发者易陷入"复杂猜想"(如怀疑框架漏洞、底层逻辑),忽略"简单原因"(如参数传错、配置错误)。奥卡姆剃刀要求:排查问题时,先验证"假设最少、最可能"的原因,再逐步复杂

      案例:接口返回"空数据"的排查流程

      • 错误思路(复杂优先):先怀疑"数据库查询逻辑错误"→ 检查MyBatis映射文件 → 查看SQL是否正确 → 最后发现是"前端传错了用户ID(传了空字符串)"。

      • 正确思路(简单优先)

        1. 先检查"请求参数":是否传了有效的userId?(1分钟验证,发现是空字符串)
        2. 若参数正常,再检查"数据库是否有该用户数据"(查询SELECT * FROM user WHERE id = ?);
        3. 若数据存在,再检查"业务逻辑是否过滤了数据"(如是否有"用户状态未激活"的判断)。

      效率差异:简单优先的排查流程可节省80%的时间,避免无意义的"复杂猜想"——这正是奥卡姆剃刀在"问题解决"中的核心价值。

      3. 应用奥卡姆剃刀的三个关键注意事项

      奥卡姆剃刀不是"万能法则",若滥用会导致"简陋设计",需遵守三个边界:

      边界说明
      不牺牲"可维护性"换简洁比如"把100行逻辑写在1个方法里",看似简洁,却无法拆分、难以修改——正确做法是"按职责拆分小方法",这是"有价值的复杂度",不应剃除。
      不牺牲"可扩展性"换简洁若需求明确"未来会增加字段"(如电商订单,未来需加"优惠券ID""物流单号"),可提前设计"灵活的字段存储方式"(如用Map<String, Object>存扩展字段),这是"必要的预判",不属于"多余实体"。
      不牺牲"安全性"换简洁登录接口若为了"简洁"去掉"验证码""密码加密",属于"简陋"而非"简洁"——安全性是核心需求,对应的设计是"必要实体",不可剃除。

      4. 结语

      奥卡姆剃刀原则的本质,是在"需求边界"内追求"最小复杂度"——它不是让我们"拒绝复杂",而是让我们"不主动制造复杂"。在编程与设计中,应用这一原则的核心步骤可概括为:

      1. 明确核心目标:识别当前需求的本质(如"用户注册"的核心是"创建账号+返回ID");
      2. 精简实现方案:用"最少的组件/代码/依赖"实现核心目标,去除所有"非必要环节";
      3. 验证基础要求:确保方案满足"可维护、可扩展、安全"的基础要求,避免沦为"简陋设计"。

      奥卡姆剃刀不仅是一种技术原则,更是一种思维方式——它教会我们在纷杂的需求和技术选项中,保持清醒的判断,聚焦于问题的本质。通过这一原则,我们能写出更易理解、更易维护、更少bug的代码,同时提升开发效率。

      在技术快速迭代的今天,奥卡姆剃刀的价值愈发凸显:它让我们在追求创新的同时,保持代码的简洁与优雅;在应对复杂需求时,回归问题的本质与初心。这不仅是对代码的要求,更是对工程师素养的锤炼——以最简洁的方式解决问题,以最清晰的思路面对挑战,这正是奥卡姆剃刀原则在技术领域的深远意义。

      +}

      2.6 场景6:调试与优化,优先排查"简单原因"

      定位 bug 或性能问题时,开发者易陷入"复杂猜想"(如怀疑框架漏洞、底层逻辑),忽略"简单原因"(如参数传错、配置错误)。奥卡姆剃刀要求:排查问题时,先验证"假设最少、最可能"的原因,再逐步复杂

      案例:接口返回"空数据"的排查流程

      • 错误思路(复杂优先):先怀疑"数据库查询逻辑错误"→ 检查MyBatis映射文件 → 查看SQL是否正确 → 最后发现是"前端传错了用户ID(传了空字符串)"。

      • 正确思路(简单优先)

        1. 先检查"请求参数":是否传了有效的userId?(1分钟验证,发现是空字符串)
        2. 若参数正常,再检查"数据库是否有该用户数据"(查询SELECT * FROM user WHERE id = ?);
        3. 若数据存在,再检查"业务逻辑是否过滤了数据"(如是否有"用户状态未激活"的判断)。

      效率差异:简单优先的排查流程可节省80%的时间,避免无意义的"复杂猜想"——这正是奥卡姆剃刀在"问题解决"中的核心价值。

      3. 应用奥卡姆剃刀的三个关键注意事项

      奥卡姆剃刀不是"万能法则",若滥用会导致"简陋设计",需遵守三个边界:

      边界说明
      不牺牲"可维护性"换简洁比如"把100行逻辑写在1个方法里",看似简洁,却无法拆分、难以修改——正确做法是"按职责拆分小方法",这是"有价值的复杂度",不应剃除。
      不牺牲"可扩展性"换简洁若需求明确"未来会增加字段"(如电商订单,未来需加"优惠券ID""物流单号"),可提前设计"灵活的字段存储方式"(如用Map<String, Object>存扩展字段),这是"必要的预判",不属于"多余实体"。
      不牺牲"安全性"换简洁登录接口若为了"简洁"去掉"验证码""密码加密",属于"简陋"而非"简洁"——安全性是核心需求,对应的设计是"必要实体",不可剃除。

      4. 结语

      奥卡姆剃刀原则的本质,是在"需求边界"内追求"最小复杂度"——它不是让我们"拒绝复杂",而是让我们"不主动制造复杂"。在编程与设计中,应用这一原则的核心步骤可概括为:

      1. 明确核心目标:识别当前需求的本质(如"用户注册"的核心是"创建账号+返回ID");
      2. 精简实现方案:用"最少的组件/代码/依赖"实现核心目标,去除所有"非必要环节";
      3. 验证基础要求:确保方案满足"可维护、可扩展、安全"的基础要求,避免沦为"简陋设计"。

      奥卡姆剃刀不仅是一种技术原则,更是一种思维方式——它教会我们在纷杂的需求和技术选项中,保持清醒的判断,聚焦于问题的本质。通过这一原则,我们能写出更易理解、更易维护、更少bug的代码,同时提升开发效率。

      在技术快速迭代的今天,奥卡姆剃刀的价值愈发凸显:它让我们在追求创新的同时,保持代码的简洁与优雅;在应对复杂需求时,回归问题的本质与初心。这不仅是对代码的要求,更是对工程师素养的锤炼——以最简洁的方式解决问题,以最清晰的思路面对挑战,这正是奥卡姆剃刀原则在技术领域的深远意义。

      diff --git a/fullstack/overview.html b/fullstack/overview.html new file mode 100644 index 00000000..b42b25d9 --- /dev/null +++ b/fullstack/overview.html @@ -0,0 +1,178 @@ + + + + + + 全景一览 | Insight Stack + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      Skip to content
      21
      + + + + 1m

      全景一览

      + + + + \ No newline at end of file diff --git a/fullstack/react-design-philosophy-ai-augmented.html b/fullstack/react-design-philosophy-ai-augmented.html new file mode 100644 index 00000000..c7749fb5 --- /dev/null +++ b/fullstack/react-design-philosophy-ai-augmented.html @@ -0,0 +1,178 @@ + + + + + + React 设计哲学:AI 协作时代的组件化开发实践指南 | Insight Stack + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      Skip to content
      5038
      + + + + 17.6m

      React 设计哲学:AI 协作时代的组件化开发实践指南

      1. 引言

      在软件工程中,约 70% 的时间应投入于架构设计、需求拆解与接口语义推敲,仅 30% 用于实际编码。进入 AI 协作时代后,这一比例依然坚如磐石——开发者必须先完成深度思考,将“清晰的问题规格(Specification)”交给 AI,AI 才能输出高质量代码。AI 提升的是 30% 编码阶段的执行力,而非取代 70% 的架构裁决。 高质量 React 应用的诞生,依然始于人类心智对数据流、副作用边界与可组合性的透彻推演。

      然而,真正驾驭 React 并非易事。许多团队在项目初期享受着组件化带来的快感,却在业务膨胀后陷入"组件地狱"——深嵌套的 prop drilling、失控的状态蔓延、难以追踪的副作用,让代码库逐渐腐化。问题的根源往往不在于 React 本身,而在于我们是否真正理解其背后的设计哲学。

      React 的精髓在于以组件化为核心,将复杂的 UI 拆解为独立、可复用的自治单元,让数据沿着从输入(props)到输出(UI 元素)的轨迹形成清晰、可控的闭环。为确保项目的可维护性与抗腐化能力,React 开发者应将以下标准内化为肌肉记忆:
      检查项核心标准架构目标
      1. 单一职责每个组件是否只做一件事(纯布局或纯逻辑)?控制认知复杂度,防止组件“上帝化”
      2. 组合优先是否优先使用了 children 或 Props 传递子组件?消除 Prop Drilling,提升灵活性
      3. DOM 扁平是否利用 <>...</> 移除了所有非必要的包装 <div>减小渲染开销,保持 DOM 树纯粹
      4. 拥抱 Hooks是否已用 Custom Hooks 替代了 HOC 嵌套?展平组件树,实现逻辑与视图的物理隔离

      2. 划分具备分层结构的“自治”组件

      组件是 React 对“关注点分离”这一软件工程经典原则的具象化落地。它将 UI 拆分为若干自治单元,每个单元对外仅暴露 props 契约,对内通过 state 管理自身行为。

      划分组件必须恪守单一职责(SRP)高内聚低耦合两条铁律:

      • 一事一议:理想状态下,一个组件只负责渲染一块特定的视觉或封装一类特定的交互。随着功能膨胀,必须果断将其裂变为更细粒度的子组件。
      • 显式通信:组件间仅通过 props 与回调通信,杜绝任何形式的隐式状态共享。

      在实践中,我们可以通过以下策略压平组件层级,维持架构的清爽:

      策略说明
      角色界定容器组件(Container):充当"调度中心",负责数据获取、状态管理与业务逻辑,随后将干净的数据流入子组件。避免在容器中混杂复杂的 DOM 结构,利用 Custom Hooks 抽离逻辑,能让 UI 层级瞬间变薄。
      展示组件(Presentational):充当"纯函数",专注于接收 props 并渲染视图,保持 DOM 结构的极度扁平。
      组合优于嵌套这是解决组件树过深的最强武器。永远不要在组件内部硬编码子组件,而是通过 children 或 render props,将子组件作为参数注入。这在语义上形成了一种"声明式 DSL",让代码本身成为直观的 UI 蓝图。
      极简接口组件的 props 契约应绝对最小化,仅暴露必要的输入。

      AI 协作小洞察:

      我们要先划分层级结构,不应该让 AI 盲目写代码,可以先让它充当“架构助理”进行结构划分与设计:

      • 投喂需求与视觉规格,提供需求描述或 UI 视觉稿截图,要求 AI(如 ChatGPT、Claude 等)辅助分析并输出组件层级树,同时解释其职责划分与层级结构设计的思路。
      • 定义职责约束,在 Prompt 中明确要求 AI 区分"容器组件"与"展示组件",并遵循单一职责原则为其命名——这既能启发思路,也能提前规避命名不当的问题。
      • 人工裁决,评估 AI 输出的结构,微调边界,确保这套“骨架”足够健壮,再进入下一步的实质性编码。

      3. 构建纯渲染的静态版本:确立工程基线

      在状态与交互介入之前,我们可以先用“数据占位符”把 UI 的纯渲染路径跑通,构建一个剥离了所有动态行为的“静态版本”。此过程不需要过多的逻辑烧脑,而是纯粹的结构编码。

      静态版本应保证组件无副作用,能为后续快照测试、服务端渲染(SSR)与 hydration 奠定可靠基础。这一步的工程价值不可估量:

      • 契约验证:强制检验当前的 props 设计是否足以表达所有的视觉状态差异。
      • 前置对齐:让设计师和产品提前验收“像素级”静态产物,规避后期可能出现的视觉返工。
      • 可信基线:为后续增量引入状态(State)与副作用(Effects)提供了一个随时可回滚的基线

      在编写代码时,我们通常采用“自顶向下”的构建顺序,即从顶层容器开始,逐层向叶子节点实现。这种策略能确保组件职责清晰,不会过早陷入局部细节,同时保证每个模块都是独立、可测试的。

      当然,在 AI 协作时代,借助 AI 生成静态版本无疑是更为高效的方式。但我们不建议直接采用全自动化构建作为最终方案——毕竟静态版本是整个项目的工程基线,一旦存在隐蔽缺陷,将为后续迭代埋下隐患。

      更稳健的做法是将全自动化与半自动化并行推进:先让 AI 基于第一阶段评审通过的组件划分树与职责描述,在独立分支中全自动化生成代码;与此同时,开发者在正式分支中以半自动化方式逐步搭建。由于全自动化产出速度极快,我们可以横向对比多份生成结果,择优验证后再整合到正式项目中。这种"边做边验"的模式,既能提升基线质量,也能加深开发者对架构的理解。

      进入静态版本构建阶段,我们需要关注以下三个关键环节:

      1、前置步骤:脚手架生成
      首先利用 AI 编程工具(如 Claude Code / Codex)快速初始化项目结构与配置文件。这一步是后续全自动化与半自动化并行模式的基础——AI 在标准化脚手架搭建上效率极高,能够迅速为我们铺好工程地基。

      2、注入规格,启动双轨模式
      将第一阶段确认好的"组件层级树与职责描述"作为明确的 Specification 喂给 AI,令其批量生成符合 React 规范的静态组件骨架。此时全自动化与半自动化两条线并行推进:AI 在独立分支快速产出多份候选代码,开发者则在主干分支逐步搭建,形成可对比、可验证的协作闭环。

      3、人机结对审查
      横向对比 AI 的自动化产出后,择优与人工代码融合,重点 Review 是否真正做到"无副作用"与"幂等渲染"。过程中也可让 AI 与人工协作,一旦发现问题或异常情况,立即通过对话纠正,确保这份静态基线的绝对纯粹——它将是后续引入状态与副作用时唯一可信的回滚锚点。

      4. 寻找状态的最简表示,敲定拓扑位置

      4.1 什么是 State?什么是 Derived Data(派生数据)?

      State 本质上是对应用随时间变化产生的差异的建模,为正确地构建应用,让应用可控,我们需要在这一阶段找出驱动 UI 运转的 State(状态)的最小完整集合

      在定义 State 之前,先做灵魂三问。先问自己三个关键问题。如果满足以下任何一条,它就绝对不是 State

      1. 随时间推移保持不变? (如静态配置) -> 不是 State。
      2. 通过 props 从父级传入? (如外部注入的数据) -> 不是 State。
      3. 能通过已有 State 或 props 计算得出? (如根据商品列表计算出的库存总量) -> 坚决不能作为 State。

      这些可通过计算得出的数据被称为 Derived Data(派生数据)。正确的做法是在渲染期间动态计算它们,或使用 useMemo 进行性能优化,而不是将其塞入 useState 中徒增同步烦恼。

      一份合格的状态必须:最小(剔除可推导字段)且完整(下游 UI 能基于此状态集合进行确定性渲染)。

      4.2 敲定 State 的安放位置

      小提示:防范状态爆炸与泄漏

      • 单一真实数据源:同一业务实体在组件树中只能存在一份状态副本。如果祖先节点已有,就通过 props 传递,严禁在不同组件内重复 useState
      • 无泄漏下沉:把状态隔离在局部子树时,必须显式定义读写边界——仅对真正需要的子孙暴露接口。禁止在模块顶层声明可变状态,防止状态隐式穿透组件边界。

      确定了“是什么”之后,更关键的是“放在哪”。State 的安置需要在状态提升(Lifting State Up)状态下沉(Colocating State)之间寻找动态平衡:

      • 状态提升(Lifting State Up):若多个兄弟组件需要共享同一状态,毫不犹豫地将其提升至它们最近的公共父节点。
      • 状态下沉(Colocating State):若状态仅在特定子树内部流转,应通过局部 Context 或轻量级状态库(Zustand / Jotai)将其隔离,避免污染全局。

      架构目标是绘制出一张清晰的数据流拓扑图:状态变更只沿单向轨道流动,出现 Bug 时,可以像排查电路图一样用万用表逐点测量。

      4. 建立反向数据流:让回调成为刚性契约

      React 的数据流天然是自顶向下的(Top-Down)。这种单向流动牺牲了双向绑定的“便捷性”,换来的是数据流转的绝对清晰与可预测性

      当底层展示组件需要向上级反馈用户行为时,我们需要设计反向数据流,其本质是将“UI 事件”转化为严谨的“回调契约”

      1. 父组件通过 props 向子组件下发契约:onXxx: (data: T) => void
      2. 子组件在适当时机触发契约,但不关心父组件如何处理,借此维持自身的纯粹与解耦。
      3. 父组件在回调中执行 setState,触发自顶向下的重新渲染,完成闭环。

      这种 事件 -> 回调 -> 状态突变 -> 重渲染 的循环,构成了 React 响应式架构的最小内核。面对跨层级通信时,可以引入 Context 或状态管理工具来收敛"回调地狱",但单向数据流的铁律绝不能被破坏

      5. 规范驱动开发(SDD):从执行者转变为立法者

      随着前四个阶段的稳步推进,基础架构已然确立,应用项目也进入了更深层次的开发迭代阶段。此时,如何高效地解决"怎么写"的问题?这正是 AI 协作编程大显身手的时刻。

      规范驱动开发(Specification-Driven Development,SDD)是一种比 Vibe Coding 更为可靠的人机协作实践模式:人类负责制定规范,AI 负责实现代码。这种分工让开发者从繁琐的编码劳动中解放出来,专注于真正创造价值的方案选择与设计决策。

      5.1 SDD 模式的核心流程与实践要点

      SDD 模式遵循一个五步闭环:规划阶段 → 生成规范 → 人工 Review → 自动化开发 → 工程验证

      阶段描述
      规划阶段让 AI 分析业务场景,输出设计文档。这一阶段的核心是明确"做什么"——包括模块边界、数据结构、接口签名、约束条件等。
      生成规范基于规划结果,让 AI 生成可指导编程的实现规范(Specification)。规范是一份可执行的契约,包含类型定义、函数签名、测试用例、边界条件等。规范的质量直接决定了代码的质量
      人工 Review开发者审核规范的合理性。这是人类决策的关键环节——确保设计符合架构原则、无冗余无泄漏、命名语义清晰、数据流方向明确。Review 通过后,规范成为 AI 实现的唯一依据。
      自动化开发确认规范后,让 AI 基于规范实现完整的功能模块。要求 AI 遵循 TDD 模式——先编写测试用例,再实现逻辑,确保行为的可预测性。每次开发应聚焦于一个完整、恰当粒度的功能或独立模块,避免碎片化。
      工程验证配置项目的 lint、类型检查与测试套件,由 AI 自动运行验证,形成质量闭环。若发现问题,应优先引导 AI 自行修正,而非手动干预。

      SDD 模式的实践要点可归纳为:

      • 规范先行,代码后置:永远不要让 AI 在没有规范的情况下直接写代码。模糊的需求描述只会让 AI 制造技术债务。一份清晰的规范,能让 AI 产出可维护的代码。

      • 恰当粒度,完整交付:每次让 AI 开发一个完整的功能模块,而非零散的代码片段。完整的模块有清晰的边界、完整的测试、可独立验证的行为。这种粒度既能保证开发效率,又能确保代码质量。

      • TDD 内嵌,测试驱动:在规范中明确要求 AI 先写测试、再写实现。测试用例是规范的具象化表达,也是验证代码正确性的唯一标准。

      • 引导修正,避免手动修补:当代码未通过验证时,优先引导 AI 自行修正,而非直接手动修改。手动修补会干扰 AI 对项目上下文的理解,导致后续生成的代码一致性下降。

      • 工程闭环,持续迭代:lint、类型检查、测试套件是质量的三道防线。每次开发完成后必须运行完整验证,确保代码符合项目规范。验证通过后再进入下一个模块的开发。

      5.2 SDD 模式的适用场景

      SDD 模式适用于多数应用的功能迭代开发阶段。在前端领域,它与 React 的声明式范式尤为契合,特别适合以下场景:

      • 状态管理模块:状态是应用的核心骨架,需要严格的类型约束与变更追踪。SDD 能确保状态设计遵循 SSOT 原则,杜绝冗余与泄漏。

      • 交互逻辑开发:反向数据流涉及组件间的通信契约,是典型的"接口语义推敲"场景。SDD 能确保回调命名语义清晰、数据流方向明确。

      • 独立组件开发:针对功能内聚、可复用的独立组件(如表单控件、数据卡片、模态框等),需先明确其 Props 契约、内部状态边界及副作用生命周期,再交由 AI 实现具体渲染逻辑与交互细节。

      • 基础设施代码:Custom Hooks、工具函数、类型定义等基础设施代码,适合用 SDD 模式批量生成,确保接口一致性。

      5.3 为什么 React 与 SDD 天生一对?

      React 的声明式(Declarative)特性意味着我们只需描述 State → UI 的映射关系——给定特定的状态输入,界面应当呈现何种输出,完全由开发者声明式地定义,而非通过命令式地操作 DOM 来达成。

      如果说 SDD(规格驱动开发)是人机协作的一套"宪法",那么 React 就是完美的"执行机构"。两者的天作之合并非偶然,而是源于底层架构范式的深度契合。React 所倡导的"描述即实现"的声明式编程范式,本质上就是一种显式契约(Props Contract),能够有效压缩 AI 的"幻觉空间"。

      当我们在 Spec 中定义好 interface Props 时,实际上是为 AI 划定了一个认知边界。AI 无需费力猜测上下文,只需在 Props 的约束范围内寻找局部最优解。这种高度的封装性从物理层面隔绝了 AI 产生"幻觉"的可能,确保生成的组件是高内聚、低耦合的自治单元。

      这与 SDD 的思维高度一致:开发者只需定义"映射规格"(即状态到 UI 的转换规则、组件的 Props 契约、数据的流动路径),而具体的实现细节——如何高效地 diff 虚拟 DOM、如何批量处理状态更新、如何优化重渲染性能——完全交由 AI 填充。在 SDD 模式下,人类聚焦于"做什么"(What)和"为什么"(Why),AI 负责"怎么做"(How)。这正是声明式编程与规范驱动开发在哲学层面的深度契合。

      6.结语:工程师的不可替代性

      当我们回望 React 设计哲学的四个核心步骤——组件划分、静态基线、状态定位、数据流闭环,会发现它们共同指向一个本质命题:如何在复杂性中建立秩序

      组件化是对 UI 复杂性的分解,静态版本是对渲染行为的锚定,最小状态是对数据冗余的剔除,单向数据流是对变更轨迹的约束。这些设计原则并非 React 独有,而是软件工程几十年沉淀下来的智慧结晶——单一职责、关注点分离、显式优于隐式、数据流的可追溯性

      AI 时代的到来,并未改变这些原则的内核,反而让它们的价值更加凸显。当 AI 能够以惊人的速度生成代码时,"写什么"的决策权比"怎么写"的执行力更为稀缺。一个清晰的设计规范,能让 AI 产出可维护的代码;而一个模糊的需求描述,只会让 AI 制造更多技术债务。

      规范驱动开发(SDD)的本质是将架构思维外化为可执行的契约。开发者不再是代码的"搬运工",而是规范的"立法者"。我们定义组件边界、敲定状态拓扑、设计回调契约——AI 则在我们设定的框架内高效填充实现细节。这种分工,让开发者从繁琐的编码劳动中解放出来,将精力集中于真正创造价值的架构决策。

      最后,请记住:工具会迭代,技术会过时,但对复杂性的驾驭能力永远是工程师的核心竞争力。React 的 API 可能会在未来被新的框架取代,但"如何在复杂性中建立秩序"这一命题,将伴随软件工程的始终。愿你在这场技术演进中,始终站在架构设计的高地,用清晰的思维驾驭强大的工具,构建出经得起时间考验的软件系统。

      + + + + \ No newline at end of file diff --git "a/01.\345\205\250\346\240\210/40.\345\211\215\347\253\257\345\267\245\347\250\213/11.React \346\234\215\345\212\241\347\253\257\347\212\266\346\200\201\347\256\241\347\220\206\347\232\204\350\214\203\345\274\217\350\275\254\347\247\273\344\270\216\351\200\211\345\236\213\346\267\261\345\272\246\345\215\232\345\274\210.html" b/fullstack/server-state-management.html similarity index 82% rename from "01.\345\205\250\346\240\210/40.\345\211\215\347\253\257\345\267\245\347\250\213/11.React \346\234\215\345\212\241\347\253\257\347\212\266\346\200\201\347\256\241\347\220\206\347\232\204\350\214\203\345\274\217\350\275\254\347\247\273\344\270\216\351\200\211\345\236\213\346\267\261\345\272\246\345\215\232\345\274\210.html" rename to fullstack/server-state-management.html index db710ab9..c10a5495 100644 --- "a/01.\345\205\250\346\240\210/40.\345\211\215\347\253\257\345\267\245\347\250\213/11.React \346\234\215\345\212\241\347\253\257\347\212\266\346\200\201\347\256\241\347\220\206\347\232\204\350\214\203\345\274\217\350\275\254\347\247\273\344\270\216\351\200\211\345\236\213\346\267\261\345\272\246\345\215\232\345\274\210.html" +++ b/fullstack/server-state-management.html @@ -6,12 +6,12 @@ 不止于 Fetch:React 服务端状态管理的范式转移与选型深度博弈 | Insight Stack - + - - - - + + + + @@ -30,7 +30,7 @@ - +
      Skip to content

      不止于 Fetch:React 服务端状态管理的范式转移与选型深度博弈

      摘要总结: 本文聚焦 UI 状态与服务端状态的管理边界,对比 SWR(基于 stale-while-revalidate 协议的轻量方案)与 TanStack Query(精密异步状态机)两者的核心机制差异,通过缓存策略、乐观更新、依赖查询等实战代码场景展开论述,最终给出以项目复杂度为维度的选型结论与决策框架。

      1. 引言

      在现代前端工程中,状态可严格区分为 UI 状态(UI State)服务端状态(Server State) 两类。对于 UI 状态的管理,开发者已较为熟悉,通常可借助 useStateuseEffect 等 Hooks,或 zustandjotai 等状态管理库来实现。然而,服务端状态的管理往往缺乏统一且高效的解决方案,开发者通常需要自行实现。

      在传统的数据获取流程中,我们一般使用 fetchaxios 向后端或 REST API 发送 HTTP 请求,随后手动将数据获取逻辑与前端业务逻辑及 UI 状态管理进行整合,以完成数据处理并驱动界面更新。

      TanStack QuerySWR 等库的出现,为数据获取提供了更加简洁和高效的解决方案。

      1. SWR

      1.1 简介与核心流程说明

      SWR is a minimal API with built-in caching, revalidation, and request deduplication. It keeps your UI fast, consistent, and always up to date — with a single React hook.

      SWR 是一个基于 React Hooks 的轻量级库,它的 API 简单易用,同时提供了强大的功能。它的设计目标是简化数据获取和缓存的过程。它的核心思想是“ stale-while-revalidate ”,即先返回缓存数据(stale),同时发送请求去更新缓存(revalidate),核心运作流也非常简洁:

      • Stale:首先从本地缓存中返回数据,实现快速响应,无白屏。
      • Fetch:在后台发送 Fetch 请求获取最新数据。
      • Revalidate:拿到最新数据后,对比缓存,若有变化则触发 React 重新渲染并更新缓存。

      这种机制彻底改变了传统 useEffect + setState 带来的“加载中 -> 渲染”的阻塞式体验,让应用在感官上具有“实时性”。

      简单示例如下:

      JSX
      import useSWR from 'swr';
      +  

      不止于 Fetch:React 服务端状态管理的范式转移与选型深度博弈

      摘要总结: 本文聚焦 UI 状态与服务端状态的管理边界,对比 SWR(基于 stale-while-revalidate 协议的轻量方案)与 TanStack Query(精密异步状态机)两者的核心机制差异,通过缓存策略、乐观更新、依赖查询等实战代码场景展开论述,最终给出以项目复杂度为维度的选型结论与决策框架。

      1. 引言

      在现代前端工程中,状态可严格区分为 UI 状态(UI State)服务端状态(Server State) 两类。对于 UI 状态的管理,开发者已较为熟悉,通常可借助 useStateuseEffect 等 Hooks,或 zustandjotai 等状态管理库来实现。然而,服务端状态的管理往往缺乏统一且高效的解决方案,开发者通常需要自行实现。

      在传统的数据获取流程中,我们一般使用 fetchaxios 向后端或 REST API 发送 HTTP 请求,随后手动将数据获取逻辑与前端业务逻辑及 UI 状态管理进行整合,以完成数据处理并驱动界面更新。

      TanStack QuerySWR 等库的出现,为数据获取提供了更加简洁和高效的解决方案。

      1. SWR

      1.1 简介与核心流程说明

      SWR is a minimal API with built-in caching, revalidation, and request deduplication. It keeps your UI fast, consistent, and always up to date — with a single React hook.

      SWR 是一个基于 React Hooks 的轻量级库,它的 API 简单易用,同时提供了强大的功能。它的设计目标是简化数据获取和缓存的过程。它的核心思想是“ stale-while-revalidate ”,即先返回缓存数据(stale),同时发送请求去更新缓存(revalidate),核心运作流也非常简洁:

      • Stale:首先从本地缓存中返回数据,实现快速响应,无白屏。
      • Fetch:在后台发送 Fetch 请求获取最新数据。
      • Revalidate:拿到最新数据后,对比缓存,若有变化则触发 React 重新渲染并更新缓存。

      这种机制彻底改变了传统 useEffect + setState 带来的“加载中 -> 渲染”的阻塞式体验,让应用在感官上具有“实时性”。

      简单示例如下:

      JSX
      import useSWR from 'swr';
       import React from 'react';
       
       // 自定义 fetcher 函数,用于发送 HTTP 请求并获取数据
      @@ -380,7 +380,7 @@
             queryClient.invalidateQueries({ queryKey: ['todos'] });
           },
         });
      -}

      3. 选型评估:SWR vs React Query

      在 React 生态中,SWR 与 TanStack Query (React Query) 是最主流的两个服务端状态管理方案。两者各有侧重,适用于不同的项目场景。

      以下从多个维度进行对比分析,帮助我们根据项目需求做出合适的技术选型。

      3.1 核心设计与功能对比分析

      评估维度Vercel SWRTanStack Query (RQ)
      核心哲学极简主义、渐进式增强。核心是围绕 stale-while-revalidate 协议,以最小的 API 表面积提供极致的“快照渲染”体验。大而全的异步状态机。接管一切服务端状态,提供极度精细的生命周期控制和强大的底层 API。
      Bundle Size~4.3 kB (Minified + Gzipped)对现代轻量级构建极为友好。~13 kB (Minified + Gzipped)体积较大,但带来了开箱即用的完整生态。
      缓存标识 (Key)String (URL) 主导。天生契合 RESTful 路径。Array (数组) 主导。天生支持复杂组合查询与确定性哈希。
      API 契约天然契合 SDD (Contract-First Generation)。以 API 端点作为天然的 Key,前后端接口约束极其清晰。高度抽象。需要团队自行建立严格的 QueryKey 命名与管理规范。
      学习曲线极低,半天即可全团队推行。中等偏高。需深刻理解 staleTime、gcTime 等底层状态机逻辑。
      DevTools第三方支持,相对简陋。官方内置,极其强大。可视化时间旅行、缓存审查器,复杂场景下的 Debug 神器。

      两者在核心功能方面的对比分析:

      1. 数据变更与乐观更新 (Mutations & Optimistic UI) SWR 的局限:SWR 的 mutate 相对简单粗暴。开发者需要手动编写拦截逻辑、捕获异常,并手动维护回滚(Rollback)前的数据快照。在处理链式调用或复杂的并行变更时,代码容易变得面条化。

      TanStack Query 的压倒性优势:提供了专门的 useMutation Hook,它内置了极其优雅的 onMutate、onSuccess、onError、onSettled 生命周期回调。配合它的 Context 透传机制,实现带错误回滚的乐观更新是一种标准的、工程化的体验。

      1. 缓存失效与精细化刷新 (Query Invalidation) SWR 的方案: 全局 mutate(key),如果更新了一个项目详情,想刷新列表,就需要准确知道列表的 Key 才能触发它。

      RQ 的方案queryClient.invalidateQueries({ queryKey: ['projects'] })。RQ 的数组 Key 具有层级模糊匹配能力。当开发者变更了某个项目,一句代码可以使所有以 ['projects'] 开头的查询(如列表、统计面板、概览)全部自动在后台失效并重新获取,这在复杂中后台应用中是杀手级功能

      1. 依赖查询与请求瀑布流 (Dependent Queries):两者都支持基于前一个请求的结果发起下一个请求。但 TanStack Query 提供了 select 数据转换器,允许在组件订阅前对底层数据进行高性能的派生和过滤,多个组件共享一份基础缓存但各自 select 不同的视图,渲染性能更佳。

      3.2 场景驱动选型:到底需要哪一个?

      结合实际的研发场景,特别是那些涉及复杂中间态和高频交互的领域,可以得出两条选择结论:

      1、如果项目是一个重操作、重状态流转、强关联数据的复杂工程(例如包含大量配置面板、生成流水线、拖拽保存的工具型产品),我们就应当承担那额外的 8kB 体积和初期学习成本,直接选用 TanStack Query,它的工程化上限更高,长远来看能省去大量由于手动维护复杂缓存而产生的隐性技术债。

      2、相反,如果项目是一个重展示、高频读取、重前端轻交互的现代 Web 应用,并且你推崇极简的架构代码,SWR 就是更好的选择。

      场景 A:应该毫不犹豫选择 SWR 的情况

      • 轻量级/展示型为主的 C 端产品:核心诉求是首屏快、无白屏、切 Tab 时数据瞬间出现。SWR 的极简调度能用最低的性能开销换取最好的感官体验。

      • API 结构高度契合 RESTful 且数据流向单一:如果你的接口设计已经非常规范(Contract-First),直接把 URL 当作 Cache Key,代码将极其干净。

      • 追求极致的现代前端审美:配合 Vite/SWC 等现代工具链,你希望保持依赖树的纯净和 Bundle 的极限压缩,不希望引入过重的状态机。

      场景 B:应该毫不犹豫选择 TanStack Query 的情况

      • 超大型 B 端/企业级工作台: 页面上同时存在十几个需要联动的数据板块。你需要 TanStack Query 强大的 invalidateQueries 来保证数据的一致性,同时也极其依赖官方 DevTools 来排查状态污染。

      • AI-Native 的 Agentic 工作流交互: 在构建 AI 智能体应用时,用户的每一个 Prompt 可能会触发后端一系列的流式响应、工具调用(Tool Use)和状态变更。TanStack Query 严密的状态机能更好地管理这些复杂的“进行中”、“部分成功”、“需用户介入”等组合异步状态。

      • 复杂图形解析工具:应用往往涉及大量的中间态保存、节点解析重试、以及频繁的与服务端的同步(Save Draft, Commit Changes),开发者需要 useMutation 强大的生命周期来控制这些复杂的异步交互流,并在生成失败时优雅地回滚 UI。

      +}

      3. 选型评估:SWR vs React Query

      在 React 生态中,SWR 与 TanStack Query (React Query) 是最主流的两个服务端状态管理方案。两者各有侧重,适用于不同的项目场景。

      以下从多个维度进行对比分析,帮助我们根据项目需求做出合适的技术选型。

      3.1 核心设计与功能对比分析

      评估维度Vercel SWRTanStack Query (RQ)
      核心哲学极简主义、渐进式增强。核心是围绕 stale-while-revalidate 协议,以最小的 API 表面积提供极致的“快照渲染”体验。大而全的异步状态机。接管一切服务端状态,提供极度精细的生命周期控制和强大的底层 API。
      Bundle Size~4.3 kB (Minified + Gzipped)对现代轻量级构建极为友好。~13 kB (Minified + Gzipped)体积较大,但带来了开箱即用的完整生态。
      缓存标识 (Key)String (URL) 主导。天生契合 RESTful 路径。Array (数组) 主导。天生支持复杂组合查询与确定性哈希。
      API 契约天然契合 SDD (Contract-First Generation)。以 API 端点作为天然的 Key,前后端接口约束极其清晰。高度抽象。需要团队自行建立严格的 QueryKey 命名与管理规范。
      学习曲线极低,半天即可全团队推行。中等偏高。需深刻理解 staleTime、gcTime 等底层状态机逻辑。
      DevTools第三方支持,相对简陋。官方内置,极其强大。可视化时间旅行、缓存审查器,复杂场景下的 Debug 神器。

      两者在核心功能方面的对比分析:

      1. 数据变更与乐观更新 (Mutations & Optimistic UI) SWR 的局限:SWR 的 mutate 相对简单粗暴。开发者需要手动编写拦截逻辑、捕获异常,并手动维护回滚(Rollback)前的数据快照。在处理链式调用或复杂的并行变更时,代码容易变得面条化。

      TanStack Query 的压倒性优势:提供了专门的 useMutation Hook,它内置了极其优雅的 onMutate、onSuccess、onError、onSettled 生命周期回调。配合它的 Context 透传机制,实现带错误回滚的乐观更新是一种标准的、工程化的体验。

      1. 缓存失效与精细化刷新 (Query Invalidation) SWR 的方案: 全局 mutate(key),如果更新了一个项目详情,想刷新列表,就需要准确知道列表的 Key 才能触发它。

      RQ 的方案queryClient.invalidateQueries({ queryKey: ['projects'] })。RQ 的数组 Key 具有层级模糊匹配能力。当开发者变更了某个项目,一句代码可以使所有以 ['projects'] 开头的查询(如列表、统计面板、概览)全部自动在后台失效并重新获取,这在复杂中后台应用中是杀手级功能

      1. 依赖查询与请求瀑布流 (Dependent Queries):两者都支持基于前一个请求的结果发起下一个请求。但 TanStack Query 提供了 select 数据转换器,允许在组件订阅前对底层数据进行高性能的派生和过滤,多个组件共享一份基础缓存但各自 select 不同的视图,渲染性能更佳。

      3.2 场景驱动选型:到底需要哪一个?

      结合实际的研发场景,特别是那些涉及复杂中间态和高频交互的领域,可以得出两条选择结论:

      1、如果项目是一个重操作、重状态流转、强关联数据的复杂工程(例如包含大量配置面板、生成流水线、拖拽保存的工具型产品),我们就应当承担那额外的 8kB 体积和初期学习成本,直接选用 TanStack Query,它的工程化上限更高,长远来看能省去大量由于手动维护复杂缓存而产生的隐性技术债。

      2、相反,如果项目是一个重展示、高频读取、重前端轻交互的现代 Web 应用,并且你推崇极简的架构代码,SWR 就是更好的选择。

      场景 A:应该毫不犹豫选择 SWR 的情况

      • 轻量级/展示型为主的 C 端产品:核心诉求是首屏快、无白屏、切 Tab 时数据瞬间出现。SWR 的极简调度能用最低的性能开销换取最好的感官体验。

      • API 结构高度契合 RESTful 且数据流向单一:如果你的接口设计已经非常规范(Contract-First),直接把 URL 当作 Cache Key,代码将极其干净。

      • 追求极致的现代前端审美:配合 Vite/SWC 等现代工具链,你希望保持依赖树的纯净和 Bundle 的极限压缩,不希望引入过重的状态机。

      场景 B:应该毫不犹豫选择 TanStack Query 的情况

      • 超大型 B 端/企业级工作台: 页面上同时存在十几个需要联动的数据板块。你需要 TanStack Query 强大的 invalidateQueries 来保证数据的一致性,同时也极其依赖官方 DevTools 来排查状态污染。

      • AI-Native 的 Agentic 工作流交互: 在构建 AI 智能体应用时,用户的每一个 Prompt 可能会触发后端一系列的流式响应、工具调用(Tool Use)和状态变更。TanStack Query 严密的状态机能更好地管理这些复杂的“进行中”、“部分成功”、“需用户介入”等组合异步状态。

      • 复杂图形解析工具:应用往往涉及大量的中间态保存、节点解析重试、以及频繁的与服务端的同步(Save Draft, Commit Changes),开发者需要 useMutation 强大的生命周期来控制这些复杂的异步交互流,并在生成失败时优雅地回滚 UI。

      diff --git "a/01.\345\205\250\346\240\210/80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273/01.\347\274\226\350\257\221\344\270\216\350\260\203\350\257\225 TypeScript \351\241\271\347\233\256\346\214\207\345\215\227.html" b/fullstack/typescript-compilation-debugging-guide.html similarity index 88% rename from "01.\345\205\250\346\240\210/80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273/01.\347\274\226\350\257\221\344\270\216\350\260\203\350\257\225 TypeScript \351\241\271\347\233\256\346\214\207\345\215\227.html" rename to fullstack/typescript-compilation-debugging-guide.html index 9f0e7362..71324245 100644 --- "a/01.\345\205\250\346\240\210/80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273/01.\347\274\226\350\257\221\344\270\216\350\260\203\350\257\225 TypeScript \351\241\271\347\233\256\346\214\207\345\215\227.html" +++ b/fullstack/typescript-compilation-debugging-guide.html @@ -6,12 +6,12 @@ TypeScript 编译与调试完全指南 | Insight Stack - + - - - - + + + + @@ -30,7 +30,7 @@ - +
      Skip to content

      TypeScript 编译与调试完全指南

      摘要总结: TypeScript 作为 JavaScript 的静态类型超集,不仅提供了类型安全,还构建了完善的编译工具链和调试能力。本文系统梳理 TypeScript 项目的编译与调试全流程,涵盖 TSC 编译器使用、tsconfig.json 各场景配置(单体项目、Monorepo 多包项目)、source map 浏览器调试、ESLint 静态检查与 Jest 单元测试等工程实践。通过对编译选项(strict、module、moduleResolution、incremental 等)的详细解读,以及 React+Vite、Node.js、npm 库等典型项目配置示例,帮助读者建立对 TypeScript 编译体系的完整认知。掌握这些核心技能,能够帮助开发者更高效地构建和维护高质量的 TypeScript 应用。

      编写代码只是开发工作的起点,真正决定项目质量的是后续的编译与调试环节。TypeScript 作为 JavaScript 的静态类型超集,不仅带来了类型安全,更提供了强大的编译工具和调试能力,让我们能够更高效地构建和维护可靠的应用程序。

      本文将对 TypeScript 项目的编译与调试进行梳理,包括编译工具 TSC 的使用、编译选项的配置、调试工具的使用等。

      1. TypeScript 编译配置与 tsconfig.json

      TSC(TypeScript Compiler)是 TypeScript 官方提供的编译工具,负责将 TypeScript 代码(.ts.tsx)转换为 JavaScript 代码(.js.jsx)。

      虽然你可以直接在终端运行 tsc 命令来编译单个文件,但在实际项目中,我们通常需要处理大量文件。为了提高编译命令的复用性和可维护性,TypeScript 提供了配置文件的方式来管理编译设置:

      • 配置文件:使用 tsconfig.json 文件集中管理待编译文件路径、编译选项和输出路径等。你可以通过 tsc --init 命令快速生成一个默认配置文件,然后根据项目需求进行调整。
      • 配置位置:通常将 tsconfig.json 放在项目根目录下。对于 Monorepo 项目结构,每个子项目可以拥有独立的配置文件,实现更精细的编译控制。

      1.1 tsconfig.json 核心配置梳理

      以下是一个生产环境常用的 tsconfig.json 配置示例,包含了 TypeScript 核心编译选项的详细注释说明:

      json
      {
      +  

      TypeScript 编译与调试完全指南

      摘要总结: TypeScript 作为 JavaScript 的静态类型超集,不仅提供了类型安全,还构建了完善的编译工具链和调试能力。本文系统梳理 TypeScript 项目的编译与调试全流程,涵盖 TSC 编译器使用、tsconfig.json 各场景配置(单体项目、Monorepo 多包项目)、source map 浏览器调试、ESLint 静态检查与 Jest 单元测试等工程实践。通过对编译选项(strict、module、moduleResolution、incremental 等)的详细解读,以及 React+Vite、Node.js、npm 库等典型项目配置示例,帮助读者建立对 TypeScript 编译体系的完整认知。掌握这些核心技能,能够帮助开发者更高效地构建和维护高质量的 TypeScript 应用。

      编写代码只是开发工作的起点,真正决定项目质量的是后续的编译与调试环节。TypeScript 作为 JavaScript 的静态类型超集,不仅带来了类型安全,更提供了强大的编译工具和调试能力,让我们能够更高效地构建和维护可靠的应用程序。

      本文将对 TypeScript 项目的编译与调试进行梳理,包括编译工具 TSC 的使用、编译选项的配置、调试工具的使用等。

      1. TypeScript 编译配置与 tsconfig.json

      TSC(TypeScript Compiler)是 TypeScript 官方提供的编译工具,负责将 TypeScript 代码(.ts.tsx)转换为 JavaScript 代码(.js.jsx)。

      虽然你可以直接在终端运行 tsc 命令来编译单个文件,但在实际项目中,我们通常需要处理大量文件。为了提高编译命令的复用性和可维护性,TypeScript 提供了配置文件的方式来管理编译设置:

      • 配置文件:使用 tsconfig.json 文件集中管理待编译文件路径、编译选项和输出路径等。你可以通过 tsc --init 命令快速生成一个默认配置文件,然后根据项目需求进行调整。
      • 配置位置:通常将 tsconfig.json 放在项目根目录下。对于 Monorepo 项目结构,每个子项目可以拥有独立的配置文件,实现更精细的编译控制。

      1.1 tsconfig.json 核心配置梳理

      以下是一个生产环境常用的 tsconfig.json 配置示例,包含了 TypeScript 核心编译选项的详细注释说明:

      json
      {
         /*
          * ============================================
          * 编译信息配置
      @@ -718,7 +718,7 @@
           "test:watch": "jest --watch",
           "test:coverage": "jest --coverage"
         }
      -}

      运行测试:

      bash
      npm test

      4.2.5 高级特性

      Jest 还提供了一些高级特性,如异步测试、模拟函数、快照测试等,可以满足各种复杂的测试需求。更多详细信息请可参考 Jest 官方文档

      • 异步测试:支持 Promise 和 async/await
      • 模拟函数:使用 jest.fn() 创建模拟函数
      • 快照测试:生成组件或数据结构的快照
      • 测试覆盖率:自动生成覆盖率报告

      5. 结语

      TypeScript 的价值不仅在于静态类型检查带来的代码提示和编译时错误发现,更在于其完善的编译体系、调试能力和配套的质量保障工具。

      在实际项目中,我们需要关注以下几个层面:

      关注层面说明
      配置管理合理规划 tsconfig.json 的分层结构,无论是单体项目还是 Monorepo 架构,都能通过 extendsreferences 实现配置的复用与独立定制。
      代码质量ESLint 和 Prettier 与 TypeScript 相辅相成,前者保障代码规范,后者统一代码风格,共同减少团队协作中的摩擦。
      调试体验善用 source map 等调试技术,在保持源码可读性的同时,不牺牲生产环境的性能。
      测试覆盖完善的测试用例是类型检查之外的最后一道防线,Jest 等工具让我们能够更自信地进行代码重构。

      掌握这些编译与调试的核心技能,能够帮助我们更高效地构建和维护高质量的 TypeScript 应用。希望本文能为你的项目实践提供一些参考和帮助。

      +}

      运行测试:

      bash
      npm test

      4.2.5 高级特性

      Jest 还提供了一些高级特性,如异步测试、模拟函数、快照测试等,可以满足各种复杂的测试需求。更多详细信息请可参考 Jest 官方文档

      • 异步测试:支持 Promise 和 async/await
      • 模拟函数:使用 jest.fn() 创建模拟函数
      • 快照测试:生成组件或数据结构的快照
      • 测试覆盖率:自动生成覆盖率报告

      5. 结语

      TypeScript 的价值不仅在于静态类型检查带来的代码提示和编译时错误发现,更在于其完善的编译体系、调试能力和配套的质量保障工具。

      在实际项目中,我们需要关注以下几个层面:

      关注层面说明
      配置管理合理规划 tsconfig.json 的分层结构,无论是单体项目还是 Monorepo 架构,都能通过 extendsreferences 实现配置的复用与独立定制。
      代码质量ESLint 和 Prettier 与 TypeScript 相辅相成,前者保障代码规范,后者统一代码风格,共同减少团队协作中的摩擦。
      调试体验善用 source map 等调试技术,在保持源码可读性的同时,不牺牲生产环境的性能。
      测试覆盖完善的测试用例是类型检查之外的最后一道防线,Jest 等工具让我们能够更自信地进行代码重构。

      掌握这些编译与调试的核心技能,能够帮助我们更高效地构建和维护高质量的 TypeScript 应用。希望本文能为你的项目实践提供一些参考和帮助。

      diff --git "a/01.\345\205\250\346\240\210/80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273/10.\350\201\212\344\270\200\350\201\212 Typescript \346\263\233\345\236\213.html" b/fullstack/typescript-generic-types.html similarity index 83% rename from "01.\345\205\250\346\240\210/80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273/10.\350\201\212\344\270\200\350\201\212 Typescript \346\263\233\345\236\213.html" rename to fullstack/typescript-generic-types.html index 1465c730..db28b6ba 100644 --- "a/01.\345\205\250\346\240\210/80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273/10.\350\201\212\344\270\200\350\201\212 Typescript \346\263\233\345\236\213.html" +++ b/fullstack/typescript-generic-types.html @@ -6,12 +6,12 @@ 聊一聊 TypeScript 中的泛型 | Insight Stack - + - - - - + + + + @@ -30,7 +30,7 @@ - +
      Skip to content

      聊一聊 TypeScript 中的泛型

      摘要总结: 泛型(Generics)是 TypeScript 中一种强大的类型系统特性,允许定义类型参数化的组件,使代码能够在多种类型上安全运行,同时保持类型检查。本文从泛型的基本概念出发,对比泛型与 any 类型的本质差异(类型安全、代码复用、类型推断、可读性),深入剖析类型参数化、类型检查、类型推断与类型擦除四方面工作原理。通过大量实战代码演示泛型函数、泛型接口、泛型类及泛型类型别名的高级应用,并系统讲解基本类型约束、接口约束、多重约束与 keyof 约束等高阶用法。泛型的学习路径本质上是从具体到抽象的思维训练,掌握泛型意味着掌握了 TypeScript 类型系统高阶能力的钥匙。

      1. 泛型的基本概念和作用

      1.1 核心定义

      泛型(Generics) 是 TypeScript 中一种强大的类型系统特性,允许定义类型参数化的组件,使代码能够在多种类型上安全运行,同时保持类型检查。泛型的核心思想是将类型作为参数传递给函数、接口或类,实现"编写一次,复用多次"的效果。

      1.2 泛型与 any 类型的对比

      特性泛型any 类型
      类型安全✅ 编译时进行类型检查❌ 完全失去类型检查
      代码复用✅ 支持多种类型复用✅ 支持多种类型,但失去类型信息
      类型推断✅ 编译器可推断具体类型❌ 无法推断具体类型
      可读性✅ 明确类型意图❌ 隐藏类型信息

      1.3 泛型的工作原理

      理解泛型的工作原理,需要从四个方面来把握:

      1、类型参数化

      当我们定义一个泛型函数 function foo<T>(arg: T): T 时,T 就像是一个"位置的占位符"。在编写代码时,我们还不知道 T 具体是什么类型,但它已经具备了类型的语义——在参数位置、返回值位置,甚至是后续的变量声明中,T 都会被当作一个有效的类型来使用。

      2、类型检查

      TypeScript 编译器会对泛型代码进行严格的类型检查。例如,在函数体内对 T 类型的参数调用只有特定类型才有的方法时,编译器会报错。这种检查发生在编译阶段,而不是运行时,从而避免了许多潜在的 bug。

      3、类型推断

      当我们调用泛型函数时,TypeScript 会根据传入的参数自动推断 T 的具体类型。比如调用 identity(42),编译器自动推断 Tnumber。这一步是可选的,如果无法推断,我们也可以显式指定类型参数 identity<number>(42)

      4、类型擦除

      这是泛型的一个重要特性——泛型类型信息只存在于编译阶段。编译为 JavaScript 时,所有 <T> 相关的类型标注都会被擦除,只保留普通的类型注释或完全没有任何类型信息。例如 function identity<T>(arg: T): T 编译后会变成 function identity(arg) { return arg; },最终产物中不存在任何泛型的痕迹。

      1.4 泛型的核心优势

      泛型之所以重要,是因为它解决了 JavaScript 类型系统中的几个核心问题:

      核心优势说明
      代码复用性的质变在没有泛型的时代,如果我们想让一个函数同时支持 string 和 number 类型,通常需要编写两个独立函数,或者使用 any 类型牺牲类型安全。而泛型让我们编写一套代码,就能安全地处理多种类型。例如,一个 identity 函数既可以处理 number,也可以处理 string,甚至是自定义的对象类型。
      类型安全是最大的保障使用 any 类型意味着彻底放弃类型检查,任何类型错误都要到运行时才能发现。而泛型在编译阶段就能捕获类型不匹配的问题,将 bug 消灭在摇篮里。这对于大型项目尤为重要,因为运行时类型错误往往难以定位和修复。
      代码意图更加清晰any 类型像是一个"黑箱",开发者无法从类型声明中得知这个值应该是什么类型。而泛型 Array<T>Promise<T> 等声明方式,让代码自描述性更强,后续维护者能够快速理解数据的结构和流向。
      面向未来的扩展性基于泛型设计的接口和类,不需要修改原有代码就能支持新的数据类型。比如我们定义了一个 Response<T> 接口,当业务需要新增一种数据类型时,只需要传入新的类型参数即可,而无需改动接口定义本身。
      推动更好的设计泛型鼓励开发者从一开始就从通用的角度思考问题,设计出更具抽象性和复用性的组件。这种思考方式与面向对象设计模式中的"依赖倒置"、"开闭原则"等思想不谋而合。

      1.5 泛型的应用场景

      泛型在实际开发中的应用非常广泛,以下是几个最常见的场景:

      应用场景说明
      通用数据结构的实现数据结构往往是通用的——一个栈不应该只能存储 number,它应该能存储任意类型。泛型让我们能够定义如 Stack<T>Queue<T>LinkedList<T> 这样真正通用的数据结构,同时保持对内部元素类型的严格检查。
      工具函数和类库开发日常开发中的工具函数,如深拷贝、JSON 序列化、数组处理等,都非常适合使用泛型。这类函数需要处理各种不同的数据类型,泛型能够在保持类型安全的同时,实现真正的复用。
      API 响应数据的类型化与后端接口交互时,响应数据的结构往往是固定的,但具体的数据类型可能不同。通过泛型 ApiResponse<T>,我们可以为每个接口定义精确的返回类型,同时保持 API 请求逻辑的统一。
      前端组件库开发在 React、Vue 等框架中,组件通常需要处理各种类型的 props 和 state。泛型组件如 Table<T>List<T> 等,能够在提供类型安全的同时,适应不同的业务数据模型。
      通用接口和类的设计面向对象编程中,我们经常需要定义一些有通用约束的接口。比如定义一个 Repository<T> 接口,所有实体仓储都实现这个接口,但每个仓储操作的实体类型各不相同。泛型让这种设计成为可能。

      2. 泛型代码示例

      2.1 基础泛型函数

      typescript
      // 泛型标识函数:返回与输入相同类型的值
      +  

      聊一聊 TypeScript 中的泛型

      摘要总结: 泛型(Generics)是 TypeScript 中一种强大的类型系统特性,允许定义类型参数化的组件,使代码能够在多种类型上安全运行,同时保持类型检查。本文从泛型的基本概念出发,对比泛型与 any 类型的本质差异(类型安全、代码复用、类型推断、可读性),深入剖析类型参数化、类型检查、类型推断与类型擦除四方面工作原理。通过大量实战代码演示泛型函数、泛型接口、泛型类及泛型类型别名的高级应用,并系统讲解基本类型约束、接口约束、多重约束与 keyof 约束等高阶用法。泛型的学习路径本质上是从具体到抽象的思维训练,掌握泛型意味着掌握了 TypeScript 类型系统高阶能力的钥匙。

      1. 泛型的基本概念和作用

      1.1 核心定义

      泛型(Generics) 是 TypeScript 中一种强大的类型系统特性,允许定义类型参数化的组件,使代码能够在多种类型上安全运行,同时保持类型检查。泛型的核心思想是将类型作为参数传递给函数、接口或类,实现"编写一次,复用多次"的效果。

      1.2 泛型与 any 类型的对比

      特性泛型any 类型
      类型安全✅ 编译时进行类型检查❌ 完全失去类型检查
      代码复用✅ 支持多种类型复用✅ 支持多种类型,但失去类型信息
      类型推断✅ 编译器可推断具体类型❌ 无法推断具体类型
      可读性✅ 明确类型意图❌ 隐藏类型信息

      1.3 泛型的工作原理

      理解泛型的工作原理,需要从四个方面来把握:

      1、类型参数化

      当我们定义一个泛型函数 function foo<T>(arg: T): T 时,T 就像是一个"位置的占位符"。在编写代码时,我们还不知道 T 具体是什么类型,但它已经具备了类型的语义——在参数位置、返回值位置,甚至是后续的变量声明中,T 都会被当作一个有效的类型来使用。

      2、类型检查

      TypeScript 编译器会对泛型代码进行严格的类型检查。例如,在函数体内对 T 类型的参数调用只有特定类型才有的方法时,编译器会报错。这种检查发生在编译阶段,而不是运行时,从而避免了许多潜在的 bug。

      3、类型推断

      当我们调用泛型函数时,TypeScript 会根据传入的参数自动推断 T 的具体类型。比如调用 identity(42),编译器自动推断 Tnumber。这一步是可选的,如果无法推断,我们也可以显式指定类型参数 identity<number>(42)

      4、类型擦除

      这是泛型的一个重要特性——泛型类型信息只存在于编译阶段。编译为 JavaScript 时,所有 <T> 相关的类型标注都会被擦除,只保留普通的类型注释或完全没有任何类型信息。例如 function identity<T>(arg: T): T 编译后会变成 function identity(arg) { return arg; },最终产物中不存在任何泛型的痕迹。

      1.4 泛型的核心优势

      泛型之所以重要,是因为它解决了 JavaScript 类型系统中的几个核心问题:

      核心优势说明
      代码复用性的质变在没有泛型的时代,如果我们想让一个函数同时支持 string 和 number 类型,通常需要编写两个独立函数,或者使用 any 类型牺牲类型安全。而泛型让我们编写一套代码,就能安全地处理多种类型。例如,一个 identity 函数既可以处理 number,也可以处理 string,甚至是自定义的对象类型。
      类型安全是最大的保障使用 any 类型意味着彻底放弃类型检查,任何类型错误都要到运行时才能发现。而泛型在编译阶段就能捕获类型不匹配的问题,将 bug 消灭在摇篮里。这对于大型项目尤为重要,因为运行时类型错误往往难以定位和修复。
      代码意图更加清晰any 类型像是一个"黑箱",开发者无法从类型声明中得知这个值应该是什么类型。而泛型 Array<T>Promise<T> 等声明方式,让代码自描述性更强,后续维护者能够快速理解数据的结构和流向。
      面向未来的扩展性基于泛型设计的接口和类,不需要修改原有代码就能支持新的数据类型。比如我们定义了一个 Response<T> 接口,当业务需要新增一种数据类型时,只需要传入新的类型参数即可,而无需改动接口定义本身。
      推动更好的设计泛型鼓励开发者从一开始就从通用的角度思考问题,设计出更具抽象性和复用性的组件。这种思考方式与面向对象设计模式中的"依赖倒置"、"开闭原则"等思想不谋而合。

      1.5 泛型的应用场景

      泛型在实际开发中的应用非常广泛,以下是几个最常见的场景:

      应用场景说明
      通用数据结构的实现数据结构往往是通用的——一个栈不应该只能存储 number,它应该能存储任意类型。泛型让我们能够定义如 Stack<T>Queue<T>LinkedList<T> 这样真正通用的数据结构,同时保持对内部元素类型的严格检查。
      工具函数和类库开发日常开发中的工具函数,如深拷贝、JSON 序列化、数组处理等,都非常适合使用泛型。这类函数需要处理各种不同的数据类型,泛型能够在保持类型安全的同时,实现真正的复用。
      API 响应数据的类型化与后端接口交互时,响应数据的结构往往是固定的,但具体的数据类型可能不同。通过泛型 ApiResponse<T>,我们可以为每个接口定义精确的返回类型,同时保持 API 请求逻辑的统一。
      前端组件库开发在 React、Vue 等框架中,组件通常需要处理各种类型的 props 和 state。泛型组件如 Table<T>List<T> 等,能够在提供类型安全的同时,适应不同的业务数据模型。
      通用接口和类的设计面向对象编程中,我们经常需要定义一些有通用约束的接口。比如定义一个 Repository<T> 接口,所有实体仓储都实现这个接口,但每个仓储操作的实体类型各不相同。泛型让这种设计成为可能。

      2. 泛型代码示例

      2.1 基础泛型函数

      typescript
      // 泛型标识函数:返回与输入相同类型的值
       // <T>:类型参数,代表任意类型
       // arg: T:参数类型为 T
       // : T:返回值类型为 T
      @@ -505,7 +505,7 @@
       
       // 编译报错:普通对象不是 DatabaseModel 的子类
       // const plainObject = { id: 1, name: 'Test' };
      -// saveToDatabase(plainObject);

      4.6 小结

      泛型约束是 TypeScript 泛型系统中的核心机制,通过限制泛型参数的类型范围,实现了类型安全与代码复用的平衡。不同类型的泛型约束适用于不同的场景:

      约束类型适用场景说明
      基本类型约束需要处理特定基本类型的场景如数字、字符串等,确保可以安全使用 .length.toFixed() 等内置方法
      接口约束项目开发中最常用的约束形式通过定义接口规范数据结构,确保数据具有预期的属性和方法,如 extends HasName 约束对象必须有 name 属性
      多重约束需要泛型参数具备多种能力的场景通过 & 操作符组合多个约束条件,如 <T extends HasName & HasId> 要求同时满足多个接口
      Keyof 约束构建类型安全的属性访问工具函数结合 keyof 操作符实现,如 <T, K extends keyof T> 确保访问的属性确实存在于对象中
      类约束处理继承体系的场景确保泛型参数是某个基类的子类,继承其属性和方法,常用于数据库模型、UI 组件等场景

      泛型约束的核心价值在于平衡类型安全代码通用性

      价值维度体现
      质量编译期捕获类型错误,减少运行时异常
      复用通用的函数和组件,一次编写,多处复用
      可读明确的类型约束,让代码意图一目了然
      扩展灵活应对复杂的数据结构和继承关系

      泛型约束与接口、keyof、类等特性结合,构成了 TypeScript 类型系统的高阶能力,是构建大型可靠应用的重要基础。

      5. 结语

      泛型不仅仅是一种语法特性,更是一种抽象思维的体现。

      从本文可以看到,泛型的学习曲线实际上是从具体到抽象的过程:起初我们学习 <T> 的写法、基本函数的使用;进而理解约束、keyof、多重泛型等高阶用法;最终,我们学会用泛型的思维方式去设计通用的数据结构、工具函数和组件接口。

      这条学习路径,本质上与软件设计中"从特殊到一般"的抽象能力培养路径一致。一个真正掌握了泛型的开发者,看待问题的角度会发生转变——不再满足于"针对这个具体问题写这段具体代码",而是会思考"这个问题能否抽象成一个通用方案,让未来类似的问题也能复用"

      这种思维方式的价值远超泛型本身,它会渗透到代码设计的方方面面。TypeScript 的类型系统是一座宝库,泛型只是其中的一个子集。希望本文不仅帮助你掌握了泛型,更帮助你窥见了 TypeScript 类型系统的魅力所在。

      +// saveToDatabase(plainObject);

      4.6 小结

      泛型约束是 TypeScript 泛型系统中的核心机制,通过限制泛型参数的类型范围,实现了类型安全与代码复用的平衡。不同类型的泛型约束适用于不同的场景:

      约束类型适用场景说明
      基本类型约束需要处理特定基本类型的场景如数字、字符串等,确保可以安全使用 .length.toFixed() 等内置方法
      接口约束项目开发中最常用的约束形式通过定义接口规范数据结构,确保数据具有预期的属性和方法,如 extends HasName 约束对象必须有 name 属性
      多重约束需要泛型参数具备多种能力的场景通过 & 操作符组合多个约束条件,如 <T extends HasName & HasId> 要求同时满足多个接口
      Keyof 约束构建类型安全的属性访问工具函数结合 keyof 操作符实现,如 <T, K extends keyof T> 确保访问的属性确实存在于对象中
      类约束处理继承体系的场景确保泛型参数是某个基类的子类,继承其属性和方法,常用于数据库模型、UI 组件等场景

      泛型约束的核心价值在于平衡类型安全代码通用性

      价值维度体现
      质量编译期捕获类型错误,减少运行时异常
      复用通用的函数和组件,一次编写,多处复用
      可读明确的类型约束,让代码意图一目了然
      扩展灵活应对复杂的数据结构和继承关系

      泛型约束与接口、keyof、类等特性结合,构成了 TypeScript 类型系统的高阶能力,是构建大型可靠应用的重要基础。

      5. 结语

      泛型不仅仅是一种语法特性,更是一种抽象思维的体现。

      从本文可以看到,泛型的学习曲线实际上是从具体到抽象的过程:起初我们学习 <T> 的写法、基本函数的使用;进而理解约束、keyof、多重泛型等高阶用法;最终,我们学会用泛型的思维方式去设计通用的数据结构、工具函数和组件接口。

      这条学习路径,本质上与软件设计中"从特殊到一般"的抽象能力培养路径一致。一个真正掌握了泛型的开发者,看待问题的角度会发生转变——不再满足于"针对这个具体问题写这段具体代码",而是会思考"这个问题能否抽象成一个通用方案,让未来类似的问题也能复用"

      这种思维方式的价值远超泛型本身,它会渗透到代码设计的方方面面。TypeScript 的类型系统是一座宝库,泛型只是其中的一个子集。希望本文不仅帮助你掌握了泛型,更帮助你窥见了 TypeScript 类型系统的魅力所在。

      diff --git "a/01.\345\205\250\346\240\210/80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273/20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227/4.Typescript \345\257\271\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\347\232\204\345\242\236\345\274\272.html" b/fullstack/typescript-module-programming-enhancement.html similarity index 74% rename from "01.\345\205\250\346\240\210/80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273/20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227/4.Typescript \345\257\271\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\347\232\204\345\242\236\345\274\272.html" rename to fullstack/typescript-module-programming-enhancement.html index cb213e50..e9761e3e 100644 --- "a/01.\345\205\250\346\240\210/80.\345\205\250\346\240\210\345\237\272\347\241\200\347\264\240\345\205\273/20.\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\345\256\236\350\267\265\346\214\207\345\215\227/4.Typescript \345\257\271\346\250\241\345\235\227\345\214\226\347\274\226\347\250\213\347\232\204\345\242\236\345\274\272.html" +++ b/fullstack/typescript-module-programming-enhancement.html @@ -6,12 +6,12 @@ 从逻辑隔离到类型契约:TypeScript 对模块化编程的增强 | Insight Stack - + - - - - + + + + @@ -30,7 +30,7 @@ - +
      Skip to content

      从逻辑隔离到类型契约:TypeScript 对模块化编程的增强

      摘要总结: TypeScript 将模块间的依赖关系从简单的代码引用提升为编译时类型契约。本文系统讲解 TypeScript 对 ES Modules 的类型增强,涵盖 import type 运行时优化、接口契约、声明文件 .d.ts 及 tsconfig 模块化配置。

      1. 引言

      在原生 JavaScript 模块化解决了代码组织问题后,TypeScript(TS)进一步将其推向了工业级高度。TS 不仅仅是为模块添加了类型标注,它通过类型导出导入、编译时优化、以及声明文件系统,将模块间的依赖关系从简单的“代码引用”提升到了“契约交互”。

      本文我们将聚焦于 TypeScript 如何通过类型系统增强模块化编程,并探讨在现代工程(尤其是 TS 5.0+ 时代)下的最佳配置实践。

      2. 类型导出与导入:极致的运行时优化

      TypeScript 对 ES Modules 语法最显著的扩展是支持“仅类型”(Type-only)的导出与导入。这不仅是语义上的清晰,更是性能优化的关键——类型导入在编译为 JS 后会被完全抹除,确保不会引入冗余的运行时负载。

      示例代码

      typescript
      // types.ts - 类型导出
      +  

      从逻辑隔离到类型契约:TypeScript 对模块化编程的增强

      摘要总结: TypeScript 将模块间的依赖关系从简单的代码引用提升为编译时类型契约。本文系统讲解 TypeScript 对 ES Modules 的类型增强,涵盖 import type 运行时优化、接口契约、声明文件 .d.ts 及 tsconfig 模块化配置。

      1. 引言

      在原生 JavaScript 模块化解决了代码组织问题后,TypeScript(TS)进一步将其推向了工业级高度。TS 不仅仅是为模块添加了类型标注,它通过类型导出导入、编译时优化、以及声明文件系统,将模块间的依赖关系从简单的“代码引用”提升到了“契约交互”。

      本文我们将聚焦于 TypeScript 如何通过类型系统增强模块化编程,并探讨在现代工程(尤其是 TS 5.0+ 时代)下的最佳配置实践。

      2. 类型导出与导入:极致的运行时优化

      TypeScript 对 ES Modules 语法最显著的扩展是支持“仅类型”(Type-only)的导出与导入。这不仅是语义上的清晰,更是性能优化的关键——类型导入在编译为 JS 后会被完全抹除,确保不会引入冗余的运行时负载。

      示例代码

      typescript
      // types.ts - 类型导出
       export interface User {
         id: string;
         name: string;
      @@ -253,7 +253,7 @@
       
       // app.ts
       import { power } from './math.js';
      -console.log(power(2, 3)); // 输出:8

      8. 结语:构建稳固的类型防线

      TypeScript 对模块化的增强,本质上是将工程质量的保障从“运行时测试”提前到了“编译时检查”。通过合理使用类型导入、规范的声明文件以及现代的编译配置,我们可以构建起一套坚不可摧的代码契约。

      在全栈开发的语境下,这种增强不仅限于前端。当我们在 Node.js 服务端和 React 前端之间共享一套类型声明模块时,就会发现“全栈一致性”才真正从理想变成了现实。

      +console.log(power(2, 3)); // 输出:8

      8. 结语:构建稳固的类型防线

      TypeScript 对模块化的增强,本质上是将工程质量的保障从“运行时测试”提前到了“编译时检查”。通过合理使用类型导入、规范的声明文件以及现代的编译配置,我们可以构建起一套坚不可摧的代码契约。

      在全栈开发的语境下,这种增强不仅限于前端。当我们在 Node.js 服务端和 React 前端之间共享一套类型声明模块时,就会发现“全栈一致性”才真正从理想变成了现实。

      diff --git a/growth/books.html b/growth/books.html new file mode 100644 index 00000000..ca44b95a --- /dev/null +++ b/growth/books.html @@ -0,0 +1,177 @@ + + + + + + 好书推荐 | Insight Stack + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      Skip to content
      1847
      + + + + 6.4m

      好书推荐

      1. AI 与数学思维

      在大模型发展日新月异的今天,理解 AI 本质上是在升级我们资深的“认知操作系统”, 理解 AI,本质上是理解数据、数学与逻辑如何重构这个世界

      这套书单从数学思维的底层逻辑出发,让我们理解 ChatGPT 等大模型背后的计算机制,将硬核的神经网络与概率统计转化为优化生活的决策工具。它不仅能界定机器智能的边界,更颠覆了传统的“目标论”,倡导在不确定性中通过“踏脚石”思维寻找突破性创新的可能。AI 的研究实践告诉我们,伟大的突破往往无法被预设,唯有拥抱“寻宝者思维”才能在未知中偶遇奇迹,我们需要颠覆传统的创新范式。

      心中有数:生活中的数学思维
      点击查看详情
      《心中有数:生活中的数学思维》
      刘雪峰
      4.9
      数学思维科普决策

      本书通过大量贴近日常的例子,展示数学思维如何优化我们的生活决策。作者用概率、统计、最优化等数学工具,为生活、职场、人际交往中的权衡问题提供分析框架,帮助读者在面对不确定性时像计算机一样找到“最优解”。

      智慧的疆界:从图灵机到人工智能
      点击查看详情
      《智慧的疆界:从图灵机到人工智能》
      周志明
      5.0
      人工智能科技史通识读物

      本书是一部面向大众的人工智能通识读物。作者周明以时间为主线,将人工智能的发展历程、关键人物与里程碑事件串联起来,从五个维度展开:学术理论、历史沿革、技术应用、研究成果以及面临的困难与未来挑战。全书旨在用通俗的语言和巧妙的结构,把人工智能从“阳春白雪”的学术殿堂带到公众视野,帮助读者理解 AI 能做什么、做不到什么,以及背后的技术与思想根源。

      为什么伟大不能被计划
      点击查看详情
      《为什么伟大不能被计划》
      肯尼斯·斯坦利 / 乔尔·雷曼
      4.5
      人工智能创新思维认知科学

      本书由两位前沿AI科学家合著,提出了颠覆传统“目标-计划”思维的全新视角。结合AI研究实践,书中论证了伟大成就往往并非出自精心设计的蓝图,而是源于对未知的好奇、随机探索与不断试错。通过“寻宝者思维”和“踏脚石模型”等方法,为读者在高度不确定的环境中激发突破性创新提供了具体的行动框架。

      这就是ChatGPT
      点击查看详情
      《这就是ChatGPT》
      斯蒂芬·沃尔弗拉姆
      4.3
      人工智能大模型ChatGPT

      本书由著名科学家斯蒂芬·沃尔弗拉姆撰写,全景式拆解了ChatGPT的内部工作机制。作者用通俗语言解释了神经网络和自回归架构等核心技术,探讨了简单的计算规则如何涌现出令人惊叹的智能,帮助读者深刻理解大语言模型为何能生成高质量的人类水平文本。

      人工智能:现代方法(第4版)(上下册)
      点击查看详情
      《人工智能:现代方法(第4版)(上下册)》
      [美]斯图尔特·罗素(Stuart Russell) / [美]彼得·诺维格(Peter Norvig)
      5.0
      人工智能教材理论实践结合经典著作计算机科学

      本书是人工智能领域的经典权威教材,系统、深入地探讨AI领域的理论与实践,以统一风格融合当今流行的AI思想与术语到前沿应用中,真正实现理论与实践相结合。全书分7个部分共28章,理论部分涵盖逻辑、概率、连续数学、感知、推理、学习、行动及公平、信任、社会公益和安全等社会议题;实践部分选取微电子设备、机器人行星探测器、在线服务、AlphaZero、人形机器人、自动驾驶、AI辅助医疗等热门场景。由加州大学伯克利分校教授斯图尔特·罗素与前谷歌研究总监彼得·诺维格联合撰写,被全球1500多所高校采用,适合作为AI相关专业本科生和研究生教材,也可作为专业人员的参考书。

      模型思维:简化世界的人工智能模型
      点击查看详情
      《模型思维:简化世界的人工智能模型》
      龚才春
      4.8
      模型思维人工智能算法模型机器学习入门实践

      本书聚焦“如何用模型简化世界”的核心主题,将人工智能在现实业务中面临的难题归纳为权重、状态、序列、表示、相似、分类六大问题,并围绕该框架讲解对应模型思路与算法。书中弱化复杂数学公式,以大量生活化、业务化案例阐释模型理论与落地场景,帮助读者建立“模型—场景”映射关系,降低AI模型学习门槛,既是人工智能初学者的入门读物,也可为企业工程师、科研人员提供实践参考,适合各类读者学习并将模型思维应用到生活与工作中。

      你看起来好像……我爱你:AI的工作原理以及它为这个世界带来的稀奇古怪
      点击查看详情
      《你看起来好像……我爱你:AI的工作原理以及它为这个世界带来的稀奇古怪》
      贾内尔·沙内
      4.2
      人工智能趣味科普漫画算法

      这是一部写给普通读者的人工智能趣味科普读物。作者贾内尔·沙内结合生活化的比喻和超级可爱的漫画,深入浅出地讲解了AI的基本工作原理、实际应用及其局限性。书中通过大量幽默的AI实验与“翻车”案例,带领读者在轻松捧腹的氛围中,准确理解算法能做什么、不能做什么。

      AI经济:机器人时代的工作、财富和社会福利
      点击查看详情
      《AI经济:机器人时代的工作、财富和社会福利》
      罗杰·布特尔
      4.1
      人工智能经济学社会学未来趋势

      本书由知名经济学家罗杰·布特尔撰写,聚焦AI与机器人技术对经济和社会的深远影响。作者拨开艰涩的科技术语,从经济增长、通货膨胀及财富分配等宏观视角,理性剖析AI革命将如何重塑我们的工作、教育与休闲方式,以乐观的姿态为迎接未来的社会变革指明路径。

      2. 产品与商业

      about site background

      2.1 产品 Sense 与创造

      在产品成功率不足 10% 的残酷市场中,好的创造绝非源于盲目的灵感,而是建立在极致的风险验证与深刻的人性洞察之上。

      卓越的产品力不仅关乎功能设计,更是一场关于策略与创造力的刻意练习:我们需要通过“预型”思维以极低成本进行真实数据验证,确保我们在投入开发前是在“做对产品”;并利用用户模型、交易模型等底层框架,将零散的需求转化为可获利的商业方案。

      做对产品
      点击查看详情
      《做对产品》
      阿尔贝托·索维亚
      4.8
      产品思维创业商业方法论

      谷歌首任产品总监阿尔贝托·索维亚结合在谷歌、斯坦福的实战经验与自身代价高昂的创业失败经历,总结出的一套防败手册。书中揭示了新产品高达90%的“市场失败律”,并创新性地提出了“预型”(Pre型)理念,指导团队在正式开发前,以极低的成本和真实数据快速验证关键假设,确保把创意打磨成“正确的它”。

      俞军产品方法论
      点击查看详情
      《俞军产品方法论》
      俞军
      4.4
      产品思维产品经理互联网方法论

      “百度贴吧之父”俞军二十余年产品实践与思考的系统总结。本书将产品经理定义为“以科学方法研究人性并转化为商业方案”的交叉学科,深入解析了用户模型、交易模型和决策模型三大核心框架,为产品人提供了一套在不确定环境中权衡多方利益的实战指南。

      策略产品经理:模型与方法论
      点击查看详情
      《策略产品经理:模型与方法论》
      青十五
      3.9
      产品经理策略产品算法思维

      本书围绕“策略产品经理”这一复合角色,系统性地构建了从理念到实践的完整知识框架。作者从机器学习理论与经济学视角出发,结合推荐、搜索、广告、风控等核心业务场景,深入浅出地讲解了函数建模与策略应用,并对策略产品经理的核心能力与团队建设给出了详尽指导。

      创造:用非传统方式做有价值的事
      点击查看详情
      《创造:用非传统方式做有价值的事》
      托尼·法德尔
      4.9
      产品思维管理学创业

      本书是iPod、iPhone、Nest等爆款产品幕后推手托尼·法德尔30余年职业经历的智慧结晶。作者毫无保留地分享了他在产品设计、团队管理、职业选择和公司经营等方面的“非传统”方法论,帮助读者在各自的领域内刻意练习创造力,做真正有价值的事。

      产品思维
      点击查看详情
      《产品思维》
      刘飞
      4.2
      产品思维产品经理个人成长互联网

      实战派产品经理刘飞结合在一线大厂的丰富经验,围绕产品人如何实现能力跃迁展开的底层能力指南。全书掰开揉碎地讲解了认知盲点与实践痛点,通过“认知用户”“创造价值”和“产品落地”三大核心板块,系统拆解了从建立用户模型、高质量决策到快速迭代验证的完整产品方法论。

      产品思维:创新设计的六条法则(全彩)
      点击查看详情
      《产品思维:创新设计的六条法则(全彩)》
      张印帅
      4.0
      产品设计创新思维方法论设计灵感

      本书围绕作者张印帅多年产品设计实践总结出的6条创意公式展开,旨在帮助读者系统化地获取设计灵感并解决创新难题。全书通过大量经典案例,详细解析了从发散思考到重组创新的全过程,并在最后提供了从需求到草图再到最终方案的完整项目落地演示。

      2.2 商业化

      在追逐“独角兽”和规模扩张的狂热迷思之后,真正的商业高手正在重新回归本质:盈利才是企业的核心护城河。 这套书单为我们揭示了一种更具韧性的商业路径——“小而美”的极简经营。它教导我们如何拒绝低效的内卷与忙碌,通过“做更少但创造更多价值”的思维,打造在不确定时代下依然能保持稳定现金流的“慢公司”。

      商业的成功,往往源于敢于挑战“难而正确”的事。从皮克斯如何建立允许失败的创意土壤,到 Waze 如何通过解决被忽视的痛点实现跨越式成长,这些世界级案例证明了:卓越的组织不仅需要极简的流程与高效的分布式协作(远程办公),更需要一种“冷静”的文化,将利润置于规模之上。

      小而美:持续盈利的经营法则
      点击查看详情
      《小而美:持续盈利的经营法则》
      萨希尔·拉文吉亚
      5.0
      创业商业模式极简主义

      本书打破了硅谷盲目追求“独角兽”的扩张迷思,聚焦于“规模不是唯一出路”的商业现实。作者结合创立Gumroad的亲身经历,提出了“极简创业经营”理念。全书指导创业者与管理者如何通过从社区切入、聚焦核心能力、精简团队等方式,用最少的资源打造出不仅能活下去,而且还能持续盈利的“慢公司”。

      做难而正确的事:进步最快的方式
      点击查看详情
      《做难而正确的事:进步最快的方式》
      尤里·莱文
      4.9
      创业产品思维商业管理

      Waze联合创始人尤里·莱文写给创业者和管理者的行动指南。作者结合连续打造两家估值超10亿美元公司的实战经验,提出“先做难事、再做正确事”的核心哲学。全书通过13个阶段的系统拆解,指导读者如何寻找真正的用户痛点、构建高价值产品,并在不确定的环境中通过不断复盘实现跨越式成长。

      创新公司:皮克斯的启示
      点击查看详情
      《创新公司:皮克斯的启示》
      艾德·卡特姆
      4.5
      创新思维组织文化企业管理

      皮克斯联合创始人艾德·卡特姆结合《玩具总动员》《机器人瓦力》等经典动画的幕后制作故事,深度揭示了皮克斯如何长期保持创意领先的秘密。本书不仅详述了皮克斯从初创到壮大的历程,更抽丝剥茧地解析了其在团队文化、跨部门协作、人才培养和允许失败等方面的独特创意管理机制,为各类组织提供了可复制的创新指南。

      重来:更为简单的商业思维
      点击查看详情
      《重来:更为简单的商业思维》
      贾森·弗里德 / 戴维·海涅迈尔·汉森
      4.3
      商业思维创业企业管理极简主义

      37signals联合创始人基于十年创业实战经验,写给职场人与创业者的极简商业法则。本书摒弃了传统的MBA术语与复杂的商业教条,以“辛辣、直接、靠谱”的语言,颠覆了关于项目管理、人才招聘、产品设计与企业文化的常规认知,教导读者如何在真实的商业世界中“做更少,但创造更多价值”。

      重来2:更为简单高效的远程工作方式
      点击查看详情
      《重来2:更为简单高效的远程工作方式》
      贾森·弗里德 / 戴维·海涅迈尔·汉森
      4.1
      企业管理远程工作工作方式团队协作

      Basecamp(原37signals)创始人基于自身团队多年的全球分布式协作经验,为企业和个人提供的一套远程工作“思想升级包”。本书直面行业争议,破解了“创新只能面对面”及“文化会淡化”等常见误区,并系统提供了借助异步沟通、协作工具与流程设计来打造高效、人性化远程团队的实战指南。

      重来3:做得更少,但赚得更多
      点击查看详情
      《重来3:做得更少,但赚得更多》
      贾森·弗里德 / 戴维·海涅迈尔·汉森
      4.2
      工作方式反内卷企业文化

      Basecamp创始人带来的“反内卷”与“反过度忙碌”的管理指南。作者基于近20年带领54人团队服务全球10万家企业的成功经验,直击现代企业盲目扩张、无效加班等八大症结。全书主张以“冷静”颠覆“忙碌”文化,指导企业和个人通过40小时工作制、拒绝KPI和异步沟通等极简方式,在不牺牲生活质量的前提下实现健康发展与持续盈利。

      3. 效率与效能

      在信息过载与高压竞争的现代环境中,平庸与卓越的分水岭不再是做事的速度,而是决策的精度与责任的边界。这套书单为我们提供了一套从个人认知到组织协作的“效能防线”:首先,它引导我们完成从“时钟”到“罗盘”的思维跨越,打破盲目追求速度的迷思,确保将核心精力倾注在真正产生长远复利的“重要非紧急”事务之上。 真正的效能源于对复杂性的科学驾驭:

      • 通过“清单革命”式的认知防护,我们将最佳实践外化为可靠的防错系统,弥补人类在极端环境下的认知局限;
      • “猴子管理法”则以生动的视角重塑了职场协作的责任逻辑,教我们通过有效授权拒绝无谓的干扰,释放战略思考的精力;
      要事第一
      点击查看详情
      《要事第一》
      史蒂芬·柯维 / 罗杰·梅里尔 / 丽贝卡·梅里尔
      4.5
      时间管理自我管理经典思维

      作为《高效能人士的七个习惯》的延伸与加强版,本书提出了颠覆传统的“第四代时间管理”方法。作者强调,比提升做事速度(时钟)更重要的是找准人生的方向(罗盘)。全书指导读者通过自我意识的觉醒,以原则和价值观为中心,将精力聚焦于“重要而不紧急”的长期目标上,从而在繁忙的现代生活中真正做到“要事第一”。

      清单革命
      点击查看详情
      《清单革命》
      阿图·葛文德
      4.6
      管理学认知科学工作效率

      这是一部针对现代复杂世界所撰写的“认知防护手册”。作者阿图·葛文德通过医疗、建筑、投资等高风险领域的真实案例,揭示了人类在海量信息与高压环境下极易出现的判断疏忽。书中提出了“权力下放、简单至上、人为根本、持续改善”四大原则,指导读者将最佳实践外化为可操作的清单,从而在复杂系统中构建一道低成本、高回报的安全防线。

      别让猴子跳回背上
      点击查看详情
      《别让猴子跳回背上》
      威廉·安肯三世
      4.3
      时间管理领导力项目管理

      这是一部以“猴子”生动隐喻任务与责任的经典管理学著作。作者威廉·安肯三世深刻剖析了管理者常被琐事淹没的时间困境,并提出系统化的“猴子管理法”。通过明确任务归属、责任递减与有效授权,指导管理者如何把不属于自己的“猴子”交出去,从而释放精力专注于最高价值的战略思考,实现团队与个人的共同成长。

      4. 学习与成长

      在信息爆炸与快速变革的时代,真正的成长不再是知识的被动堆砌,而是认知系统的彻底迭代。这套书单为我们构建了一个从底层思维到人生经营的闭环:

      • 首先,通过批判性思维与深度阅读夯实“元能力”,在泛滥的信息中识别本质,将他人的洞见转化为自己的血肉;
      • 其次,利用“检索力”打破信息差,确保自己在任何领域都能快速获取高质量资源,掌握逆风而行的主动权。

      人生不是一场盲目的长跑,而是一场基于“原则”的精密经营。从达利欧的系统化决策,到纳瓦尔的财富与幸福逻辑,这些智者教导我们如何利用杠杆、坚持长期主义,将自己视作一家“人生有限公司”来经营。我们需要摆脱“优秀绵羊”式的被动驱动,通过识别成长的“第二曲线”,在巅峰时刻主动寻求突破,将自己打造成不可替代的稀缺资产。阅读这些经典,不仅是为了习得技能,更是为了在算法与焦虑的夹击中,重塑内心的宁静与独立判断的勇气。

      学会提问(原书第12版)
      点击查看详情
      《学会提问(原书第12版)》
      尼尔·布朗 / 斯图尔特·基利
      5.0
      批判性思维逻辑学认知科学经典书

      这是一部培养批判性思维的经典实战指南。作者尼尔·布朗与斯图尔特·基利结合长期的教学与研究实践,提供了一套系统化、可操作的提问流程。全书通过大量真实情境案例,教导读者如何在信息泛滥的时代识别隐含假设、区分事实与观点,用高质量的“判断性问题”看透事物本质,从而做出更理性的决策。

      如何阅读一本书
      点击查看详情
      《如何阅读一本书》
      莫提默·J. 艾德勒 / 查尔斯·范多伦
      5.0
      阅读方法思维训练经典

      阅读领域的“元方法”指南。作者艾德勒与范多伦将阅读划分为基础阅读、检视阅读、分析阅读与主题阅读四个进阶层次,并强调阅读是一项主动的思考活动。本书不仅提供了从“快速略读”到“系统拆解论点”的实操技巧,更致力于通过提问、归纳与批判,将阅读转化为训练理解力、批判力与终身学习的终极工具。

      检索力:打破信息差的科学方法
      点击查看详情
      《检索力:打破信息差的科学方法》
      龚芙蓉
      4.2
      信息素养检索能力思维认知

      本书聚焦“检索力”这一核心技能,旨在帮助读者在信息过载的时代主动掌握“逆风而行”的搜索能力。作者龚芙蓉结合二十余年实践经验,用生动的人文与诺贝尔奖级科学案例,将枯燥的检索工具化为有趣的故事。不仅教授非线性、迭代式的搜索技巧,更致力于重塑读者的探究精神,赋予其走出“信息茧房”的勇气。

      原则
      点击查看详情
      《原则》
      瑞·达利欧
      4.8
      投资方法论自我管理

      桥水基金创始人瑞·达利欧总结四十余年投资、管理与人生经验的集大成之作。作者提出将生活和工作像机器一样系统化,确立了“极度求真”与“极度透明”两大基石,并通过“创意择优”与“基于可信度的决策机制”来迭代思维。书中包含500多条可操作原则,旨在帮助读者在复杂世界中保持开放心态、看清现实,并做出最优决策。

      价值
      点击查看详情
      《价值》
      张磊
      4.6
      价值投资商业思维创业

      高瓴资本创始人张磊首部个人及投资思想著作。全书通过回顾作者的个人求学与创业历程,系统阐释了“长期主义”与“重仓中国”的核心投资理念,并首次披露了高瓴投资的七大公式。作者将十余个典型投资案例与个人价值修养相结合,揭示了如何在不确定的商业环境中,通过坚持原则、敬畏规则与持续创新,创造长久、真实的价值。

      纳瓦尔宝典
      点击查看详情
      《纳瓦尔宝典》
      埃里克·乔根森 / 纳瓦尔·拉维坎特
      4.7
      财富管理个人成长幸福哲学思维认知

      这是一部汇集硅谷著名投资人纳瓦尔·拉维坎特过去十年关于财富与幸福思考的行动指南。全书摒弃了“致富靠运气”的传统观念,提出积累财富与幸福生活是可以通过学习掌握的技能。通过系统整理推特、播客与访谈中的智慧,本书为读者提供了如何在快速变化的科技与经济环境中,利用杠杆、发挥个人独特性,进而实现财务自由并获得持久内心满足的方法论。

      优秀的绵羊
      点击查看详情
      《优秀的绵羊》
      威廉·德雷谢维奇
      4.2
      博雅教育社会学个人成长

      耶鲁大学前教授威廉·德雷谢维奇对美国常春藤精英教育体制的尖锐批判之作。作者通过二十余年的教学观察,指出顶尖学府培养出一群虽然聪明、优秀,但普遍焦虑、缺乏目标感且唯命是从的“优秀绵羊”。本书呼吁社会重新审视教育的本质,摆脱对名校与高薪的盲目崇拜,回归博雅教育,鼓励学生探索内在驱动力与自我价值。

      把自己变成稀缺资产
      点击查看详情
      《把自己变成稀缺资产》
      何思平
      4.2
      个人成长思维认知自我管理投资理财

      这是一个将“人生”视作“公司”来经营的实战指南。作者何思平结合自身从严重口吃到演讲冠军、再到连续创业成功的跨越式经历,提出了“人生有限公司”的经营哲学。全书通过“生命立方体”模型,从认知、实践、精力管理三个维度拆解了如何通过持续输出与跨界学习,将自己打造为具有高壁垒、不可替代的“稀缺资产”。

      成长第二曲线:跨越S型持续成长
      点击查看详情
      《成长第二曲线:跨越S型持续成长》
      查尔斯·汉迪
      4.5
      管理学个人成长人生哲学未来趋势

      管理大师查尔斯·汉迪的“人生长跑指南”。本书通过书信体形式,深度探讨了在数字时代背景下个人如何识别并跨越“第二曲线”。汉迪指出,无论组织还是个人,都受制于S型增长曲线,只有在第一曲线衰退前主动布局新的增长点,并保持内在价值的独立与进化,才能在不断变化的环境中获得持续且有意义的成长。

      5. 人文社科

      在宏观历史与微观现实间构建认知:在碎片化与不确定性并存的时代,穿透表象、直达本质的洞察力成为必需。这套单为我们开启了两扇窗:

      • 一扇望向万年文明的宏大坐标,通过《枪炮、病菌与钢铁》的跨学科视野,拆解地理环境如何冷酷而偶然地重塑全球版图,彻底颠覆“文明优越论”的傲慢;
      • 另一扇则照向当下社会的真实肌理,在梁晓声对各阶层生存困境的细腻描摹中,读懂大时代变革背后隐秘的结构性逻辑与阶层焦虑。

      人文思考的终极价值,在于如何将宏大叙事转化为个人的行动力量。正如项飙所倡导的“把自己作为方法”,这些著作不仅是知识的传递,更是思维的松绑。它们教导我们不再做时代的被动旁观者,而是学会在个人体验与宏观世界之间搭建桥梁,通过重建“附近”的小世界,在喧嚣中找准自我的定位。

      枪炮、病菌与钢铁
      点击查看详情
      《枪炮、病菌与钢铁》
      贾雷德·戴蒙德
      4.8
      人类历史地理决定论社会学跨学科

      一部重新定义人类历史发展的宏大著作。作者贾雷德·戴蒙德通过生物学、地理学、人类学等多学科交叉视角,强有力地反驳了“种族决定论”和“西方文明优越论”。他提出,决定文明兴衰的关键并非种族,而是环境因素、地理格局以及动植物驯化的差异,这些自然条件的偶然性最终导致了技术、免疫力和权力结构的差异,从而重塑了现代世界的全球版图。

      中国社会各阶层分析
      点击查看详情
      《中国社会各阶层分析》
      梁晓声
      4.3
      社会观察阶层研究现实主义

      茅盾文学奖得主梁晓声基于多年社会观察的现实题材力作。作者将快速变迁的中国社会划分为不同阶层,以平民视角细腻描摹各群体的生存状态、心理困境与阶层焦虑。全书不追求纯学术的枯燥分析,而是通过文学化的社会观察,勾勒出一幅当代中国社会的“浮世绘”,引导读者在时代坐标中找准定位,理解社会变迁背后的结构性逻辑。

      把自己作为方法
      点击查看详情
      《把自己作为方法》
      项飙 / 吴琦
      4.6
      社会学访谈录思想方法

      两代学人项飙与吴琦历时三年、跨越五地的深度对话实录。本书从项飙的个人经验切入,探讨了中国社会近半个世纪的变迁、全球化与民粹主义等宏大议题。在自我泛滥与思想受困的时代,作者提出“把自己作为方法”,指导读者如何在全球化年代重新定位自我、重建“附近”,并在个人体验与宏观叙事之间搭建起思考与行动的桥梁。

      6. 健康生活

      about site background

      在面临大概率活到100岁的“长寿时代”,传统的线性人生模式正在失效。我们需要对“健康”进行一次彻底的认知重构:健康不再仅仅是“没有疾病”,而是支撑我们跨越漫长生命周期、应对多阶段人生挑战的最核心“无形资产”。想要让这套生命系统长期平稳运行,真正的解法并不在医院的处方笺里,而是隐藏在我们每天的日常选择中。

      决定我们长期健康状态的,有 99 %取决于日常习惯。我们需要在休息、饮食、运动、睡眠这四个高频生活维度中,植入微小但杠杆率极高的改变(例如12小时进食窗口、10分钟高强度运动、睡前屏蔽数字通知等)。用最低的执行成本,置换身心状态的巨大回报。

      百岁人生:长寿时代的生活和工作
      点击查看详情
      《百岁人生:长寿时代的生活和工作》
      琳达·格拉顿 / 安德鲁·斯科特
      4.3
      人生规划长寿时代社会学

      基于伦敦商学院的经典课程,作者琳达·格拉顿与安德鲁·斯科特提出,面对一半概率活到100岁的长寿时代,传统的“学习-工作-退休”三段式人生模式已彻底失效。本书指导读者如何重新设计人生,通过拥抱多阶段人生模型,在更长的生命周期中平衡工作、学习与休闲,并强调在财务资产之外,更要注重健康、友谊与知识等“无形资产”的持续投入与增值。

      重启吧!我的健康人生
      点击查看详情
      《重启吧!我的健康人生》
      兰根·查特吉
      4.6
      生活方式预防医学身心健康自我管理

      英国临床医生基于20多年行医经验写就。本书主张“生活方式即良药”,围绕休息、饮食、运动和睡眠四个领域设计了20个微小行动计划,帮助现代人通过低成本的习惯改变逆转慢性问题。

      你是你吃出来的:吃对少生病,病了这样吃
      点击查看详情
      《你是你吃出来的:吃对少生病,病了这样吃》
      夏萌
      5.0
      饮食科普营养学健康管理

      前安贞医院营养科主任夏萌结合十余年临床经验写成。本书颠覆“低油低脂”误区,提出回归进化的“65%植物+35%动物”膳食配比,并针对14种常见慢病给出“四分法”饮食干预方案,帮助读者重建健康饮食观。

      你是你吃出来的2
      点击查看详情
      《你是你吃出来的2》
      夏萌
      4.6
      饮食指导科普疾病防治

      聚焦高血压、高脂血症、糖尿病等7大常见慢病,从临床营养医学角度逐一破除诸如“血压高不能吃肉”等饮食误区,提供系统的“上游-中游-下游”疾病防控思路与个体化营养处方。

      + + + + \ No newline at end of file diff --git "a/30.\346\202\246\350\257\273\346\227\266\345\205\211/21.\345\246\202\344\275\225\347\224\204\345\210\253\347\234\237\346\255\243\346\234\211\347\224\250\347\232\204\344\277\241\346\201\257.html" b/growth/distinguish-useful-information.html similarity index 61% rename from "30.\346\202\246\350\257\273\346\227\266\345\205\211/21.\345\246\202\344\275\225\347\224\204\345\210\253\347\234\237\346\255\243\346\234\211\347\224\250\347\232\204\344\277\241\346\201\257.html" rename to growth/distinguish-useful-information.html index 7b5e8f3b..31b2d6c9 100644 --- "a/30.\346\202\246\350\257\273\346\227\266\345\205\211/21.\345\246\202\344\275\225\347\224\204\345\210\253\347\234\237\346\255\243\346\234\211\347\224\250\347\232\204\344\277\241\346\201\257.html" +++ b/growth/distinguish-useful-information.html @@ -6,12 +6,12 @@ 如何甄别真正有用的信息 | Insight Stack - + - - - - + + + + @@ -30,7 +30,7 @@ - +
      Skip to content

      如何甄别真正有用的信息

      摘要总结:在信息高度透明的时代,浅层信息差已被彻底抹平,信息本身的价值不断稀释。人与人的核心差距不再是获取信息的渠道,而是高信噪比信息的甄别能力、深度思考能力与落地执行力,唯有以思考校验信息、以执行验证价值,形成“信息-判断-实践-反馈”的思考与执行闭环,才能突破信息壁垒、创造真正价值。

      在互联网技术普及的当下,信息已从“稀缺资源”转变为“泛滥资源”。过去依赖地域差、稀缺性的浅表层信息差逐渐被抹平,开发者通过网络可轻松获取各类技术文档、行业动态、赚钱模式,但真正能将信息转化为价值的仍是少数人。核心矛盾已从“获取信息”转变为“驾驭信息”——信息本身的价值弱化,而信息解读能力、行动执行力、筛选甄别力成为拉开差距的关键

      1. 打破“信息差”的系统性错觉

      过去,由于地域限制和传播介质的稀缺,赚钱或成功的模式往往是粗放的,建立在浅表层的“信息不对称”上,但随着技术的演进,这种低维度的信息差正在被迅速抹平。人们经常陷入“赚不到钱/抓不住机会是因为缺少信息差”的认知偏差,但本质问题在于“人本身的差距”,具体体现在三个层面:

      1.1 表面是你在筛选信息,实际是信息在筛选人

      举个最常见的例子:大家都知道做技术输出、写独立博客或做个人产品能带来长期的复利,但为什么真正跑通全栈并沉淀下来的人凤毛麟角?

      阻碍多数人的原因通常有三个:

      • 缺乏持久化机制、执行断层:无法在短期内看到正向反馈(ROI),导致进程中途中断,缺乏持续输出的执行力(如技术文章更新、用户运营)。
      • 缺乏深度计算:只是浮于表面的搬运,没有沉下心来对技术或业务进行深度解析与架构思考。
      • 对不确定性(Uncertainty)的恐惧:看不到确定性的回报,对投入产出比产生动摇,导致长期投入的决策被取消。

      面对这些公开的“赚钱/成长路径”,看似是我们在评估它,实际上是这些高门槛的路径在天然地筛选掉那些缺乏定力和长远产品嗅觉的人。

      1.2 警惕算法构建的“信息茧房”

      在网络推荐算法和同温层环境的双重作用下,我们每天接收的输入往往带有严重的偏置。这种不够客观的环境,容易导致我们在遇到真正有价值、但与既有认知冲突的客观观点时,产生本能的防御和抵触。

      对于开发者和内容创作者而言,打破认知茧房本身就是一种巨大的信息差。任何技术栈或商业模式,都需要博采众长。不要对非本领域的观点一味抛出异常,而是要建立辩证的“中间件”来过滤和吸收,做好信息的甄别与筛选。

      2. 信息泛滥与脑力带宽的消耗

      信息即权力,掌握高维信息的人确实拥有更强的资源调配能力。但关键在于,没有人有义务把复杂的底层逻辑拆解成现成的方法论,手把手教到完全理解为止。真正造成人与人之间差距的,是解析和编译信息的能力——同样的信息,不同的人能提炼出完全不同的价值。

      2.1 从“追求差”到“对抗泛滥”

      如今的问题早已不是信息匮乏,而是信息熵增与泛滥。这不仅带来了极度内卷的竞争,还伴随着传播过程中的信息失真。市面上很多被大肆宣扬的“风口”,仔细扒开源码就会发现:你所看到的,其实都是别人精心设计好让你看到的。

      当一个赛道人人都争先恐后时,如果你真想创造价值,不如“反者道之动”,静观其变,等待系统重构的新机会。拥挤的赛道最终必然走向卷利润、卷价格的“劣币驱逐良币”死循环。

      2.2 无效信息是对算力的极大消耗

      很多人把赚不到钱、做不成事归结于“信息积累不够”,于是疯狂地囤积资料、拼命地订阅各种干货,试图通过扩大信息摄入量来超越别人。 这是一个极其危险的谬论。获取和处理信息,本质上是一件极其消耗系统资源(精力和能量)的事情。

      如果一个人单凭拼凑信息就能战胜市场,那大家都不需要埋头精耕细作了。人的脑容量和认知带宽是有限的,一旦缓存(Cache)被大量低质、无用的噪音占满,真正高价值的信号就无法进入,想得太多、做得太少,只会引发严重的内耗。

      3. 价值创造的核心:思考+执行,突破信息壁垒

      信息本质是工具,而非目的,人的核心竞争力永远是“思考+执行”,二者形成的能力壁垒,远高于单纯的信息壁垒:思考 + 执行 > 纯执行 + 不思考 > 纯思考 + 不执行 > 不思考 + 不执行

      • 思考+执行:通过思考判断信息价值,通过执行验证选择,形成“信息-判断-实践-反馈”的闭环
      • 执行+不思考:机械落地但缺乏方向,效率低下但可能偶然踩中机会。
      • 思考+不执行:仅停留在“知道”阶段,信息无法转化为任何价值。
      • 不思考+不执行:完全被动接收信息,与机会绝缘。

      “思考+执行”之所以重要,是因为它们构成了反馈闭环:思考是为了对输入的信息进行校验和逻辑判断,执行是为了将假设放入真实环境中跑通测试,从而向目标逼近

      信息不对称的根源,其实是“内部能力不对称”。将相同的技术趋势、项目机会放在两位开发者面前:前者能通过思考拆解落地路径、通过执行验证可行性;后者仅停留在“了解”层面,差距便由此产生。人们最终能获得的价值,取决于自身的思考深度、执行力度、认知高度——想要获得更多,唯一路径是“精进自身”,让能力匹配目标。

      真正有价值的信息,如果传达给一个没有执行力的人,就永远停留在“已知”的内存态,无法落盘,吸收、运用和产生价值的任何一个环节都不会发生。

      我们通常以为自己没成事是因为缺少某个关键的“信息差”,实际上连这个“以为”的诊断都错了。真正的原因,往往是思考的深度和执行的颗粒度不到位,导致机会流失。人终归只能赚到自己系统架构支撑得起的那部分收益,想要获得更多,唯一的路径是重构和精进自己。

      4. 行动指南

      4.1 信息筛选:果断做减法,锚定核心目标

      • 停止抱怨外界信息的真伪,主动建立个人过滤机制,拒绝"信息焦虑",定期清理无效信息源(如低价值技术社群、重复资讯推送)。
      • 明确自身阶段目标(如“3个月掌握某框架落地”“半年实现副业变现”),仅筛选与目标强相关的信息,把有限的算力留给最高优的任务。

      4.2 信息解读:穿透表象,洞察未言之意

      • 接收信息时(如技术文章、行业分享),不仅要关注"说了什么",更要洞察"没说什么"(如技术的适用场景、潜在坑点、变现逻辑的隐藏环节)。
      • 优先与高信噪比人群深度交流(如资深开发者、落地型创业者、领域专家),这类沟通往往直击本质、减少冗余,能快速触达核心信息与隐性经验,同时反向倒逼自身思考质量的提升。

      4.3 差异破局:向内求索,强化“思考+执行”

      与其说世界上存在信息差,不如说是"人差"。将同样的文档和源码置于两人面前,由于"底层编译器"(认知框架与执行系统)的差异,前者的洞察与后者的产出必然判若云泥。一切信息不对称的表象之下,真正分野的永远是内在的认知深度与执行密度。我们只有通过持续的思考和执行提升自己的能力,才能在信息时代中获得价值。

      • 停止抱怨"信息不真实"这类外部归因,把精力放在自己能掌控的事情上——提升思考深度和执行效率。
      • 建立"信息落地清单":每当获得有价值的信息,立刻拆解成三个部分——思考要点(比如是否适合自己)、执行步骤(比如本周验证什么)、反馈节点(比如两周后复盘效果),别让信息躺在那里吃灰。
      +

      如何甄别真正有用的信息

      摘要总结:在信息高度透明的时代,浅层信息差已被彻底抹平,信息本身的价值不断稀释。人与人的核心差距不再是获取信息的渠道,而是高信噪比信息的甄别能力、深度思考能力与落地执行力,唯有以思考校验信息、以执行验证价值,形成“信息-判断-实践-反馈”的思考与执行闭环,才能突破信息壁垒、创造真正价值。

      在互联网技术普及的当下,信息已从“稀缺资源”转变为“泛滥资源”。过去依赖地域差、稀缺性的浅表层信息差逐渐被抹平,开发者通过网络可轻松获取各类技术文档、行业动态、赚钱模式,但真正能将信息转化为价值的仍是少数人。核心矛盾已从“获取信息”转变为“驾驭信息”——信息本身的价值弱化,而信息解读能力、行动执行力、筛选甄别力成为拉开差距的关键

      1. 打破“信息差”的系统性错觉

      过去,由于地域限制和传播介质的稀缺,赚钱或成功的模式往往是粗放的,建立在浅表层的“信息不对称”上,但随着技术的演进,这种低维度的信息差正在被迅速抹平。人们经常陷入“赚不到钱/抓不住机会是因为缺少信息差”的认知偏差,但本质问题在于“人本身的差距”,具体体现在三个层面:

      1.1 表面是你在筛选信息,实际是信息在筛选人

      举个最常见的例子:大家都知道做技术输出、写独立博客或做个人产品能带来长期的复利,但为什么真正跑通全栈并沉淀下来的人凤毛麟角?

      阻碍多数人的原因通常有三个:

      • 缺乏持久化机制、执行断层:无法在短期内看到正向反馈(ROI),导致进程中途中断,缺乏持续输出的执行力(如技术文章更新、用户运营)。
      • 缺乏深度计算:只是浮于表面的搬运,没有沉下心来对技术或业务进行深度解析与架构思考。
      • 对不确定性(Uncertainty)的恐惧:看不到确定性的回报,对投入产出比产生动摇,导致长期投入的决策被取消。

      面对这些公开的“赚钱/成长路径”,看似是我们在评估它,实际上是这些高门槛的路径在天然地筛选掉那些缺乏定力和长远产品嗅觉的人。

      1.2 警惕算法构建的“信息茧房”

      在网络推荐算法和同温层环境的双重作用下,我们每天接收的输入往往带有严重的偏置。这种不够客观的环境,容易导致我们在遇到真正有价值、但与既有认知冲突的客观观点时,产生本能的防御和抵触。

      对于开发者和内容创作者而言,打破认知茧房本身就是一种巨大的信息差。任何技术栈或商业模式,都需要博采众长。不要对非本领域的观点一味抛出异常,而是要建立辩证的“中间件”来过滤和吸收,做好信息的甄别与筛选。

      2. 信息泛滥与脑力带宽的消耗

      信息即权力,掌握高维信息的人确实拥有更强的资源调配能力。但关键在于,没有人有义务把复杂的底层逻辑拆解成现成的方法论,手把手教到完全理解为止。真正造成人与人之间差距的,是解析和编译信息的能力——同样的信息,不同的人能提炼出完全不同的价值。

      2.1 从“追求差”到“对抗泛滥”

      如今的问题早已不是信息匮乏,而是信息熵增与泛滥。这不仅带来了极度内卷的竞争,还伴随着传播过程中的信息失真。市面上很多被大肆宣扬的“风口”,仔细扒开源码就会发现:你所看到的,其实都是别人精心设计好让你看到的。

      当一个赛道人人都争先恐后时,如果你真想创造价值,不如“反者道之动”,静观其变,等待系统重构的新机会。拥挤的赛道最终必然走向卷利润、卷价格的“劣币驱逐良币”死循环。

      2.2 无效信息是对算力的极大消耗

      很多人把赚不到钱、做不成事归结于“信息积累不够”,于是疯狂地囤积资料、拼命地订阅各种干货,试图通过扩大信息摄入量来超越别人。 这是一个极其危险的谬论。获取和处理信息,本质上是一件极其消耗系统资源(精力和能量)的事情。

      如果一个人单凭拼凑信息就能战胜市场,那大家都不需要埋头精耕细作了。人的脑容量和认知带宽是有限的,一旦缓存(Cache)被大量低质、无用的噪音占满,真正高价值的信号就无法进入,想得太多、做得太少,只会引发严重的内耗。

      3. 价值创造的核心:思考+执行,突破信息壁垒

      信息本质是工具,而非目的,人的核心竞争力永远是“思考+执行”,二者形成的能力壁垒,远高于单纯的信息壁垒:思考 + 执行 > 纯执行 + 不思考 > 纯思考 + 不执行 > 不思考 + 不执行

      • 思考+执行:通过思考判断信息价值,通过执行验证选择,形成“信息-判断-实践-反馈”的闭环
      • 执行+不思考:机械落地但缺乏方向,效率低下但可能偶然踩中机会。
      • 思考+不执行:仅停留在“知道”阶段,信息无法转化为任何价值。
      • 不思考+不执行:完全被动接收信息,与机会绝缘。

      “思考+执行”之所以重要,是因为它们构成了反馈闭环:思考是为了对输入的信息进行校验和逻辑判断,执行是为了将假设放入真实环境中跑通测试,从而向目标逼近

      信息不对称的根源,其实是“内部能力不对称”。将相同的技术趋势、项目机会放在两位开发者面前:前者能通过思考拆解落地路径、通过执行验证可行性;后者仅停留在“了解”层面,差距便由此产生。人们最终能获得的价值,取决于自身的思考深度、执行力度、认知高度——想要获得更多,唯一路径是“精进自身”,让能力匹配目标。

      真正有价值的信息,如果传达给一个没有执行力的人,就永远停留在“已知”的内存态,无法落盘,吸收、运用和产生价值的任何一个环节都不会发生。

      我们通常以为自己没成事是因为缺少某个关键的“信息差”,实际上连这个“以为”的诊断都错了。真正的原因,往往是思考的深度和执行的颗粒度不到位,导致机会流失。人终归只能赚到自己系统架构支撑得起的那部分收益,想要获得更多,唯一的路径是重构和精进自己。

      4. 行动指南

      4.1 信息筛选:果断做减法,锚定核心目标

      • 停止抱怨外界信息的真伪,主动建立个人过滤机制,拒绝"信息焦虑",定期清理无效信息源(如低价值技术社群、重复资讯推送)。
      • 明确自身阶段目标(如“3个月掌握某框架落地”“半年实现副业变现”),仅筛选与目标强相关的信息,把有限的算力留给最高优的任务。

      4.2 信息解读:穿透表象,洞察未言之意

      • 接收信息时(如技术文章、行业分享),不仅要关注"说了什么",更要洞察"没说什么"(如技术的适用场景、潜在坑点、变现逻辑的隐藏环节)。
      • 优先与高信噪比人群深度交流(如资深开发者、落地型创业者、领域专家),这类沟通往往直击本质、减少冗余,能快速触达核心信息与隐性经验,同时反向倒逼自身思考质量的提升。

      4.3 差异破局:向内求索,强化“思考+执行”

      与其说世界上存在信息差,不如说是"人差"。将同样的文档和源码置于两人面前,由于"底层编译器"(认知框架与执行系统)的差异,前者的洞察与后者的产出必然判若云泥。一切信息不对称的表象之下,真正分野的永远是内在的认知深度与执行密度。我们只有通过持续的思考和执行提升自己的能力,才能在信息时代中获得价值。

      • 停止抱怨"信息不真实"这类外部归因,把精力放在自己能掌控的事情上——提升思考深度和执行效率。
      • 建立"信息落地清单":每当获得有价值的信息,立刻拆解成三个部分——思考要点(比如是否适合自己)、执行步骤(比如本周验证什么)、反馈节点(比如两周后复盘效果),别让信息躺在那里吃灰。
      diff --git "a/30.\346\202\246\350\257\273\346\227\266\345\205\211/10.\350\257\273\344\271\246\344\270\211\350\246\201\344\270\211\344\270\215\350\246\201.html" b/growth/reading-tips.html similarity index 55% rename from "30.\346\202\246\350\257\273\346\227\266\345\205\211/10.\350\257\273\344\271\246\344\270\211\350\246\201\344\270\211\344\270\215\350\246\201.html" rename to growth/reading-tips.html index 28a37570..06de9598 100644 --- "a/30.\346\202\246\350\257\273\346\227\266\345\205\211/10.\350\257\273\344\271\246\344\270\211\350\246\201\344\270\211\344\270\215\350\246\201.html" +++ b/growth/reading-tips.html @@ -6,12 +6,12 @@ 读书“三要”和“三不要” | Insight Stack - + - - - - + + + + @@ -30,7 +30,7 @@ - +
      Skip to content

      读书“三要”和“三不要”

      摘要总结:在信息爆炸的时代,读书依然是获取深度知识最高效的方式之一。但“捧起书”并不等于“有收获”,怎么读往往比读什么更重要。本文总结了读书的“三要”与“三不要”:从完整阅读观摩大师思维、带着问题构建知识树,到通过讨论检验理解;同时提醒阅读者警惕哀怨心态对阅读初衷的异化、避免陷入对物理媒介的“玩物丧志”,以及切忌脱离现实的“真空”阅读。阅读不仅是向内探索的精神之旅,更是向外理解真实世界、创造社会价值的实用工具。

      about site background

      1. 我们为什么需要读书?

      读书是从外界接受信息的一种方式,与聊天、浏览网页、听播客、看电视并无本质区别。但书这种媒介与其他信息媒介相比,有其独有的优势:

      • 深度与严谨:书籍往往是创作者多年思考、长期写作的产物,经过专业编辑反复修改校对,知识密度远高于日常谈话或碎片内容。
      • 专注与反刍:读书允许读者专注其中,书中的信息因此往往条理清晰、逻辑严密,语言也更为精练紧凑。读者可以随时停下翻回反复琢磨、推敲。相比之下,电视画面一闪而过,很难进行层层递进的深入分析。
      • 知识密度高:沉淀在书中的信息,往往逻辑性强、语言精练紧凑(即所谓的“书面语”),知识含量远超日常碎片化信息。认真读完一本好书,获得的知识与思考深度,往往超过看几部剧、刷几小时短视频,甚至聊几个小时天的总和。

      认真读一本好书,往往比看一部电视剧或漫无目的地浏览网页能获得更多知识。但这并不意味着“只要捧起书就一定有收获”,关键在于怎么读

      2. 读书"三要"

      第一“要”:完整地读,整本地读

      对于好书,要完整地读、整本地读,不要只捡结论。

      很多人习惯直接看结论和观点,觉得这样效率高。但这样做有一个根本缺陷:你只得到了答案,却错过了思考方法本身

      掌握思考方法的唯一途径,是通过完整地阅读来观摩优秀的大师是如何思考的——他们如何一步步推导出结论,如何分析和批判不同的观点,遇到困难时又如何转换视角。看得多了,自然能渐渐窥见门道,再辅以勤恳的思考训练,才能真正将思维方法内化。

      相反,只知道观点、不掌握方法的后果,是"刻舟求剑"

      • 理论的适用条件只要稍有些变化,便无所适从,只会把那几条观点反复背诵套用。
      • 经典著作往往具有复杂性,读起来必须动脑筋。只背诵结论不是传授学问的方法,而是培养盲从信徒的方法,而不是做学问的路径。

      第二“要”:带着问题去读,构建知识树

      要带着问题去读书,将散乱的信息构建成清晰的知识树。

      每一本知识性书籍,背后都有一个(或一组)核心问题。知识性书籍的诞生,往往是为了解答、批驳或赞同某个特定的观点,好的作者会先把他要回答的问题交代清楚,再展开论述。

      • 还原“问题情境”:很多流传至今的名著,现代人之所以读不进去,是因为对当时的“问题情境”一无所知。许多经典在当年都是锋芒毕露、针锋相对的论辩性作品,是为了解决当时的痛点而生。一旦你了解了这些背景,事先知道了这本书在学科谱系中的位置,阅读就会变得像追踪一场精彩的辩论一样有趣。

      • 连点成树:带着亟待回答的问题去读书,不但不会觉得枯燥,反而能充分享受新知的乐趣。这样吸收进来的知识不再是无意义的堆积物,而是沿着“批判—反批判—再批判”线索生长出来的、清晰的知识树。有了知识树,才能真正形成自己的思想观念,才能条理清晰地理解世界。

      • 善用指引:老师或导读无法代替你读书,但可以帮你解释问题情境、指明知识门径、交代语境(所谓“师傅领进门,修行在个人”),大大提高你的阅读效率和理解深度。

      第三“要”:与人(或AI)讨论,检验理解的试金石

      读完一本书,要找人讨论(也可以与能力较强的 AI 工具深度对话),讨论是检验理解的试金石。

      独自阅读常形成模糊的理解链条,容易产生“我懂了”的幻觉,唯有能用自己的语言让别人听懂,才算真正理解。

      真正的理解有一个更高的标准:把书中的观点用自己的话讲给别人听,让对方也能听懂。"看懂"和"讲清楚"之间,差着十万八千里。很多时候,所谓"看懂",不过是在脑中形成了一条模糊、不连贯的"理解链"。只有当你必须用自己的语言向别人复述,并且要做到言之成理、自圆其说时,那些薄弱、缺失的环节才会立刻暴露出来(含糊的地方你会直接卡壳)。

      在“刁难”中查漏补缺,讲述的过程会倒逼你:

      1. 把逻辑理清楚,确保"因为"和"所以"之间真的成立;
      2. 发现自己还没搞懂的地方,带着新问题回去再读;
      3. 在他人的追问和质疑中,不断深化理解。

      我曾尝试将几本书的内容讲给没时间阅读的朋友听。他们可不会把我当“老师”来尊敬,遇到疑问或不同意见就会随时打断,甚至以把我“问倒”为乐。结果是,我原以为完全看懂的书,被他们一通“胡搅蛮缠”后,发现竟然还有那么多没吃透的地方,只能回去重读。下一次见面时,我必须把他们的质疑解释清楚。但也正因如此,那几本书成了我书架上理解最透彻、收获最大的书。

      这里的讲述不是单方面的课堂宣讲,而是面对面的平等讨论、寻找高质量的对话。如果对话者水平高、讨论深入,效果极佳。在如今,你甚至可以把逻辑推理能力较强的 AI 工具当作你的“讨论搭子”,让它对你的观点进行提问和反驳,以此来迫使自己真正透彻地掌握知识。

      3. 读书"三不要"

      第一“不要”:不要怀揣哀怨心态,避免读书目的被异化

      不要有哀怨心态,被哀怨情绪控制,就失去了读书的平常心和客观理解力。

      读书多不等于人才,未提供社会价值则难致富。若因此怨天尤人,读书将异化为排解情绪与博取关注的工具。

      一个人一旦被哀怨情绪控制,就会彻底失去读书的平常心和客观理解力。

      • 警惕“价值转化”的幻觉:有些人确实读了不少书,说起话来头头是道,也时常能得到他人的赞许。这容易让人产生一种幻觉,自认是个“被埋没的人才”。但实际上,读书多不等于人才,真正的财富来源于你能否为别人提供有价值的商品或服务。得到别人的口头赞许,与让别人掏钱买你的服务之间,有着巨大的鸿沟。

      • 警惕心态失衡与怨天尤人:当自诩为“人才”却迟迟未能发家致富时,很多人不会反思自己是否创造了真正的社会价值,而是将原因归咎于外界,静等着“伯乐”来发掘。当看到身边不读书的人纷纷买车买房时,这种着急就会演变成气急败坏、鄙夷与哀怨,甚至觉得“社会太不公平”。

      • 防止阅读初衷的异化:这是最致命的一点。当怨气占据大脑,读书对于这类人来说,就不再是客观接受信息、理解世界的方式了,而是沦为了一种排解郁闷、打发时间的消极手段。他们的关注点会从书本内容彻底转移到别人的眼光上,内心的潜台词变成了表演:“你们还没看到我刻苦读书的身姿吗?还不承认我是个人才吗?还不提高我的收入吗?”

      第二“不要”:不要玩物丧志,陷入对物理媒介的过度迷恋

      不要玩物丧志,过度沉溺书籍细节与附属品会导致“玩物丧志”。若读书脱离获取信息的目的,则难以在知识学问上有所成就。

      • 回归阅读的本质:读书的核心目的是为了获取信息、汲取知识,而不是为了把玩那一束装订起来的纸张。随着阅读的深入,很多人容易沉溺于书籍带来的附加体验(如纸张的手感、油墨的香气、版本的考究)。这种对物理形态的偏好可以理解,但必须有所节制,一旦喧宾夺主,甚至因此拒绝更高效的媒介,就是南辕北辙了。

      • 顺应媒介演进的效率趋势,时代趋势不可逆:纵观历史,从丝绸、竹简到纸张,再到如今的电子书,信息媒介的演进始终朝着“更低成本、更高效率”的方向发展。在信息时代,电子书在便携性、易储性、内容可检索性(如一键全文搜索)以及知识共享方面,拥有纸质书无法比拟的优势,这对于快速定位关键信息、构建个人知识树而言是极大的助力。

      • 警惕被“旧习惯”绑架:很多抗拒电子书的人,强调的种种理由其实与“读书”本身关系不大,更多是不愿改变旧有的阅读习惯,不愿放弃读书以外的把玩乐趣。为了坚持这种旧习惯,而不惜牺牲信息流转和获取的效率,这在信息爆炸的时代是得不偿失的。

      • 积极拥抱新媒介的红利:真正以求知为目的的人,从来都会积极拥抱新的传播工具。在这个时代,固守传统媒介的人获取知识的成本会越来越高、效率越来越低;而愿意接纳新媒介的阅读者,则能以更轻松、愉快的方式,获取最丰沛的知识。

      第三“不要”:不要只读书不知现实,避免知识结构陷入“真空”

      书籍仅承载极少知识,大量隐性知识存于现实社会。只读书会导致知识结构缺陷,难以应对实务,故不可脱离现实。

      书本知识只是认识世界的一小部分,脱离现实的纯粹阅读,会导致知识结构的严重扭曲。

      • 认清书籍的局限性:知识以各种方式存在于社会的各个角落,书籍所承载的仅仅是世界知识总量中极小的一部分。由于书籍要求书面化、系统且连贯,它必然无法记录下大量不稳定、转瞬即逝、碎片化或难以用语言明确表达的知识。

      • 重视庞大的“隐性知识”:在现实社会中,存在着诸如谈话交流、个人经验、行为方式、商业模式及人际关系等海量的非书本知识。如果一个人只是一味读书而极少参与社会实践,就会完全错失这部分在数量上更为庞大的知识宝库,导致知识结构出现重大缺陷。

      • 警惕脱离现实的“扭曲认知”:如果只读书而不参与社会实践,会导致知识结构存在重大缺陷,在处理现实事务时会暴露无遗。在数学、计算机或棋类等高度抽象、无需太多社会经验的领域,仅凭逻辑推演确实可以成就“少年天才”。但真实世界的绝大多数领域(如法律、商业、服务业等)极度依赖从业者的社会经验和现实感。只读书不仅会造成处理实际事务时能力低下,更会以一小部分取代整体,形成对真实世界的扭曲认知。仅靠抽象逻辑是无法解决复杂现实问题的,这也是为什么世界上会有15岁的黑客,却绝不会有15岁的人事经理或法官。

      4. 让书籍成为连接自我与现实的桥梁

      读书从来不是为了把自己变成一个装满各类观点的“两脚书橱”,而是为了升级我们思考现实、解决问题的“底层操作系统”。

      无论是坚持“三要”(掌握方法、构建体系、检验真知),还是警惕“三不要”(拒绝异化、拥抱高效、扎根现实),最终的指向都是同一个:打破书本与现实的壁垒,让知识真正为你所用。 在获取信息门槛越来越低的今天,独立思考和将知识转化为实际价值的能力愈发珍贵。

      愿我们都能带着平常心去阅读,在书中观摩大师的智慧,在现实中创造真实的价值,享受纯粹而充实的悦读时光。

      +

      读书“三要”和“三不要”

      摘要总结:在信息爆炸的时代,读书依然是获取深度知识最高效的方式之一。但“捧起书”并不等于“有收获”,怎么读往往比读什么更重要。本文总结了读书的“三要”与“三不要”:从完整阅读观摩大师思维、带着问题构建知识树,到通过讨论检验理解;同时提醒阅读者警惕哀怨心态对阅读初衷的异化、避免陷入对物理媒介的“玩物丧志”,以及切忌脱离现实的“真空”阅读。阅读不仅是向内探索的精神之旅,更是向外理解真实世界、创造社会价值的实用工具。

      about site background

      1. 我们为什么需要读书?

      读书是从外界接受信息的一种方式,与聊天、浏览网页、听播客、看电视并无本质区别。但书这种媒介与其他信息媒介相比,有其独有的优势:

      • 深度与严谨:书籍往往是创作者多年思考、长期写作的产物,经过专业编辑反复修改校对,知识密度远高于日常谈话或碎片内容。
      • 专注与反刍:读书允许读者专注其中,书中的信息因此往往条理清晰、逻辑严密,语言也更为精练紧凑。读者可以随时停下翻回反复琢磨、推敲。相比之下,电视画面一闪而过,很难进行层层递进的深入分析。
      • 知识密度高:沉淀在书中的信息,往往逻辑性强、语言精练紧凑(即所谓的“书面语”),知识含量远超日常碎片化信息。认真读完一本好书,获得的知识与思考深度,往往超过看几部剧、刷几小时短视频,甚至聊几个小时天的总和。

      认真读一本好书,往往比看一部电视剧或漫无目的地浏览网页能获得更多知识。但这并不意味着“只要捧起书就一定有收获”,关键在于怎么读

      2. 读书"三要"

      第一“要”:完整地读,整本地读

      对于好书,要完整地读、整本地读,不要只捡结论。

      很多人习惯直接看结论和观点,觉得这样效率高。但这样做有一个根本缺陷:你只得到了答案,却错过了思考方法本身

      掌握思考方法的唯一途径,是通过完整地阅读来观摩优秀的大师是如何思考的——他们如何一步步推导出结论,如何分析和批判不同的观点,遇到困难时又如何转换视角。看得多了,自然能渐渐窥见门道,再辅以勤恳的思考训练,才能真正将思维方法内化。

      相反,只知道观点、不掌握方法的后果,是"刻舟求剑"

      • 理论的适用条件只要稍有些变化,便无所适从,只会把那几条观点反复背诵套用。
      • 经典著作往往具有复杂性,读起来必须动脑筋。只背诵结论不是传授学问的方法,而是培养盲从信徒的方法,而不是做学问的路径。

      第二“要”:带着问题去读,构建知识树

      要带着问题去读书,将散乱的信息构建成清晰的知识树。

      每一本知识性书籍,背后都有一个(或一组)核心问题。知识性书籍的诞生,往往是为了解答、批驳或赞同某个特定的观点,好的作者会先把他要回答的问题交代清楚,再展开论述。

      • 还原“问题情境”:很多流传至今的名著,现代人之所以读不进去,是因为对当时的“问题情境”一无所知。许多经典在当年都是锋芒毕露、针锋相对的论辩性作品,是为了解决当时的痛点而生。一旦你了解了这些背景,事先知道了这本书在学科谱系中的位置,阅读就会变得像追踪一场精彩的辩论一样有趣。

      • 连点成树:带着亟待回答的问题去读书,不但不会觉得枯燥,反而能充分享受新知的乐趣。这样吸收进来的知识不再是无意义的堆积物,而是沿着“批判—反批判—再批判”线索生长出来的、清晰的知识树。有了知识树,才能真正形成自己的思想观念,才能条理清晰地理解世界。

      • 善用指引:老师或导读无法代替你读书,但可以帮你解释问题情境、指明知识门径、交代语境(所谓“师傅领进门,修行在个人”),大大提高你的阅读效率和理解深度。

      第三“要”:与人(或AI)讨论,检验理解的试金石

      读完一本书,要找人讨论(也可以与能力较强的 AI 工具深度对话),讨论是检验理解的试金石。

      独自阅读常形成模糊的理解链条,容易产生“我懂了”的幻觉,唯有能用自己的语言让别人听懂,才算真正理解。

      真正的理解有一个更高的标准:把书中的观点用自己的话讲给别人听,让对方也能听懂。"看懂"和"讲清楚"之间,差着十万八千里。很多时候,所谓"看懂",不过是在脑中形成了一条模糊、不连贯的"理解链"。只有当你必须用自己的语言向别人复述,并且要做到言之成理、自圆其说时,那些薄弱、缺失的环节才会立刻暴露出来(含糊的地方你会直接卡壳)。

      在“刁难”中查漏补缺,讲述的过程会倒逼你:

      1. 把逻辑理清楚,确保"因为"和"所以"之间真的成立;
      2. 发现自己还没搞懂的地方,带着新问题回去再读;
      3. 在他人的追问和质疑中,不断深化理解。

      我曾尝试将几本书的内容讲给没时间阅读的朋友听。他们可不会把我当“老师”来尊敬,遇到疑问或不同意见就会随时打断,甚至以把我“问倒”为乐。结果是,我原以为完全看懂的书,被他们一通“胡搅蛮缠”后,发现竟然还有那么多没吃透的地方,只能回去重读。下一次见面时,我必须把他们的质疑解释清楚。但也正因如此,那几本书成了我书架上理解最透彻、收获最大的书。

      这里的讲述不是单方面的课堂宣讲,而是面对面的平等讨论、寻找高质量的对话。如果对话者水平高、讨论深入,效果极佳。在如今,你甚至可以把逻辑推理能力较强的 AI 工具当作你的“讨论搭子”,让它对你的观点进行提问和反驳,以此来迫使自己真正透彻地掌握知识。

      3. 读书"三不要"

      第一“不要”:不要怀揣哀怨心态,避免读书目的被异化

      不要有哀怨心态,被哀怨情绪控制,就失去了读书的平常心和客观理解力。

      读书多不等于人才,未提供社会价值则难致富。若因此怨天尤人,读书将异化为排解情绪与博取关注的工具。

      一个人一旦被哀怨情绪控制,就会彻底失去读书的平常心和客观理解力。

      • 警惕“价值转化”的幻觉:有些人确实读了不少书,说起话来头头是道,也时常能得到他人的赞许。这容易让人产生一种幻觉,自认是个“被埋没的人才”。但实际上,读书多不等于人才,真正的财富来源于你能否为别人提供有价值的商品或服务。得到别人的口头赞许,与让别人掏钱买你的服务之间,有着巨大的鸿沟。

      • 警惕心态失衡与怨天尤人:当自诩为“人才”却迟迟未能发家致富时,很多人不会反思自己是否创造了真正的社会价值,而是将原因归咎于外界,静等着“伯乐”来发掘。当看到身边不读书的人纷纷买车买房时,这种着急就会演变成气急败坏、鄙夷与哀怨,甚至觉得“社会太不公平”。

      • 防止阅读初衷的异化:这是最致命的一点。当怨气占据大脑,读书对于这类人来说,就不再是客观接受信息、理解世界的方式了,而是沦为了一种排解郁闷、打发时间的消极手段。他们的关注点会从书本内容彻底转移到别人的眼光上,内心的潜台词变成了表演:“你们还没看到我刻苦读书的身姿吗?还不承认我是个人才吗?还不提高我的收入吗?”

      第二“不要”:不要玩物丧志,陷入对物理媒介的过度迷恋

      不要玩物丧志,过度沉溺书籍细节与附属品会导致“玩物丧志”。若读书脱离获取信息的目的,则难以在知识学问上有所成就。

      • 回归阅读的本质:读书的核心目的是为了获取信息、汲取知识,而不是为了把玩那一束装订起来的纸张。随着阅读的深入,很多人容易沉溺于书籍带来的附加体验(如纸张的手感、油墨的香气、版本的考究)。这种对物理形态的偏好可以理解,但必须有所节制,一旦喧宾夺主,甚至因此拒绝更高效的媒介,就是南辕北辙了。

      • 顺应媒介演进的效率趋势,时代趋势不可逆:纵观历史,从丝绸、竹简到纸张,再到如今的电子书,信息媒介的演进始终朝着“更低成本、更高效率”的方向发展。在信息时代,电子书在便携性、易储性、内容可检索性(如一键全文搜索)以及知识共享方面,拥有纸质书无法比拟的优势,这对于快速定位关键信息、构建个人知识树而言是极大的助力。

      • 警惕被“旧习惯”绑架:很多抗拒电子书的人,强调的种种理由其实与“读书”本身关系不大,更多是不愿改变旧有的阅读习惯,不愿放弃读书以外的把玩乐趣。为了坚持这种旧习惯,而不惜牺牲信息流转和获取的效率,这在信息爆炸的时代是得不偿失的。

      • 积极拥抱新媒介的红利:真正以求知为目的的人,从来都会积极拥抱新的传播工具。在这个时代,固守传统媒介的人获取知识的成本会越来越高、效率越来越低;而愿意接纳新媒介的阅读者,则能以更轻松、愉快的方式,获取最丰沛的知识。

      第三“不要”:不要只读书不知现实,避免知识结构陷入“真空”

      书籍仅承载极少知识,大量隐性知识存于现实社会。只读书会导致知识结构缺陷,难以应对实务,故不可脱离现实。

      书本知识只是认识世界的一小部分,脱离现实的纯粹阅读,会导致知识结构的严重扭曲。

      • 认清书籍的局限性:知识以各种方式存在于社会的各个角落,书籍所承载的仅仅是世界知识总量中极小的一部分。由于书籍要求书面化、系统且连贯,它必然无法记录下大量不稳定、转瞬即逝、碎片化或难以用语言明确表达的知识。

      • 重视庞大的“隐性知识”:在现实社会中,存在着诸如谈话交流、个人经验、行为方式、商业模式及人际关系等海量的非书本知识。如果一个人只是一味读书而极少参与社会实践,就会完全错失这部分在数量上更为庞大的知识宝库,导致知识结构出现重大缺陷。

      • 警惕脱离现实的“扭曲认知”:如果只读书而不参与社会实践,会导致知识结构存在重大缺陷,在处理现实事务时会暴露无遗。在数学、计算机或棋类等高度抽象、无需太多社会经验的领域,仅凭逻辑推演确实可以成就“少年天才”。但真实世界的绝大多数领域(如法律、商业、服务业等)极度依赖从业者的社会经验和现实感。只读书不仅会造成处理实际事务时能力低下,更会以一小部分取代整体,形成对真实世界的扭曲认知。仅靠抽象逻辑是无法解决复杂现实问题的,这也是为什么世界上会有15岁的黑客,却绝不会有15岁的人事经理或法官。

      4. 让书籍成为连接自我与现实的桥梁

      读书从来不是为了把自己变成一个装满各类观点的“两脚书橱”,而是为了升级我们思考现实、解决问题的“底层操作系统”。

      无论是坚持“三要”(掌握方法、构建体系、检验真知),还是警惕“三不要”(拒绝异化、拥抱高效、扎根现实),最终的指向都是同一个:打破书本与现实的壁垒,让知识真正为你所用。 在获取信息门槛越来越低的今天,独立思考和将知识转化为实际价值的能力愈发珍贵。

      愿我们都能带着平常心去阅读,在书中观摩大师的智慧,在现实中创造真实的价值,享受纯粹而充实的悦读时光。

      diff --git a/hashmap.json b/hashmap.json index 792b8e14..ac749f1a 100644 --- a/hashmap.json +++ b/hashmap.json @@ -1 +1 @@ -{"01.全栈_00.overview.md":"DRHSs2EE","01.全栈_01.ai native 工程思维_01.不止于代码:构建 ai 时代全栈工程师的“认知三层塔”.md":"DnAdo66b","01.全栈_01.ai native 工程思维_02.重构开发者:ai 时代下的工程师能力图谱与演进指南.md":"BzWlQ04R","01.全栈_01.ai native 工程思维_10.读 anthropic 研究报告,探寻 ai 时代的工程范式重塑.md":"BxS8ZWIM","01.全栈_10.ai 编程实践指南_00.ai编程工具与资源.md":"0WWjtM47","01.全栈_40.前端工程_01.react 设计哲学:ai 协作时代的组件化开发实践指南.md":"ip_V3kmi","01.全栈_40.前端工程_02.css工程化.md":"DUPhvCof","01.全栈_40.前端工程_03.jamstack 梳理与实践指南.md":"CdkgDOAk","01.全栈_40.前端工程_11.react 服务端状态管理的范式转移与选型深度博弈.md":"BpMi6J2x","01.全栈_60.网络与通信_01.从 http 到 websocket 的技术选型指南.md":"int3cA6G","01.全栈_60.网络与通信_02.流式 http 与 sse 协议:从概念辨析到生产实践.md":"Cp-uzdUB","01.全栈_60.网络与通信_03.退避轮询与长轮询的原理、实战与选型决策.md":"C2A_-RUG","01.全栈_80.全栈基础素养_00.奥卡姆剃刀原则:从理论到编程设计的实践指南.md":"B1vmVkqI","01.全栈_80.全栈基础素养_01.编译与调试 typescript 项目指南.md":"BHyEzAuH","01.全栈_80.全栈基础素养_10.聊一聊 typescript 泛型.md":"BpsDJhtc","01.全栈_80.全栈基础素养_20.模块化编程实践指南_0.overview.md":"CwRE_Svk","01.全栈_80.全栈基础素养_20.模块化编程实践指南_1.前端模块化编程基础.md":"BVmOGo8x","01.全栈_80.全栈基础素养_20.模块化编程实践指南_2.不同模块化规范梳理.md":"CRGmbaTn","01.全栈_80.全栈基础素养_20.模块化编程实践指南_3.es modules 核心规范与实践解析.md":"fPkWGUxd","01.全栈_80.全栈基础素养_20.模块化编程实践指南_4.typescript 对模块化编程的增强.md":"hJ1lv1QY","01.全栈_80.全栈基础素养_20.模块化编程实践指南_5.模块化编程原则与最佳实践.md":"LTILHYsI","01.全栈_80.全栈基础素养_20.模块化编程实践指南_6.解析 nodejs 中的模块化.md":"CGHtK9Bj","01.全栈_90.工具与资源推荐_90.全栈技术资源推荐.md":"BBjcdRsJ","10.产品 sense_00.学习与实践全景.md":"BlAoRUPp","10.产品 sense_01.产品观察与分析_11.ai-powered 搜索引擎观察分析:perplexity 与知识工作者.md":"BRTIJ78C","10.产品 sense_02.新 t 型人_20.读后感:ai 原生时代的复合型人才,究竟需要怎样的特质?.md":"Xe0P5HJr","10.产品 sense_02.新 t 型人_21.工程师如何构建产品 sense.md":"CO18rPj4","10.产品 sense_04.产品创造与商业化_30.《小而美:持续盈利的经营法则》读后感.md":"gAigzrX9","10.产品 sense_05.方法论_40.洞察力模型.md":"j-w2xxuV","10.产品 sense_05.方法论_50.用经济学思维做产品.md":"CUbjYJmR","20.ai 学习与实践_00.ai 学习与实践全景一览.md":"Bq7k-xXb","20.ai 学习与实践_02.agent 系列_01.agent概览与综述.md":"DMvs5K_Q","20.ai 学习与实践_02.agent 系列_02.agent 规划模块.md":"C3XAsz_e","20.ai 学习与实践_02.agent 系列_03.构建 agentic 生态:将零散组件化为可持续的工作流.md":"Dzka5_K9","20.ai 学习与实践_02.agent 系列_10.agent skills.md":"BYP2Q09s","20.ai 学习与实践_04.社区活动与实践小项目_10.基于 claude agent sdk 搭建 deep research agent.md":"DtQSvR-M","20.ai 学习与实践_04.社区活动与实践小项目_20.基于 claude agent sdk 搭建 agent.md":"CAQEdrbh","20.ai 学习与实践_04.社区活动与实践小项目_60.数学小助手.md":"BVW8ytPR","20.ai 学习与实践_04.社区活动与实践小项目_70.诗歌小精灵.md":"C1VKntBb","20.ai 学习与实践_90.资源与工具推荐_01.好用的 ai 助手与工作站推荐.md":"DT78Ux7f","20.ai 学习与实践_90.资源与工具推荐_11. llm api 平台推荐与选型指南.md":"qaanG5K2","30.悦读时光_01.好书推荐.md":"lGftAF4x","30.悦读时光_10.读书三要三不要.md":"BQj2m1KY","30.悦读时光_21.如何甄别真正有用的信息.md":"C7EJFVmA","31.开源洞察_00.overview.md":"DsfCImvx","31.开源洞察_01.fetch-event-source 源码解读.md":"BP_UYyAh","40.关于_01.关于我.md":"CkzMieuF","40.关于_30.成长随笔_01.走出“目标隧道”:用系统与数学思维重构底层逻辑.md":"DJ7lWg_C","40.关于_30.成长随笔_10.向内思变:当疫情给世界按下暂停键,去重构生活秩序.md":"Cj12M61O","40.关于_30.成长随笔_20.减肥这件小事阶段随笔汇总.md":"DNHfVn0b","@pages_categoriespage.md":"DalPAP0h","@pages_tagspage.md":"nlt9sHhH","index.md":"CZC8OIc5"} +{"about_growth_inner-experience.md":"BDM8RLCo","about_growth_outer-experience.md":"C1TluC0P","about_growth_weight-loss.md":"CcX0Vwvs","about_me.md":"D2x_SpuM","ai_agent_claude-agent-sdk-basic-build.md":"CbEYO8B7","ai_agent_composition-ai-components.md":"BflEWWJ-","ai_agent_deepresearch-agent.md":"imeO63Es","ai_agent_math-bot.md":"Cb5BGcKV","ai_agent_overview.md":"D1UmPrSV","ai_agent_planning-module.md":"aYa-27wb","ai_agent_poetry-bot.md":"CkdEgtHV","ai_agent_skills-practice-summary.md":"DVPxItk9","ai_llm-api-resources.md":"DeMA4EoR","ai_overview.md":"B81zOyyZ","ai_tools-assistant.md":"CUVUaLDk","categories.md":"8sjp6zOv","fullstack_ai-change-work-workflow.md":"D9DK-zPn","fullstack_ai-coding_resources.md":"CCLNidMN","fullstack_ai-engineer-capability.md":"DWEvYZ-g","fullstack_ai-native.md":"DhuHpOPy","fullstack_css-engineering.md":"CyF7_CNd","fullstack_decode-es-modules.md":"D2FiEXNA","fullstack_different-module-programming-specifications.md":"471jsJdi","fullstack_frontend-module-programming-basic.md":"CYF2zgUz","fullstack_full-stack-resources.md":"CsBwRi3-","fullstack_jamstack.md":"BHwDJOwo","fullstack_module-programming-practice-guide.md":"C6GZ5LNW","fullstack_module-programming-principles-best-practices.md":"B-Jmi3dC","fullstack_networking-polling-optimization.md":"COzdcUPj","fullstack_networking-protocol-selection-guide.md":"Hd5lMFSd","fullstack_networking-sse-practice.md":"CCWohLJK","fullstack_nodejs-module-programming-summary.md":"CrdU3lTR","fullstack_occams-razor-software-design.md":"hjL2O9E6","fullstack_overview.md":"Cxlo3Aed","fullstack_react-design-philosophy-ai-augmented.md":"CMWFdXhO","fullstack_server-state-management.md":"ETGJXNWa","fullstack_typescript-compilation-debugging-guide.md":"C39DJVwc","fullstack_typescript-generic-types.md":"Cbx1pLcE","fullstack_typescript-module-programming-enhancement.md":"CDxy6Uow","growth_books.md":"B9CjQKY5","growth_distinguish-useful-information.md":"CwjMB2nE","growth_reading-tips.md":"Dg4fAO7r","index.md":"D7QupwhI","product-sense_ai-native-composite-talents.md":"B6c5Dih7","product-sense_engineer-build-product-sense.md":"-nPPujxn","product-sense_insight-model.md":"Du_YgLvh","product-sense_overview.md":"yd9f580t","product-sense_perplexity-knowledge-worker.md":"VS0_MKCD","product-sense_small-rule-learn.md":"CojjSdfB","product-sense_using-economics-thinking.md":"Do__YKV9","repo-insight_fetch-event-source.md":"TsCwUya2","repo-insight_overview.md":"BlcYlci7","tags.md":"DelZTtSB"} diff --git a/index.html b/index.html index a9f784be..e30f876e 100644 --- a/index.html +++ b/index.html @@ -6,12 +6,12 @@ 首页 | Insight Stack Blog - + - - - - + + + + @@ -30,7 +30,7 @@ - +
      Skip to content
        联系方式

        欢迎通过以下方式与我交流 👋

        Insight Stack BlogAI & 全栈技术 & 产品思考与成长记录

        ✨探索技术前沿,沉淀产品思考,记录成长点滴,相信时间的力量

        Insight Stack Blog
        AI & 全栈技术 & 产品思考与成长记录
        联系方式

        欢迎通过以下方式与我交流 👋

        Insight Stack BlogAI & 全栈技术 & 产品思考与成长记录

        ✨探索技术前沿,沉淀产品思考,记录成长点滴,相信时间的力量

        Insight Stack Blog
        AI & 全栈技术 & 产品思考与成长记录