import React, { useEffect, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import type { AppDispatch, RootState } from '@/states/store'; import { fetchViewsOrProtocols } from '@/states/patient/viewSelection'; import { setCurrentBodyPart } from '@/states/bodyPartSlice'; // ✅ 独立 SVG 文件(不内联) // import { ReactComponent as HumanSvg } from '@/assets/imgs/VirtualHuman/human.svg'; import HumanSvg from '@/assets/imgs/VirtualHuman/human.svg'; interface HumanBodySvgProps { // 容器样式(覆盖默认的 .human-container) containerStyle?: React.CSSProperties; // SVG 样式(覆盖默认的 .human-svg) svgStyle?: React.CSSProperties; // 自定义类名(追加到默认类名) className?: string; // 完全自定义的内联样式 style?: React.CSSProperties; } const HumanBody: React.FC = ({ containerStyle, svgStyle, className, style }) => { const [activePart, setActivePart] = useState(null); const dispatch = useDispatch(); const currentPatientType = useSelector( (state: RootState) => state.patientType.current ); const bodyPartsState = useSelector( (state: RootState) => state.bodyPart.byPatientType ); const selected = useSelector( (state: RootState) => state.selection.selected ); /** * SVG 统一点击入口(事件委托) */ const handleSvgClick = (e: React.MouseEvent) => { const target = e.target as Element; let serverName; // 情况 1:点在 image 上(少数浏览器) if (target.tagName === 'image') { console.log((target as SVGImageElement).dataset.part); serverName= (target as SVGImageElement).dataset.part; } // 情况 2:点在 g 上 if (target.tagName === 'g') { const image = target.querySelector('image[data-part]'); if (image) { console.log((image as SVGImageElement).dataset.part); serverName= (image as SVGImageElement).dataset.part; } } if (!serverName) return; console.log('点击身体部位:', serverName); setActivePart(serverName); const selectedBodyPart = bodyPartsState.find( (item) => item.body_part_id === serverName ) || null; dispatch(setCurrentBodyPart(selectedBodyPart)); dispatch( fetchViewsOrProtocols({ selection: selected, patientType: currentPatientType?.patient_type_id ?? null, bodyPart: serverName, }) ); }; /** * 控制 SVG 高亮状态 * 不修改 SVG 文件本身 */ useEffect(() => { const svg = document.querySelector( '.human-svg' ) as SVGSVGElement | null; if (!svg) return; // 清空所有状态 svg.querySelectorAll('[id]').forEach((el) => { el.classList.remove('active'); el.classList.add('inactive'); }); if (activePart) { const activeEl = svg.querySelector( `#${CSS.escape(activePart)}` ); activeEl?.classList.remove('inactive'); activeEl?.classList.add('active'); } }, [activePart]); return ( <> {/* ===== 样式(集中在一个文件内)===== */} {/* ===== SVG 容器 ===== */}
); } export default HumanBody;