167 lines
7.8 KiB
Vue
167 lines
7.8 KiB
Vue
<template>
|
||
<section id="home" class="page-section block">
|
||
<!-- Hero -->
|
||
<div class="grid grid-cols-1 lg:grid-cols-12 gap-12 mb-24 items-center animate-reveal">
|
||
<div class="lg:col-span-7 space-y-8">
|
||
<p class="text-art-accent font-mono text-sm tracking-widest uppercase mb-4">前端架构师 & 创意开发者</p>
|
||
<h1 class="font-serif text-5xl md:text-7xl lg:text-8xl leading-[1.1] text-white text-glow">
|
||
<span class="block italic opacity-80">设计</span>
|
||
<span class="block font-bold">铸造数字</span>
|
||
<span class="block font-bold pl-12 md:pl-24">灵魂</span>
|
||
</h1>
|
||
<p class="text-art-muted text-lg md:text-xl max-w-xl leading-relaxed mt-8 font-light">
|
||
在代码的逻辑与设计的感性之间寻找平衡。我是<span class="text-white font-bold">年糕崽崽</span>,不仅仅构建页面,更在构建<span class="text-white border-b border-white/20 pb-0.5">沉浸式体验</span>。
|
||
</p>
|
||
<div class="pt-8 flex items-center gap-6">
|
||
<button @click="$router.push('/works')" class="group flex items-center gap-2 text-white border-b border-white pb-1 hover:text-art-accent hover:border-art-accent transition-all">
|
||
<span>浏览作品集</span>
|
||
<i data-lucide="arrow-right" class="w-4 h-4 transform group-hover:translate-x-1 transition-transform"></i>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div class="lg:col-span-5 relative h-[400px] lg:h-[600px] w-full flex items-center justify-center">
|
||
<div class="relative w-full h-full">
|
||
<div class="absolute inset-0 border border-white/10 rounded-full rotate-12 scale-90"></div>
|
||
<div class="absolute inset-0 border border-white/5 rounded-full -rotate-6 scale-75"></div>
|
||
<div
|
||
id="home-hero-work"
|
||
class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-64 h-80 bg-gradient-to-br from-white/10 to-transparent backdrop-blur-md border border-white/10 rounded-sm shadow-2xl rotate-6 hover:rotate-0 transition-transform duration-700 z-10 flex flex-col p-6 justify-between cursor-pointer"
|
||
@click="$router.push('/works/' + latestWork.id)"
|
||
>
|
||
<div class="text-white/50 text-xs">最新作品</div>
|
||
<div class="font-serif text-3xl italic text-white">{{ latestWork.title }}</div>
|
||
<div class="flex justify-end"><i data-lucide="arrow-up-right" class="text-white"></i></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Bento Grid -->
|
||
<div class="space-y-6 animate-reveal" style="animation-delay: 0.2s;">
|
||
<div class="flex items-end justify-between border-b border-white/10 pb-4 mb-8">
|
||
<h2 class="font-serif text-3xl italic text-white">精选内容</h2>
|
||
<span class="font-mono text-xs text-art-muted">下滑探索更多</span>
|
||
</div>
|
||
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 auto-rows-[300px]" id="bento-grid">
|
||
<!-- Bento items will be rendered here -->
|
||
<div
|
||
class="md:col-span-2 art-card rounded-2xl p-8 flex flex-col justify-end group cursor-pointer"
|
||
@click="$router.push('/blog/' + featuredPost.id)"
|
||
>
|
||
<div class="absolute inset-0 bg-gradient-to-t from-black/80 via-black/20 to-transparent z-10"></div>
|
||
<div class="absolute inset-0 bg-[url('https://images.unsplash.com/photo-1618005182384-a83a8bd57fbe?q=80&w=2564&auto=format&fit=crop')] bg-cover bg-center transition-transform duration-700 group-hover:scale-105 opacity-60 mix-blend-overlay"></div>
|
||
<div class="relative z-20 space-y-2">
|
||
<div class="flex items-center gap-3">
|
||
<span class="px-2 py-1 text-[10px] font-mono border border-white/20 rounded-full text-white backdrop-blur-sm">{{ featuredPost.categoryName || '未分类' }}</span>
|
||
<span class="text-xs text-white/60">{{ featuredPost.date }}</span>
|
||
</div>
|
||
<h3 class="font-serif text-3xl text-white group-hover:text-art-accent transition-colors">当极简主义遇见复杂数据:Dashboard 设计哲学</h3>
|
||
</div>
|
||
</div>
|
||
<div
|
||
class="art-card rounded-2xl p-8 flex flex-col justify-between group"
|
||
>
|
||
<div class="flex justify-between items-start">
|
||
<i data-lucide="code-2" class="w-8 h-8 text-white/40 group-hover:text-art-accent transition-colors"></i>
|
||
<i data-lucide="arrow-up-right" class="w-5 h-5 text-white/20"></i>
|
||
</div>
|
||
<div>
|
||
<div class="text-4xl font-mono font-bold text-white mb-2">120+</div>
|
||
<div class="text-sm text-art-muted">开源提交 (Commits)</div>
|
||
<div class="text-xs text-art-muted mt-2 opacity-60">Vue, React, Three.js</div>
|
||
</div>
|
||
</div>
|
||
<div
|
||
class="art-card rounded-2xl p-6 md:p-8 flex flex-col justify-between group cursor-pointer bg-[#050505]"
|
||
@click="$router.push('/snippets')"
|
||
>
|
||
<div class="font-mono text-xs text-art-muted mb-4">// React Hook: useArt</div>
|
||
<div class="font-mono text-sm text-gray-400 overflow-hidden opacity-60 group-hover:opacity-100 transition-opacity">
|
||
<span class="code-keyword">const</span> <span class="code-func">useCreative</span> = () => {<br>
|
||
<span class="code-keyword">return</span> <span class="code-string">"Innovation"</span>;<br>
|
||
}
|
||
</div>
|
||
<div class="mt-4 flex items-center gap-2 text-sm font-medium text-white">
|
||
<span>访问代码实验室</span>
|
||
<i data-lucide="chevron-right" class="w-4 h-4 text-art-accent"></i>
|
||
</div>
|
||
</div>
|
||
<div
|
||
class="md:col-span-2 art-card rounded-2xl p-8 md:p-12 flex flex-col md:flex-row items-center justify-between gap-8 group cursor-pointer bg-gradient-to-r from-art-surface to-transparent"
|
||
@click="$router.push('/services')"
|
||
>
|
||
<div class="space-y-4">
|
||
<h3 class="font-serif text-3xl text-white">需要独特的前端架构?</h3>
|
||
<p class="text-art-muted max-w-sm">不论是 WebGL 3D 交互网站,还是高性能的 SaaS 管理系统,我都能提供专业的解决方案。</p>
|
||
</div>
|
||
<div class="h-16 w-16 rounded-full border border-white/20 flex items-center justify-center group-hover:bg-white group-hover:text-black transition-all duration-300">
|
||
<i data-lucide="arrow-right" class="w-6 h-6"></i>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { ref, onMounted, onBeforeMount } from 'vue'
|
||
import { fetchWorks, fetchPosts, Work, Post } from '../services/api'
|
||
import { useScrollAnimation } from '../composables/useScrollAnimation'
|
||
|
||
const { initObserver } = useScrollAnimation()
|
||
|
||
const latestWork = ref<Work>({
|
||
id: 'nova',
|
||
title: 'Nova 交易平台',
|
||
category: '金融科技',
|
||
year: '2023',
|
||
heroImg: '',
|
||
desc: '',
|
||
techStack: [],
|
||
gallery: [],
|
||
links: { live: '#' },
|
||
next: ''
|
||
})
|
||
|
||
const featuredPost = ref<Post>({
|
||
id: 'refactor',
|
||
title: '当极简主义遇见复杂数据',
|
||
category: '设计思维',
|
||
date: '2025-10-24',
|
||
excerpt: '',
|
||
content: ''
|
||
})
|
||
|
||
const loading = ref(false)
|
||
const error = ref('')
|
||
|
||
const fetchHomeData = async () => {
|
||
loading.value = true
|
||
error.value = ''
|
||
try {
|
||
const [works, posts] = await Promise.all([
|
||
fetchWorks(),
|
||
fetchPosts()
|
||
])
|
||
|
||
if (works && works.length > 0) {
|
||
latestWork.value = works[0]
|
||
}
|
||
|
||
if (posts && posts.length > 0) {
|
||
featuredPost.value = posts[0]
|
||
}
|
||
} catch (err) {
|
||
console.error('Error fetching home data:', err)
|
||
error.value = '获取首页数据失败'
|
||
} finally {
|
||
loading.value = false
|
||
// 启用滚动动画
|
||
initObserver()
|
||
}
|
||
}
|
||
|
||
onMounted(() => {
|
||
fetchHomeData()
|
||
})
|
||
</script> |