This commit is contained in:
freedakgmail
2025-12-22 00:38:20 +08:00
parent 5a604e89f9
commit c2b890994d
9 changed files with 507 additions and 240 deletions
+55 -3
View File
@@ -47,7 +47,7 @@ import type { D3OrgChartRef } from "@/components/tree/d3-org-chart-flow"
type ViewMode = "traditional" | "d3-org-chart"
export default function TreePage() {
const { treeData, currentTree, refreshData } = useFamily()
const { treeData, currentTree, refreshData, highlightedMemberId, setHighlightedMemberId } = useFamily()
const { calculateRelationship } = useRelationship()
const { data: session, status } = useSession()
const { showAlert } = useDialog()
@@ -119,9 +119,14 @@ export default function TreePage() {
const containerRef = useRef<HTMLDivElement>(null)
const d3ChartRef = useRef<D3OrgChartRef>(null)
// 传统族谱初始定位到始祖并自适应缩放
// 传统族谱初始定位到始祖并自适应缩放(如果有高亮成员则跳过)
useEffect(() => {
if (viewMode !== 'traditional' || hasInitialPositioned || !treeData.rootId) return
// 如果有高亮成员,跳过初始定位,让高亮定位逻辑处理
if (highlightedMemberId) {
setHasInitialPositioned(true)
return
}
// 找到始祖成员:优先使用标记为 isFounder 的成员,否则使用 rootId 对应的成员
const founderMember = Object.values(treeData.members).find(m => m.isFounder === true)
@@ -180,7 +185,7 @@ export default function TreePage() {
}, 500)
return () => clearTimeout(timer)
}, [viewMode, treeData.rootId, treeData.members, hasInitialPositioned])
}, [viewMode, treeData.rootId, treeData.members, hasInitialPositioned, highlightedMemberId])
// 切换视图模式时重置初始定位状态和缩放位置
useEffect(() => {
@@ -189,6 +194,53 @@ export default function TreePage() {
setPosition({ x: 0, y: 0 })
}, [viewMode])
// 当有高亮成员时,定位到该成员并居中显示,设置 scale 为 1.0
useEffect(() => {
if (viewMode !== 'traditional' || !highlightedMemberId) return
// 第一步:重置位置和缩放为初始状态
setScale(1)
setPosition({ x: 0, y: 0 })
// 延迟执行,等待 DOM 完全渲染(需要足够长的时间让树完全展开)
const timer = setTimeout(() => {
if (!containerRef.current) {
return
}
// 查找高亮成员的 DOM 元素
const highlightedNode = containerRef.current.querySelector(`[data-member-id="${highlightedMemberId}"]`) as HTMLElement
if (!highlightedNode) {
return
}
const containerRect = containerRef.current.getBoundingClientRect()
const nodeRect = highlightedNode.getBoundingClientRect()
// 计算容器中心
const containerCenterX = containerRect.width / 2
const containerCenterY = containerRect.height / 2
// 此时 position 已经是 {x:0, y:0},所以节点位置就是相对于原点的位置
// 我们需要计算让节点居中的偏移量
const nodeCenterX = nodeRect.left - containerRect.left + nodeRect.width / 2
const nodeCenterY = nodeRect.top - containerRect.top + nodeRect.height / 2
// 计算偏移量
const offsetX = containerCenterX - nodeCenterX
const offsetY = containerCenterY - nodeCenterY
setPosition({ x: offsetX, y: offsetY })
// 30秒后清除高亮状态
setTimeout(() => {
setHighlightedMemberId(null)
}, 30000)
}, 1000) // 增加到1秒,确保DOM完全渲染
return () => clearTimeout(timer)
}, [viewMode, highlightedMemberId, setHighlightedMemberId])
// 传统族谱自适应视图函数
const handleTraditionalFitView = useCallback(() => {
if (!containerRef.current || !treeData.rootId) return