Files
nl-blogs/client/src/pages/Home.vue
2026-01-19 16:14:08 +08:00

167 lines
7.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<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>
&nbsp;&nbsp;<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>