初始化

This commit is contained in:
李琦
2026-01-15 13:51:44 +08:00
commit b7b6d3e39e
156 changed files with 38913 additions and 0 deletions

View File

@@ -0,0 +1,152 @@
<template>
<section id="snippets" class="page-section block animate-slide-down">
<div class="max-w-7xl mx-auto pt-32 px-6 pb-20">
<div class="mb-12 text-center">
<h2 class="font-serif text-5xl italic text-white mb-6">代码实验室</h2>
<p class="text-art-muted">点击下方卡片查看代码与实时效果</p>
</div>
<!-- Loading state -->
<div v-if="loading" class="flex justify-center items-center h-64">
<div class="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-art-accent"></div>
</div>
<!-- Error state -->
<div v-else-if="error" class="text-center text-red-500 py-20">
<p class="mb-4">{{ error }}</p>
<button @click="fetchSnippetsData" class="px-4 py-2 bg-art-accent text-white rounded hover:bg-opacity-80 transition-colors">
重试
</button>
</div>
<!-- Snippets list -->
<div v-else class="grid grid-cols-1 lg:grid-cols-2 gap-8" id="snippets-grid">
<!-- Snippets will be rendered here -->
<div
v-for="snippet in snippets"
:key="snippet.id"
class="art-card rounded-2xl p-8 group cursor-pointer transition-all hover:translate-y-[-5px]"
@click="openSnippet(snippet)"
>
<div class="flex items-center gap-3 mb-4">
<i data-lucide="code-2" class="w-6 h-6 text-art-accent"></i>
<span class="font-mono text-sm text-art-muted">{{ getSnippetType(snippet.type) }}</span>
</div>
<h3 class="text-2xl font-serif text-white mb-4 group-hover:text-art-accent transition-colors">{{ snippet.title }}</h3>
<pre class="font-mono text-sm text-art-muted leading-relaxed overflow-hidden text-ellipsis line-clamp-4">{{ snippet.code }}</pre>
<div class="flex items-center justify-end mt-6">
<i data-lucide="arrow-up-right" class="w-5 h-5 text-white/50 transform group-hover:translate-x-1 group-hover:-translate-y-1 transition-transform"></i>
</div>
</div>
</div>
</div>
</section>
</template>
<script setup lang="ts">
import { ref, onMounted, onBeforeMount } from 'vue'
import { fetchSnippets, Snippet } from '../services/api'
import { useScrollAnimation } from '../composables/useScrollAnimation'
const snippets = ref<Snippet[]>([])
const loading = ref(false)
const error = ref('')
const fetchSnippetsData = async () => {
loading.value = true
error.value = ''
try {
const snippetsData = await fetchSnippets()
snippets.value = snippetsData
} catch (err) {
console.error('Error fetching snippets:', err)
error.value = '获取代码片段失败,请稍后重试'
// 如果API调用失败使用静态数据作为备选
snippets.value = [
{
id: 'mouse',
title: 'React 鼠标追踪 Hook',
code: `import { useState, useEffect } from 'react';
export const useMousePosition = () => {
const [pos, setPos] = useState({ x: 0, y: 0 });
useEffect(() => {
const update = (e) => setPos({ x: e.clientX, y: e.clientY });
window.addEventListener('mousemove', update);
return () => window.removeEventListener('mousemove', update);
}, []);
return pos;
};`,
type: 'mouse'
},
{
id: 'glass',
title: 'CSS 极致毛玻璃效果',
code: `.glass-panel {
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(16px);
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1);
}`,
type: 'glass'
},
{
id: 'noise',
title: 'SVG 噪点纹理滤镜',
code: `<filter id="noise">
<feTurbulence type="fractalNoise" baseFrequency="0.8" /
</filter>`,
type: 'noise'
},
{
id: 'animate',
title: 'CSS 流畅动画',
code: `.animate-float {
animation: float 6s ease-in-out infinite;
}
@keyframes float {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-20px); }
}`,
type: 'animate'
}
]
} finally {
loading.value = false
}
}
const getSnippetType = (type: string) => {
const typeMap: Record<string, string> = {
javascript: 'JavaScript',
css: 'CSS',
html: 'HTML',
mouse: 'React Hook',
glass: 'CSS',
noise: 'SVG',
animate: 'CSS Animation'
}
return typeMap[type] || type
}
const openSnippet = (snippet: any) => {
// 使用全局函数打开代码片段模态框
if (window.showSnippet) {
window.showSnippet(snippet.title, snippet.code)
}
}
onBeforeMount(() => {
fetchSnippetsData()
})
onMounted(() => {
// 启用滚动动画
useScrollAnimation()
// 初始化Lucide图标
if (window.lucide) {
window.lucide.createIcons()
}
})
</script>