0.0.0.4
This commit is contained in:
@@ -9,9 +9,11 @@ import { Input } from "@/components/ui/input"
|
||||
import { Label } from "@/components/ui/label"
|
||||
import { Textarea } from "@/components/ui/textarea"
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
|
||||
import { CalendarIcon, User, Scroll, Users } from "lucide-react"
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
|
||||
import { CalendarIcon, User, Scroll, Users, Images, BookOpen } from "lucide-react"
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
||||
import { ImageUpload } from "@/components/ui/image-upload"
|
||||
import { PhotoGallery } from "./photo-gallery"
|
||||
import { StoryManager } from "./story-manager"
|
||||
|
||||
interface MemberFormProps {
|
||||
initialData?: Partial<FamilyMember>
|
||||
@@ -110,6 +112,42 @@ export function MemberForm({ initialData, existingMembers = [], onSubmit, onCanc
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Circular Reference Detection (循环引用检测)
|
||||
if (formData.fatherId || formData.motherId) {
|
||||
const visited = new Set<string>()
|
||||
const checkCircular = (memberId: string): boolean => {
|
||||
if (memberId === formData.id) return true
|
||||
if (visited.has(memberId)) return false
|
||||
visited.add(memberId)
|
||||
|
||||
const member = existingMembers.find((m) => m.id === memberId)
|
||||
if (!member) return false
|
||||
|
||||
if (member.fatherId && checkCircular(member.fatherId)) return true
|
||||
if (member.motherId && checkCircular(member.motherId)) return true
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
if (formData.fatherId && checkCircular(formData.fatherId)) {
|
||||
newErrors.push("检测到循环引用:不能将自己的后代设置为父亲")
|
||||
}
|
||||
if (formData.motherId && checkCircular(formData.motherId)) {
|
||||
newErrors.push("检测到循环引用:不能将自己的后代设置为母亲")
|
||||
}
|
||||
}
|
||||
|
||||
// 5. Self-Reference Detection (自我引用检测)
|
||||
if (formData.fatherId === formData.id) {
|
||||
newErrors.push("不能将自己设置为自己的父亲")
|
||||
}
|
||||
if (formData.motherId === formData.id) {
|
||||
newErrors.push("不能将自己设置为自己的母亲")
|
||||
}
|
||||
if (formData.spouseIds?.includes(formData.id || "")) {
|
||||
newErrors.push("不能将自己设置为自己的配偶")
|
||||
}
|
||||
|
||||
setErrors(newErrors)
|
||||
return newErrors.length === 0
|
||||
}
|
||||
@@ -297,6 +335,58 @@ export function MemberForm({ initialData, existingMembers = [], onSubmit, onCanc
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Contact Information */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2 text-lg font-serif">
|
||||
<User className="h-5 w-5" />
|
||||
联系方式 (Contact Information)
|
||||
</CardTitle>
|
||||
<CardDescription>在世成员的联系方式</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="phone">手机号 (Mobile Phone)</Label>
|
||||
<Input
|
||||
id="phone"
|
||||
type="tel"
|
||||
value={formData.phone || ""}
|
||||
onChange={(e) => handleChange("phone", e.target.value)}
|
||||
placeholder="e.g. 13800138000"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="telephone">固定电话 (Telephone)</Label>
|
||||
<Input
|
||||
id="telephone"
|
||||
type="tel"
|
||||
value={formData.telephone || ""}
|
||||
onChange={(e) => handleChange("telephone", e.target.value)}
|
||||
placeholder="e.g. 0592-1234567"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="email">邮箱 (Email)</Label>
|
||||
<Input
|
||||
id="email"
|
||||
type="email"
|
||||
value={formData.email || ""}
|
||||
onChange={(e) => handleChange("email", e.target.value)}
|
||||
placeholder="e.g. example@email.com"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2 md:col-span-2">
|
||||
<Label htmlFor="address">现居地址 (Address)</Label>
|
||||
<Input
|
||||
id="address"
|
||||
value={formData.address || ""}
|
||||
onChange={(e) => handleChange("address", e.target.value)}
|
||||
placeholder="e.g. 福建省厦门市思明区XX路XX号"
|
||||
/>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Biography */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
@@ -315,6 +405,40 @@ export function MemberForm({ initialData, existingMembers = [], onSubmit, onCanc
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Photo Gallery */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2 text-lg font-serif">
|
||||
<Images className="h-5 w-5" />
|
||||
照片墙 (Photo Gallery)
|
||||
</CardTitle>
|
||||
<CardDescription>上传多张照片记录珍贵时刻</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<PhotoGallery
|
||||
photoIds={formData.photoIds || []}
|
||||
onChange={(photoIds) => handleChange("photoIds", photoIds)}
|
||||
/>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Family Stories */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2 text-lg font-serif">
|
||||
<BookOpen className="h-5 w-5" />
|
||||
家族故事 (Family Stories)
|
||||
</CardTitle>
|
||||
<CardDescription>记录与此成员相关的家族故事</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<StoryManager
|
||||
stories={formData.stories || []}
|
||||
onChange={(stories) => handleChange("stories", stories)}
|
||||
/>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Relationships */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
|
||||
Reference in New Issue
Block a user