0.8.0.0
This commit is contained in:
+118
-77
@@ -29,6 +29,8 @@ import {
|
||||
ContextMenuSeparator,
|
||||
ContextMenuTrigger,
|
||||
} from "@/components/ui/context-menu"
|
||||
import { GenerationWarningDialog } from "@/components/tree/generation-warning-dialog"
|
||||
import { isFirstGenerationMember, shouldShowGenerationWarning } from "@/lib/generation-utils"
|
||||
|
||||
// 占位符类型
|
||||
interface PlaceholderMember {
|
||||
@@ -81,8 +83,14 @@ const MemberCard = memo(function MemberCard({
|
||||
canEdit: boolean
|
||||
onOpenAddDialog: (member: FamilyMember, type: RelationType) => void
|
||||
}) {
|
||||
// 代数重新计算警告对话框状态
|
||||
const [showWarningDialog, setShowWarningDialog] = useState(false)
|
||||
const [pendingRelationType, setPendingRelationType] = useState<'father' | 'mother' | null>(null)
|
||||
|
||||
// 判断是否是始祖(使用 rootMemberId 而不是 isFounder 字段)
|
||||
const isFounder = member.id === currentTreeId
|
||||
|
||||
// 判断是否是配偶
|
||||
const isFounder = member.isFounder === true
|
||||
const isSpouse = !member.fatherId && !member.motherId &&
|
||||
member.spouseIds && member.spouseIds.length > 0 &&
|
||||
!isFounder
|
||||
@@ -132,7 +140,8 @@ const MemberCard = memo(function MemberCard({
|
||||
case 'father':
|
||||
params.set('childId', member.id)
|
||||
params.set('gender', 'MALE')
|
||||
params.set('generation', (member.generation - 1).toString())
|
||||
// 如果是第1代成员,新父母的世代也设为1(后端会重新计算所有成员世代)
|
||||
params.set('generation', member.generation === 1 ? '1' : (member.generation - 1).toString())
|
||||
// 如果已有母亲,设为配偶
|
||||
if (member.motherId) {
|
||||
params.set('spouseId', member.motherId)
|
||||
@@ -141,7 +150,8 @@ const MemberCard = memo(function MemberCard({
|
||||
case 'mother':
|
||||
params.set('childId', member.id)
|
||||
params.set('gender', 'FEMALE')
|
||||
params.set('generation', (member.generation - 1).toString())
|
||||
// 如果是第1代成员,新父母的世代也设为1(后端会重新计算所有成员世代)
|
||||
params.set('generation', member.generation === 1 ? '1' : (member.generation - 1).toString())
|
||||
// 如果已有父亲,设为配偶
|
||||
if (member.fatherId) {
|
||||
params.set('spouseId', member.fatherId)
|
||||
@@ -183,14 +193,28 @@ const MemberCard = memo(function MemberCard({
|
||||
}
|
||||
|
||||
const handleAddMember = (type: RelationType) => {
|
||||
// 检查是否需要显示代数重新计算警告
|
||||
if ((type === 'father' || type === 'mother') && shouldShowGenerationWarning(member, type)) {
|
||||
setPendingRelationType(type)
|
||||
setShowWarningDialog(true)
|
||||
return
|
||||
}
|
||||
onOpenAddDialog(member, type)
|
||||
}
|
||||
|
||||
// 确认添加父母后的处理
|
||||
const handleConfirmAddParent = () => {
|
||||
if (pendingRelationType) {
|
||||
onOpenAddDialog(member, pendingRelationType)
|
||||
setPendingRelationType(null)
|
||||
}
|
||||
}
|
||||
|
||||
// 卡片内容
|
||||
const cardContent = (
|
||||
<div className="relative group">
|
||||
<Link href={`/members/${member.id}${typeof window !== 'undefined' ? window.location.search : ''}`}>
|
||||
<ChineseCard variant="default" className={`hover:shadow-lg transition-all cursor-pointer h-full ${cardStyle}`}>
|
||||
<ChineseCard variant="default" className={`hover:shadow-lg transition-all cursor-pointer h-full rounded-xl ${cardStyle}`}>
|
||||
<ChineseCardContent className="px-4 py-3 flex items-center gap-5">
|
||||
<div className="relative flex-shrink-0">
|
||||
<AvatarDisplay
|
||||
@@ -345,73 +369,86 @@ const MemberCard = memo(function MemberCard({
|
||||
|
||||
// 有编辑权限时,包裹右键菜单
|
||||
return (
|
||||
<ContextMenu>
|
||||
<ContextMenuTrigger asChild>
|
||||
{cardContent}
|
||||
</ContextMenuTrigger>
|
||||
<ContextMenuContent className="w-48">
|
||||
<ContextMenuLabel className="text-xs text-muted-foreground">
|
||||
为 {member.fullName} 添加
|
||||
</ContextMenuLabel>
|
||||
<ContextMenuSeparator />
|
||||
|
||||
{canAddFather && (
|
||||
<ContextMenuItem
|
||||
className="gap-2 cursor-pointer"
|
||||
onPointerDown={(e) => {
|
||||
e.preventDefault()
|
||||
handleAddMember('father')
|
||||
}}
|
||||
>
|
||||
<UserPlus className="h-4 w-4 text-blue-500" />
|
||||
添加父亲
|
||||
</ContextMenuItem>
|
||||
)}
|
||||
|
||||
{canAddMother && (
|
||||
<ContextMenuItem
|
||||
className="gap-2 cursor-pointer"
|
||||
onPointerDown={(e) => {
|
||||
e.preventDefault()
|
||||
handleAddMember('mother')
|
||||
}}
|
||||
>
|
||||
<UserPlus className="h-4 w-4 text-pink-500" />
|
||||
添加母亲
|
||||
</ContextMenuItem>
|
||||
)}
|
||||
|
||||
{(canAddFather || canAddMother) && (canAddSpouse || canAddChild) && (
|
||||
<>
|
||||
<ContextMenu>
|
||||
<ContextMenuTrigger asChild>
|
||||
{cardContent}
|
||||
</ContextMenuTrigger>
|
||||
<ContextMenuContent className="w-48">
|
||||
<ContextMenuLabel className="text-xs text-muted-foreground">
|
||||
为 {member.fullName} 添加
|
||||
</ContextMenuLabel>
|
||||
<ContextMenuSeparator />
|
||||
)}
|
||||
|
||||
{canAddSpouse && (
|
||||
<ContextMenuItem
|
||||
className="gap-2 cursor-pointer"
|
||||
onPointerDown={(e) => {
|
||||
e.preventDefault()
|
||||
handleAddMember('spouse')
|
||||
}}
|
||||
>
|
||||
<Users className="h-4 w-4 text-red-500" />
|
||||
添加配偶
|
||||
</ContextMenuItem>
|
||||
)}
|
||||
|
||||
{canAddChild && (
|
||||
<ContextMenuItem
|
||||
className="gap-2 cursor-pointer"
|
||||
onPointerDown={(e) => {
|
||||
e.preventDefault()
|
||||
handleAddMember('child')
|
||||
}}
|
||||
>
|
||||
<Baby className="h-4 w-4 text-green-500" />
|
||||
添加子女
|
||||
</ContextMenuItem>
|
||||
)}
|
||||
</ContextMenuContent>
|
||||
</ContextMenu>
|
||||
|
||||
{canAddFather && (
|
||||
<ContextMenuItem
|
||||
className="gap-2 cursor-pointer"
|
||||
onPointerDown={(e) => {
|
||||
e.preventDefault()
|
||||
handleAddMember('father')
|
||||
}}
|
||||
>
|
||||
<UserPlus className="h-4 w-4 text-blue-500" />
|
||||
添加父亲
|
||||
</ContextMenuItem>
|
||||
)}
|
||||
|
||||
{canAddMother && (
|
||||
<ContextMenuItem
|
||||
className="gap-2 cursor-pointer"
|
||||
onPointerDown={(e) => {
|
||||
e.preventDefault()
|
||||
handleAddMember('mother')
|
||||
}}
|
||||
>
|
||||
<UserPlus className="h-4 w-4 text-pink-500" />
|
||||
添加母亲
|
||||
</ContextMenuItem>
|
||||
)}
|
||||
|
||||
{(canAddFather || canAddMother) && (canAddSpouse || canAddChild) && (
|
||||
<ContextMenuSeparator />
|
||||
)}
|
||||
|
||||
{canAddSpouse && (
|
||||
<ContextMenuItem
|
||||
className="gap-2 cursor-pointer"
|
||||
onPointerDown={(e) => {
|
||||
e.preventDefault()
|
||||
handleAddMember('spouse')
|
||||
}}
|
||||
>
|
||||
<Users className="h-4 w-4 text-red-500" />
|
||||
添加配偶
|
||||
</ContextMenuItem>
|
||||
)}
|
||||
|
||||
{canAddChild && (
|
||||
<ContextMenuItem
|
||||
className="gap-2 cursor-pointer"
|
||||
onPointerDown={(e) => {
|
||||
e.preventDefault()
|
||||
handleAddMember('child')
|
||||
}}
|
||||
>
|
||||
<Baby className="h-4 w-4 text-green-500" />
|
||||
添加子女
|
||||
</ContextMenuItem>
|
||||
)}
|
||||
</ContextMenuContent>
|
||||
</ContextMenu>
|
||||
|
||||
{/* 代数重新计算警告对话框 */}
|
||||
{pendingRelationType && (
|
||||
<GenerationWarningDialog
|
||||
open={showWarningDialog}
|
||||
onOpenChange={setShowWarningDialog}
|
||||
memberName={member.fullName}
|
||||
relationType={pendingRelationType}
|
||||
onConfirm={handleConfirmAddParent}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
})
|
||||
|
||||
@@ -495,14 +532,16 @@ export default function MembersPage() {
|
||||
})
|
||||
}
|
||||
} else if (relationType === "father") {
|
||||
params.set("generation", String(relationDialog.member.generation - 1))
|
||||
// 如果是第1代成员,新父母的世代也设为1(后端会重新计算所有成员世代)
|
||||
params.set("generation", String(relationDialog.member.generation === 1 ? 1 : relationDialog.member.generation - 1))
|
||||
params.set("childId", relationDialog.member.id)
|
||||
params.set("gender", "MALE")
|
||||
if (relationDialog.member.motherId) {
|
||||
params.set("spouseId", relationDialog.member.motherId)
|
||||
}
|
||||
} else if (relationType === "mother") {
|
||||
params.set("generation", String(relationDialog.member.generation - 1))
|
||||
// 如果是第1代成员,新父母的世代也设为1(后端会重新计算所有成员世代)
|
||||
params.set("generation", String(relationDialog.member.generation === 1 ? 1 : relationDialog.member.generation - 1))
|
||||
params.set("childId", relationDialog.member.id)
|
||||
params.set("gender", "FEMALE")
|
||||
if (relationDialog.member.fatherId) {
|
||||
@@ -642,7 +681,8 @@ export default function MembersPage() {
|
||||
// 配偶定义:没有父母但有配偶的成员(嫁入/娶入的成员)
|
||||
// 其他所有成员都应该显示,包括孤立成员
|
||||
const familyMembers = members.filter(m => {
|
||||
const isFounder = m.isFounder === true
|
||||
// 使用 treeData.rootId 判断始祖,而不是 isFounder 字段
|
||||
const isFounder = m.id === treeData.rootId
|
||||
const hasFamilyParents = m.fatherId || m.motherId
|
||||
const hasSpouse = m.spouseIds && m.spouseIds.length > 0
|
||||
|
||||
@@ -661,8 +701,9 @@ export default function MembersPage() {
|
||||
|
||||
// 对家族成员按年龄排序
|
||||
const sortedFamilyMembers = familyMembers.sort((a, b) => {
|
||||
const aIsFounder = a.isFounder === true
|
||||
const bIsFounder = b.isFounder === true
|
||||
// 使用 treeData.rootId 判断始祖
|
||||
const aIsFounder = a.id === treeData.rootId
|
||||
const bIsFounder = b.id === treeData.rootId
|
||||
if (aIsFounder && !bIsFounder) return -1
|
||||
if (!aIsFounder && bIsFounder) return 1
|
||||
|
||||
@@ -689,7 +730,7 @@ export default function MembersPage() {
|
||||
actualCount: actualMemberCount
|
||||
}
|
||||
})
|
||||
}, [filteredMembers])
|
||||
}, [filteredMembers, treeData.rootId])
|
||||
|
||||
const clearFilters = () => {
|
||||
setSelectedSurname("all")
|
||||
@@ -866,7 +907,7 @@ export default function MembersPage() {
|
||||
const params = new URLSearchParams(window.location.search)
|
||||
router.push(`/tree?${params.toString()}`)
|
||||
}}
|
||||
currentTreeId={currentTree?.id}
|
||||
currentTreeId={treeData.rootId || undefined}
|
||||
canEdit={permissions.canCreate(currentTree?.currentUserRole)}
|
||||
onOpenAddDialog={handleOpenAddDialog}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user