Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .vitepress/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.temp
cache
.vite
.vite
dist
233 changes: 225 additions & 8 deletions .vitepress/components/code-group.vue
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,228 @@ const currentTab = ref('index.vue');
</script>

<template>
<el-tabs
v-model="currentTab"
>
<el-tab-pane v-for="tab in tabs" :label="tab.label" :name="tab.label" >
<component :is="tab.component" class="border-0" />
</el-tab-pane>
</el-tabs>
</template>
<div class="code-group-container">
<el-tabs
v-model="currentTab"
class="code-group-tabs"
tab-position="top"
>
<el-tab-pane
v-for="tab in tabs"
:key="tab.label"
:label="tab.label"
:name="tab.label"
class="code-group-pane"
>
<div class="code-content-wrapper">
<component :is="tab.component" class="code-content" />
</div>
Comment on lines +47 to +49
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

动态渲染插槽可能不稳定:slot 函数并非组件,建议用 render 包装后再挂载

slots[file] 返回的是插槽函数而非组件定义,直接作为 <component :is="..."> 的值在某些场景下会出现渲染异常或丢失 class 的问题。建议用一个带 render 的对象包装,且将样式类应用在稳定的包裹元素上。

可在本段内做最小改动如下:

-        <div class="code-content-wrapper">
-          <component :is="tab.component" class="code-content" />
-        </div>
+        <div class="code-content-wrapper">
+          <div class="code-content">
+            <component :is="tab.component ? { render: () => tab.component?.() } : 'div'" />
+          </div>
+        </div>

抱歉,我注意到未生成任何验证脚本。为了确认 tab.component 的类型及其在模板中的使用,建议先查看 .vitepress/components/code-group.vue 中相关代码。请允许我运行以下脚本来获取上下文:

#!/bin/bash
# 输出 code-group.vue 前 100 行以查看 template 部分
sed -n '1,100p' .vitepress/components/code-group.vue

为确认 tab.component 的真实类型及用法,先查看 .vitepress/components/code-group.vue 的 template 和 script 部分:


🏁 Script executed:

#!/bin/bash
# 输出前 200 行以查看 template 和 script 上下文
sed -n '1,200p' .vitepress/components/code-group.vue

# 查找所有 tab.component 的引用位置
grep -n "tab.component" .vitepress/components/code-group.vue || true

Length of output: 4327


封装动态插槽渲染以避免渲染异常和样式丢失

直接把 slots[file](插槽渲染函数)作为 <component :is="…"> 会在部分场景下丢失 class 或渲染异常。建议将它包装成带 render 方法的组件定义,并把样式类放到稳定的外层容器上:

• 文件:.vitepress/components/code-group.vue
• 位置:约第 47–49 行

         <div class="code-content-wrapper">
-          <component :is="tab.component" class="code-content" />
+          <div class="code-content">
+            <component
+              :is="
+                tab.component
+                  ? { render: () => tab.component?.() }
+                  : 'div'
+              "
+            />
+          </div>
         </div>

请在合并前采纳此改动,确保插槽渲染稳定且样式正确生效。

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<div class="code-content-wrapper">
<component :is="tab.component" class="code-content" />
</div>
<div class="code-content-wrapper">
<div class="code-content">
<component
:is="
tab.component
? { render: () => tab.component?.() }
: 'div'
"
/>
</div>
</div>
🤖 Prompt for AI Agents
In .vitepress/components/code-group.vue around lines 47–49, directly using the
slot render function as <component :is="tab.component" class="code-content" />
can lose classes or cause render errors; wrap the slot function into a component
object that exposes a render(h) (or render) method (e.g., { render: () =>
slots[file]() }) and pass that to :is, and move the "code-content" class to a
stable outer wrapper element so styles are applied reliably while the inner
dynamic component only handles rendering.

</el-tab-pane>
</el-tabs>
</div>
</template>

<style scoped>
.code-group-container {
width: 100%;
background: var(--vp-c-bg-alt);
}

.code-group-tabs {
width: 100%;
}

.code-content-wrapper {
position: relative;
background: var(--vp-code-block-bg);
border-radius: 0 0 8px 8px;
overflow: hidden;
}

.code-content {
display: block;
width: 100%;
margin: 0;
padding: 0;
border: none;
background: transparent;
overflow-x: auto;
}

