feat: 精简首页 - 删除作品区域及多余社交链接

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Superuser
2026-05-18 21:00:34 +08:00
parent f71bb136fa
commit 8386c982c3
+3 -252
View File
@@ -1,176 +1,8 @@
import { useRef, useState, useCallback, useEffect } from "react";
import { Link } from "react-router"; import { Link } from "react-router";
import { motion } from "framer-motion"; import { motion } from "framer-motion";
import { ArrowUpRight, FileText } from "lucide-react"; import { FileText } from "lucide-react";
import Navbar from "@/components/Navbar"; import Navbar from "@/components/Navbar";
const projects = [
{
id: 1,
title: "ServerQA 自动化测试平台",
desc: "服务器领域的自动化测试框架,支持接口与性能测试",
tags: ["Python", "Pytest", "Locust"],
image: "/images/project-1.jpg",
},
{
id: 2,
title: "PerfMon 性能监控中心",
desc: "服务器性能实时监控与历史趋势分析仪表盘",
tags: ["Grafana", "Prometheus", "Go"],
image: "/images/project-2.jpg",
},
{
id: 3,
title: "VibeCI 测试流水线",
desc: "基于 Vibe Coding 理念的测试持续集成工具",
tags: ["Node.js", "Docker", "GitHub Actions"],
image: "/images/project-3.jpg",
},
{
id: 4,
title: "FaultSim 故障模拟器",
desc: "分布式系统的混沌工程测试与故障注入工具",
tags: ["Python", "Kubernetes", "gRPC"],
image: "/images/project-4.jpg",
},
{
id: 5,
title: "LogLens 日志分析工具",
desc: "大规模日志的智能聚合、搜索与异常检测平台",
tags: ["ELK", "React", "ClickHouse"],
image: "/images/project-5.jpg",
},
{
id: 6,
title: "TestHub 用例管理平台",
desc: "测试用例的编写、评审、执行与覆盖率追踪系统",
tags: ["Next.js", "PostgreSQL", "tRPC"],
image: "/images/project-6.jpg",
},
];
function WorkGrid() {
const containerRef = useRef<HTMLUListElement>(null);
const itemRefs = useRef<(HTMLLIElement | null)[]>([]);
const [mouseX, setMouseX] = useState(0);
const [mouseY, setMouseY] = useState(0);
const [containerX, setContainerX] = useState(200);
const [containerY, setContainerY] = useState(200);
const [isHovering, setIsHovering] = useState(false);
const rafRef = useRef<number | null>(null);
const calculateDistance = useCallback(
(node: HTMLLIElement) => {
if (!containerX || !containerY) return 0;
const rect = node.getBoundingClientRect();
const distance = Math.sqrt(
Math.pow(rect.left + rect.width / 2 - containerX, 2) +
Math.pow(rect.top + rect.height / 2 - containerY, 2)
);
return Math.round(distance * 100) / 100;
},
[containerX, containerY]
);
const handleMouseMove = useCallback(
(e: React.MouseEvent) => {
if (!containerRef.current) return;
const rect = containerRef.current.getBoundingClientRect();
setMouseX(e.clientX - rect.left);
setMouseY(e.clientY - rect.top);
if (rafRef.current) cancelAnimationFrame(rafRef.current);
rafRef.current = requestAnimationFrame(() => {
itemRefs.current.forEach((node) => {
if (node) {
const dist = calculateDistance(node);
node.style.setProperty("--box-distance", `${dist}px`);
}
});
});
},
[calculateDistance]
);
const handleMouseEnter = useCallback(() => {
if (!containerRef.current) return;
const rect = containerRef.current.getBoundingClientRect();
setContainerX(rect.width / 2);
setContainerY(rect.height / 2);
setIsHovering(true);
}, []);
const handleMouseLeave = useCallback(() => {
setIsHovering(false);
}, []);
useEffect(() => {
return () => {
if (rafRef.current) cancelAnimationFrame(rafRef.current);
};
}, []);
return (
<ul
ref={containerRef}
className="work-grid"
onMouseMove={handleMouseMove}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
style={
{
"--x": `${mouseX}px`,
"--y": `${mouseY}px`,
"--is-hovering": isHovering ? 1 : 0,
} as React.CSSProperties
}
>
{projects.map((project, index) => (
<li
key={project.id}
ref={(el) => { itemRefs.current[index] = el; }}
className="grid__item"
style={{
opacity: 0,
animation: `fadeInItem 0.6s cubic-bezier(0.19, 1, 0.22, 1) ${index * 0.1}s forwards`,
}}
>
<div className="image-reveal-container" style={{ background: "#f7f6f3" }}>
<div className="aspect-[3/2] overflow-hidden">
<img
src={project.image}
alt={project.title}
className="w-full h-full object-cover"
/>
</div>
<div className="p-5">
<h3 className="text-[#141414] font-semibold text-lg mb-1">{project.title}</h3>
<p className="text-[#5a5a5a] text-sm leading-relaxed mb-3">{project.desc}</p>
<div className="flex flex-wrap gap-2">
{project.tags.map((tag) => (
<span
key={tag}
className="text-xs px-2.5 py-1 rounded-full bg-[#e8e6e1] text-[#5a5a5a] font-medium"
>
{tag}
</span>
))}
</div>
</div>
<div className="item__content-overlay" />
<div className="reveal-frame top-left" style={{ top: 0, left: 0 }} />
<div className="reveal-frame top-right" style={{ top: 0, right: 0 }} />
<div className="reveal-frame right-top" style={{ top: 0, right: 0 }} />
<div className="reveal-frame right-bottom" style={{ bottom: 0, right: 0 }} />
<div className="reveal-frame bottom-right" style={{ bottom: 0, right: 0 }} />
<div className="reveal-frame bottom-left" style={{ bottom: 0, left: 0 }} />
</div>
</li>
))}
</ul>
);
}
export default function Home() { export default function Home() {
return ( return (
<div className="min-h-screen" style={{ background: "#e8e6e1" }}> <div className="min-h-screen" style={{ background: "#e8e6e1" }}>
@@ -224,14 +56,6 @@ export default function Home() {
transition={{ duration: 0.8, delay: 0.3, ease: [0.19, 1, 0.22, 1] }} transition={{ duration: 0.8, delay: 0.3, ease: [0.19, 1, 0.22, 1] }}
className="flex flex-wrap gap-4" className="flex flex-wrap gap-4"
> >
<a
href="#works"
className="inline-flex items-center gap-2 px-7 py-3.5 rounded-2xl text-white font-medium text-base transition-all duration-300 hover:shadow-lg hover:translate-y-[-2px]"
style={{ background: "#4a6cf7" }}
>
<ArrowUpRight size={18} />
</a>
<Link <Link
to="/blog" to="/blog"
className="inline-flex items-center gap-2 px-7 py-3.5 rounded-2xl font-medium text-base transition-all duration-300 hover:shadow-md hover:translate-y-[-2px]" className="inline-flex items-center gap-2 px-7 py-3.5 rounded-2xl font-medium text-base transition-all duration-300 hover:shadow-md hover:translate-y-[-2px]"
@@ -255,7 +79,7 @@ export default function Home() {
<div className="flex flex-wrap items-center gap-3"> <div className="flex flex-wrap items-center gap-3">
{/* Bilibili */} {/* Bilibili */}
<a <a
href="https://space.bilibili.com/" href="https://space.bilibili.com/297925716?spm_id_from=333.1007.0.0"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
className="group flex items-center gap-2 px-4 py-2.5 rounded-xl text-sm font-medium transition-all duration-300 hover:shadow-md" className="group flex items-center gap-2 px-4 py-2.5 rounded-xl text-sm font-medium transition-all duration-300 hover:shadow-md"
@@ -270,7 +94,7 @@ export default function Home() {
{/* CSDN */} {/* CSDN */}
<a <a
href="https://blog.csdn.net/" href="https://blog.csdn.net/weixin_45839854?spm=1000.2115.3001.5343"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
className="group flex items-center gap-2 px-4 py-2.5 rounded-xl text-sm font-medium transition-all duration-300 hover:shadow-md" className="group flex items-center gap-2 px-4 py-2.5 rounded-xl text-sm font-medium transition-all duration-300 hover:shadow-md"
@@ -283,80 +107,13 @@ export default function Home() {
<span>CSDN</span> <span>CSDN</span>
</a> </a>
{/* GitHub */}
<a
href="https://github.com/"
target="_blank"
rel="noopener noreferrer"
className="group flex items-center gap-2 px-4 py-2.5 rounded-xl text-sm font-medium transition-all duration-300 hover:shadow-md"
style={{ background: "#f7f6f3", color: "#5a5a5a" }}
title="GitHub"
>
<svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor">
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
</svg>
<span>GitHub</span>
</a>
{/* Juejin 掘金 */}
<a
href="https://juejin.cn/user/"
target="_blank"
rel="noopener noreferrer"
className="group flex items-center gap-2 px-4 py-2.5 rounded-xl text-sm font-medium transition-all duration-300 hover:shadow-md"
style={{ background: "#f7f6f3", color: "#5a5a5a" }}
title="稀土掘金"
>
<svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor">
<path d="M4.2 4h15.6c.6 0 1 .4 1 1v1.3c0 .6-.4 1-1 1H4.2c-.6 0-1-.4-1-1V5c0-.6.4-1 1-1zm0 4.7h10.4c.6 0 1 .4 1 1v1.3c0 .6-.4 1-1 1H4.2c-.6 0-1-.4-1-1v-1.3c0-.6.4-1 1-1zm0 4.6h15.6c.6 0 1 .4 1 1v1.3c0 .6-.4 1-1 1H4.2c-.6 0-1-.4-1-1v-1.3c0-.6.4-1 1-1zm0 4.7h10.4c.6 0 1 .4 1 1V20c0 .6-.4 1-1 1H4.2c-.6 0-1-.4-1-1v-1c0-.6.4-1 1-1z"/>
</svg>
<span></span>
</a>
{/* Zhihu 知乎 */}
<a
href="https://www.zhihu.com/people/"
target="_blank"
rel="noopener noreferrer"
className="group flex items-center gap-2 px-4 py-2.5 rounded-xl text-sm font-medium transition-all duration-300 hover:shadow-md"
style={{ background: "#f7f6f3", color: "#5a5a5a" }}
title="知乎"
>
<svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor">
<path d="M5.721 0C2.251 0 0 2.25 0 5.719V18.28C0 21.751 2.252 24 5.721 24h12.56C21.751 24 24 21.75 24 18.281V5.72C24 2.249 21.75 0 18.281 0zm1.964 4.078c-.271.73-.5 1.434-.68 2.11h4.587c.545-.006.445 1.168.445 1.168H6.283a58.104 58.104 0 0 1-.037 3.32h3.342c.524.006.59 1.22.59 1.22H6.183c.04.8.228 2.025.455 3.07.215.977.475 1.74.717 2.087.24.346.414.31.6.27.184-.04.56-.346.84-1.028.28-.683.397-1.565.397-1.565h1.34s-.06.966-.373 2.032c-.315 1.066-.93 2.468-2.37 2.91-1.44.442-2.453-.224-2.916-.85-.462-.626-.78-2.026-.97-3.18-.19-1.155-.255-2.36-.255-3.165H2.26c.006-.55.12-1.224.12-1.22h1.88V6.186H3.47c-.12 0-.164-.82-.164-1.108h4.38zm8.137.004h1.56l2.14 8.39 2.17-8.39h1.49l-3.16 10.868h-1.15l-3.05-10.868zm-2.76 0h1.39v10.868h-1.39V4.082z"/>
</svg>
<span></span>
</a>
</div> </div>
</motion.div> </motion.div>
</div> </div>
</section> </section>
{/* Works Section */}
<section id="works" className="py-24 md:py-32" style={{ background: "#e8e6e1" }}>
<div className="max-w-7xl mx-auto px-6">
<motion.div
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, margin: "-100px" }}
transition={{ duration: 0.8, ease: [0.19, 1, 0.22, 1] }}
className="mb-16"
>
<h2
className="font-semibold mb-4"
style={{ fontSize: "clamp(32px, 4vw, 48px)", lineHeight: 1.1, color: "#141414" }}
>
</h2>
<p className="text-[#5a5a5a] text-lg max-w-xl">
</p>
</motion.div>
<WorkGrid />
</div>
</section>
{/* Footer */} {/* Footer */}
<footer className="py-12" style={{ background: "#e8e6e1" }}> <footer className="py-12" style={{ background: "#e8e6e1" }}>
<div className="max-w-7xl mx-auto px-6 text-center"> <div className="max-w-7xl mx-auto px-6 text-center">
@@ -375,12 +132,6 @@ export default function Home() {
</div> </div>
</footer> </footer>
<style>{`
@keyframes fadeInItem {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
`}</style>
</div> </div>
); );
} }