0.7.0.0
This commit is contained in:
+65
-76
@@ -273,17 +273,17 @@ export default function MemberProfilePage() {
|
||||
return (
|
||||
<div className="min-h-screen flex flex-col bg-background">
|
||||
<SiteHeader />
|
||||
<main className="container mx-auto py-8 px-4 md:px-6">
|
||||
<Tabs value={editActiveTab} onValueChange={setEditActiveTab} className="flex flex-col h-[calc(100vh-8rem)]">
|
||||
<main className="container mx-auto py-4 md:py-8 px-3 md:px-6">
|
||||
<Tabs value={editActiveTab} onValueChange={setEditActiveTab} className="flex flex-col h-[calc(100vh-6rem)] md:h-[calc(100vh-8rem)]">
|
||||
{/* 固定头部区域 */}
|
||||
<div className="flex-shrink-0 pb-4 border-b border-border">
|
||||
{/* 返回按钮 */}
|
||||
<BackButton onClick={() => setIsEditing(false)} label="返回" />
|
||||
|
||||
{/* Header Section */}
|
||||
<div className="flex flex-col md:flex-row justify-between items-start gap-6 pb-4">
|
||||
<div className="flex items-start gap-6">
|
||||
<div className="h-24 w-24 rounded-lg bg-muted flex items-center justify-center border-2 border-primary/20 overflow-hidden">
|
||||
<div className="flex flex-col md:flex-row justify-between items-start gap-3 md:gap-6 pb-3 md:pb-4">
|
||||
<div className="flex items-start gap-3 md:gap-6">
|
||||
<div className="h-16 w-16 md:h-24 md:w-24 rounded-lg bg-muted flex items-center justify-center border-2 border-primary/20 overflow-hidden flex-shrink-0">
|
||||
{member.avatarUrl ? (
|
||||
<img
|
||||
src={member.avatarUrl}
|
||||
@@ -292,15 +292,15 @@ export default function MemberProfilePage() {
|
||||
/>
|
||||
) : (
|
||||
member.gender === 'FEMALE' ? (
|
||||
<CircleUserRound className="h-16 w-16 text-pink-400" />
|
||||
<CircleUserRound className="h-10 w-10 md:h-16 md:w-16 text-pink-400" />
|
||||
) : (
|
||||
<CircleUser className="h-16 w-16 text-blue-400" />
|
||||
<CircleUser className="h-10 w-10 md:h-16 md:w-16 text-blue-400" />
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<div className="flex items-center gap-3 mb-2">
|
||||
<h1 className="text-3xl font-bold font-serif text-foreground flex items-center gap-2">
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="flex items-center gap-2 md:gap-3 mb-1 md:mb-2 flex-wrap">
|
||||
<h1 className="text-xl md:text-3xl font-bold font-serif text-foreground flex items-center gap-1 md:gap-2">
|
||||
{member.isFounder && <span className="text-amber-600 text-2xl">👑</span>}
|
||||
<MemberNameWithStatus
|
||||
name={member.fullName}
|
||||
@@ -308,16 +308,16 @@ export default function MemberProfilePage() {
|
||||
/>
|
||||
</h1>
|
||||
{member.isFounder ? (
|
||||
<span className="px-3 py-1 bg-gradient-to-r from-amber-100 to-orange-100 text-amber-800 text-sm font-semibold rounded-full border-2 border-amber-300 shadow-sm">
|
||||
<span className="px-2 md:px-3 py-0.5 md:py-1 bg-gradient-to-r from-amber-100 to-orange-100 text-amber-800 text-xs md:text-sm font-semibold rounded-full border-2 border-amber-300 shadow-sm">
|
||||
始祖 · {member.generation}世
|
||||
</span>
|
||||
) : (
|
||||
<span className="px-2 py-1 bg-primary/10 text-primary text-sm font-medium rounded-full border border-primary/20">
|
||||
<span className="px-1.5 md:px-2 py-0.5 md:py-1 bg-primary/10 text-primary text-xs md:text-sm font-medium rounded-full border border-primary/20">
|
||||
{member.generation}世
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<p className="text-muted-foreground">
|
||||
<p className="text-sm md:text-base text-muted-foreground">
|
||||
{member.isFounder
|
||||
? '修改始祖信息将影响整个家族树'
|
||||
: '更新成员信息'}
|
||||
@@ -345,11 +345,11 @@ export default function MemberProfilePage() {
|
||||
</div>
|
||||
|
||||
{/* Tab 导航栏 */}
|
||||
<TabsList className="flex flex-wrap gap-2 bg-muted/70 p-1 w-fit">
|
||||
<TabsTrigger value="info">基本信息</TabsTrigger>
|
||||
<TabsTrigger value="details">详细资料</TabsTrigger>
|
||||
<TabsTrigger value="photos">生平影像</TabsTrigger>
|
||||
<TabsTrigger value="stories">家族故事</TabsTrigger>
|
||||
<TabsList className="grid grid-cols-4 md:flex md:flex-wrap gap-1 md:gap-2 bg-muted/70 p-1 w-full md:w-fit h-auto">
|
||||
<TabsTrigger value="info" className="text-xs md:text-sm px-2 md:px-3 py-1.5">基本信息</TabsTrigger>
|
||||
<TabsTrigger value="details" className="text-xs md:text-sm px-2 md:px-3 py-1.5">详细资料</TabsTrigger>
|
||||
<TabsTrigger value="photos" className="text-xs md:text-sm px-2 md:px-3 py-1.5">生平影像</TabsTrigger>
|
||||
<TabsTrigger value="stories" className="text-xs md:text-sm px-2 md:px-3 py-1.5">家族故事</TabsTrigger>
|
||||
</TabsList>
|
||||
|
||||
{/* 始祖特殊提示框 */}
|
||||
@@ -396,10 +396,10 @@ export default function MemberProfilePage() {
|
||||
return (
|
||||
<div className="min-h-screen flex flex-col bg-background">
|
||||
<SiteHeader />
|
||||
<main className="container mx-auto py-8 px-4 md:px-6">
|
||||
<Tabs defaultValue="info" className="flex flex-col h-[calc(100vh-8rem)]">
|
||||
<main className="container mx-auto py-4 md:py-8 px-3 md:px-6">
|
||||
<Tabs defaultValue="info" className="flex flex-col h-[calc(100vh-6rem)] md:h-[calc(100vh-8rem)]">
|
||||
{/* 固定头部区域 */}
|
||||
<div className="flex-shrink-0 pb-4 border-b border-border">
|
||||
<div className="flex-shrink-0 pb-3 md:pb-4 border-b border-border">
|
||||
{/* 返回按钮 */}
|
||||
<BackButton
|
||||
onClick={() => router.push(`/members${typeof window !== 'undefined' ? window.location.search : ''}`)}
|
||||
@@ -407,10 +407,10 @@ export default function MemberProfilePage() {
|
||||
/>
|
||||
|
||||
{/* Header Section */}
|
||||
<div className="flex flex-col md:flex-row justify-between items-start gap-6 pb-4">
|
||||
<div className="flex items-start gap-6">
|
||||
<div className="relative group">
|
||||
<div className="h-24 w-24 rounded-lg bg-muted flex items-center justify-center border-2 border-primary/20 overflow-hidden">
|
||||
<div className="flex flex-col md:flex-row justify-between items-start gap-3 md:gap-6 pb-3 md:pb-4">
|
||||
<div className="flex items-start gap-3 md:gap-6">
|
||||
<div className="relative group flex-shrink-0">
|
||||
<div className="h-16 w-16 md:h-24 md:w-24 rounded-lg bg-muted flex items-center justify-center border-2 border-primary/20 overflow-hidden">
|
||||
{avatarBlobUrl ? (
|
||||
<img
|
||||
src={avatarBlobUrl}
|
||||
@@ -419,15 +419,15 @@ export default function MemberProfilePage() {
|
||||
/>
|
||||
) : (
|
||||
member.gender === 'FEMALE' ? (
|
||||
<CircleUserRound className="h-16 w-16 text-pink-400" />
|
||||
<CircleUserRound className="h-10 w-10 md:h-16 md:w-16 text-pink-400" />
|
||||
) : (
|
||||
<CircleUser className="h-16 w-16 text-blue-400" />
|
||||
<CircleUser className="h-10 w-10 md:h-16 md:w-16 text-blue-400" />
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
{permissions.canUpdate(role) && (
|
||||
<label className="absolute inset-0 flex items-center justify-center bg-black/50 opacity-0 group-hover:opacity-100 transition-opacity cursor-pointer rounded-lg">
|
||||
<Camera className="h-6 w-6 text-white" />
|
||||
<Camera className="h-5 w-5 md:h-6 md:w-6 text-white" />
|
||||
<input
|
||||
type="file"
|
||||
accept="image/*"
|
||||
@@ -443,10 +443,10 @@ export default function MemberProfilePage() {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<div className="flex items-center gap-3 mb-2">
|
||||
<h1 className="text-3xl font-bold font-serif text-foreground flex items-center gap-2">
|
||||
{member.isFounder && <span className="text-amber-600 text-2xl">👑</span>}
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="flex items-center gap-2 md:gap-3 mb-1 md:mb-2 flex-wrap">
|
||||
<h1 className="text-xl md:text-3xl font-bold font-serif text-foreground flex items-center gap-1 md:gap-2">
|
||||
{member.isFounder && <span className="text-amber-600 text-lg md:text-2xl">👑</span>}
|
||||
<MemberNameWithStatus
|
||||
name={member.fullName}
|
||||
isDead={!!member.deathDate}
|
||||
@@ -455,16 +455,16 @@ export default function MemberProfilePage() {
|
||||
/>
|
||||
</h1>
|
||||
{member.isFounder ? (
|
||||
<span className="px-3 py-1 bg-gradient-to-r from-amber-100 to-orange-100 text-amber-800 text-sm font-semibold rounded-full border-2 border-amber-300 shadow-sm">
|
||||
<span className="px-2 md:px-3 py-0.5 md:py-1 bg-gradient-to-r from-amber-100 to-orange-100 text-amber-800 text-xs md:text-sm font-semibold rounded-full border-2 border-amber-300 shadow-sm">
|
||||
始祖 · {member.generation}世
|
||||
</span>
|
||||
) : (
|
||||
<span className="px-2 py-1 bg-primary/10 text-primary text-sm font-medium rounded-full border border-primary/20">
|
||||
<span className="px-1.5 md:px-2 py-0.5 md:py-1 bg-primary/10 text-primary text-xs md:text-sm font-medium rounded-full border border-primary/20">
|
||||
{member.generation}世
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex flex-wrap gap-x-4 gap-y-1 text-sm text-muted-foreground">
|
||||
<div className="flex flex-wrap gap-x-2 md:gap-x-4 gap-y-1 text-xs md:text-sm text-muted-foreground">
|
||||
{member.courtesyName && <span>字:{member.courtesyName}</span>}
|
||||
{member.artName && <span>号:{member.artName}</span>}
|
||||
{member.generationName && <span>字辈:{member.generationName}</span>}
|
||||
@@ -473,71 +473,60 @@ export default function MemberProfilePage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-2 flex-wrap">
|
||||
<div className="flex gap-1.5 md:gap-2 flex-wrap">
|
||||
{permissions.canCreate(role) && (
|
||||
<>
|
||||
{!member.isFounder && !member.fatherId && (
|
||||
<Button variant="outline" size="sm" onClick={handleQuickAddFather} className="gap-1">
|
||||
<UserPlus className="h-4 w-4" /> 添加父亲
|
||||
</Button>
|
||||
)}
|
||||
{!member.isFounder && !member.motherId && (
|
||||
<Button variant="outline" size="sm" onClick={handleQuickAddMother} className="gap-1">
|
||||
<UserPlus className="h-4 w-4" /> 添加母亲
|
||||
</Button>
|
||||
)}
|
||||
<Button variant="default" size="sm" onClick={handleQuickAddChild} className="gap-1">
|
||||
<UserPlus className="h-4 w-4" /> 添加子女
|
||||
<Button variant="default" size="sm" onClick={handleQuickAddChild} className="gap-1 text-xs md:text-sm h-7 md:h-8 px-2 md:px-3">
|
||||
<UserPlus className="h-3 w-3 md:h-4 md:w-4" /> <span className="hidden sm:inline">添加</span>子女
|
||||
</Button>
|
||||
<Button variant="secondary" size="sm" onClick={handleQuickAddSpouse} className="gap-1">
|
||||
<UserPlus className="h-4 w-4" /> 添加配偶
|
||||
<Button variant="secondary" size="sm" onClick={handleQuickAddSpouse} className="gap-1 text-xs md:text-sm h-7 md:h-8 px-2 md:px-3">
|
||||
<UserPlus className="h-3 w-3 md:h-4 md:w-4" /> <span className="hidden sm:inline">添加</span>配偶
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
<Button variant="outline" size="icon" onClick={() => window.print()} title="打印">
|
||||
<Printer className="h-4 w-4" />
|
||||
<Button variant="outline" size="icon" onClick={() => window.print()} title="打印" className="h-7 w-7 md:h-8 md:w-8">
|
||||
<Printer className="h-3 w-3 md:h-4 md:w-4" />
|
||||
</Button>
|
||||
<Button variant="outline" size="icon" title="分享">
|
||||
<Share2 className="h-4 w-4" />
|
||||
<Button variant="outline" size="icon" title="分享" className="h-7 w-7 md:h-8 md:w-8">
|
||||
<Share2 className="h-3 w-3 md:h-4 md:w-4" />
|
||||
</Button>
|
||||
{permissions.canUpdate(role) && (
|
||||
<Button variant="outline" size="sm" onClick={() => setIsEditing(true)} className="gap-1">
|
||||
<Edit className="h-4 w-4" /> 编辑
|
||||
<Button variant="outline" size="sm" onClick={() => setIsEditing(true)} className="gap-1 text-xs md:text-sm h-7 md:h-8 px-2 md:px-3">
|
||||
<Edit className="h-3 w-3 md:h-4 md:w-4" /> 编辑
|
||||
</Button>
|
||||
)}
|
||||
{permissions.canDeleteMember(role) && (
|
||||
<Button variant="destructive" size="icon" onClick={handleDelete} title="删除">
|
||||
<Trash className="h-4 w-4" />
|
||||
<Button variant="destructive" size="icon" onClick={handleDelete} title="删除" className="h-7 w-7 md:h-8 md:w-8">
|
||||
<Trash className="h-3 w-3 md:h-4 md:w-4" />
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Tab 导航栏 */}
|
||||
<TabsList className="flex flex-wrap gap-2 bg-muted/70 p-1 w-fit">
|
||||
<TabsTrigger value="info">基本信息</TabsTrigger>
|
||||
<TabsTrigger value="details">详细资料</TabsTrigger>
|
||||
<TabsTrigger value="photos">生平影像</TabsTrigger>
|
||||
<TabsTrigger value="stories">家族故事</TabsTrigger>
|
||||
<TabsTrigger value="history">时间线</TabsTrigger>
|
||||
<TabsList className="grid grid-cols-5 md:flex md:flex-wrap gap-1 md:gap-2 bg-muted/70 p-1 w-full md:w-fit h-auto">
|
||||
<TabsTrigger value="info" className="text-[11px] md:text-sm px-1.5 md:px-3 py-1.5">基本信息</TabsTrigger>
|
||||
<TabsTrigger value="details" className="text-[11px] md:text-sm px-1.5 md:px-3 py-1.5">详细资料</TabsTrigger>
|
||||
<TabsTrigger value="photos" className="text-[11px] md:text-sm px-1.5 md:px-3 py-1.5">生平影像</TabsTrigger>
|
||||
<TabsTrigger value="stories" className="text-[11px] md:text-sm px-1.5 md:px-3 py-1.5">家族故事</TabsTrigger>
|
||||
<TabsTrigger value="history" className="text-[11px] md:text-sm px-1.5 md:px-3 py-1.5">时间线</TabsTrigger>
|
||||
</TabsList>
|
||||
|
||||
{/* 始祖特殊提示框 */}
|
||||
{/* 始祖特殊提示框 - 移动端简化 */}
|
||||
{member.isFounder && (
|
||||
<div className="mt-6 p-6 bg-gradient-to-br from-amber-50 via-orange-50 to-amber-50 border-2 border-amber-400 rounded-xl shadow-md">
|
||||
<div className="flex items-start gap-4">
|
||||
<div className="flex-shrink-0 w-14 h-14 bg-gradient-to-br from-amber-200 to-orange-200 rounded-full flex items-center justify-center shadow-sm">
|
||||
<span className="text-3xl">👑</span>
|
||||
<div className="mt-3 md:mt-6 p-3 md:p-6 bg-gradient-to-br from-amber-50 via-orange-50 to-amber-50 border-2 border-amber-400 rounded-xl shadow-md">
|
||||
<div className="flex items-start gap-2 md:gap-4">
|
||||
<div className="flex-shrink-0 w-10 h-10 md:w-14 md:h-14 bg-gradient-to-br from-amber-200 to-orange-200 rounded-full flex items-center justify-center shadow-sm">
|
||||
<span className="text-xl md:text-3xl">👑</span>
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<h2 className="text-2xl font-serif font-bold text-amber-900 mb-3">
|
||||
<div className="flex-1 min-w-0">
|
||||
<h2 className="text-lg md:text-2xl font-serif font-bold text-amber-900 mb-1 md:mb-3">
|
||||
家族始祖
|
||||
</h2>
|
||||
<p className="text-base text-amber-800 leading-relaxed font-serif">
|
||||
<p className="text-sm md:text-base text-amber-800 leading-relaxed font-serif">
|
||||
此为家族树之<span className="font-bold text-amber-900">始祖</span>,
|
||||
<span className="font-bold text-amber-900">第一世</span>传人。
|
||||
<br />
|
||||
血脉由此而始,世系因此而传。
|
||||
<span className="hidden md:inline"><br />血脉由此而始,世系因此而传。</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -548,10 +537,10 @@ export default function MemberProfilePage() {
|
||||
{/* Tab 内容区域 - 可滚动 */}
|
||||
<div className="flex-1 overflow-y-auto">
|
||||
{/* 基本信息Tab - 包含基本信息和家庭关系 */}
|
||||
<TabsContent value="info" className="mt-6 space-y-6">
|
||||
<TabsContent value="info" className="mt-3 md:mt-6 space-y-4 md:space-y-6">
|
||||
{/* 基本信息 */}
|
||||
<ChineseCard variant="default" cornerOrnament className={`w-full shadow-sm ${cardStyle}`}>
|
||||
<ChineseCardContent className="p-6">
|
||||
<ChineseCardContent className="p-3 md:p-6">
|
||||
<ChineseCardTitle className="text-lg font-serif font-semibold mb-4">基本信息</ChineseCardTitle>
|
||||
<dl className="grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4 gap-x-8 gap-y-4 text-sm">
|
||||
<div>
|
||||
|
||||
+34
-35
@@ -157,50 +157,50 @@ export default function NewMemberPage() {
|
||||
return (
|
||||
<div className="min-h-screen flex flex-col bg-background">
|
||||
<SiteHeader />
|
||||
<main className="container mx-auto py-8 px-4 md:px-6">
|
||||
<Tabs value={activeTab} onValueChange={setActiveTab} className="flex flex-col h-[calc(100vh-8rem)]">
|
||||
<main className="container mx-auto py-4 md:py-8 px-3 md:px-6">
|
||||
<Tabs value={activeTab} onValueChange={setActiveTab} className="flex flex-col h-[calc(100vh-6rem)] md:h-[calc(100vh-8rem)]">
|
||||
{/* 固定头部区域 */}
|
||||
<div className="flex-shrink-0 pb-4 border-b border-border">
|
||||
<div className="flex-shrink-0 pb-3 md:pb-4 border-b border-border">
|
||||
{/* 返回按钮 */}
|
||||
<BackButton onClick={() => router.back()} />
|
||||
|
||||
{/* Header Section */}
|
||||
<div className="flex flex-col md:flex-row justify-between items-start gap-6 pb-4">
|
||||
<div className="flex items-start gap-6">
|
||||
<div className={`h-24 w-24 rounded-lg bg-muted flex items-center justify-center border-2 ${isFirstMember ? 'border-amber-400 bg-amber-50/30' : 'border-primary/20'} overflow-hidden`}>
|
||||
<div className="flex flex-col md:flex-row justify-between items-start gap-3 md:gap-6 pb-3 md:pb-4">
|
||||
<div className="flex items-start gap-3 md:gap-6">
|
||||
<div className={`h-14 w-14 md:h-24 md:w-24 rounded-lg bg-muted flex items-center justify-center border-2 ${isFirstMember ? 'border-amber-400 bg-amber-50/30' : 'border-primary/20'} overflow-hidden flex-shrink-0`}>
|
||||
{isFirstMember ? (
|
||||
<span className="text-4xl">👑</span>
|
||||
<span className="text-2xl md:text-4xl">👑</span>
|
||||
) : (
|
||||
<UserPlus className="h-16 w-16 text-muted-foreground" />
|
||||
<UserPlus className="h-8 w-8 md:h-16 md:w-16 text-muted-foreground" />
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<div className="flex items-center gap-3 mb-2">
|
||||
<h1 className="text-3xl font-bold font-serif text-foreground flex items-center gap-2">
|
||||
{isFirstMember && <span className="text-amber-600 text-2xl">👑</span>}
|
||||
{isFirstMember ? '添加家族始祖' : `添加家族${memberType}`}
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="flex items-center gap-2 md:gap-3 mb-1 md:mb-2 flex-wrap">
|
||||
<h1 className="text-lg md:text-3xl font-bold font-serif text-foreground flex items-center gap-1 md:gap-2">
|
||||
{isFirstMember && <span className="text-amber-600 text-lg md:text-2xl">👑</span>}
|
||||
{isFirstMember ? '添加家族始祖' : `添加${memberType}`}
|
||||
</h1>
|
||||
{isFirstMember && (
|
||||
<span className="px-3 py-1 bg-gradient-to-r from-amber-100 to-orange-100 text-amber-800 text-sm font-semibold rounded-full border-2 border-amber-300 shadow-sm">
|
||||
<span className="px-2 md:px-3 py-0.5 md:py-1 bg-gradient-to-r from-amber-100 to-orange-100 text-amber-800 text-xs md:text-sm font-semibold rounded-full border-2 border-amber-300 shadow-sm">
|
||||
始祖 · 1世
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<p className="text-muted-foreground">
|
||||
<p className="text-xs md:text-base text-muted-foreground">
|
||||
{isFirstMember
|
||||
? '请认真填写始祖信息,这将是家族历史的起点'
|
||||
: `填写${memberType}信息,完善家族树`}
|
||||
? '请认真填写始祖信息'
|
||||
: `填写${memberType}信息`}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-2 flex-wrap">
|
||||
<Button type="button" variant="outline" onClick={() => router.back()}>
|
||||
<div className="flex gap-1.5 md:gap-2 flex-wrap">
|
||||
<Button type="button" variant="outline" onClick={() => router.back()} className="text-xs md:text-sm h-7 md:h-9 px-2 md:px-4">
|
||||
取消
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
className="bg-primary text-primary-foreground hover:bg-primary/90"
|
||||
className="bg-primary text-primary-foreground hover:bg-primary/90 text-xs md:text-sm h-7 md:h-9 px-2 md:px-4"
|
||||
onClick={() => {
|
||||
const form = document.querySelector('form')
|
||||
if (form) {
|
||||
@@ -214,29 +214,28 @@ export default function NewMemberPage() {
|
||||
</div>
|
||||
|
||||
{/* Tab 导航栏 */}
|
||||
<TabsList className="flex flex-wrap gap-2 bg-muted/70 p-1 w-fit">
|
||||
<TabsTrigger value="info">基本信息</TabsTrigger>
|
||||
<TabsTrigger value="details">详细资料</TabsTrigger>
|
||||
<TabsTrigger value="photos">生平影像</TabsTrigger>
|
||||
<TabsTrigger value="stories">家族故事</TabsTrigger>
|
||||
<TabsList className="grid grid-cols-4 md:flex md:flex-wrap gap-1 md:gap-2 bg-muted/70 p-1 w-full md:w-fit h-auto">
|
||||
<TabsTrigger value="info" className="text-xs md:text-sm px-2 md:px-3 py-1.5">基本信息</TabsTrigger>
|
||||
<TabsTrigger value="details" className="text-xs md:text-sm px-2 md:px-3 py-1.5">详细资料</TabsTrigger>
|
||||
<TabsTrigger value="photos" className="text-xs md:text-sm px-2 md:px-3 py-1.5">生平影像</TabsTrigger>
|
||||
<TabsTrigger value="stories" className="text-xs md:text-sm px-2 md:px-3 py-1.5">家族故事</TabsTrigger>
|
||||
</TabsList>
|
||||
|
||||
{/* 始祖特殊提示框 */}
|
||||
{/* 始祖特殊提示框 - 移动端简化 */}
|
||||
{isFirstMember && (
|
||||
<div className="mt-6 p-6 bg-gradient-to-br from-amber-50 via-orange-50 to-amber-50 border-2 border-amber-400 rounded-xl shadow-md">
|
||||
<div className="flex items-start gap-4">
|
||||
<div className="flex-shrink-0 w-14 h-14 bg-gradient-to-br from-amber-200 to-orange-200 rounded-full flex items-center justify-center shadow-sm">
|
||||
<span className="text-3xl">👑</span>
|
||||
<div className="mt-3 md:mt-6 p-3 md:p-6 bg-gradient-to-br from-amber-50 via-orange-50 to-amber-50 border-2 border-amber-400 rounded-xl shadow-md">
|
||||
<div className="flex items-start gap-2 md:gap-4">
|
||||
<div className="flex-shrink-0 w-10 h-10 md:w-14 md:h-14 bg-gradient-to-br from-amber-200 to-orange-200 rounded-full flex items-center justify-center shadow-sm">
|
||||
<span className="text-xl md:text-3xl">👑</span>
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<h2 className="text-2xl font-serif font-bold text-amber-900 mb-3">
|
||||
<div className="flex-1 min-w-0">
|
||||
<h2 className="text-lg md:text-2xl font-serif font-bold text-amber-900 mb-1 md:mb-3">
|
||||
立家族之根基
|
||||
</h2>
|
||||
<p className="text-base text-amber-800 leading-relaxed font-serif">
|
||||
<p className="text-sm md:text-base text-amber-800 leading-relaxed font-serif">
|
||||
此为家族树之<span className="font-bold text-amber-900">始祖</span>,
|
||||
<span className="font-bold text-amber-900">第一世</span>传人。
|
||||
<br />
|
||||
血脉由此而始,世系因此而传。
|
||||
<span className="hidden md:inline"><br />血脉由此而始,世系因此而传。</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+5
-13
@@ -38,33 +38,25 @@ interface PlaceholderMember {
|
||||
|
||||
type MemberOrPlaceholder = FamilyMember | PlaceholderMember
|
||||
|
||||
// 提取占位符生成逻辑为独立函数
|
||||
function addPlaceholdersToFamilyUnit(
|
||||
// 提取配偶添加逻辑为独立函数(移除占位符,让卡片自然流动排列)
|
||||
function addSpousesToFamilyUnit(
|
||||
member: FamilyMember,
|
||||
spouses: FamilyMember[],
|
||||
processedSpouses: Set<string>
|
||||
): MemberOrPlaceholder[] {
|
||||
const result: MemberOrPlaceholder[] = [member]
|
||||
let familyUnitSize = 1 // 主成员自己
|
||||
|
||||
// 添加配偶
|
||||
// 添加配偶(紧跟在主成员后面)
|
||||
if (member.spouseIds && member.spouseIds.length > 0) {
|
||||
member.spouseIds.forEach(spouseId => {
|
||||
const spouse = spouses.find(m => m.id === spouseId)
|
||||
if (spouse && !processedSpouses.has(spouseId)) {
|
||||
result.push(spouse)
|
||||
processedSpouses.add(spouseId)
|
||||
familyUnitSize++
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 计算需要添加的占位符数量,确保填满4的倍数
|
||||
const placeholdersNeeded = (4 - (familyUnitSize % 4)) % 4
|
||||
for (let i = 0; i < placeholdersNeeded; i++) {
|
||||
result.push({ id: `placeholder-${member.id}-${i}`, isPlaceholder: true })
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -679,12 +671,12 @@ export default function MembersPage() {
|
||||
return aDate.localeCompare(bDate)
|
||||
})
|
||||
|
||||
// 使用优化后的函数添加配偶和占位符
|
||||
// 添加配偶(紧跟在主成员后面,不使用占位符)
|
||||
const result: MemberOrPlaceholder[] = []
|
||||
const processedSpouses = new Set<string>()
|
||||
|
||||
sortedFamilyMembers.forEach(member => {
|
||||
const familyUnit = addPlaceholdersToFamilyUnit(member, members, processedSpouses)
|
||||
const familyUnit = addSpousesToFamilyUnit(member, members, processedSpouses)
|
||||
result.push(...familyUnit)
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user