Files
photography/frontend/app/page.tsx
xujiang af222afc33 feat: 完成前后端API联调测试并修复配置问题
- 启动后端go-zero API服务 (端口8080)
- 修复前端API配置中的端口号 (8888→8080)
- 完善前端API状态监控组件
- 创建categoryService服务层
- 更新前端数据查询和转换逻辑
- 完成完整API集成测试,验证所有接口正常工作
- 验证用户认证、分类管理、照片管理等核心功能
- 创建API集成测试脚本
- 更新任务进度文档

测试结果:
 后端健康检查正常
 用户认证功能正常 (admin/admin123)
 分类API正常 (5个分类)
 照片API正常 (0张照片,数据库为空)
 前后端API连接完全正常

下一步: 实现照片展示页面和搜索过滤功能
2025-07-11 11:42:14 +08:00

157 lines
5.1 KiB
TypeScript
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.

"use client"
import { useState, useEffect, useMemo } from "react"
import { PhotoGallery } from "@/components/photo-gallery"
import { PhotoModal } from "@/components/photo-modal"
import { Navigation } from "@/components/navigation"
import { FilterBar } from "@/components/filter-bar"
import { LoadingSpinner } from "@/components/loading-spinner"
import { TimelineView } from "@/components/timeline-view"
import { AboutView } from "@/components/about-view"
import { ContactView } from "@/components/contact-view"
import { ApiStatus } from "@/components/api-status"
import { usePhotos, type Photo } from "@/lib/queries"
import { useToast } from "@/components/ui/use-toast"
export default function HomePage() {
const { data: photos = [], isLoading, error } = usePhotos()
const { toast } = useToast()
const [selectedPhoto, setSelectedPhoto] = useState<Photo | null>(null)
const [activeCategory, setActiveCategory] = useState("all")
const [activeTab, setActiveTab] = useState("gallery")
useEffect(() => {
if (error) {
const isRealApi = process.env.NEXT_PUBLIC_USE_REAL_API === 'true'
toast({
title: "数据加载失败",
description: isRealApi
? "无法连接到后端API请确保后端服务正在运行 (localhost:8888)"
: "无法连接到Mock API请确保Mock API正在运行 (localhost:3001)",
variant: "destructive",
})
}
}, [error, toast])
const filteredPhotos = useMemo(() => {
if (activeCategory === "all") {
return photos
}
return photos.filter((photo: Photo) => photo.category === activeCategory)
}, [photos, activeCategory])
const handleFilter = (category: string) => {
setActiveCategory(category)
}
const handlePhotoClick = (photo: Photo) => {
setSelectedPhoto(photo)
}
const handleCloseModal = () => {
setSelectedPhoto(null)
}
const handlePrevPhoto = () => {
if (!selectedPhoto) return
const currentPhotos = activeTab === "gallery" ? filteredPhotos : photos
const currentIndex = currentPhotos.findIndex((p: Photo) => p.id === selectedPhoto.id)
const prevIndex = currentIndex > 0 ? currentIndex - 1 : currentPhotos.length - 1
setSelectedPhoto(currentPhotos[prevIndex])
}
const handleNextPhoto = () => {
if (!selectedPhoto) return
const currentPhotos = activeTab === "gallery" ? filteredPhotos : photos
const currentIndex = currentPhotos.findIndex((p: Photo) => p.id === selectedPhoto.id)
const nextIndex = currentIndex < currentPhotos.length - 1 ? currentIndex + 1 : 0
setSelectedPhoto(currentPhotos[nextIndex])
}
const handleTabChange = (tab: string) => {
setActiveTab(tab)
// Reset filters when switching tabs
if (tab === "timeline") {
setActiveCategory("all")
}
}
const handleContactClick = () => {
setActiveTab("contact")
}
const getPageTitle = () => {
switch (activeTab) {
case "gallery":
return "摄影作品集"
case "timeline":
return "创作时间线"
case "about":
return "关于我"
case "contact":
return "联系合作"
default:
return "摄影作品集"
}
}
const getPageDescription = () => {
switch (activeTab) {
case "gallery":
return "用镜头记录世界的美好瞬间,每一张照片都是时光的诗篇"
case "timeline":
return "按时间顺序回顾摄影创作历程,见证技艺与视角的成长轨迹"
case "about":
return "分享我的摄影故事,探索光影背后的创作理念与人生感悟"
case "contact":
return "期待与您合作,共同创造独特而珍贵的视觉记忆"
default:
return "用镜头记录世界的美好瞬间,每一张照片都是时光的诗篇"
}
}
if (isLoading) {
return <LoadingSpinner />
}
return (
<div className="min-h-screen bg-white">
<Navigation activeTab={activeTab} onTabChange={handleTabChange} />
<main className="container mx-auto px-4 py-8">
{(activeTab === "gallery" || activeTab === "timeline") && (
<div className="text-center mb-12">
<h1 className="text-4xl md:text-6xl font-light text-gray-900 mb-4">{getPageTitle()}</h1>
<p className="text-lg text-gray-600 max-w-2xl mx-auto">{getPageDescription()}</p>
</div>
)}
{activeTab === "gallery" && (
<>
<FilterBar activeCategory={activeCategory} onFilter={handleFilter} />
<PhotoGallery photos={filteredPhotos} onPhotoClick={handlePhotoClick} />
</>
)}
{activeTab === "timeline" && <TimelineView photos={photos} onPhotoClick={handlePhotoClick} />}
{activeTab === "about" && <AboutView onContactClick={handleContactClick} />}
{activeTab === "contact" && <ContactView />}
</main>
{selectedPhoto && (
<PhotoModal
photo={selectedPhoto}
onClose={handleCloseModal}
onPrev={handlePrevPhoto}
onNext={handleNextPhoto}
/>
)}
{/* API状态指示器 - 仅开发环境 */}
<ApiStatus />
</div>
)
}