feat: 添加产品经理和全栈开发角色资源文件

初始化产品经理和全栈开发角色的相关资源文件,包括角色定义、知识库、思维模式和执行流程文档
This commit is contained in:
2025-07-21 22:47:16 +08:00
parent 581bd40184
commit ff20f6f23a
104 changed files with 74 additions and 9967 deletions

View File

@ -0,0 +1,160 @@
"use client"
import { useEffect } from "react"
import Image from "next/image"
import { X, ChevronLeft, ChevronRight, Camera, MapPin, Calendar } from "lucide-react"
import { Button } from "@/components/ui/button"
import { Badge } from "@/components/ui/badge"
import { Card, CardContent } from "@/components/ui/card"
interface PhotoModalProps {
photo: any
onClose: () => void
onPrev: () => void
onNext: () => void
}
export function PhotoModal({ photo, onClose, onPrev, onNext }: PhotoModalProps) {
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
switch (e.key) {
case "Escape":
onClose()
break
case "ArrowLeft":
onPrev()
break
case "ArrowRight":
onNext()
break
}
}
document.addEventListener("keydown", handleKeyDown)
document.body.style.overflow = "hidden"
return () => {
document.removeEventListener("keydown", handleKeyDown)
document.body.style.overflow = "unset"
}
}, [onClose, onPrev, onNext])
return (
<div className="fixed inset-0 z-50 bg-black/95 flex items-center justify-center p-4">
{/* Close button */}
<Button
variant="ghost"
size="sm"
className="absolute top-4 right-4 z-10 text-white hover:bg-white/10"
onClick={onClose}
>
<X className="h-6 w-6" />
</Button>
{/* Navigation buttons */}
<Button
variant="ghost"
size="sm"
className="absolute left-4 top-1/2 -translate-y-1/2 z-10 text-white hover:bg-white/10"
onClick={onPrev}
>
<ChevronLeft className="h-8 w-8" />
</Button>
<Button
variant="ghost"
size="sm"
className="absolute right-4 top-1/2 -translate-y-1/2 z-10 text-white hover:bg-white/10"
onClick={onNext}
>
<ChevronRight className="h-8 w-8" />
</Button>
<div className="w-full max-w-7xl mx-auto grid lg:grid-cols-3 gap-6 h-full max-h-[90vh]">
{/* Main image */}
<div className="lg:col-span-2 relative flex items-center justify-center">
<div className="relative w-full h-full max-h-[80vh] flex items-center justify-center">
<Image
src={photo.src || "/placeholder.svg"}
alt={photo.title}
width={1200}
height={800}
className="max-w-full max-h-full object-contain"
priority
/>
</div>
</div>
{/* Photo information */}
<div className="lg:col-span-1 overflow-y-auto">
<Card className="bg-white/95 backdrop-blur-sm">
<CardContent className="p-6">
<div className="space-y-6">
{/* Title and description */}
<div>
<h2 className="text-2xl font-light text-gray-900 mb-2">{photo.title}</h2>
<p className="text-gray-600 leading-relaxed">{photo.description}</p>
</div>
{/* Tags */}
<div>
<h3 className="text-sm font-medium text-gray-900 mb-2"></h3>
<div className="flex flex-wrap gap-2">
{photo.tags.map((tag: string) => (
<Badge key={tag} variant="secondary">
{tag}
</Badge>
))}
</div>
</div>
{/* Date and location */}
<div className="grid grid-cols-1 gap-4">
<div className="flex items-center gap-2 text-gray-600">
<Calendar className="h-4 w-4" />
<span className="text-sm">{photo.date}</span>
</div>
<div className="flex items-center gap-2 text-gray-600">
<MapPin className="h-4 w-4" />
<span className="text-sm">{photo.exif.location}</span>
</div>
</div>
{/* EXIF information */}
<div>
<h3 className="text-sm font-medium text-gray-900 mb-3 flex items-center gap-2">
<Camera className="h-4 w-4" />
</h3>
<div className="space-y-2 text-sm text-gray-600">
<div className="flex justify-between">
<span></span>
<span className="font-medium">{photo.exif.camera}</span>
</div>
<div className="flex justify-between">
<span></span>
<span className="font-medium">{photo.exif.lens}</span>
</div>
<div className="flex justify-between">
<span></span>
<span className="font-medium">{photo.exif.settings}</span>
</div>
</div>
</div>
{/* Keyboard shortcuts */}
<div className="pt-4 border-t border-gray-200">
<h3 className="text-sm font-medium text-gray-900 mb-2"></h3>
<div className="text-xs text-gray-500 space-y-1">
<div>ESC - </div>
<div> - </div>
</div>
</div>
</div>
</CardContent>
</Card>
</div>
</div>
</div>
)
}