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:
@@ -609,7 +609,7 @@ watch(sidebarCollapsed, (collapsed) => {
|
||||
</div>
|
||||
</ClientOnly>
|
||||
<ClientOnly>
|
||||
<ReadingProgress />
|
||||
<ReadingProgress v-if="!isHomePage && !isWelcomePage" />
|
||||
</ClientOnly>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -2,6 +2,16 @@
|
||||
import { ref, onMounted, onUnmounted, computed } from 'vue'
|
||||
import { useRouter, withBase, useData } from 'vitepress'
|
||||
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 { 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 = () => {
|
||||
if (appendixWrapper.value) {
|
||||
const { scrollLeft, clientWidth, scrollWidth } = appendixWrapper.value
|
||||
@@ -109,10 +127,22 @@ const i18n = {
|
||||
sub: '从前端到后端,从数据库到上线。',
|
||||
cards: [
|
||||
{
|
||||
title: '全栈路径总览',
|
||||
headline: '先看清全局再动手。',
|
||||
desc: '一页看懂 Stage 2:前端、后端、数据库与部署如何串成完整链路。',
|
||||
link: '/zh-cn/stage-2/'
|
||||
title: '素材生成 Agent',
|
||||
headline: '先把素材生产提速。',
|
||||
desc: '从 Lovart 和 Nanobanana 出发,搭建自己的素材生产工作流和绘图 Agent。',
|
||||
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: '真实数据项目',
|
||||
@@ -125,6 +155,12 @@ const i18n = {
|
||||
headline: '让世界看到你的作品。',
|
||||
desc: '使用 CloudBase、Vercel、Zeabur 等平台,一口气打通从代码到公网访问的完整流程。',
|
||||
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.',
|
||||
cards: [
|
||||
{
|
||||
title: 'Stage Overview',
|
||||
headline: 'See the whole map first.',
|
||||
desc: 'Start from the Stage 2 overview and understand how frontend, backend and infra fit together.',
|
||||
link: '/zh-cn/stage-2/'
|
||||
title: 'Asset Agent',
|
||||
headline: 'Speed up content production.',
|
||||
desc: 'Build your own design-asset workflow and drawing agent with Lovart and Nanobanana.',
|
||||
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',
|
||||
@@ -286,6 +334,12 @@ const i18n = {
|
||||
headline: 'Ship it to the world.',
|
||||
desc: 'Use CloudBase, Vercel and Zeabur to turn local projects into publicly reachable sites.',
|
||||
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: 初中级开发 (全栈)
|
||||
const stage2Cards = [
|
||||
{
|
||||
title: '全栈路径总览',
|
||||
headline: '先看清全局再动手。',
|
||||
desc: '一页看懂 Stage 2:前端、后端、数据库与部署如何串成完整链路。',
|
||||
imageColor: '#E0C3FC',
|
||||
visualType: 'code',
|
||||
link: '/zh-cn/stage-2/'
|
||||
image: stage2LovartCover,
|
||||
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',
|
||||
visualType: 'server',
|
||||
image: stage2SupabaseCover,
|
||||
imageAlt: 'Supabase 数据库控制台截图',
|
||||
link: '/zh-cn/stage-2/backend/2.2-database-supabase/'
|
||||
},
|
||||
{
|
||||
title: '部署上线',
|
||||
headline: '让世界看到你的作品。',
|
||||
desc: '使用 CloudBase、Vercel、Zeabur 等平台,一口气打通从代码到公网访问的完整流程。',
|
||||
imageColor: '#96E6A1',
|
||||
visualType: 'cloud',
|
||||
image: stage2ZeaburCover,
|
||||
imageAlt: 'Zeabur 部署流程截图',
|
||||
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)
|
||||
const stage3Cards = [
|
||||
{
|
||||
@@ -1807,6 +1883,8 @@ const stage3Cards = [
|
||||
desc: '用 Electron 做语音转文字桌面程序,一次开发同时跑在 Windows、macOS、Linux。',
|
||||
tag: 'Stage 3',
|
||||
visualType: 'phone',
|
||||
image: stage3ElectronCover,
|
||||
imageAlt: 'Electron 语音转文字桌面应用预览图',
|
||||
link: '/zh-cn/stage-3/cross-platform/3.10-electron-voice-to-text/'
|
||||
},
|
||||
{
|
||||
@@ -1814,6 +1892,8 @@ const stage3Cards = [
|
||||
desc: '用 Claude Agent Teams 组建 AI 开发小队,多代理协作完成大型任务。',
|
||||
tag: 'Advanced',
|
||||
visualType: 'ai',
|
||||
image: stage3AgentTeamsCover,
|
||||
imageAlt: 'Claude Agent Teams 协作流程封面图',
|
||||
link: '/zh-cn/stage-3/core-skills/agent-teams/'
|
||||
},
|
||||
{
|
||||
@@ -1821,6 +1901,8 @@ const stage3Cards = [
|
||||
desc: '用循环脚本和 Ralph 插件管理长时间任务,让 Claude Code 过夜稳定跑完工作。',
|
||||
tag: 'Architecture',
|
||||
visualType: 'arch',
|
||||
image: stage3LongRunningCover,
|
||||
imageAlt: 'Claude Code 长时间执行与循环任务封面图',
|
||||
link: '/zh-cn/stage-3/core-skills/long-running-tasks/'
|
||||
},
|
||||
{
|
||||
@@ -1828,6 +1910,9 @@ const stage3Cards = [
|
||||
desc: '搭建个人网站与技术博客,让你的项目和经验长期沉淀并被更多人看到。',
|
||||
tag: 'Brand',
|
||||
visualType: 'brand',
|
||||
image: stage3PersonalBrandCover,
|
||||
imageAlt: '个人网站与学术博客示例截图',
|
||||
imageClass: 'prod-image--personal-brand',
|
||||
link: '/zh-cn/stage-3/personal-brand/3.7-personal-website-blog/'
|
||||
}
|
||||
]
|
||||
@@ -2019,6 +2104,7 @@ const appendixCards = [
|
||||
style="height: 0"
|
||||
/>
|
||||
|
||||
<div class="section-band section-band-learning">
|
||||
<!-- Stage 1: Product Manager -->
|
||||
<section
|
||||
id="pm"
|
||||
@@ -2079,25 +2165,30 @@ const appendixCards = [
|
||||
|
||||
<div class="comm-grid">
|
||||
<a
|
||||
v-for="(card, index) in stage2Cards"
|
||||
v-for="(card, index) in localizedStage2Cards"
|
||||
:key="index"
|
||||
:href="withBase(t.stage2.cards[index].link)"
|
||||
:href="withBase(card.link)"
|
||||
class="comm-card glass"
|
||||
>
|
||||
<div
|
||||
class="comm-visual"
|
||||
:style="{ backgroundColor: card.imageColor }"
|
||||
>
|
||||
<div class="visual-placeholder" />
|
||||
<img
|
||||
:src="card.image"
|
||||
:alt="card.imageAlt || card.title"
|
||||
loading="lazy"
|
||||
>
|
||||
</div>
|
||||
<div class="comm-text">
|
||||
<h4 class="comm-title">{{ t.stage2.cards[index].title }}</h4>
|
||||
<p class="comm-desc">{{ t.stage2.cards[index].desc }}</p>
|
||||
<h4 class="comm-title">{{ card.title }}</h4>
|
||||
<p class="comm-desc">{{ card.desc }}</p>
|
||||
<span class="comm-note">进一步了解 ›</span>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<!-- Stage 3: Senior Dev -->
|
||||
<section
|
||||
@@ -2128,7 +2219,14 @@ const appendixCards = [
|
||||
<div class="prod-tag">{{ card.tag }}</div>
|
||||
<h4>{{ t.stage3.cards[index].title }}</h4>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
@@ -2162,56 +2260,73 @@ const appendixCards = [
|
||||
:key="index"
|
||||
:href="withBase(card.link)"
|
||||
class="appendix-card"
|
||||
>
|
||||
<div
|
||||
class="appendix-icon-wrapper"
|
||||
:class="'icon-' + (index % 4)"
|
||||
>
|
||||
<span class="appendix-emoji">{{
|
||||
['🤖', '🧠', '🎨', '🚀', '⚙️', '💾', '🛠️', '🌐'][index] || '📚'
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="appendix-content">
|
||||
<p class="appendix-text">
|
||||
<span class="appendix-title">{{ card.title }}.</span>
|
||||
{{ card.desc }}
|
||||
</p>
|
||||
</div>
|
||||
<span class="appendix-title">{{ card.title }}</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Slider Indicator -->
|
||||
<div
|
||||
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
|
||||
class="control-btn play-btn"
|
||||
aria-label="Auto Scroll"
|
||||
@click="autoScroll"
|
||||
class="appendix-arrow-btn"
|
||||
:class="{ disabled: currentPage === 0 }"
|
||||
:disabled="currentPage === 0"
|
||||
aria-label="向左滑动"
|
||||
@click="scrollAppendixByPage(-1)"
|
||||
>
|
||||
<svg
|
||||
width="12"
|
||||
height="14"
|
||||
viewBox="0 0 12 14"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<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"
|
||||
fill="currentColor"
|
||||
d="M11.5 5.5L7 10L11.5 14.5"
|
||||
stroke="currentColor"
|
||||
stroke-width="2.4"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
<div class="indicator-track">
|
||||
<div
|
||||
v-for="i in totalPages"
|
||||
:key="i"
|
||||
class="indicator-dot"
|
||||
:class="{ active: currentPage === i - 1 }"
|
||||
@click="scrollToPage(i - 1)"
|
||||
<button
|
||||
class="appendix-arrow-btn"
|
||||
:class="{ disabled: currentPage >= totalPages - 1 }"
|
||||
:disabled="currentPage >= totalPages - 1"
|
||||
aria-label="向右滑动"
|
||||
@click="scrollAppendixByPage(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>
|
||||
</section>
|
||||
@@ -2303,6 +2418,24 @@ a {
|
||||
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 {
|
||||
color: var(--vp-c-text-2);
|
||||
}
|
||||
@@ -2572,19 +2705,43 @@ a {
|
||||
padding: 0 40px;
|
||||
}
|
||||
|
||||
.section-junior,
|
||||
.section-appendix {
|
||||
.section-band-learning {
|
||||
width: 100vw;
|
||||
max-width: none;
|
||||
margin: 0 calc(50% - 50vw) 96px;
|
||||
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-bottom: 64px;
|
||||
}
|
||||
|
||||
.dark .section-junior,
|
||||
.dark .section-appendix {
|
||||
.dark .section-band-learning {
|
||||
background: rgba(255, 255, 255, 0.03);
|
||||
}
|
||||
|
||||
.dark .section-appendix {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
margin-bottom: 44px;
|
||||
}
|
||||
@@ -2688,41 +2845,52 @@ a {
|
||||
|
||||
/* Communication Grid (Now used for Stage 2) */
|
||||
.comm-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
display: flex;
|
||||
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 {
|
||||
flex: 0 0 380px;
|
||||
border-radius: 32px;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);
|
||||
border: 1px solid rgba(0, 0, 0, 0.04);
|
||||
box-shadow: none;
|
||||
border: 1px solid rgba(0, 0, 0, 0.025);
|
||||
transition: transform 0.3s;
|
||||
display: block;
|
||||
scroll-snap-align: start;
|
||||
}
|
||||
|
||||
.comm-card:hover {
|
||||
transform: translateY(-6px);
|
||||
transform: scale(1.015);
|
||||
}
|
||||
|
||||
.comm-visual {
|
||||
height: 220px;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.visual-placeholder {
|
||||
position: absolute;
|
||||
bottom: 20px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
border-radius: 50%;
|
||||
backdrop-filter: blur(10px);
|
||||
.comm-visual img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
object-fit: cover;
|
||||
object-position: top center;
|
||||
}
|
||||
|
||||
.comm-text {
|
||||
@@ -2761,6 +2929,13 @@ a {
|
||||
padding: 0 20px 40px;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
scroll-snap-type: x mandatory;
|
||||
overscroll-behavior-x: contain;
|
||||
scrollbar-width: none;
|
||||
-ms-overflow-style: none;
|
||||
}
|
||||
|
||||
.scroll-container::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.scroll-track {
|
||||
@@ -2773,7 +2948,7 @@ a {
|
||||
width: 300px;
|
||||
height: 400px;
|
||||
border-radius: 32px;
|
||||
background: #fff;
|
||||
background: #f7f7f9;
|
||||
padding: 30px;
|
||||
scroll-snap-align: center;
|
||||
text-decoration: none !important;
|
||||
@@ -2781,12 +2956,12 @@ a {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
transition: transform 0.3s;
|
||||
border: 1px solid rgba(0, 0, 0, 0.04);
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);
|
||||
border: 1px solid rgba(0, 0, 0, 0.025);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.prod-card:hover {
|
||||
transform: translateY(-6px);
|
||||
transform: scale(1.015);
|
||||
}
|
||||
|
||||
.prod-tag {
|
||||
@@ -2817,19 +2992,33 @@ a {
|
||||
.prod-visual {
|
||||
margin-top: auto;
|
||||
height: 150px;
|
||||
background: linear-gradient(135deg, #dbeafe 0%, #e5e7eb 100%);
|
||||
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-scroll-wrapper {
|
||||
overflow-x: auto;
|
||||
scroll-snap-type: x mandatory;
|
||||
padding-bottom: 10px;
|
||||
margin: 0 -20px;
|
||||
padding: 0 20px;
|
||||
padding: 0 20px 12px;
|
||||
scrollbar-width: none;
|
||||
-ms-overflow-style: none;
|
||||
overscroll-behavior-x: contain;
|
||||
}
|
||||
|
||||
.appendix-scroll-wrapper::-webkit-scrollbar {
|
||||
@@ -2837,172 +3026,123 @@ a {
|
||||
}
|
||||
|
||||
.appendix-track {
|
||||
display: grid;
|
||||
grid-template-rows: repeat(2, 1fr);
|
||||
grid-auto-flow: column;
|
||||
grid-auto-columns: minmax(280px, 1fr);
|
||||
gap: 32px 24px;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 40px;
|
||||
width: max-content;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.appendix-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
gap: 12px;
|
||||
text-decoration: none !important;
|
||||
color: inherit !important;
|
||||
background: #fff;
|
||||
padding: 24px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.04);
|
||||
border-radius: 28px;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.04);
|
||||
background: transparent;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
scroll-snap-align: start;
|
||||
width: 100%;
|
||||
min-height: 360px;
|
||||
width: 120px;
|
||||
min-height: 120px;
|
||||
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 {
|
||||
transform: translateY(-4px);
|
||||
transform: scale(1.03);
|
||||
}
|
||||
|
||||
.appendix-icon-wrapper {
|
||||
width: 100%;
|
||||
height: 190px;
|
||||
border-radius: 24px;
|
||||
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-emoji {
|
||||
font-size: 52px;
|
||||
line-height: 1;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.appendix-title {
|
||||
font-weight: 600;
|
||||
color: #1d1d1f;
|
||||
margin-right: 6px;
|
||||
font-size: 12px;
|
||||
color: #3c3c43;
|
||||
margin: 0;
|
||||
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 */
|
||||
@@ -3255,10 +3395,6 @@ a {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.comm-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
display: none;
|
||||
}
|
||||
@@ -3271,13 +3407,23 @@ a {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.section-junior,
|
||||
.section-appendix {
|
||||
border-radius: 28px;
|
||||
padding-top: 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 {
|
||||
margin: 0 16px 40px;
|
||||
border-radius: 28px;
|
||||
@@ -3329,22 +3475,22 @@ a {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
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%;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
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 {
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
border: 1px solid rgba(255, 255, 255, 0.06);
|
||||
background: var(--vp-c-bg-mute);
|
||||
}
|
||||
|
||||
.feature-card:hover {
|
||||
transform: translateY(-6px);
|
||||
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.08);
|
||||
transform: scale(1.015);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.feature-icon {
|
||||
@@ -3388,6 +3534,10 @@ a {
|
||||
.feature-grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
|
||||
.comm-card {
|
||||
flex-basis: 340px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
@@ -3397,5 +3547,9 @@ a {
|
||||
.feature-card {
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.comm-card {
|
||||
flex-basis: min(86vw, 340px);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -299,6 +299,14 @@
|
||||
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 {
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
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 开发团队——有的负责前端,有的负责后端,有的负责测试,它们可以**同时工作、互相交流、协同完成复杂任务**。
|
||||
|
||||

|
||||
|
||||
### 从单助手到团队协作
|
||||
|
||||
在深入了解 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 像真正的开发者一样,持续工作直到任务真正完成。
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## 核心原理:为什么 AI 会"过早停止"?
|
||||
|
||||
Reference in New Issue
Block a user