更加优雅的首页加载动画

This commit is contained in:
锦恢 2025-06-06 17:24:32 +08:00
parent f6c410a231
commit f5683dd52a
7 changed files with 429 additions and 195 deletions

View File

@ -111,11 +111,12 @@ function makeHomeAnimation() {
const elements = [ const elements = [
{ selector: ".bilibili-player-container", start: "top 65%", end: "top 65%" }, { selector: "#home-0", trigger: '#home-0', start: "top 65%", end: "top 65%" },
{ selector: "#openmcp-为谁准备", trigger: '#openmcp-为谁准备', start: "top 65%", end: "top 65%" }, { selector: ".bilibili-player-container", trigger: '#home-0', start: "top 65%", end: "top 65%" },
{ selector: ".k-tabs", trigger: '#openmcp-为谁准备', start: "top 65%", end: "top 65%" }, { selector: "#home-1", trigger: '#home-1', start: "top 65%", end: "top 65%" },
{ selector: "#问题解答-faq", trigger: '#问题解答-faq', start: "top 65%", end: "top 65%" }, { selector: ".k-tabs", trigger: '#home-1', start: "top 65%", end: "top 65%" },
{ selector: ".el-collapse", trigger: '#问题解答-faq', start: "top 65%", end: "top 65%" }, { selector: "#home-2", trigger: '#home-2', start: "top 65%", end: "top 65%" },
{ selector: ".el-collapse", trigger: '#home-2', start: "top 65%", end: "top 65%" },
]; ];
elements.forEach(element => { elements.forEach(element => {

View File

@ -1,9 +1,11 @@
<template> <template>
<div class="k-tabs" :style="panelStyle"> <div class="k-tabs">
<div class="k-tabs-tags"> <div class="k-tabs-tags">
<div class="k-tabs-tag-item" v-for="pane of tabsContainer.paneInfos" :key="pane.id" <div class="k-tabs-tag-item" v-for="pane of tabsContainer.paneInfos" :key="pane.id"
:ref="el => tabsContainer.getPanes(el, pane.id)" @click="tabsContainer.switchLabel(pane.id)" :ref="el => tabsContainer.getPanes(el, pane.id)" @click="tabsContainer.switchLabel(pane.id)" :class="{
:class="{ 'active-tab': tabsContainer.lastPaneId === pane.id }"> 'active-tab': tabsContainer.lastPaneId === pane.id,
'prev-tab': pane.id === prevActiveIndex
}">
<span :class="pane.labelClass"></span> <span :class="pane.labelClass"></span>
<span>{{ pane.label }}</span> <span>{{ pane.label }}</span>
</div> </div>
@ -15,7 +17,8 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { reactive, useSlots, provide, nextTick, computed, onMounted } from 'vue'; import { reactive, useSlots, nextTick, onMounted, ref } from 'vue';
import gsap from 'gsap';
type PaneInfo = { type PaneInfo = {
id: number; id: number;
@ -23,116 +26,96 @@ type PaneInfo = {
labelClass: string; labelClass: string;
}; };
interface TabsContainer {
paneInfos: PaneInfo[];
panes: HTMLElement[];
lastPaneId?: number;
activeLabel: string;
panelContainer?: any;
height: string;
getPanes: (el: any, id: string | number) => void;
switchLabel: (id: number) => void;
updateLabels: () => void;
}
const slots = useSlots(); const slots = useSlots();
let maxChildHeight = 0; const prevActiveIndex = ref<number | null>(null);
function resizeTab(id: number) { const tabsContainer = reactive({
const container = tabsContainer.panelContainer; paneInfos: [] as PaneInfo[],
if (container) { panes: [] as HTMLElement[],
const panels = Array.from(container.children) as HTMLElement[];
const currentPanel = panels[id];
if (currentPanel) {
maxChildHeight = Math.max(maxChildHeight, currentPanel.clientHeight);
tabsContainer.height = maxChildHeight + 'px';
}
}
}
const panelStyle = computed(() => ({
height: tabsContainer.height
}));
const tabsContainer: TabsContainer = reactive({
paneInfos: [],
panes: [],
lastPaneId: 0, lastPaneId: 0,
activeLabel: '', panelContainer: undefined as HTMLElement | undefined,
hoverBar: null,
panelContainer: undefined, getPanes(el: HTMLElement | null, id: number) {
height: '0', if (el) this.panes[id] = el;
getPanes(el: HTMLElement | null, id: string | number) {
if (el) {
this.panes[id] = el;
}
}, },
switchLabel(id: number) {
if (this.lastPaneId === id) { async switchLabel(id: number) {
return; if (this.lastPaneId === id) return;
}
const oldId = this.lastPaneId;
prevActiveIndex.value = oldId;
this.lastPaneId = id; this.lastPaneId = id;
this.activeLabel = this.paneInfos[id]?.label || '';
const container = tabsContainer.panelContainer; const container = this.panelContainer;
if (!container) return;
const panels = Array.from(container.children) as HTMLElement[]; const panels = Array.from(container.children) as HTMLElement[];
const oldPanel = panels[oldId];
const newPanel = panels[id];
// // 1. First shrink the old panel to 0.3 scale
if (oldPanel) {
await gsap.to(oldPanel, {
scale: 0.3,
opacity: 0,
duration: 0.3,
ease: "power2.in"
});
}
// 2. Hide all other panels
panels.forEach((panel, index) => { panels.forEach((panel, index) => {
console.log('index', index); if (index !== id) {
console.log('id', id); gsap.set(panel, {
display: 'none',
panel.style.transition = 'opacity 0.3s ease'; opacity: 0,
if (index === id) { scale: 1
panel.style.display = 'block'; });
setTimeout(() => {
panel.style.opacity = '1';
}, 150);
} else {
panel.style.opacity = '0';
setTimeout(() => {
panel.style.display = 'none';
}, 300);
} }
}); });
// 3. Show and animate in the new panel
gsap.set(newPanel, {
display: 'block',
opacity: 0,
scale: 1.2
});
nextTick(() => { gsap.to(newPanel, {
resizeTab(id); opacity: 1,
scale: 1,
duration: 0.4,
ease: "back.out(1.2)"
}); });
}, },
updateLabels() {
const defaultChildren = slots.default?.() || [];
this.paneInfos = []; updateLabels() {
for (const index in defaultChildren) { this.paneInfos = (slots.default?.() || []).map((vnode, index) => ({
const vnode = defaultChildren[index]; id: index,
this.paneInfos.push({ label: vnode.props?.label || '',
id: Number(index), labelClass: vnode.props?.labelClass || '',
label: vnode.props?.label || '', }));
labelClass: vnode.props?.labelClass || '',
});
}
if (this.paneInfos.length > 0) {
this.activeLabel = this.paneInfos[0]?.label || '';
nextTick(() => {
resizeTab(0);
});
}
} }
}); });
// Initialize
tabsContainer.updateLabels(); tabsContainer.updateLabels();
onMounted(() => { onMounted(() => {
if (tabsContainer.panelContainer) { if (tabsContainer.panelContainer) {
const panels = Array.from(tabsContainer.panelContainer.children) as HTMLElement[]; const panels = Array.from(tabsContainer.panelContainer.children) as HTMLElement[];
panels.forEach((panel, index) => { panels.forEach((panel, index) => {
panel.style.position = 'absolute'; panel.style.position = 'absolute';
panel.style.width = '100%';
if (index != tabsContainer.lastPaneId) {
if (index !== 0) {
panel.style.display = 'none'; panel.style.display = 'none';
panel.style.opacity = '0'; } else {
gsap.from(panel, {
scale: 1.2,
opacity: 0,
duration: 0.5
});
} }
}); });
} }
@ -142,58 +125,43 @@ onMounted(() => {
<style scoped> <style scoped>
.k-tabs { .k-tabs {
position: relative; position: relative;
height: fit-content;
} }
.k-tabs-tags { .k-tabs-tags {
display: flex; display: flex;
margin-bottom: 20px; margin-bottom: 20px;
width: 100%;
position: relative; position: relative;
z-index: 10;
gap: 8px;
} }
.k-tabs-tag-item { .k-tabs-tag-item {
background-color: var(--vp-button-alt-bg); background-color: var(--vp-button-alt-bg);
border-radius: .5em; border-radius: .5em;
margin-right: 10px; padding: 6px 16px;
padding: 2px 8px;
font-size: 0.8rem;
display: inline-block;
text-decoration: none;
cursor: pointer; cursor: pointer;
white-space: nowrap; transition: all 0.3s ease;
user-select: none; transform-origin: center;
transition: background-color 0.3s ease, transform 0.2s ease; will-change: transform;
} }
@media (min-width: 768px) { .k-tabs-tag-item.active-tab {
.k-tabs-tag-item {
padding: 6px 16px;
font-size: 1rem;
}
}
.k-tabs-tag-item:hover {
background-color: var(--vp-c-brand-2);
}
.k-tabs-tag-item.active-tab {
background-color: var(--vp-c-brand-3); background-color: var(--vp-c-brand-3);
transform: scale(1.05);
} }
@media screen and (max-width: 414px) { .k-tabs-content {
.k-tabs-tags { position: relative;
} min-height: 200px;
}
.hover-bar {
background-color: var(--vp-c-brand-3);
border-radius: .9em .9em 0 0;
transition: .35s ease-in-out;
position: absolute;
} }
.k-tabs-content>* { .k-tabs-content>* {
transition: opacity 0.3s ease; position: absolute;
top: 0;
left: 0;
width: 100%;
will-change: transform, opacity;
backface-visibility: hidden;
transform-origin: center center;
} }
</style> </style>

View File

@ -1,22 +1,24 @@
<template> <template>
<div class="wrapper"> <div class="wrapper">
<div class="bilibili-player-container"> <div class="bilibili-player-container" @mouseenter="onHover" @mouseleave="onHoverEnd">
<iframe v-if="isPlaying" :src="playerUrl" frameborder="0" allowfullscreen></iframe> <iframe v-if="isPlaying" :src="playerUrl" frameborder="0" allowfullscreen></iframe>
<div v-else class="cover-container" @click="playVideo"> <div v-else class="cover-container" @click="playVideo">
<img :src="props.cover" class="cover-image" /> <img :src="props.cover" class="cover-image" ref="coverImage" />
<button class="play-button"> <button class="play-button" ref="playButton">
<svg viewBox="0 0 24 24" width="48" height="48"> <svg viewBox="0 0 24 24" width="48" height="48">
<path fill="currentColor" d="M8 5v14l11-7z" /> <path fill="currentColor" d="M8 5v14l11-7z" />
</svg> </svg>
</button> </button>
<div class="hover-overlay"></div>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script setup> <script setup>
import { ref } from 'vue' import { ref, onMounted } from 'vue'
import gsap from 'gsap'
const props = defineProps({ const props = defineProps({
url: { url: {
@ -31,10 +33,56 @@ const props = defineProps({
const isPlaying = ref(false); const isPlaying = ref(false);
const playerUrl = ref(props.url); const playerUrl = ref(props.url);
const coverImage = ref(null);
const playButton = ref(null);
function playVideo() { function playVideo() {
isPlaying.value = true isPlaying.value = true
} }
function onHover() {
if (!isPlaying.value) {
gsap.to(coverImage.value, {
filter: 'brightness(0.7) saturate(1.2)',
duration: 0.3,
ease: 'power2.out'
});
gsap.to(playButton.value, {
scale: 1.15,
duration: 0.3,
ease: 'elastic.out(1, 0.5)'
});
gsap.to('.hover-overlay', {
opacity: 1,
duration: 0.3
});
}
}
function onHoverEnd() {
if (!isPlaying.value) {
gsap.to(coverImage.value, {
filter: 'brightness(1) saturate(1)',
duration: 0.3,
ease: 'power2.out'
});
gsap.to(playButton.value, {
scale: 1,
duration: 0.3,
ease: 'power2.out'
});
gsap.to('.hover-overlay', {
opacity: 0,
duration: 0.3
});
}
}
onMounted(() => {
//
gsap.set(coverImage.value, { filter: 'brightness(1) saturate(1)' });
gsap.set('.hover-overlay', { opacity: 0 });
});
</script> </script>
<style scoped> <style scoped>
@ -54,7 +102,13 @@ function playVideo() {
aspect-ratio: 16/9; aspect-ratio: 16/9;
border-radius: .5em; border-radius: .5em;
overflow: hidden; overflow: hidden;
border: 3px solid var(--vp-c-brand-2); transition: box-shadow 0.3s ease, border-color 0.3s ease;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.bilibili-player-container:hover {
border-color: var(--vp-c-brand-1);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
} }
.cover-container { .cover-container {
@ -68,6 +122,19 @@ function playVideo() {
width: 100%; width: 100%;
height: 100%; height: 100%;
object-fit: cover; object-fit: cover;
transition: filter 0.3s ease;
will-change: filter;
}
.hover-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(135deg, rgba(var(--vp-c-brand-2-rgb), 0.2) 0%, rgba(var(--vp-c-brand-1-rgb), 0.1) 100%);
pointer-events: none;
will-change: opacity;
} }
.play-button { .play-button {
@ -85,16 +152,24 @@ function playVideo() {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
transition: transform 0.2s ease, background-color 0.2s ease; transition: transform 0.3s ease, background-color 0.3s ease;
will-change: transform;
z-index: 2;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);
} }
.play-button:hover { .play-button:hover {
transform: translate(-50%, -50%) scale(1.1); background-color: var(--vp-c-brand-1);
background-color: var(--vp-c-brand-2); transform: translate(-50%, -50%) scale(1.2);
} }
.play-button svg { .play-button svg {
margin-left: 4px; margin-left: 4px;
transition: transform 0.2s ease;
}
.play-button:hover svg {
transform: scale(1.1);
} }
iframe { iframe {
@ -102,4 +177,24 @@ iframe {
height: 100%; height: 100%;
border: none; border: none;
} }
/* 响应式调整 */
@media (max-width: 768px) {
.bilibili-player-container {
min-width: 90vw;
min-height: calc(90vw * 9 / 16);
width: 90vw;
height: calc(90vw * 9 / 16);
}
.play-button {
width: 48px;
height: 48px;
}
.play-button svg {
width: 36px;
height: 36px;
}
}
</style> </style>

View File

@ -1,6 +1,7 @@
<template> <template>
<div style="height: fit-content; width: fit-content; position: relative;" ref="container"> <div style="height: fit-content; width: fit-content; position: relative;" ref="container">
<svg class="VPImage image-src" viewBox="0 0 612 612" fill="none" xmlns="http://www.w3.org/2000/svg" ref="svgElement"> <svg class="VPImage image-src" viewBox="0 0 612 612" fill="none" xmlns="http://www.w3.org/2000/svg"
ref="svgElement">
<defs> <defs>
<linearGradient id="gradient_1" gradientUnits="userSpaceOnUse" x1="300" y1="0" x2="300" y2="600"> <linearGradient id="gradient_1" gradientUnits="userSpaceOnUse" x1="300" y1="0" x2="300" y2="600">
<stop offset="0" stop-color="#A1A7F6" /> <stop offset="0" stop-color="#A1A7F6" />
@ -58,6 +59,11 @@
<feBlend mode="normal" in2="BackgroundImageFix_1" result="Shadow_2" /> <feBlend mode="normal" in2="BackgroundImageFix_1" result="Shadow_2" />
<feBlend mode="normal" in="SourceGraphic" in2="Shadow_2" result="Shape_3" /> <feBlend mode="normal" in="SourceGraphic" in2="Shadow_2" result="Shape_3" />
</filter> </filter>
<!-- 新增描边渐变色定义 -->
<linearGradient id="strokeGradient" gradientUnits="userSpaceOnUse" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#A48BF7" />
<stop offset="80%" stop-color="#F7F6FD" />
</linearGradient>
</defs> </defs>
<g transform="translate(6 2)"> <g transform="translate(6 2)">
<g> <g>
@ -87,102 +93,203 @@
</div> </div>
</template> </template>
<script setup> <script setup lang="ts">
import { onMounted, ref } from 'vue' import { onMounted, ref } from 'vue'
import { gsap } from 'gsap' import { gsap } from 'gsap'
const container = ref(null) const container = ref < any > (null);
const svgElement = ref(null) const svgElement = ref < any > (null);
onMounted(() => { onMounted(() => {
const paths = svgElement.value.querySelectorAll('path') const paths = svgElement.value.querySelectorAll('path');
//
// const nameClip = document.querySelector('.VPHero .heading .name.clip');
const headingText = document.querySelector('.VPHero .heading .text');
const tagline = document.querySelector('.VPHero .tagline');
const actions = document.querySelector('.VPHero .actions');
//
gsap.set(nameClip, {
transform: 'translate(50px, 80px)',
scale: 1.8,
});
gsap.set([headingText, tagline, actions], {
opacity: 0,
y: 20
});
gsap.set(paths, { gsap.set(paths, {
strokeDasharray: (i, target) => { strokeDasharray: (_, target) => {
const length = target.getTotalLength() const length = target.getTotalLength()
target.style.strokeDasharray = length target.style.strokeDasharray = length
return length return length
}, },
strokeDashoffset: (i, target) => target.getTotalLength(), strokeDashoffset: (_, target) => target.getTotalLength(),
stroke: 'var(--vp-c-brand-2)', stroke: 'url(#strokeGradient)', // 使
strokeWidth: 3, strokeWidth: 3.5,
fillOpacity: 0 fillOpacity: 0
}) })
//
const wiggleElements = [
{
el: svgElement.value.querySelector('[transform="translate(293 324)"]'),
x: "+=12", y: "+=5", rotation: "+=2"
},
{
el: svgElement.value.querySelector('[transform="translate(48 269)"]'),
x: "-=5", y: "-=10", rotation: "-=1"
},
{
el: svgElement.value.querySelector('[transform="translate(188 56)"]'),
x: "-=4", y: "+=5", rotation: "+=3"
},
{
el: svgElement.value.querySelector('[transform="translate(388 129)"]'),
x: "+=9", y: "+=4", rotation: "-=2"
}
];
// 线 // 线
const master = gsap.timeline() const master = gsap.timeline();
// 线 // 线
const drawTimeline = gsap.timeline({ const drawTimeline = gsap.timeline({
defaults: { duration: 1.5, ease: "power2.inOut" } defaults: { duration: 1.5, ease: "power2.inOut" }
}) });
// // OpenMCP
paths.forEach(path => { if (!nameClip || !headingText || !tagline || !actions) {
console.error("One or more required elements are missing.");
return;
}
drawTimeline.to(nameClip, {
transform: 'translate(50px, 80px)',
}, "<+=0.3");
// OpenMCP
paths.forEach((path: gsap.TweenTarget) => {
drawTimeline.to(path, { drawTimeline.to(path, {
strokeDashoffset: 0, strokeDashoffset: 0,
}, "<+=0.3") }, "<+=0.3");
}) });
// 线 // 线
const reverseTimeline = gsap.timeline({ const reverseTimeline = gsap.timeline({
defaults: { duration: 1.5, ease: "power2.inOut" } defaults: { duration: 1.5, ease: "power2.inOut" }
}) });
// //
paths.forEach(path => { paths.forEach(path => {
reverseTimeline.to(path, { reverseTimeline.to(path, {
fillOpacity: 1, fillOpacity: 1,
strokeDashoffset: (i, target) => target.getTotalLength() strokeDashoffset: (i, target) => target.getTotalLength()
}, "<") }, "<")
}) });
// 线 // 线
const wiggleTimeline = gsap.timeline({ const wiggleTimeline = gsap.timeline({
repeat: -1, repeat: -1,
yoyo: true, yoyo: true,
defaults: { defaults: {
duration: 2, duration: 2,
ease: "sine.inOut" ease: "sine.inOut"
} }
}) });
//
const wiggleElements = [
{
el: svgElement.value.querySelector('[transform="translate(293 324)"]'),
x: "+=12", y: "+=5", rotation: "+=2"
},
{
el: svgElement.value.querySelector('[transform="translate(48 269)"]'),
x: "-=5", y: "-=10", rotation: "-=1"
},
{
el: svgElement.value.querySelector('[transform="translate(188 56)"]'),
x: "-=4", y: "+=5", rotation: "+=3"
},
{
el: svgElement.value.querySelector('[transform="translate(388 129)"]'),
x: "+=9", y: "+=4", rotation: "-=2"
}
]
// //
wiggleElements.forEach(item => { wiggleElements.forEach(item => {
wiggleTimeline.to(item.el, { wiggleTimeline.to(item.el, {
x: item.x, x: item.x,
y: item.y, y: item.y,
rotation: item.rotation, rotation: item.rotation,
scale: item.scale,
transformOrigin: "center center" transformOrigin: "center center"
}, "<") }, "<")
}) });
// // 线
const heroTimeline = gsap.timeline({
defaults: {
duration: 0.8,
ease: "power3.out"
}
});
//
heroTimeline
.to(nameClip, {
transform: 'translate(0, 0)',
scale: 1,
duration: 1.2,
ease: "back.out(1.7)"
})
.to([headingText, tagline, actions], {
opacity: 1,
y: 0,
stagger: 0.15,
duration: 0.6
}, "-=0.4"); // 0.4
// feature
const boxTimeline = gsap.timeline({
defaults: {
duration: 0.8,
ease: "power3.out"
}
});
// box
const boxes = document.querySelectorAll('.VPFeatures .item.grid-3');
//
gsap.set(boxes, {
opacity: 0,
y: 30,
scale: 0.9
});
// 线
boxTimeline.to(boxes, {
opacity: 1,
y: 0,
scale: 1,
stagger: 0.15,
onComplete: () => {
gsap.set(boxes, { clearProps: "all" });
}
});
// heroTimeline
heroTimeline
.to(nameClip, {
transform: 'translate(0, 0)',
scale: 1,
duration: 1.0, //
ease: "elastic.out(1, 0.5)" //
})
.to([headingText, tagline], {
opacity: 1,
y: 0,
stagger: 0.2, //
duration: 0.8,
ease: "back.out(1.5)" //
}, "-=0.3")
.to(actions, {
opacity: 1,
y: 0,
duration: 0.6,
ease: "power2.out" //
}, "-=0.2");
master.add(drawTimeline) master.add(drawTimeline)
.add(reverseTimeline, "+=0.5") .add(reverseTimeline, "+=0.3") //
.add(wiggleTimeline) // .add(heroTimeline, "-=0.3")
.add(boxTimeline, "<+=1.3")
.add(wiggleTimeline, "<+=0.2");
}) })
</script> </script>

View File

@ -59,6 +59,7 @@
background-color: var(--vp-c-brand-3); background-color: var(--vp-c-brand-3);
} }
.VPFeatures .item:hover .box .title,
.VPFeatures .item:hover .box .details { .VPFeatures .item:hover .box .details {
color: var(--vp-c-white); color: var(--vp-c-white);
} }

View File

@ -266,7 +266,52 @@ iframe {
color: white; color: white;
} }
.VPHero .name.clip { .VPHero .heading .name.clip {
color: var(--vp-c-brand-2) !important; background: var(--vp-home-hero-name-background);
background-color: var(--vp-c-brand-2) !important; -webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: var(--vp-home-hero-name-color);
}
.VPHero .heading .text {
}
.VPHero .tagline {
}
.VPHero .actions {
}
#home-0 {
font-size: 40px;
line-height: 1.1;
}
#home-0 > span {
font-size: 20px;
opacity: 0.5;
line-height: 0.8;
}
#home-1 {
font-size: 40px;
line-height: 1.1;
}
#home-1 > span {
font-size: 20px;
opacity: 0.5;
line-height: 0.8;
}
#home-2 {
font-size: 40px;
line-height: 1.1;
}
#home-2 > span {
font-size: 20px;
opacity: 0.5;
line-height: 0.8;
} }

View File

@ -40,6 +40,15 @@ features:
<br><br> <br><br>
<h2 id="home-0">
为您的 MCP Agent 开发排忧解难
<br>
<span>Provide Funs and Convenien for your mcp agent dev</span>
</h2>
<BiliPlayer <BiliPlayer
url="//player.bilibili.com/player.html?isOutside=true&aid=114445745397200&bvid=BV1zYGozgEHcautoplay=false" url="//player.bilibili.com/player.html?isOutside=true&aid=114445745397200&bvid=BV1zYGozgEHcautoplay=false"
cover="https://picx.zhimg.com/80/v2-8c1f5d99066ed272554146ed8caf7cc3_1440w.png" cover="https://picx.zhimg.com/80/v2-8c1f5d99066ed272554146ed8caf7cc3_1440w.png"
@ -47,7 +56,12 @@ features:
<br> <br>
## OpenMCP 为谁准备?
<h2 id="home-1">
OpenMCP 为谁准备?
<br>
<span>The Development of OpenMCP is for ...</span>
</h2>
<br> <br>
@ -88,8 +102,11 @@ features:
<br> <br>
<h2 id="home-2">
## 问题解答 FAQ 问题解答
<br>
<span>Waiting for Your Questions</span>
</h2>
<el-collapse> <el-collapse>
<el-collapse-item title="OpenMCP 适合做什么?" name="1"> <el-collapse-item title="OpenMCP 适合做什么?" name="1">