/* Element Plus 标签页样式重写 */
.code-group-tabs :deep(.el-tabs__header) {
margin: 0;
background: var(--vp-c-bg-soft);
border-bottom: 1px solid var(--vp-c-divider);
}

.code-group-tabs :deep(.el-tabs__nav-wrap) {
padding: 0;
}

.code-group-tabs :deep(.el-tabs__nav-scroll) {
display: flex;
overflow-x: auto;
}

.code-group-tabs :deep(.el-tabs__item) {
padding: 0.75rem 1.25rem;
font-weight: 500;
font-size: 0.875rem;
color: var(--vp-c-text-2);
border: none;
background: transparent;
transition: all 0.2s ease;
white-space: nowrap;
position: relative;
}

.code-group-tabs :deep(.el-tabs__item:hover) {
color: var(--vp-c-brand-1);
background: var(--vp-c-brand-soft);
}

.code-group-tabs :deep(.el-tabs__item.is-active) {
color: var(--vp-c-brand-1);
background: var(--vp-c-bg);
font-weight: 600;
}

.code-group-tabs :deep(.el-tabs__active-bar) {
background: var(--vp-c-brand-1);
height: 2px;
border-radius: 1px;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

.code-group-tabs :deep(.el-tabs__content) {
padding: 0;
background: var(--vp-code-block-bg);
}

.code-group-tabs :deep(.el-tab-pane) {
padding: 0;
background: transparent;
}

/* 代码块内容样式优化 */
.code-content :deep(pre) {
margin: 0;
padding: 1.25rem;
background: var(--vp-code-block-bg) !important;
border-radius: 0;
font-size: 0.875rem;
line-height: 1.5;
overflow-x: auto;
}

.code-content :deep(code) {
background: transparent !important;
color: var(--vp-code-block-color);
font-family: var(--vp-font-family-mono);
font-weight: 400;
}

/* 滚动条样式 */
.code-content :deep(pre)::-webkit-scrollbar {
width: 6px;
height: 6px;
}

.code-content :deep(pre)::-webkit-scrollbar-track {
background: rgba(0, 0, 0, 0.1);
border-radius: 3px;
}

.code-content :deep(pre)::-webkit-scrollbar-thumb {
background: var(--vp-c-brand-1);
border-radius: 3px;
}

.code-content :deep(pre)::-webkit-scrollbar-thumb:hover {
background: var(--vp-c-brand-2);
}

/* 深色模式适配 */
.dark .code-group-container {
background: var(--vp-c-bg);
}

.dark .code-group-tabs :deep(.el-tabs__header) {
background: var(--vp-c-bg-alt);
border-color: var(--vp-c-border);
}

.dark .code-group-tabs :deep(.el-tabs__item.is-active) {
background: var(--vp-c-bg-soft);
}

.dark .code-content :deep(pre)::-webkit-scrollbar-track {
background: rgba(255, 255, 255, 0.1);
}

/* 响应式设计 */
@media (max-width: 768px) {
.code-group-tabs :deep(.el-tabs__item) {
padding: 0.625rem 1rem;
font-size: 0.8rem;
}

.code-content :deep(pre) {
padding: 1rem;
font-size: 0.8rem;
}
}

@media (max-width: 480px) {
.code-group-tabs :deep(.el-tabs__item) {
padding: 0.5rem 0.75rem;
font-size: 0.75rem;
}

.code-content :deep(pre) {
padding: 0.875rem;
font-size: 0.75rem;
}
}

/* 文件名样式优化 */
.code-group-tabs :deep(.el-tabs__item) {
font-family: var(--vp-font-family-mono);
}

/* 活动标签页指示器动画 */
.code-group-tabs :deep(.el-tabs__item.is-active)::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 2px;
background: linear-gradient(90deg, var(--vp-c-brand-1), var(--vp-c-brand-2));
animation: tabGlow 0.3s ease;
}

@keyframes tabGlow {
from {
opacity: 0;
transform: scaleX(0);
}
to {
opacity: 1;
transform: scaleX(1);
}
}

/* 减少动画模式支持 */
@media (prefers-reduced-motion: reduce) {
.code-group-tabs :deep(.el-tabs__active-bar),
.code-group-tabs :deep(.el-tabs__item) {
transition: none !important;
}

.code-group-tabs :deep(.el-tabs__item.is-active)::before {
animation: none;
}
}
</style>
Loading