refactor(i18n): restructure translation system with nested objects and proxy
feat(data): add projects and services data structure for dynamic rendering refactor(pages): replace hardcoded content with dynamic data-driven components
This commit is contained in:
152
src/i18n/ui.ts
152
src/i18n/ui.ts
@@ -6,53 +6,119 @@ export const languages = {
|
||||
|
||||
export const defaultLang = 'en';
|
||||
|
||||
export const ui = {
|
||||
// 定义嵌套结构的国际化数据
|
||||
const structuredUi = {
|
||||
en: {
|
||||
'nav.home': 'Home',
|
||||
'nav.about': 'About',
|
||||
'nav.services': 'Services',
|
||||
'nav.projects': 'Projects',
|
||||
'nav.blog': 'Blog',
|
||||
'nav.contact': 'Contact',
|
||||
'site.title': 'Joy Zhao - Full Stack Developer',
|
||||
'site.description': 'Full Stack Developer specializing in React, Node.js, and modern web technologies',
|
||||
'hero.githubLink': 'GitHub Profile',
|
||||
'hero.linkedinLink': 'LinkedIn Profile',
|
||||
'footer.rights': 'All rights reserved',
|
||||
'project.tag.business': 'Business Project',
|
||||
'project.tag.opensource': 'Open Source',
|
||||
'project.tag.personal': 'Personal Product',
|
||||
'project.tag.portfolio': 'Portfolio',
|
||||
'project.tag.ecommerce': 'E-Commerce',
|
||||
'project.visit': 'Visit',
|
||||
'project.demo': 'Live Demo',
|
||||
'projects.title': 'My Projects',
|
||||
'projects.description': 'A collection of my recent work, showcasing innovative solutions and clean code. Explore the details of each project below.'
|
||||
nav: {
|
||||
home: 'Home',
|
||||
about: 'About',
|
||||
services: 'Services',
|
||||
projects: 'Projects',
|
||||
blog: 'Blog',
|
||||
contact: 'Contact',
|
||||
},
|
||||
site: {
|
||||
title: 'Joy Zhao - Full Stack Developer',
|
||||
description: 'Full Stack Developer specializing in React, Node.js, and modern web technologies',
|
||||
},
|
||||
hero: {
|
||||
githubLink: 'GitHub Profile',
|
||||
linkedinLink: 'LinkedIn Profile',
|
||||
},
|
||||
footer: {
|
||||
rights: 'All rights reserved',
|
||||
},
|
||||
project: {
|
||||
tag: {
|
||||
business: 'Business Project',
|
||||
opensource: 'Open Source',
|
||||
personal: 'Personal Product',
|
||||
portfolio: 'Portfolio',
|
||||
ecommerce: 'E-Commerce',
|
||||
},
|
||||
visit: 'Visit',
|
||||
demo: 'Live Demo',
|
||||
},
|
||||
projects: {
|
||||
title: 'My Projects',
|
||||
description: 'A collection of my recent work, showcasing innovative solutions and clean code. Explore the details of each project below.',
|
||||
},
|
||||
// Projects and services content has been inlined into respective page files
|
||||
// to reduce reliance on the translation system and improve maintainability
|
||||
},
|
||||
zh: {
|
||||
'nav.home': '首页',
|
||||
'nav.about': '关于',
|
||||
'nav.services': '服务',
|
||||
'nav.projects': '项目',
|
||||
'nav.blog': '博客',
|
||||
'nav.contact': '联系',
|
||||
'site.title': 'Joy Zhao - 全栈开发者',
|
||||
'site.description': '专注于 React、Node.js 和现代 Web 技术的全栈开发者',
|
||||
'hero.githubLink': 'GitHub 主页',
|
||||
'hero.linkedinLink': 'LinkedIn 主页',
|
||||
'footer.rights': '版权所有',
|
||||
'project.tag.business': '商业项目',
|
||||
'project.tag.opensource': '开源项目',
|
||||
'project.tag.personal': '个人产品',
|
||||
'project.tag.portfolio': '作品集',
|
||||
'project.tag.ecommerce': '电子商务',
|
||||
'project.visit': '访问',
|
||||
'project.demo': '在线演示',
|
||||
'projects.title': '我的项目',
|
||||
'projects.description': '这里展示了我最近的作品集,展现了创新解决方案和整洁的代码。请浏览下方了解每个项目的详细信息。'
|
||||
nav: {
|
||||
home: '首页',
|
||||
about: '关于',
|
||||
services: '服务',
|
||||
projects: '项目',
|
||||
blog: '博客',
|
||||
contact: '联系',
|
||||
},
|
||||
site: {
|
||||
title: 'Joy Zhao - 全栈开发者',
|
||||
description: '专注于 React、Node.js 和现代 Web 技术的全栈开发者',
|
||||
},
|
||||
hero: {
|
||||
githubLink: 'GitHub 主页',
|
||||
linkedinLink: 'LinkedIn 主页',
|
||||
},
|
||||
footer: {
|
||||
rights: '版权所有',
|
||||
},
|
||||
project: {
|
||||
tag: {
|
||||
business: '商业项目',
|
||||
opensource: '开源项目',
|
||||
personal: '个人产品',
|
||||
portfolio: '作品集',
|
||||
ecommerce: '电子商务',
|
||||
},
|
||||
visit: '访问',
|
||||
demo: '在线演示',
|
||||
},
|
||||
projects: {
|
||||
title: '我的项目',
|
||||
description: '这里展示了我最近的作品集,展现了创新解决方案和整洁的代码。请浏览下方了解每个项目的详细信息。',
|
||||
},
|
||||
// Projects and services content has been inlined into respective page files
|
||||
// to reduce reliance on the translation system and improve maintainability
|
||||
}
|
||||
} as const;
|
||||
},
|
||||
} as const;
|
||||
|
||||
// 创建代理对象,保持与现有代码的兼容性
|
||||
function createCompatibleUi() {
|
||||
// 为每种语言创建代理
|
||||
const compatibleUi: Record<string, any> = {};
|
||||
|
||||
Object.keys(structuredUi).forEach(lang => {
|
||||
compatibleUi[lang] = new Proxy({}, {
|
||||
get(target, prop) {
|
||||
if (typeof prop !== 'string') return undefined;
|
||||
|
||||
// 处理点符号键 (如 'nav.home')
|
||||
const parts = prop.split('.');
|
||||
let value: any = structuredUi[lang as keyof typeof structuredUi];
|
||||
|
||||
// 遍历嵌套结构
|
||||
for (const part of parts) {
|
||||
if (value && typeof value === 'object' && part in value) {
|
||||
value = value[part as keyof typeof value];
|
||||
} else {
|
||||
return undefined; // 键不存在
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return compatibleUi;
|
||||
}
|
||||
|
||||
// 导出兼容的UI对象
|
||||
export const ui = createCompatibleUi() as typeof structuredUi;
|
||||
|
||||
// 导出结构化的UI对象,供将来使用
|
||||
export const structuredUI = structuredUi;
|
||||
@@ -2,14 +2,17 @@
|
||||
import { ui, defaultLang, languages } from './ui';
|
||||
|
||||
export type Lang = keyof typeof languages;
|
||||
export type UiKeys = keyof typeof ui[typeof defaultLang];
|
||||
|
||||
// 简化类型定义,直接使用字符串类型
|
||||
// 这样可以兼容点符号键,同时避免复杂的类型推导问题
|
||||
export type UiKeys = string;
|
||||
|
||||
|
||||
export function useTranslations(lang: Lang | undefined) {
|
||||
const currentLang = lang || defaultLang;
|
||||
return function t(key: UiKeys, ...args: any[]): string {
|
||||
let translation: string = ui[currentLang][key] || ui[defaultLang][key];
|
||||
// 使用类型断言解决索引问题
|
||||
let translation: string = (ui[currentLang] as any)[key] || (ui[defaultLang] as any)[key];
|
||||
if (args.length > 0) {
|
||||
args.forEach((arg, index) => {
|
||||
translation = translation.replace(`{${index}}`, arg);
|
||||
|
||||
204
src/lib/data.ts
204
src/lib/data.ts
@@ -1,8 +1,202 @@
|
||||
export const personalInfo = {
|
||||
name: "Joy Zhao",
|
||||
name: "Guiyang Zhao",
|
||||
location: "Shanghai, China",
|
||||
avatar:"https://avatars.githubusercontent.com/u/24975063?v=4",
|
||||
email: "zhaoguiyang18@gmail.com",
|
||||
github: "https://github.com/zguiyang",
|
||||
linkedin: "https://linkedin.com/in/zhaoguiyang"
|
||||
avatar: "/images/avatar.jpg",
|
||||
email: "zhaoguiyang@gmail.com",
|
||||
github: "https://github.com/zhaoguiyang",
|
||||
linkedin: "https://linkedin.com/in/zhaoguiyang",
|
||||
};
|
||||
|
||||
export const projects = {
|
||||
en: [
|
||||
{
|
||||
id: "taskify",
|
||||
tag: "business",
|
||||
title: "Taskify App",
|
||||
icon: "📱",
|
||||
color: "purple",
|
||||
image: {
|
||||
bg: "from-purple-500/20 to-purple-600/20",
|
||||
hover: "from-purple-500/20 to-purple-600/20",
|
||||
text: "text-purple-400",
|
||||
},
|
||||
description: [
|
||||
"A comprehensive task management application with drag-and-drop functionality.",
|
||||
"Built with React, TypeScript, and Tailwind CSS using modern development approaches.",
|
||||
"Real-time collaboration through WebSocket integration for instant updates.",
|
||||
"Advanced task filtering, sorting, and project management capabilities.",
|
||||
],
|
||||
tech: ["React", "Node.js", "MongoDB"],
|
||||
link: "#",
|
||||
},
|
||||
{
|
||||
id: "eshop",
|
||||
tag: "ecommerce",
|
||||
title: "E-Shop Platform",
|
||||
icon: "🛒",
|
||||
color: "green",
|
||||
image: {
|
||||
bg: "from-green-500/20 to-green-600/20",
|
||||
hover: "from-green-500/20 to-green-600/20",
|
||||
text: "text-green-400",
|
||||
},
|
||||
description: [
|
||||
"Scalable e-commerce platform built with Next.js, Stripe payments, and TailwindCSS.",
|
||||
"Mobile-first responsive design for optimal user experience across devices.",
|
||||
"Integrated payment processing with Stripe for secure transactions.",
|
||||
"Admin dashboard for inventory management and order processing.",
|
||||
],
|
||||
tech: ["Next.js", "Stripe", "TailwindCSS"],
|
||||
link: "#",
|
||||
},
|
||||
{
|
||||
id: "portfolio",
|
||||
tag: "portfolio",
|
||||
title: "Portfolio Site",
|
||||
icon: "🌐",
|
||||
color: "purple",
|
||||
image: {
|
||||
bg: "from-purple-500/20 to-purple-600/20",
|
||||
hover: "from-purple-500/20 to-purple-600/20",
|
||||
text: "text-purple-400",
|
||||
},
|
||||
description: [
|
||||
"Personal portfolio showcasing my work, built with HTML, TailwindCSS, and Alpine.js.",
|
||||
"Responsive design with dark mode support and smooth animations.",
|
||||
"Optimized for performance with minimal JavaScript and efficient CSS.",
|
||||
"Integrated blog section with markdown support for content management.",
|
||||
],
|
||||
tech: ["HTML", "TailwindCSS", "Alpine.js"],
|
||||
link: "#",
|
||||
},
|
||||
],
|
||||
zh: [
|
||||
{
|
||||
id: "taskify",
|
||||
tag: "business",
|
||||
title: "Taskify 应用",
|
||||
icon: "📱",
|
||||
color: "purple",
|
||||
image: {
|
||||
bg: "from-purple-500/20 to-purple-600/20",
|
||||
hover: "from-purple-500/20 to-purple-600/20",
|
||||
text: "text-purple-400",
|
||||
},
|
||||
description: [
|
||||
"一个全面的任务管理应用,具有拖放功能。",
|
||||
"使用React、TypeScript和Tailwind CSS构建,采用现代开发方法。",
|
||||
"通过WebSocket集成实现实时协作功能,实现即时更新。",
|
||||
"高级任务筛选、排序和项目管理功能。",
|
||||
],
|
||||
tech: ["React", "Node.js", "MongoDB"],
|
||||
link: "#",
|
||||
},
|
||||
{
|
||||
id: "eshop",
|
||||
tag: "ecommerce",
|
||||
title: "电商平台",
|
||||
icon: "🛒",
|
||||
color: "green",
|
||||
image: {
|
||||
bg: "from-green-500/20 to-green-600/20",
|
||||
hover: "from-green-500/20 to-green-600/20",
|
||||
text: "text-green-400",
|
||||
},
|
||||
description: [
|
||||
"使用Next.js、Stripe支付和TailwindCSS构建的可扩展电子商务平台。",
|
||||
"采用移动优先的响应式设计,提供最佳用户体验。",
|
||||
"集成Stripe支付处理,确保交易安全。",
|
||||
"管理员仪表板,用于库存管理和订单处理。",
|
||||
],
|
||||
tech: ["Next.js", "Stripe", "TailwindCSS"],
|
||||
link: "#",
|
||||
},
|
||||
{
|
||||
id: "portfolio",
|
||||
tag: "portfolio",
|
||||
title: "个人作品集网站",
|
||||
icon: "🌐",
|
||||
color: "purple",
|
||||
image: {
|
||||
bg: "from-purple-500/20 to-purple-600/20",
|
||||
hover: "from-purple-500/20 to-purple-600/20",
|
||||
text: "text-purple-400",
|
||||
},
|
||||
description: [
|
||||
"展示我的作品的个人作品集,使用HTML、TailwindCSS和Alpine.js构建。",
|
||||
"响应式设计,支持暗黑模式和平滑动画。",
|
||||
"通过最小化JavaScript和高效CSS优化性能。",
|
||||
"集成博客部分,支持markdown内容管理。",
|
||||
],
|
||||
tech: ["HTML", "TailwindCSS", "Alpine.js"],
|
||||
link: "#",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const services = {
|
||||
en: [
|
||||
{
|
||||
title: "Outsourcing Projects",
|
||||
icon: {
|
||||
svg: `<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 13.255A23.931 23.931 0 0112 15c-3.183 0-6.22-.62-9-1.745M16 6V4a2 2 0 00-2-2h-4a2 2 0 00-2 2v2m4 6h.01M5 20h14a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"></path>`,
|
||||
gradient: "from-blue-500 to-cyan-500",
|
||||
},
|
||||
items: [
|
||||
"Provide outsourcing project services for overseas clients",
|
||||
"Project packaging, can provide services in different packages",
|
||||
"Use popular technologies: React, nest.js, next.js, etc.",
|
||||
"Project delivery, provide three months of free maintenance",
|
||||
"Regardless of project size, can provide services",
|
||||
],
|
||||
color: "blue",
|
||||
},
|
||||
{
|
||||
title: "Bug Fixes",
|
||||
icon: {
|
||||
svg: `<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"></path><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>`,
|
||||
gradient: "from-red-500 to-pink-500",
|
||||
},
|
||||
items: [
|
||||
"Quickly locate and fix website issues, able to quickly locate and solve problems",
|
||||
"Help you solve any problems encountered in the project, Bug, functional optimization issues",
|
||||
"Application of Vue, React, Node and other technologies",
|
||||
"Frontend automation, deployment, monitoring, automation, etc.",
|
||||
"Only limited to Node.js projects",
|
||||
],
|
||||
color: "red",
|
||||
},
|
||||
],
|
||||
zh: [
|
||||
{
|
||||
title: "外包项目",
|
||||
icon: {
|
||||
svg: `<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 13.255A23.931 23.931 0 0112 15c-3.183 0-6.22-.62-9-1.745M16 6V4a2 2 0 00-2-2h-4a2 2 0 00-2 2v2m4 6h.01M5 20h14a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"></path>`,
|
||||
gradient: "from-blue-500 to-cyan-500",
|
||||
},
|
||||
items: [
|
||||
"为海外客户提供外包项目服务",
|
||||
"项目打包,可以提供不同套餐的服务",
|
||||
"使用流行技术:React、nest.js、next.js 等",
|
||||
"项目交付,提供三个月免费维护",
|
||||
"不论项目大小,都可以提供服务",
|
||||
],
|
||||
color: "blue",
|
||||
},
|
||||
{
|
||||
title: "Bug 修复",
|
||||
icon: {
|
||||
svg: `<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"></path><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>`,
|
||||
gradient: "from-red-500 to-pink-500",
|
||||
},
|
||||
items: [
|
||||
"快速定位和修复网站问题,能够快速定位和解决问题",
|
||||
"帮助您解决项目中遇到的任何问题,Bug、功能优化问题",
|
||||
"Vue、React、Node 等技术的应用",
|
||||
"前端自动化、部署、监控、自动化等",
|
||||
"仅限于 Node.js 项目",
|
||||
],
|
||||
color: "red",
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -5,7 +5,7 @@ import SkillsMarquee from "@/components/SkillsMarquee";
|
||||
import Footer from "@/components/Footer";
|
||||
import { useTranslations, type Lang } from "@/i18n/utils";
|
||||
import { defaultLang } from "@/i18n/ui";
|
||||
import { personalInfo } from "@/lib/data";
|
||||
import { personalInfo, services } from "@/lib/data";
|
||||
|
||||
// 使用Astro.currentLocale获取当前语言环境
|
||||
const lang = Astro.currentLocale as Lang || defaultLang;
|
||||
@@ -175,74 +175,26 @@ const pageTitle = t('site.title');
|
||||
</h2>
|
||||
|
||||
<div class="grid md:grid-cols-2 gap-8">
|
||||
<!-- Outsourcing Projects Card -->
|
||||
<div class="bg-white/70 dark:bg-slate-800/70 backdrop-blur-sm rounded-2xl p-8 border border-white/20 shadow-xl hover:shadow-2xl transition-all duration-300 hover:scale-105">
|
||||
<div class="flex items-center mb-6">
|
||||
<div class="w-12 h-12 bg-gradient-to-r from-blue-500 to-cyan-500 rounded-lg flex items-center justify-center mr-4">
|
||||
<svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 13.255A23.931 23.931 0 0112 15c-3.183 0-6.22-.62-9-1.745M16 6V4a2 2 0 00-2-2h-4a2 2 0 00-2 2v2m4 6h.01M5 20h14a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"></path>
|
||||
</svg>
|
||||
{services.en.map((service) => (
|
||||
<div class="bg-white/70 dark:bg-slate-800/70 backdrop-blur-sm rounded-2xl p-8 border border-white/20 shadow-xl hover:shadow-2xl transition-all duration-300 hover:scale-105">
|
||||
<div class="flex items-center mb-6">
|
||||
<div class={`w-12 h-12 bg-gradient-to-r ${service.icon.gradient} rounded-lg flex items-center justify-center mr-4`}>
|
||||
<svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<Fragment set:html={service.icon.svg} />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-2xl font-bold text-slate-800 dark:text-white">{service.title}</h3>
|
||||
</div>
|
||||
<h3 class="text-2xl font-bold text-slate-800 dark:text-white">Outsourcing Projects</h3>
|
||||
<ul class="space-y-3">
|
||||
{service.items.map((item, index) => (
|
||||
<li class="flex items-start">
|
||||
<span class={`text-${service.color}-500 mr-3 mt-1`}>{index + 1}.</span>
|
||||
<span class="text-slate-600 dark:text-slate-300">{item}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
<ul class="space-y-3">
|
||||
<li class="flex items-start">
|
||||
<span class="text-blue-500 mr-3 mt-1">1.</span>
|
||||
<span class="text-slate-600 dark:text-slate-300">Provide outsourcing project services for overseas clients</span>
|
||||
</li>
|
||||
<li class="flex items-start">
|
||||
<span class="text-blue-500 mr-3 mt-1">2.</span>
|
||||
<span class="text-slate-600 dark:text-slate-300">Project packaging, can provide services in different packages</span>
|
||||
</li>
|
||||
<li class="flex items-start">
|
||||
<span class="text-blue-500 mr-3 mt-1">3.</span>
|
||||
<span class="text-slate-600 dark:text-slate-300">Use popular technologies: React, nest.js, next.js, etc.</span>
|
||||
</li>
|
||||
<li class="flex items-start">
|
||||
<span class="text-blue-500 mr-3 mt-1">4.</span>
|
||||
<span class="text-slate-600 dark:text-slate-300">Project delivery, provide three months of free maintenance</span>
|
||||
</li>
|
||||
<li class="flex items-start">
|
||||
<span class="text-blue-500 mr-3 mt-1">5.</span>
|
||||
<span class="text-slate-600 dark:text-slate-300">Regardless of project size, can provide services</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Bug Fixes Card -->
|
||||
<div class="bg-white/70 dark:bg-slate-800/70 backdrop-blur-sm rounded-2xl p-8 border border-white/20 shadow-xl hover:shadow-2xl transition-all duration-300 hover:scale-105">
|
||||
<div class="flex items-center mb-6">
|
||||
<div class="w-12 h-12 bg-gradient-to-r from-red-500 to-pink-500 rounded-lg flex items-center justify-center mr-4">
|
||||
<svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"></path>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-2xl font-bold text-slate-800 dark:text-white">Bug Fixes</h3>
|
||||
</div>
|
||||
<ul class="space-y-3">
|
||||
<li class="flex items-start">
|
||||
<span class="text-red-500 mr-3 mt-1">1.</span>
|
||||
<span class="text-slate-600 dark:text-slate-300">Quickly locate and fix website issues, able to quickly locate and solve problems</span>
|
||||
</li>
|
||||
<li class="flex items-start">
|
||||
<span class="text-red-500 mr-3 mt-1">2.</span>
|
||||
<span class="text-slate-600 dark:text-slate-300">Help you solve any problems encountered in the project, Bug, functional optimization issues</span>
|
||||
</li>
|
||||
<li class="flex items-start">
|
||||
<span class="text-red-500 mr-3 mt-1">3.</span>
|
||||
<span class="text-slate-600 dark:text-slate-300">Application of Vue, React, Node and other technologies</span>
|
||||
</li>
|
||||
<li class="flex items-start">
|
||||
<span class="text-red-500 mr-3 mt-1">4.</span>
|
||||
<span class="text-slate-600 dark:text-slate-300">Frontend automation, deployment, monitoring, automation, etc.</span>
|
||||
</li>
|
||||
<li class="flex items-start">
|
||||
<span class="text-red-500 mr-3 mt-1">5.</span>
|
||||
<span class="text-slate-600 dark:text-slate-300">Only limited to Node.js projects</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -4,11 +4,15 @@ import GlassHeader from "@/components/GlassHeader";
|
||||
import Footer from "@/components/Footer";
|
||||
import { useTranslations, type Lang } from "@/i18n/utils";
|
||||
import { defaultLang } from "@/i18n/ui";
|
||||
import { projects } from "@/lib/data";
|
||||
|
||||
// 使用Astro.currentLocale获取当前语言环境
|
||||
const lang = Astro.currentLocale as Lang || defaultLang;
|
||||
const t = useTranslations(lang);
|
||||
const pageTitle = t('projects.title');
|
||||
|
||||
// 根据当前语言获取项目数据
|
||||
const currentProjects = projects[lang as keyof typeof projects] || projects.en;
|
||||
---
|
||||
|
||||
<Layout title={pageTitle}>
|
||||
@@ -41,194 +45,59 @@ const pageTitle = t('projects.title');
|
||||
|
||||
<div class="container max-w-6xl mx-auto px-6 md:px-4 relative z-10">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8 items-stretch">
|
||||
<!-- Taskify App Project -->
|
||||
<div class="group overflow-hidden border border-purple-500/20 hover:border-purple-500/40 h-full flex flex-col transition-all duration-500 hover:scale-105 bg-white/10 dark:bg-gray-800/50 backdrop-blur-sm rounded-xl relative">
|
||||
<!-- Project tag - positioned at top right -->
|
||||
<div class="absolute top-4 right-4 z-10">
|
||||
<span class="px-3 py-1 bg-blue-100 dark:bg-blue-800 text-blue-800 dark:text-blue-200 text-xs rounded-full font-medium border border-blue-200 dark:border-blue-700">{t('project.tag.business')}</span>
|
||||
</div>
|
||||
|
||||
<!-- Project image placeholder -->
|
||||
<div class="h-48 bg-gradient-to-br from-purple-500/20 to-purple-600/20 relative overflow-hidden">
|
||||
<div class="absolute inset-0 bg-gradient-to-br from-purple-500/10 to-purple-600/10 group-hover:from-purple-500/20 group-hover:to-purple-600/20 transition-all duration-500"></div>
|
||||
<div class="absolute bottom-4 left-4 right-4">
|
||||
<div class="bg-black/50 backdrop-blur-sm rounded px-3 py-1 text-xs font-mono text-purple-400">
|
||||
Taskify App
|
||||
</div>
|
||||
{currentProjects.map((project) => (
|
||||
<div class={`group overflow-hidden border border-${project.color}-500/20 hover:border-${project.color}-500/40 h-full flex flex-col transition-all duration-500 hover:scale-105 bg-white/10 dark:bg-gray-800/50 backdrop-blur-sm rounded-xl relative`}>
|
||||
<!-- Project tag - positioned at top right -->
|
||||
<div class="absolute top-4 right-4 z-10">
|
||||
<span class={`px-3 py-1 bg-${project.color}-100 dark:bg-${project.color}-800 text-${project.color}-800 dark:text-${project.color}-200 text-xs rounded-full font-medium border border-${project.color}-200 dark:border-${project.color}-700`}>{t(`project.tag.${project.tag}`)}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-6 pb-4">
|
||||
<h3 class="text-xl group-hover:text-purple-400 transition-colors duration-300 flex items-center gap-2 font-bold mb-4">
|
||||
<span class="text-purple-500">📱</span>
|
||||
Taskify App
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div class="px-6 flex-grow">
|
||||
<div class="space-y-3">
|
||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
||||
<span class="text-purple-500 mt-1">•</span>
|
||||
<span>A comprehensive task management application with drag-and-drop functionality.</span>
|
||||
</div>
|
||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
||||
<span class="text-purple-500 mt-1">•</span>
|
||||
<span>Built with React, TypeScript, and Tailwind CSS for modern development.</span>
|
||||
</div>
|
||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
||||
<span class="text-purple-500 mt-1">•</span>
|
||||
<span>Real-time collaboration features with WebSocket integration for instant updates.</span>
|
||||
</div>
|
||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
||||
<span class="text-purple-500 mt-1">•</span>
|
||||
<span>Advanced task filtering, sorting, and project management capabilities.</span>
|
||||
|
||||
<!-- Project image placeholder -->
|
||||
<div class={`h-48 bg-gradient-to-br ${project.image.bg} relative overflow-hidden`}>
|
||||
<div class={`absolute inset-0 bg-gradient-to-br ${project.image.bg} group-hover:${project.image.hover} transition-all duration-500`}></div>
|
||||
<div class="absolute bottom-4 left-4 right-4">
|
||||
<div class={`bg-black/50 backdrop-blur-sm rounded px-3 py-1 text-xs font-mono ${project.image.text}`}>
|
||||
{project.title}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tech stack indicators with unified gray styling -->
|
||||
<div class="mt-6 mb-4 flex flex-wrap gap-2">
|
||||
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">React</span>
|
||||
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">Node.js</span>
|
||||
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">MongoDB</span>
|
||||
<div class="p-6 pb-4">
|
||||
<h3 class={`text-xl group-hover:text-${project.color}-400 transition-colors duration-300 flex items-center gap-2 font-bold mb-4`}>
|
||||
<span class={`text-${project.color}-500`}>{project.icon}</span>
|
||||
{project.title}
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Visit project link -->
|
||||
<div class="p-6 pt-2">
|
||||
<a href="#" class="inline-flex items-center text-sm font-medium text-purple-500 hover:text-purple-600 dark:hover:text-purple-400 transition-colors duration-300">
|
||||
{t('project.visit')}
|
||||
<svg class="ml-1 w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- E-Shop Platform Project -->
|
||||
<div class="group overflow-hidden border border-purple-500/20 hover:border-purple-500/40 h-full flex flex-col transition-all duration-500 hover:scale-105 bg-white/10 dark:bg-gray-800/50 backdrop-blur-sm rounded-xl relative">
|
||||
<!-- Project tag - positioned at top right -->
|
||||
<div class="absolute top-4 right-4 z-10">
|
||||
<span class="px-3 py-1 bg-green-100 dark:bg-green-800 text-green-800 dark:text-green-200 text-xs rounded-full font-medium border border-green-200 dark:border-green-700">{t('project.tag.ecommerce')}</span>
|
||||
</div>
|
||||
|
||||
<!-- Project image placeholder -->
|
||||
<div class="h-48 bg-gradient-to-br from-green-500/20 to-green-600/20 relative overflow-hidden">
|
||||
<div class="absolute inset-0 bg-gradient-to-br from-green-500/10 to-green-600/10 group-hover:from-green-500/20 group-hover:to-green-600/20 transition-all duration-500"></div>
|
||||
<div class="absolute bottom-4 left-4 right-4">
|
||||
<div class="bg-black/50 backdrop-blur-sm rounded px-3 py-1 text-xs font-mono text-green-400">
|
||||
E-Shop Platform
|
||||
|
||||
<div class="px-6 flex-grow">
|
||||
<div class="space-y-3">
|
||||
{project.description.map((desc) => (
|
||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
||||
<span class={`text-${project.color}-500 mt-1`}>•</span>
|
||||
<span>{desc}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-6 pb-4">
|
||||
<h3 class="text-xl group-hover:text-green-400 transition-colors duration-300 flex items-center gap-2 font-bold mb-4">
|
||||
<span class="text-green-500">🛒</span>
|
||||
E-Shop Platform
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div class="px-6 flex-grow">
|
||||
<div class="space-y-3">
|
||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
||||
<span class="text-green-500 mt-1">•</span>
|
||||
<span>A scalable e-commerce platform with Next.js, Stripe payments, and TailwindCSS.</span>
|
||||
</div>
|
||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
||||
<span class="text-green-500 mt-1">•</span>
|
||||
<span>Responsive design with mobile-first approach for optimal user experience.</span>
|
||||
</div>
|
||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
||||
<span class="text-green-500 mt-1">•</span>
|
||||
<span>Integrated payment processing with Stripe for secure transactions.</span>
|
||||
</div>
|
||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
||||
<span class="text-green-500 mt-1">•</span>
|
||||
<span>Admin dashboard for inventory management and order processing.</span>
|
||||
|
||||
<!-- Tech stack indicators with unified gray styling -->
|
||||
<div class="mt-6 mb-4 flex flex-wrap gap-2">
|
||||
{project.tech.map((tech) => (
|
||||
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">{tech}</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tech stack indicators with unified gray styling -->
|
||||
<div class="mt-6 mb-4 flex flex-wrap gap-2">
|
||||
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">Next.js</span>
|
||||
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">Stripe</span>
|
||||
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">TailwindCSS</span>
|
||||
<!-- Visit project link -->
|
||||
<div class="p-6 pt-2">
|
||||
<a href={project.link} class={`inline-flex items-center text-sm font-medium text-${project.color}-500 hover:text-${project.color}-600 dark:hover:text-${project.color}-400 transition-colors duration-300`}>
|
||||
{t('project.visit')}
|
||||
<svg class="ml-1 w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Visit project link -->
|
||||
<div class="p-6 pt-2">
|
||||
<a href="#" class="inline-flex items-center text-sm font-medium text-green-500 hover:text-green-600 dark:hover:text-green-400 transition-colors duration-300">
|
||||
{t('project.visit')}
|
||||
<svg class="ml-1 w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Portfolio Site Project -->
|
||||
<div class="group overflow-hidden border border-purple-500/20 hover:border-purple-500/40 h-full flex flex-col transition-all duration-500 hover:scale-105 bg-white/10 dark:bg-gray-800/50 backdrop-blur-sm rounded-xl relative">
|
||||
<!-- Project tag - positioned at top right -->
|
||||
<div class="absolute top-4 right-4 z-10">
|
||||
<span class="px-3 py-1 bg-purple-100 dark:bg-purple-800 text-purple-800 dark:text-purple-200 text-xs rounded-full font-medium border border-purple-200 dark:border-purple-700">{t('project.tag.portfolio')}</span>
|
||||
</div>
|
||||
|
||||
<!-- Project image placeholder -->
|
||||
<div class="h-48 bg-gradient-to-br from-purple-500/20 to-purple-600/20 relative overflow-hidden">
|
||||
<div class="absolute inset-0 bg-gradient-to-br from-purple-500/10 to-purple-600/10 group-hover:from-purple-500/20 group-hover:to-purple-600/20 transition-all duration-500"></div>
|
||||
<div class="absolute bottom-4 left-4 right-4">
|
||||
<div class="bg-black/50 backdrop-blur-sm rounded px-3 py-1 text-xs font-mono text-purple-400">
|
||||
Portfolio Site
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-6 pb-4">
|
||||
<h3 class="text-xl group-hover:text-purple-400 transition-colors duration-300 flex items-center gap-2 font-bold mb-4">
|
||||
<span class="text-purple-500">🌐</span>
|
||||
Portfolio Site
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div class="px-6 flex-grow">
|
||||
<div class="space-y-3">
|
||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
||||
<span class="text-purple-500 mt-1">•</span>
|
||||
<span>My personal portfolio showcasing my work, built with HTML, TailwindCSS, and Alpine.js.</span>
|
||||
</div>
|
||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
||||
<span class="text-purple-500 mt-1">•</span>
|
||||
<span>Responsive design with dark mode support and smooth animations.</span>
|
||||
</div>
|
||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
||||
<span class="text-purple-500 mt-1">•</span>
|
||||
<span>Optimized for performance with minimal JavaScript and efficient CSS.</span>
|
||||
</div>
|
||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
||||
<span class="text-purple-500 mt-1">•</span>
|
||||
<span>Integrated blog section with markdown support for content management.</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tech stack indicators with unified gray styling -->
|
||||
<div class="mt-6 mb-4 flex flex-wrap gap-2">
|
||||
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">HTML</span>
|
||||
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">TailwindCSS</span>
|
||||
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">Alpine.js</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Visit project link -->
|
||||
<div class="p-6 pt-2">
|
||||
<a href="#" class="inline-flex items-center text-sm font-medium text-purple-500 hover:text-purple-600 dark:hover:text-purple-400 transition-colors duration-300">
|
||||
{t('project.visit')}
|
||||
<svg class="ml-1 w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
---
|
||||
import Layout from "@/layouts/Layout.astro";
|
||||
import GlassHeader from "@/components/GlassHeader.tsx";
|
||||
import SkillsMarquee from "@/components/SkillsMarquee.tsx";
|
||||
import Footer from "@/components/Footer.tsx";
|
||||
import GlassHeader from "@/components/GlassHeader";
|
||||
import SkillsMarquee from "@/components/SkillsMarquee";
|
||||
import Footer from "@/components/Footer";
|
||||
import { useTranslations, type Lang } from "@/i18n/utils";
|
||||
import { defaultLang } from "@/i18n/ui";
|
||||
import { personalInfo } from "@/lib/data";
|
||||
import { personalInfo, services } from "@/lib/data";
|
||||
|
||||
// 使用Astro.currentLocale获取当前语言环境
|
||||
const lang = Astro.currentLocale as Lang || defaultLang;
|
||||
@@ -175,74 +175,26 @@ const pageTitle = t('site.title');
|
||||
</h2>
|
||||
|
||||
<div class="grid md:grid-cols-2 gap-8">
|
||||
<!-- Outsourcing Projects Card -->
|
||||
<div class="bg-white/70 dark:bg-slate-800/70 backdrop-blur-sm rounded-2xl p-8 border border-white/20 shadow-xl hover:shadow-2xl transition-all duration-300 hover:scale-105">
|
||||
<div class="flex items-center mb-6">
|
||||
<div class="w-12 h-12 bg-gradient-to-r from-blue-500 to-cyan-500 rounded-lg flex items-center justify-center mr-4">
|
||||
<svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 13.255A23.931 23.931 0 0112 15c-3.183 0-6.22-.62-9-1.745M16 6V4a2 2 0 00-2-2h-4a2 2 0 00-2 2v2m4 6h.01M5 20h14a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"></path>
|
||||
</svg>
|
||||
{services.zh.map((service) => (
|
||||
<div class="bg-white/70 dark:bg-slate-800/70 backdrop-blur-sm rounded-2xl p-8 border border-white/20 shadow-xl hover:shadow-2xl transition-all duration-300 hover:scale-105">
|
||||
<div class="flex items-center mb-6">
|
||||
<div class={`w-12 h-12 bg-gradient-to-r ${service.icon.gradient} rounded-lg flex items-center justify-center mr-4`}>
|
||||
<svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<Fragment set:html={service.icon.svg} />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-2xl font-bold text-slate-800 dark:text-white">{service.title}</h3>
|
||||
</div>
|
||||
<h3 class="text-2xl font-bold text-slate-800 dark:text-white">外包项目</h3>
|
||||
<ul class="space-y-3">
|
||||
{service.items.map((item, index) => (
|
||||
<li class="flex items-start">
|
||||
<span class={`text-${service.color}-500 mr-3 mt-1`}>{index + 1}.</span>
|
||||
<span class="text-slate-600 dark:text-slate-300">{item}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
<ul class="space-y-3">
|
||||
<li class="flex items-start">
|
||||
<span class="text-blue-500 mr-3 mt-1">1.</span>
|
||||
<span class="text-slate-600 dark:text-slate-300">为海外客户提供外包项目服务</span>
|
||||
</li>
|
||||
<li class="flex items-start">
|
||||
<span class="text-blue-500 mr-3 mt-1">2.</span>
|
||||
<span class="text-slate-600 dark:text-slate-300">项目打包,可以提供不同套餐的服务</span>
|
||||
</li>
|
||||
<li class="flex items-start">
|
||||
<span class="text-blue-500 mr-3 mt-1">3.</span>
|
||||
<span class="text-slate-600 dark:text-slate-300">使用流行技术:React、nest.js、next.js 等</span>
|
||||
</li>
|
||||
<li class="flex items-start">
|
||||
<span class="text-blue-500 mr-3 mt-1">4.</span>
|
||||
<span class="text-slate-600 dark:text-slate-300">项目交付,提供三个月免费维护</span>
|
||||
</li>
|
||||
<li class="flex items-start">
|
||||
<span class="text-blue-500 mr-3 mt-1">5.</span>
|
||||
<span class="text-slate-600 dark:text-slate-300">不论项目大小,都可以提供服务</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Bug Fixes Card -->
|
||||
<div class="bg-white/70 dark:bg-slate-800/70 backdrop-blur-sm rounded-2xl p-8 border border-white/20 shadow-xl hover:shadow-2xl transition-all duration-300 hover:scale-105">
|
||||
<div class="flex items-center mb-6">
|
||||
<div class="w-12 h-12 bg-gradient-to-r from-red-500 to-pink-500 rounded-lg flex items-center justify-center mr-4">
|
||||
<svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"></path>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-2xl font-bold text-slate-800 dark:text-white">Bug 修复</h3>
|
||||
</div>
|
||||
<ul class="space-y-3">
|
||||
<li class="flex items-start">
|
||||
<span class="text-red-500 mr-3 mt-1">1.</span>
|
||||
<span class="text-slate-600 dark:text-slate-300">快速定位和修复网站问题,能够快速定位和解决问题</span>
|
||||
</li>
|
||||
<li class="flex items-start">
|
||||
<span class="text-red-500 mr-3 mt-1">2.</span>
|
||||
<span class="text-slate-600 dark:text-slate-300">帮助您解决项目中遇到的任何问题,Bug、功能优化问题</span>
|
||||
</li>
|
||||
<li class="flex items-start">
|
||||
<span class="text-red-500 mr-3 mt-1">3.</span>
|
||||
<span class="text-slate-600 dark:text-slate-300">Vue、React、Node 等技术的应用</span>
|
||||
</li>
|
||||
<li class="flex items-start">
|
||||
<span class="text-red-500 mr-3 mt-1">4.</span>
|
||||
<span class="text-slate-600 dark:text-slate-300">前端自动化、部署、监控、自动化等</span>
|
||||
</li>
|
||||
<li class="flex items-start">
|
||||
<span class="text-red-500 mr-3 mt-1">5.</span>
|
||||
<span class="text-slate-600 dark:text-slate-300">仅限于 Node.js 项目</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -4,11 +4,15 @@ import GlassHeader from "@/components/GlassHeader";
|
||||
import Footer from "@/components/Footer";
|
||||
import { useTranslations, type Lang } from "@/i18n/utils";
|
||||
import { defaultLang } from "@/i18n/ui";
|
||||
import { projects } from "@/lib/data";
|
||||
|
||||
// 使用Astro.currentLocale获取当前语言环境
|
||||
const lang = Astro.currentLocale as Lang || defaultLang;
|
||||
const t = useTranslations(lang);
|
||||
const pageTitle = t('projects.title');
|
||||
|
||||
// 根据当前语言获取项目数据
|
||||
const currentProjects = projects[lang as keyof typeof projects] || projects.en;
|
||||
---
|
||||
|
||||
<Layout title={pageTitle}>
|
||||
@@ -41,194 +45,59 @@ const pageTitle = t('projects.title');
|
||||
|
||||
<div class="container max-w-6xl mx-auto px-6 md:px-4 relative z-10">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8 items-stretch">
|
||||
<!-- Taskify App Project -->
|
||||
<div class="group overflow-hidden border border-purple-500/20 hover:border-purple-500/40 h-full flex flex-col transition-all duration-500 hover:scale-105 bg-white/10 dark:bg-gray-800/50 backdrop-blur-sm rounded-xl relative">
|
||||
<!-- Project tag - positioned at top right -->
|
||||
<div class="absolute top-4 right-4 z-10">
|
||||
<span class="px-3 py-1 bg-blue-100 dark:bg-blue-800 text-blue-800 dark:text-blue-200 text-xs rounded-full font-medium border border-blue-200 dark:border-blue-700">{t('project.tag.business')}</span>
|
||||
</div>
|
||||
|
||||
<!-- Project image placeholder -->
|
||||
<div class="h-48 bg-gradient-to-br from-purple-500/20 to-purple-600/20 relative overflow-hidden">
|
||||
<div class="absolute inset-0 bg-gradient-to-br from-purple-500/10 to-purple-600/10 group-hover:from-purple-500/20 group-hover:to-purple-600/20 transition-all duration-500"></div>
|
||||
<div class="absolute bottom-4 left-4 right-4">
|
||||
<div class="bg-black/50 backdrop-blur-sm rounded px-3 py-1 text-xs font-mono text-purple-400">
|
||||
Taskify 应用
|
||||
</div>
|
||||
{currentProjects.map((project) => (
|
||||
<div class={`group overflow-hidden border border-${project.color}-500/20 hover:border-${project.color}-500/40 h-full flex flex-col transition-all duration-500 hover:scale-105 bg-white/10 dark:bg-gray-800/50 backdrop-blur-sm rounded-xl relative`}>
|
||||
<!-- Project tag - positioned at top right -->
|
||||
<div class="absolute top-4 right-4 z-10">
|
||||
<span class={`px-3 py-1 bg-${project.color}-100 dark:bg-${project.color}-800 text-${project.color}-800 dark:text-${project.color}-200 text-xs rounded-full font-medium border border-${project.color}-200 dark:border-${project.color}-700`}>{t(`project.tag.${project.tag}`)}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-6 pb-4">
|
||||
<h3 class="text-xl group-hover:text-purple-400 transition-colors duration-300 flex items-center gap-2 font-bold mb-4">
|
||||
<span class="text-purple-500">📱</span>
|
||||
Taskify 应用
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div class="px-6 flex-grow">
|
||||
<div class="space-y-3">
|
||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
||||
<span class="text-purple-500 mt-1">•</span>
|
||||
<span>一个全面的任务管理应用,具有拖放功能。</span>
|
||||
</div>
|
||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
||||
<span class="text-purple-500 mt-1">•</span>
|
||||
<span>使用React、TypeScript和Tailwind CSS构建,采用现代开发方法。</span>
|
||||
</div>
|
||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
||||
<span class="text-purple-500 mt-1">•</span>
|
||||
<span>通过WebSocket集成实现实时协作功能,实现即时更新。</span>
|
||||
</div>
|
||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
||||
<span class="text-purple-500 mt-1">•</span>
|
||||
<span>高级任务筛选、排序和项目管理功能。</span>
|
||||
|
||||
<!-- Project image placeholder -->
|
||||
<div class={`h-48 bg-gradient-to-br ${project.image.bg} relative overflow-hidden`}>
|
||||
<div class={`absolute inset-0 bg-gradient-to-br ${project.image.bg} group-hover:${project.image.hover} transition-all duration-500`}></div>
|
||||
<div class="absolute bottom-4 left-4 right-4">
|
||||
<div class={`bg-black/50 backdrop-blur-sm rounded px-3 py-1 text-xs font-mono ${project.image.text}`}>
|
||||
{project.title}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tech stack indicators with unified gray styling -->
|
||||
<div class="mt-6 mb-4 flex flex-wrap gap-2">
|
||||
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">React</span>
|
||||
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">Node.js</span>
|
||||
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">MongoDB</span>
|
||||
<div class="p-6 pb-4">
|
||||
<h3 class={`text-xl group-hover:text-${project.color}-400 transition-colors duration-300 flex items-center gap-2 font-bold mb-4`}>
|
||||
<span class={`text-${project.color}-500`}>{project.icon}</span>
|
||||
{project.title}
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Visit project link -->
|
||||
<div class="p-6 pt-2">
|
||||
<a href="#" class="inline-flex items-center text-sm font-medium text-purple-500 hover:text-purple-600 dark:hover:text-purple-400 transition-colors duration-300">
|
||||
{t('project.visit')}
|
||||
<svg class="ml-1 w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- E-Shop Platform Project -->
|
||||
<div class="group overflow-hidden border border-purple-500/20 hover:border-purple-500/40 h-full flex flex-col transition-all duration-500 hover:scale-105 bg-white/10 dark:bg-gray-800/50 backdrop-blur-sm rounded-xl relative">
|
||||
<!-- Project tag - positioned at top right -->
|
||||
<div class="absolute top-4 right-4 z-10">
|
||||
<span class="px-3 py-1 bg-green-100 dark:bg-green-800 text-green-800 dark:text-green-200 text-xs rounded-full font-medium border border-green-200 dark:border-green-700">{t('project.tag.ecommerce')}</span>
|
||||
</div>
|
||||
|
||||
<!-- Project image placeholder -->
|
||||
<div class="h-48 bg-gradient-to-br from-green-500/20 to-green-600/20 relative overflow-hidden">
|
||||
<div class="absolute inset-0 bg-gradient-to-br from-green-500/10 to-green-600/10 group-hover:from-green-500/20 group-hover:to-green-600/20 transition-all duration-500"></div>
|
||||
<div class="absolute bottom-4 left-4 right-4">
|
||||
<div class="bg-black/50 backdrop-blur-sm rounded px-3 py-1 text-xs font-mono text-green-400">
|
||||
电商平台
|
||||
|
||||
<div class="px-6 flex-grow">
|
||||
<div class="space-y-3">
|
||||
{project.description.map((desc) => (
|
||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
||||
<span class={`text-${project.color}-500 mt-1`}>•</span>
|
||||
<span>{desc}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-6 pb-4">
|
||||
<h3 class="text-xl group-hover:text-green-400 transition-colors duration-300 flex items-center gap-2 font-bold mb-4">
|
||||
<span class="text-green-500">🛒</span>
|
||||
电商平台
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div class="px-6 flex-grow">
|
||||
<div class="space-y-3">
|
||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
||||
<span class="text-green-500 mt-1">•</span>
|
||||
<span>使用Next.js、Stripe支付和TailwindCSS构建的可扩展电子商务平台。</span>
|
||||
</div>
|
||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
||||
<span class="text-green-500 mt-1">•</span>
|
||||
<span>采用移动优先的响应式设计,提供最佳用户体验。</span>
|
||||
</div>
|
||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
||||
<span class="text-green-500 mt-1">•</span>
|
||||
<span>集成Stripe支付处理,确保交易安全。</span>
|
||||
</div>
|
||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
||||
<span class="text-green-500 mt-1">•</span>
|
||||
<span>管理员仪表板,用于库存管理和订单处理。</span>
|
||||
|
||||
<!-- Tech stack indicators with unified gray styling -->
|
||||
<div class="mt-6 mb-4 flex flex-wrap gap-2">
|
||||
{project.tech.map((tech) => (
|
||||
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">{tech}</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tech stack indicators with unified gray styling -->
|
||||
<div class="mt-6 mb-4 flex flex-wrap gap-2">
|
||||
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">Next.js</span>
|
||||
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">Stripe</span>
|
||||
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">TailwindCSS</span>
|
||||
<!-- Visit project link -->
|
||||
<div class="p-6 pt-2">
|
||||
<a href={project.link} class={`inline-flex items-center text-sm font-medium text-${project.color}-500 hover:text-${project.color}-600 dark:hover:text-${project.color}-400 transition-colors duration-300`}>
|
||||
{t('project.visit')}
|
||||
<svg class="ml-1 w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Visit project link -->
|
||||
<div class="p-6 pt-2">
|
||||
<a href="#" class="inline-flex items-center text-sm font-medium text-green-500 hover:text-green-600 dark:hover:text-green-400 transition-colors duration-300">
|
||||
{t('project.visit')}
|
||||
<svg class="ml-1 w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Portfolio Site Project -->
|
||||
<div class="group overflow-hidden border border-purple-500/20 hover:border-purple-500/40 h-full flex flex-col transition-all duration-500 hover:scale-105 bg-white/10 dark:bg-gray-800/50 backdrop-blur-sm rounded-xl relative">
|
||||
<!-- Project tag - positioned at top right -->
|
||||
<div class="absolute top-4 right-4 z-10">
|
||||
<span class="px-3 py-1 bg-purple-100 dark:bg-purple-800 text-purple-800 dark:text-purple-200 text-xs rounded-full font-medium border border-purple-200 dark:border-purple-700">{t('project.tag.portfolio')}</span>
|
||||
</div>
|
||||
|
||||
<!-- Project image placeholder -->
|
||||
<div class="h-48 bg-gradient-to-br from-purple-500/20 to-purple-600/20 relative overflow-hidden">
|
||||
<div class="absolute inset-0 bg-gradient-to-br from-purple-500/10 to-purple-600/10 group-hover:from-purple-500/20 group-hover:to-purple-600/20 transition-all duration-500"></div>
|
||||
<div class="absolute bottom-4 left-4 right-4">
|
||||
<div class="bg-black/50 backdrop-blur-sm rounded px-3 py-1 text-xs font-mono text-purple-400">
|
||||
个人作品集网站
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-6 pb-4">
|
||||
<h3 class="text-xl group-hover:text-purple-400 transition-colors duration-300 flex items-center gap-2 font-bold mb-4">
|
||||
<span class="text-purple-500">🌐</span>
|
||||
个人作品集网站
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div class="px-6 flex-grow">
|
||||
<div class="space-y-3">
|
||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
||||
<span class="text-purple-500 mt-1">•</span>
|
||||
<span>展示我的作品的个人作品集,使用HTML、TailwindCSS和Alpine.js构建。</span>
|
||||
</div>
|
||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
||||
<span class="text-purple-500 mt-1">•</span>
|
||||
<span>响应式设计,支持暗黑模式和平滑动画。</span>
|
||||
</div>
|
||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
||||
<span class="text-purple-500 mt-1">•</span>
|
||||
<span>通过最小化JavaScript和高效CSS优化性能。</span>
|
||||
</div>
|
||||
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
|
||||
<span class="text-purple-500 mt-1">•</span>
|
||||
<span>集成博客部分,支持markdown内容管理。</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tech stack indicators with unified gray styling -->
|
||||
<div class="mt-6 mb-4 flex flex-wrap gap-2">
|
||||
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">HTML</span>
|
||||
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">TailwindCSS</span>
|
||||
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">Alpine.js</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Visit project link -->
|
||||
<div class="p-6 pt-2">
|
||||
<a href="#" class="inline-flex items-center text-sm font-medium text-purple-500 hover:text-purple-600 dark:hover:text-purple-400 transition-colors duration-300">
|
||||
{t('project.visit')}
|
||||
<svg class="ml-1 w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
Reference in New Issue
Block a user