feat(homepage): update feature cards with images and improve UI

- Add cover images for stage 2 and 3 feature cards
- Enhance card hover effects and scrolling behavior
- Improve appendix section with new navigation controls
- Update stage 2 content with more specific learning paths
This commit is contained in:
sanbuphy
2026-03-27 18:17:31 +08:00
parent 547cf834ec
commit 4438edf4d5
7 changed files with 551 additions and 323 deletions
+1 -1
View File
@@ -609,7 +609,7 @@ watch(sidebarCollapsed, (collapsed) => {
</div> </div>
</ClientOnly> </ClientOnly>
<ClientOnly> <ClientOnly>
<ReadingProgress /> <ReadingProgress v-if="!isHomePage && !isWelcomePage" />
</ClientOnly> </ClientOnly>
</template> </template>
+396 -242
View File
@@ -2,6 +2,16 @@
import { ref, onMounted, onUnmounted, computed } from 'vue' import { ref, onMounted, onUnmounted, computed } from 'vue'
import { useRouter, withBase, useData } from 'vitepress' import { useRouter, withBase, useData } from 'vitepress'
import GitHubStars from './GitHubStars.vue' import GitHubStars from './GitHubStars.vue'
import stage2LovartCover from '../../../zh-cn/stage-2/frontend/2.0-lovart-assets/images/image1.png'
import stage2FigmaCover from '../../../zh-cn/stage-2/frontend/2.1-figma-mastergo/images/image8.png'
import stage2DesignToCodeCover from '../../../zh-cn/stage-2/frontend/2.6-design-to-code/images/image42.png'
import stage2SupabaseCover from '../../../zh-cn/stage-2/backend/2.2-database-supabase/images/image1.png'
import stage2ZeaburCover from '../../../zh-cn/stage-2/backend/2.5-zeabur-deployment/images/image1.png'
import stage2DifyCover from '../../../zh-cn/stage-2/ai-capabilities/2.1-dify-knowledge-base/images/image1.png'
import stage3ElectronCover from '../../../zh-cn/stage-3/cross-platform/3.10-electron-voice-to-text/images/image3.png'
import stage3AgentTeamsCover from '../../../zh-cn/stage-3/core-skills/agent-teams/images/home-cover.svg'
import stage3LongRunningCover from '../../../zh-cn/stage-3/core-skills/long-running-tasks/images/home-cover.svg'
import stage3PersonalBrandCover from '../../../zh-cn/stage-3/personal-brand/3.7-personal-website-blog/images/image1.png'
const router = useRouter() const router = useRouter()
const { site, page, lang } = useData() const { site, page, lang } = useData()
@@ -54,6 +64,14 @@ const scrollToPage = (pageIndex) => {
} }
} }
const scrollAppendixByPage = (direction) => {
const nextPage = Math.min(
totalPages.value - 1,
Math.max(0, currentPage.value + direction)
)
scrollToPage(nextPage)
}
const autoScroll = () => { const autoScroll = () => {
if (appendixWrapper.value) { if (appendixWrapper.value) {
const { scrollLeft, clientWidth, scrollWidth } = appendixWrapper.value const { scrollLeft, clientWidth, scrollWidth } = appendixWrapper.value
@@ -109,10 +127,22 @@ const i18n = {
sub: '从前端到后端,从数据库到上线。', sub: '从前端到后端,从数据库到上线。',
cards: [ cards: [
{ {
title: '全栈路径总览', title: '素材生成 Agent',
headline: '先看清全局再动手。', headline: '先把素材生产提速。',
desc: '一页看懂 Stage 2:前端、后端、数据库与部署如何串成完整链路。', desc: '从 Lovart 和 Nanobanana 出发,搭建自己的素材生产工作流和绘图 Agent。',
link: '/zh-cn/stage-2/' link: '/zh-cn/stage-2/frontend/2.0-lovart-assets/'
},
{
title: 'Figma 与 MasterGo',
headline: '先把设计工具用顺。',
desc: '掌握专业 UI 设计工具的基础操作,理解从设计稿到开发协作的关键链路。',
link: '/zh-cn/stage-2/frontend/2.1-figma-mastergo/'
},
{
title: '设计稿转代码',
headline: '把原型真正变成页面。',
desc: '学习如何将设计原型转成可以在浏览器里运行的前端代码,减少手工重搭。',
link: '/zh-cn/stage-2/frontend/2.6-design-to-code/'
}, },
{ {
title: '真实数据项目', title: '真实数据项目',
@@ -125,6 +155,12 @@ const i18n = {
headline: '让世界看到你的作品。', headline: '让世界看到你的作品。',
desc: '使用 CloudBase、Vercel、Zeabur 等平台,一口气打通从代码到公网访问的完整流程。', desc: '使用 CloudBase、Vercel、Zeabur 等平台,一口气打通从代码到公网访问的完整流程。',
link: '/zh-cn/stage-2/backend/2.5-zeabur-deployment/' link: '/zh-cn/stage-2/backend/2.5-zeabur-deployment/'
},
{
title: 'AI 知识库集成',
headline: '让应用接上智能问答。',
desc: '学习用 Dify 构建 AI 应用和知识库,把检索增强能力接进你的真实产品。',
link: '/zh-cn/stage-2/ai-capabilities/2.1-dify-knowledge-base/'
} }
] ]
}, },
@@ -270,10 +306,22 @@ const i18n = {
sub: 'Understand the full journey from frontend to backend, database and deployment.', sub: 'Understand the full journey from frontend to backend, database and deployment.',
cards: [ cards: [
{ {
title: 'Stage Overview', title: 'Asset Agent',
headline: 'See the whole map first.', headline: 'Speed up content production.',
desc: 'Start from the Stage 2 overview and understand how frontend, backend and infra fit together.', desc: 'Build your own design-asset workflow and drawing agent with Lovart and Nanobanana.',
link: '/zh-cn/stage-2/' link: '/zh-cn/stage-2/frontend/2.0-lovart-assets/'
},
{
title: 'Figma & MasterGo',
headline: 'Get fluent with design tools.',
desc: 'Learn the basics of modern UI design tools and how design files flow into development.',
link: '/zh-cn/stage-2/frontend/2.1-figma-mastergo/'
},
{
title: 'Design to Code',
headline: 'Turn mockups into pages.',
desc: 'Convert prototypes into real frontend code that runs in the browser instead of staying as static designs.',
link: '/zh-cn/stage-2/frontend/2.6-design-to-code/'
}, },
{ {
title: 'Real Data Project', title: 'Real Data Project',
@@ -286,6 +334,12 @@ const i18n = {
headline: 'Ship it to the world.', headline: 'Ship it to the world.',
desc: 'Use CloudBase, Vercel and Zeabur to turn local projects into publicly reachable sites.', desc: 'Use CloudBase, Vercel and Zeabur to turn local projects into publicly reachable sites.',
link: '/zh-cn/stage-2/backend/2.5-zeabur-deployment/' link: '/zh-cn/stage-2/backend/2.5-zeabur-deployment/'
},
{
title: 'AI Knowledge Base',
headline: 'Plug AI into the app.',
desc: 'Use Dify to build AI workflows and knowledge-base powered product experiences.',
link: '/zh-cn/stage-2/ai-capabilities/2.1-dify-knowledge-base/'
} }
] ]
}, },
@@ -1775,31 +1829,53 @@ const stage1Cards = [
// Stage 2: 初中级开发 (全栈) // Stage 2: 初中级开发 (全栈)
const stage2Cards = [ const stage2Cards = [
{ {
title: '全栈路径总览',
headline: '先看清全局再动手。',
desc: '一页看懂 Stage 2:前端、后端、数据库与部署如何串成完整链路。',
imageColor: '#E0C3FC', imageColor: '#E0C3FC',
visualType: 'code', image: stage2LovartCover,
link: '/zh-cn/stage-2/' imageAlt: 'Lovart 素材生产 Agent 界面截图',
link: '/zh-cn/stage-2/frontend/2.0-lovart-assets/'
},
{
imageColor: '#D8C4F8',
image: stage2FigmaCover,
imageAlt: 'Figma 与 MasterGo 设计工具截图',
link: '/zh-cn/stage-2/frontend/2.1-figma-mastergo/'
},
{
imageColor: '#C7DDFB',
image: stage2DesignToCodeCover,
imageAlt: '设计稿转代码示意截图',
link: '/zh-cn/stage-2/frontend/2.6-design-to-code/'
}, },
{ {
title: '真实数据项目',
headline: '连上真正的数据库。',
desc: '在 Supabase 上设计数据表和权限,用真实读写操作支撑你的产品数据层。',
imageColor: '#8EC5FC', imageColor: '#8EC5FC',
visualType: 'server', image: stage2SupabaseCover,
imageAlt: 'Supabase 数据库控制台截图',
link: '/zh-cn/stage-2/backend/2.2-database-supabase/' link: '/zh-cn/stage-2/backend/2.2-database-supabase/'
}, },
{ {
title: '部署上线',
headline: '让世界看到你的作品。',
desc: '使用 CloudBase、Vercel、Zeabur 等平台,一口气打通从代码到公网访问的完整流程。',
imageColor: '#96E6A1', imageColor: '#96E6A1',
visualType: 'cloud', image: stage2ZeaburCover,
imageAlt: 'Zeabur 部署流程截图',
link: '/zh-cn/stage-2/backend/2.5-zeabur-deployment/' link: '/zh-cn/stage-2/backend/2.5-zeabur-deployment/'
},
{
imageColor: '#A7F3D0',
image: stage2DifyCover,
imageAlt: 'Dify 知识库工作台截图',
link: '/zh-cn/stage-2/ai-capabilities/2.1-dify-knowledge-base/'
} }
] ]
const localizedStage2Cards = computed(() => {
return t.value.stage2.cards.map((card, index) => {
const visual = stage2Cards.find((item) => item.link === card.link) || stage2Cards[index]
return {
...card,
...visual
}
})
})
// Stage 3: 高级开发 (小程序 & AI) // Stage 3: 高级开发 (小程序 & AI)
const stage3Cards = [ const stage3Cards = [
{ {
@@ -1807,6 +1883,8 @@ const stage3Cards = [
desc: '用 Electron 做语音转文字桌面程序,一次开发同时跑在 Windows、macOS、Linux。', desc: '用 Electron 做语音转文字桌面程序,一次开发同时跑在 Windows、macOS、Linux。',
tag: 'Stage 3', tag: 'Stage 3',
visualType: 'phone', visualType: 'phone',
image: stage3ElectronCover,
imageAlt: 'Electron 语音转文字桌面应用预览图',
link: '/zh-cn/stage-3/cross-platform/3.10-electron-voice-to-text/' link: '/zh-cn/stage-3/cross-platform/3.10-electron-voice-to-text/'
}, },
{ {
@@ -1814,6 +1892,8 @@ const stage3Cards = [
desc: '用 Claude Agent Teams 组建 AI 开发小队,多代理协作完成大型任务。', desc: '用 Claude Agent Teams 组建 AI 开发小队,多代理协作完成大型任务。',
tag: 'Advanced', tag: 'Advanced',
visualType: 'ai', visualType: 'ai',
image: stage3AgentTeamsCover,
imageAlt: 'Claude Agent Teams 协作流程封面图',
link: '/zh-cn/stage-3/core-skills/agent-teams/' link: '/zh-cn/stage-3/core-skills/agent-teams/'
}, },
{ {
@@ -1821,6 +1901,8 @@ const stage3Cards = [
desc: '用循环脚本和 Ralph 插件管理长时间任务,让 Claude Code 过夜稳定跑完工作。', desc: '用循环脚本和 Ralph 插件管理长时间任务,让 Claude Code 过夜稳定跑完工作。',
tag: 'Architecture', tag: 'Architecture',
visualType: 'arch', visualType: 'arch',
image: stage3LongRunningCover,
imageAlt: 'Claude Code 长时间执行与循环任务封面图',
link: '/zh-cn/stage-3/core-skills/long-running-tasks/' link: '/zh-cn/stage-3/core-skills/long-running-tasks/'
}, },
{ {
@@ -1828,6 +1910,9 @@ const stage3Cards = [
desc: '搭建个人网站与技术博客,让你的项目和经验长期沉淀并被更多人看到。', desc: '搭建个人网站与技术博客,让你的项目和经验长期沉淀并被更多人看到。',
tag: 'Brand', tag: 'Brand',
visualType: 'brand', visualType: 'brand',
image: stage3PersonalBrandCover,
imageAlt: '个人网站与学术博客示例截图',
imageClass: 'prod-image--personal-brand',
link: '/zh-cn/stage-3/personal-brand/3.7-personal-website-blog/' link: '/zh-cn/stage-3/personal-brand/3.7-personal-website-blog/'
} }
] ]
@@ -2019,6 +2104,7 @@ const appendixCards = [
style="height: 0" style="height: 0"
/> />
<div class="section-band section-band-learning">
<!-- Stage 1: Product Manager --> <!-- Stage 1: Product Manager -->
<section <section
id="pm" id="pm"
@@ -2079,25 +2165,30 @@ const appendixCards = [
<div class="comm-grid"> <div class="comm-grid">
<a <a
v-for="(card, index) in stage2Cards" v-for="(card, index) in localizedStage2Cards"
:key="index" :key="index"
:href="withBase(t.stage2.cards[index].link)" :href="withBase(card.link)"
class="comm-card glass" class="comm-card glass"
> >
<div <div
class="comm-visual" class="comm-visual"
:style="{ backgroundColor: card.imageColor }" :style="{ backgroundColor: card.imageColor }"
> >
<div class="visual-placeholder" /> <img
:src="card.image"
:alt="card.imageAlt || card.title"
loading="lazy"
>
</div> </div>
<div class="comm-text"> <div class="comm-text">
<h4 class="comm-title">{{ t.stage2.cards[index].title }}</h4> <h4 class="comm-title">{{ card.title }}</h4>
<p class="comm-desc">{{ t.stage2.cards[index].desc }}</p> <p class="comm-desc">{{ card.desc }}</p>
<span class="comm-note">进一步了解 </span> <span class="comm-note">进一步了解 </span>
</div> </div>
</a> </a>
</div> </div>
</section> </section>
</div>
<!-- Stage 3: Senior Dev --> <!-- Stage 3: Senior Dev -->
<section <section
@@ -2128,7 +2219,14 @@ const appendixCards = [
<div class="prod-tag">{{ card.tag }}</div> <div class="prod-tag">{{ card.tag }}</div>
<h4>{{ t.stage3.cards[index].title }}</h4> <h4>{{ t.stage3.cards[index].title }}</h4>
<p>{{ t.stage3.cards[index].desc }}</p> <p>{{ t.stage3.cards[index].desc }}</p>
<div class="prod-visual" /> <div class="prod-visual">
<img
:src="card.image"
:alt="card.imageAlt"
:class="card.imageClass"
loading="lazy"
>
</div>
</a> </a>
</div> </div>
</div> </div>
@@ -2162,56 +2260,73 @@ const appendixCards = [
:key="index" :key="index"
:href="withBase(card.link)" :href="withBase(card.link)"
class="appendix-card" class="appendix-card"
>
<div
class="appendix-icon-wrapper"
:class="'icon-' + (index % 4)"
> >
<span class="appendix-emoji">{{ <span class="appendix-emoji">{{
['🤖', '🧠', '🎨', '🚀', '⚙️', '💾', '🛠️', '🌐'][index] || '📚' ['🤖', '🧠', '🎨', '🚀', '⚙️', '💾', '🛠️', '🌐'][index] || '📚'
}}</span> }}</span>
</div> <span class="appendix-title">{{ card.title }}</span>
<div class="appendix-content">
<p class="appendix-text">
<span class="appendix-title">{{ card.title }}.</span>
{{ card.desc }}
</p>
</div>
</a> </a>
</div> </div>
</div> </div>
<!-- Slider Indicator -->
<div <div
v-if="totalPages > 1" v-if="totalPages > 1"
class="appendix-controls" class="appendix-scroll-hint"
> >
<div class="appendix-progress-track">
<div
class="appendix-progress-thumb"
:style="{
width: `${100 / totalPages}%`,
transform: `translateX(${currentPage * 100}%)`
}"
/>
</div>
<div class="appendix-scroll-actions">
<button <button
class="control-btn play-btn" class="appendix-arrow-btn"
aria-label="Auto Scroll" :class="{ disabled: currentPage === 0 }"
@click="autoScroll" :disabled="currentPage === 0"
aria-label="向左滑动"
@click="scrollAppendixByPage(-1)"
> >
<svg <svg
width="12" width="20"
height="14" height="20"
viewBox="0 0 12 14" viewBox="0 0 20 20"
fill="none" fill="none"
xmlns="http://www.w3.org/2000/svg"
> >
<path <path
d="M10.5 5.76795C11.1667 6.15285 11.1667 7.1151 10.5 7.5L2.25 12.2631C1.58333 12.648 0.75 12.1669 0.75 11.3971L0.75 1.87084C0.75 1.10104 1.58333 0.61991 2.25 1.00481L10.5 5.76795Z" d="M11.5 5.5L7 10L11.5 14.5"
fill="currentColor" stroke="currentColor"
stroke-width="2.4"
stroke-linecap="round"
stroke-linejoin="round"
/> />
</svg> </svg>
</button> </button>
<div class="indicator-track"> <button
<div class="appendix-arrow-btn"
v-for="i in totalPages" :class="{ disabled: currentPage >= totalPages - 1 }"
:key="i" :disabled="currentPage >= totalPages - 1"
class="indicator-dot" aria-label="向右滑动"
:class="{ active: currentPage === i - 1 }" @click="scrollAppendixByPage(1)"
@click="scrollToPage(i - 1)" >
<svg
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
>
<path
d="M8.5 5.5L13 10L8.5 14.5"
stroke="currentColor"
stroke-width="2.4"
stroke-linecap="round"
stroke-linejoin="round"
/> />
</svg>
</button>
</div> </div>
</div> </div>
</section> </section>
@@ -2303,6 +2418,24 @@ a {
color: inherit; color: inherit;
} }
:is(.feature-card, .comm-card, .prod-card, .appendix-card, .buy-btn) {
border-bottom: none !important;
outline: none !important;
-webkit-tap-highlight-color: transparent;
}
:is(
.feature-card,
.comm-card,
.prod-card,
.appendix-card,
.buy-btn
):is(:hover, :focus, :focus-visible, :active) {
border-bottom-color: transparent !important;
text-decoration: none !important;
outline: none !important;
}
.highlight { .highlight {
color: var(--vp-c-text-2); color: var(--vp-c-text-2);
} }
@@ -2572,19 +2705,43 @@ a {
padding: 0 40px; padding: 0 40px;
} }
.section-junior, .section-band-learning {
.section-appendix { width: 100vw;
max-width: none;
margin: 0 calc(50% - 50vw) 96px;
background: #f5f5f7; background: #f5f5f7;
border-radius: 40px; border-radius: 0;
padding-top: 64px;
padding-bottom: 64px;
padding-left: max(40px, calc((100vw - 1280px) / 2 + 40px));
padding-right: max(40px, calc((100vw - 1280px) / 2 + 40px));
}
.section-band-learning .section-container {
max-width: 1280px;
margin: 0 auto;
padding: 0;
}
.section-band-learning .section-junior {
margin-top: 72px;
}
.section-appendix {
background: transparent;
border-radius: 0;
padding-top: 64px; padding-top: 64px;
padding-bottom: 64px; padding-bottom: 64px;
} }
.dark .section-junior, .dark .section-band-learning {
.dark .section-appendix {
background: rgba(255, 255, 255, 0.03); background: rgba(255, 255, 255, 0.03);
} }
.dark .section-appendix {
background: transparent;
}
.section-header { .section-header {
margin-bottom: 44px; margin-bottom: 44px;
} }
@@ -2688,41 +2845,52 @@ a {
/* Communication Grid (Now used for Stage 2) */ /* Communication Grid (Now used for Stage 2) */
.comm-grid { .comm-grid {
display: grid; display: flex;
grid-template-columns: repeat(3, 1fr);
gap: 24px; gap: 24px;
overflow-x: auto;
width: calc(100% + 40px);
margin: 0 -20px;
padding: 0 20px 16px;
scroll-snap-type: x mandatory;
-webkit-overflow-scrolling: touch;
overscroll-behavior-x: contain;
scrollbar-width: none;
-ms-overflow-style: none;
}
.comm-grid::-webkit-scrollbar {
display: none;
} }
.comm-card { .comm-card {
flex: 0 0 380px;
border-radius: 32px; border-radius: 32px;
overflow: hidden; overflow: hidden;
background: #fff; background: #fff;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05); box-shadow: none;
border: 1px solid rgba(0, 0, 0, 0.04); border: 1px solid rgba(0, 0, 0, 0.025);
transition: transform 0.3s; transition: transform 0.3s;
display: block; display: block;
scroll-snap-align: start;
} }
.comm-card:hover { .comm-card:hover {
transform: translateY(-6px); transform: scale(1.015);
} }
.comm-visual { .comm-visual {
height: 220px; height: 220px;
width: 100%; width: 100%;
position: relative; position: relative;
overflow: hidden;
} }
.visual-placeholder { .comm-visual img {
position: absolute; width: 100%;
bottom: 20px; height: 100%;
left: 50%; display: block;
transform: translateX(-50%); object-fit: cover;
width: 60px; object-position: top center;
height: 60px;
background: rgba(255, 255, 255, 0.5);
border-radius: 50%;
backdrop-filter: blur(10px);
} }
.comm-text { .comm-text {
@@ -2761,6 +2929,13 @@ a {
padding: 0 20px 40px; padding: 0 20px 40px;
-webkit-overflow-scrolling: touch; -webkit-overflow-scrolling: touch;
scroll-snap-type: x mandatory; scroll-snap-type: x mandatory;
overscroll-behavior-x: contain;
scrollbar-width: none;
-ms-overflow-style: none;
}
.scroll-container::-webkit-scrollbar {
display: none;
} }
.scroll-track { .scroll-track {
@@ -2773,7 +2948,7 @@ a {
width: 300px; width: 300px;
height: 400px; height: 400px;
border-radius: 32px; border-radius: 32px;
background: #fff; background: #f7f7f9;
padding: 30px; padding: 30px;
scroll-snap-align: center; scroll-snap-align: center;
text-decoration: none !important; text-decoration: none !important;
@@ -2781,12 +2956,12 @@ a {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
transition: transform 0.3s; transition: transform 0.3s;
border: 1px solid rgba(0, 0, 0, 0.04); border: 1px solid rgba(0, 0, 0, 0.025);
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05); box-shadow: none;
} }
.prod-card:hover { .prod-card:hover {
transform: translateY(-6px); transform: scale(1.015);
} }
.prod-tag { .prod-tag {
@@ -2817,19 +2992,33 @@ a {
.prod-visual { .prod-visual {
margin-top: auto; margin-top: auto;
height: 150px; height: 150px;
background: linear-gradient(135deg, #dbeafe 0%, #e5e7eb 100%);
border-radius: 20px; border-radius: 20px;
opacity: 1; overflow: hidden;
background: linear-gradient(135deg, #dbeafe 0%, #e5e7eb 100%);
}
.prod-visual img {
width: 100%;
height: 100%;
display: block;
object-fit: cover;
object-position: center;
}
.prod-visual img.prod-image--personal-brand {
transform: scale(1.18) translateY(-10px);
transform-origin: center top;
} }
/* Appendix Horizontal Scroll */ /* Appendix Horizontal Scroll */
.appendix-scroll-wrapper { .appendix-scroll-wrapper {
overflow-x: auto; overflow-x: auto;
scroll-snap-type: x mandatory; scroll-snap-type: x mandatory;
padding-bottom: 10px;
margin: 0 -20px; margin: 0 -20px;
padding: 0 20px; padding: 0 20px 12px;
scrollbar-width: none; scrollbar-width: none;
-ms-overflow-style: none;
overscroll-behavior-x: contain;
} }
.appendix-scroll-wrapper::-webkit-scrollbar { .appendix-scroll-wrapper::-webkit-scrollbar {
@@ -2837,172 +3026,123 @@ a {
} }
.appendix-track { .appendix-track {
display: grid; display: flex;
grid-template-rows: repeat(2, 1fr); align-items: flex-start;
grid-auto-flow: column; gap: 40px;
grid-auto-columns: minmax(280px, 1fr);
gap: 32px 24px;
width: max-content; width: max-content;
padding-bottom: 10px;
} }
.appendix-card { .appendix-card {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: flex-start; align-items: center;
justify-content: flex-start;
gap: 12px;
text-decoration: none !important; text-decoration: none !important;
color: inherit !important; color: inherit !important;
background: #fff; background: transparent;
padding: 24px; padding: 0;
border: 1px solid rgba(0, 0, 0, 0.04); border: 0;
border-radius: 28px; box-shadow: none;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.04);
scroll-snap-align: start; scroll-snap-align: start;
width: 100%; width: 120px;
min-height: 360px; min-height: 120px;
transition: transform 0.25s ease; transition: transform 0.25s ease;
text-align: center;
} }
/* Slider Controls */
.appendix-controls {
display: flex;
align-items: center;
justify-content: center;
gap: 16px;
margin-top: 40px;
}
.control-btn {
width: 44px;
height: 44px;
border-radius: 50%;
background: #fff;
border: none;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
color: var(--vp-c-text-1);
transition: all 0.2s;
}
.control-btn:hover {
background: #f0f0f2;
transform: scale(1.05);
}
.indicator-track {
display: flex;
align-items: center;
gap: 8px;
background: #fff;
padding: 6px 12px;
border-radius: 20px;
height: 44px;
}
.indicator-dot {
width: 8px;
height: 8px;
border-radius: 4px;
background: #b8b8bd;
cursor: pointer;
transition: all 0.3s cubic-bezier(0.25, 0.1, 0.25, 1);
opacity: 0.5;
}
.indicator-dot.active {
width: 32px;
background: #1d1d1f;
opacity: 1;
}
.indicator-dot:hover {
opacity: 0.8;
}
/* Remove hover effects */
.appendix-card:hover { .appendix-card:hover {
transform: translateY(-4px); transform: scale(1.03);
} }
.appendix-icon-wrapper { .appendix-emoji {
width: 100%; font-size: 52px;
height: 190px; line-height: 1;
border-radius: 24px; display: block;
display: flex;
align-items: center;
justify-content: center;
font-size: 88px;
margin-bottom: 14px;
/* Glassmorphism / VisionOS Style */
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.06);
/* No transition */
}
/* Remove hover effects on icon */
.appendix-card:hover .appendix-icon-wrapper {
/* No transform or shadow change */
}
/* Transparent Tinted Gradients for icons (VisionOS Style) */
/* AI - Blue */
.icon-0 {
background: linear-gradient(
180deg,
rgba(0, 122, 255, 0.16) 0%,
rgba(0, 122, 255, 0.06) 100%
);
border: 1px solid rgba(0, 122, 255, 0.15);
}
/* Frontend - Orange */
.icon-1 {
background: linear-gradient(
180deg,
rgba(255, 149, 0, 0.16) 0%,
rgba(255, 149, 0, 0.06) 100%
);
border: 1px solid rgba(255, 149, 0, 0.15);
}
/* Backend - Pink */
.icon-2 {
background: linear-gradient(
180deg,
rgba(255, 45, 85, 0.16) 0%,
rgba(255, 45, 85, 0.06) 100%
);
border: 1px solid rgba(255, 45, 85, 0.15);
}
/* General - Green */
.icon-3 {
background: linear-gradient(
180deg,
rgba(52, 199, 89, 0.16) 0%,
rgba(52, 199, 89, 0.06) 100%
);
border: 1px solid rgba(52, 199, 89, 0.15);
}
.appendix-content {
text-align: left;
}
.appendix-text {
font-size: 13px;
line-height: 1.5;
color: #6e6e73;
margin: 0;
font-weight: 400;
letter-spacing: -0.01em;
} }
.appendix-title { .appendix-title {
font-weight: 600; font-weight: 600;
color: #1d1d1f; color: #3c3c43;
margin-right: 6px; margin: 0;
font-size: 12px; font-size: 14px;
line-height: 1.35;
letter-spacing: -0.01em;
white-space: normal;
}
.appendix-scroll-hint {
position: relative;
display: flex;
align-items: center;
justify-content: flex-end;
gap: 18px;
margin-top: 20px;
min-height: 40px;
}
.appendix-progress-track {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 160px;
height: 4px;
border-radius: 999px;
background: rgba(60, 60, 67, 0.08);
overflow: hidden;
}
.appendix-progress-thumb {
height: 100%;
border-radius: inherit;
background: rgba(60, 60, 67, 0.28);
transition: transform 0.25s ease;
}
.appendix-scroll-actions {
display: flex;
align-items: center;
gap: 10px;
margin-left: auto;
margin-right: 56px;
}
.appendix-arrow-btn {
width: 38px;
height: 38px;
border-radius: 999px;
border: 1px solid rgba(60, 60, 67, 0.05);
background: rgba(60, 60, 67, 0.05);
color: rgba(60, 60, 67, 0.62);
display: inline-flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition:
background-color 0.2s ease,
color 0.2s ease,
transform 0.2s ease;
}
.appendix-arrow-btn:hover {
background: rgba(255, 255, 255, 0.78);
border-color: rgba(60, 60, 67, 0.08);
color: rgba(60, 60, 67, 0.74);
transform: scale(1.04);
}
.appendix-arrow-btn.disabled,
.appendix-arrow-btn:disabled {
opacity: 0.42;
cursor: default;
transform: none;
}
.appendix-arrow-btn.disabled:hover,
.appendix-arrow-btn:disabled:hover {
background: rgba(60, 60, 67, 0.05);
color: rgba(60, 60, 67, 0.62);
} }
/* Footer */ /* Footer */
@@ -3255,10 +3395,6 @@ a {
height: auto; height: auto;
} }
.comm-grid {
grid-template-columns: 1fr;
}
.nav-links { .nav-links {
display: none; display: none;
} }
@@ -3271,13 +3407,23 @@ a {
white-space: nowrap; white-space: nowrap;
} }
.section-junior,
.section-appendix { .section-appendix {
border-radius: 28px;
padding-top: 42px; padding-top: 42px;
padding-bottom: 42px; padding-bottom: 42px;
} }
.section-band-learning {
margin-bottom: 96px;
padding-top: 42px;
padding-bottom: 42px;
padding-left: 24px;
padding-right: 24px;
}
.section-band-learning .section-junior {
margin-top: 56px;
}
.footer-callout { .footer-callout {
margin: 0 16px 40px; margin: 0 16px 40px;
border-radius: 28px; border-radius: 28px;
@@ -3329,22 +3475,22 @@ a {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
transition: all 0.3s cubic-bezier(0.25, 0.1, 0.25, 1); transition: all 0.3s cubic-bezier(0.25, 0.1, 0.25, 1);
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05); box-shadow: none;
height: 100%; height: 100%;
position: relative; position: relative;
overflow: hidden; overflow: hidden;
text-decoration: none !important; text-decoration: none !important;
border: 1px solid rgba(0, 0, 0, 0.04); border: 1px solid rgba(0, 0, 0, 0.025);
} }
.dark .feature-card { .dark .feature-card {
border: 1px solid rgba(255, 255, 255, 0.08); border: 1px solid rgba(255, 255, 255, 0.06);
background: var(--vp-c-bg-mute); background: var(--vp-c-bg-mute);
} }
.feature-card:hover { .feature-card:hover {
transform: translateY(-6px); transform: scale(1.015);
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.08); box-shadow: none;
} }
.feature-icon { .feature-icon {
@@ -3388,6 +3534,10 @@ a {
.feature-grid { .feature-grid {
grid-template-columns: repeat(2, 1fr); grid-template-columns: repeat(2, 1fr);
} }
.comm-card {
flex-basis: 340px;
}
} }
@media (max-width: 640px) { @media (max-width: 640px) {
@@ -3397,5 +3547,9 @@ a {
.feature-card { .feature-card {
padding: 24px; padding: 24px;
} }
.comm-card {
flex-basis: min(86vw, 340px);
}
} }
</style> </style>
+8
View File
@@ -299,6 +299,14 @@
border: 1px solid rgba(255, 255, 255, 0.3); border: 1px solid rgba(255, 255, 255, 0.3);
} }
.VPHome .reading-progress {
display: none !important;
}
body:has(.VPHome) .reading-progress {
display: none !important;
}
.dark .glass { .dark .glass {
background: rgba(0, 0, 0, 0.7); background: rgba(0, 0, 0, 0.7);
border: 1px solid rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.1);
@@ -0,0 +1,33 @@
<svg width="1200" height="720" viewBox="0 0 1200 720" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="1200" height="720" rx="40" fill="url(#bg)"/>
<rect x="72" y="84" width="1056" height="552" rx="32" fill="white" fill-opacity="0.78"/>
<rect x="120" y="138" width="250" height="180" rx="24" fill="#0F172A"/>
<text x="152" y="204" fill="white" font-family="Arial, sans-serif" font-size="38" font-weight="700">Team Lead</text>
<text x="152" y="252" fill="#BFDBFE" font-family="Arial, sans-serif" font-size="24">拆解任务</text>
<text x="152" y="288" fill="#BFDBFE" font-family="Arial, sans-serif" font-size="24">协调成员</text>
<rect x="470" y="138" width="250" height="180" rx="24" fill="#1D4ED8"/>
<text x="505" y="204" fill="white" font-family="Arial, sans-serif" font-size="38" font-weight="700">Agent A</text>
<text x="505" y="252" fill="#DBEAFE" font-family="Arial, sans-serif" font-size="24">Frontend</text>
<rect x="810" y="138" width="250" height="180" rx="24" fill="#7C3AED"/>
<text x="844" y="204" fill="white" font-family="Arial, sans-serif" font-size="38" font-weight="700">Agent B</text>
<text x="844" y="252" fill="#EDE9FE" font-family="Arial, sans-serif" font-size="24">Backend</text>
<rect x="292" y="398" width="250" height="150" rx="24" fill="#059669"/>
<text x="328" y="460" fill="white" font-family="Arial, sans-serif" font-size="34" font-weight="700">Agent C</text>
<text x="328" y="502" fill="#D1FAE5" font-family="Arial, sans-serif" font-size="22">Testing</text>
<rect x="658" y="398" width="250" height="150" rx="24" fill="#EA580C"/>
<text x="694" y="460" fill="white" font-family="Arial, sans-serif" font-size="34" font-weight="700">Task List</text>
<text x="694" y="502" fill="#FFEDD5" font-family="Arial, sans-serif" font-size="22">共享任务板</text>
<path d="M370 228H470" stroke="#2563EB" stroke-width="12" stroke-linecap="round"/>
<path d="M720 228H810" stroke="#6366F1" stroke-width="12" stroke-linecap="round"/>
<path d="M600 318V398" stroke="#0F172A" stroke-width="12" stroke-linecap="round"/>
<path d="M542 472H658" stroke="#475569" stroke-width="12" stroke-linecap="round"/>
<text x="120" y="604" fill="#0F172A" font-family="Arial, sans-serif" font-size="58" font-weight="700">Claude Agent Teams</text>
<text x="120" y="652" fill="#475569" font-family="Arial, sans-serif" font-size="28">多代理并行协作,像真正开发团队一样分工与联动</text>
<defs>
<linearGradient id="bg" x1="69" y1="38" x2="1102" y2="701" gradientUnits="userSpaceOnUse">
<stop stop-color="#DBEAFE"/>
<stop offset="0.48" stop-color="#EDE9FE"/>
<stop offset="1" stop-color="#FEF3C7"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

@@ -6,6 +6,8 @@
想象一下,以前你使用 Claude Code,就像是一个项目经理带着一个超级能干的助手工作。无论任务多复杂,只有这一个助手在干活。现在有了 Agent Teams,你可以组建一支完整的 AI 开发团队——有的负责前端,有的负责后端,有的负责测试,它们可以**同时工作、互相交流、协同完成复杂任务**。 想象一下,以前你使用 Claude Code,就像是一个项目经理带着一个超级能干的助手工作。无论任务多复杂,只有这一个助手在干活。现在有了 Agent Teams,你可以组建一支完整的 AI 开发团队——有的负责前端,有的负责后端,有的负责测试,它们可以**同时工作、互相交流、协同完成复杂任务**。
![](images/home-cover.svg)
### 从单助手到团队协作 ### 从单助手到团队协作
在深入了解 Agent Teams 之前,让我们先理解它解决的问题。 在深入了解 Agent Teams 之前,让我们先理解它解决的问题。
@@ -0,0 +1,29 @@
<svg width="1200" height="720" viewBox="0 0 1200 720" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="1200" height="720" rx="40" fill="url(#bg)"/>
<rect x="72" y="82" width="1056" height="556" rx="32" fill="white" fill-opacity="0.82"/>
<rect x="124" y="132" width="420" height="214" rx="28" fill="#111827"/>
<text x="164" y="202" fill="#F9FAFB" font-family="Arial, sans-serif" font-size="34" font-weight="700">while true</text>
<text x="164" y="254" fill="#93C5FD" font-family="Arial, sans-serif" font-size="30">claude --continue</text>
<text x="164" y="306" fill="#A7F3D0" font-family="Arial, sans-serif" font-size="30">check completion</text>
<circle cx="760" cy="240" r="128" fill="#DBEAFE"/>
<circle cx="760" cy="240" r="92" fill="#2563EB"/>
<path d="M760 184V240L802 270" stroke="white" stroke-width="18" stroke-linecap="round" stroke-linejoin="round"/>
<rect x="124" y="410" width="280" height="138" rx="24" fill="#0EA5E9"/>
<text x="158" y="468" fill="white" font-family="Arial, sans-serif" font-size="32" font-weight="700">Stop Hook</text>
<text x="158" y="510" fill="#E0F2FE" font-family="Arial, sans-serif" font-size="22">拦截提前退出</text>
<rect x="462" y="410" width="280" height="138" rx="24" fill="#10B981"/>
<text x="496" y="468" fill="white" font-family="Arial, sans-serif" font-size="32" font-weight="700">Ralph</text>
<text x="496" y="510" fill="#D1FAE5" font-family="Arial, sans-serif" font-size="22">自动重试推进</text>
<rect x="800" y="410" width="280" height="138" rx="24" fill="#F59E0B"/>
<text x="834" y="468" fill="white" font-family="Arial, sans-serif" font-size="32" font-weight="700">Overnight</text>
<text x="834" y="510" fill="#FEF3C7" font-family="Arial, sans-serif" font-size="22">长任务稳定执行</text>
<text x="124" y="608" fill="#111827" font-family="Arial, sans-serif" font-size="58" font-weight="700">Claude Code 长时间工作</text>
<text x="124" y="656" fill="#4B5563" font-family="Arial, sans-serif" font-size="28">循环、检查与重试,让任务持续跑到真正完成</text>
<defs>
<linearGradient id="bg" x1="72" y1="32" x2="1114" y2="696" gradientUnits="userSpaceOnUse">
<stop stop-color="#E0F2FE"/>
<stop offset="0.5" stop-color="#ECFCCB"/>
<stop offset="1" stop-color="#FEF3C7"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

@@ -12,6 +12,8 @@
本章要解决的核心问题是:如何让 Claude Code 像真正的开发者一样,持续工作直到任务真正完成。 本章要解决的核心问题是:如何让 Claude Code 像真正的开发者一样,持续工作直到任务真正完成。
![](images/home-cover.svg)
--- ---
## 核心原理:为什么 AI 会"过早停止" ## 核心原理:为什么 AI 会"过早停止"