import React, { useEffect, useState, useRef } from 'react'; import { useSelector, useDispatch } from 'react-redux'; import { ExtendedBodyPosition } from '../../../states/exam/bodyPositionListSlice'; import { RootState, AppDispatch } from '../../../states/store'; import { message, Badge } from 'antd'; import { CheckOutlined, CloseOutlined } from '@ant-design/icons'; import AppendViewIcon from '@/components/AppendViewIcon'; import ImageViewer from './ImageViewer'; import { getExposedImageUrl, getViewIconUrl } from '../../../API/bodyPosition'; import { manualSelectBodyPositionWithFlowSwitch, autoSelectFirstBodyPosition, } from '@/domain/exam/bodyPositionSelection'; import AppendViewModal from './AppendViewModal'; interface BodyPositionListProps { layout: 'horizontal' | 'vertical'; showAddButton?: boolean; } const BodyPositionList: React.FC = ({ layout, showAddButton = true, }) => { const dispatch = useDispatch(); const currentKey = useSelector( (state: RootState) => state.BusinessFlow.currentKey ); // 🔧 修改:处理单击事件 const handleImageClick = async ( bodyPosition: ExtendedBodyPosition ): Promise => { console.log(`[BodyPositionList] Single-click on: ${bodyPosition.view_name}`); // 单击时,禁止自动流程切换 await manualSelectBodyPositionWithFlowSwitch( bodyPosition, dispatch, currentKey, false // allowFlowSwitch = false(禁止流程切换) ); }; // 🆕 新增:处理双击事件 const handleImageDoubleClick = async ( bodyPosition: ExtendedBodyPosition ): Promise => { console.log(`[BodyPositionList] Double-click on: ${bodyPosition.view_name}`); // 双击时,允许自动流程切换 await manualSelectBodyPositionWithFlowSwitch( bodyPosition, dispatch, currentKey, true // allowFlowSwitch = true(允许流程切换) ); }; const bodyPositions = useSelector( (state: RootState) => state.bodyPositionList.bodyPositions ); const selectedBodyPosition = useSelector( (state: RootState) => state.bodyPositionList.selectedBodyPosition ); // 🔧 修复:使用 ref 跟踪是否已经执行过初始化 // 避免在 judgeImage 等操作导致 bodyPositions 引用改变时重复执行 const hasInitializedRef = useRef(false); useEffect(() => { // 只在第一次体位列表有值时执行自动选择 if (bodyPositions.length > 0 && !hasInitializedRef.current) { hasInitializedRef.current = true; console.log( '[BodyPositionList] Auto-selecting first body position on component mount' ); autoSelectFirstBodyPosition(bodyPositions, dispatch, currentKey).catch( (error) => { message.error( `Failed to auto-select the first body position ${error}` ); } ); } }, [bodyPositions, dispatch, currentKey]); const [isAppendModalOpen, setIsAppendModalOpen] = useState(false); const addBodyPositionClick = (): void => { console.log('[BodyPositionList] Add button clicked'); console.log( '[BodyPositionList] selectedBodyPosition:', selectedBodyPosition ); if (!selectedBodyPosition) { message.warning('请先选择一个体位'); return; } console.log('[BodyPositionList] Opening append modal'); setIsAppendModalOpen(true); }; const handleModalClose = (): void => { setIsAppendModalOpen(false); }; return ( // 父级是flex,这里是grid,grid的高度需要设置为0,并且flex-grow,这样才能不撑开grid
{bodyPositions.map((bodyPosition, index) => (
handleImageClick(bodyPosition)} onDoubleClick={() => handleImageDoubleClick(bodyPosition)} /> {/* 左上角:判断状态badge */} {bodyPosition.dview.expose_status === 'Exposed' && bodyPosition.dview.judged_status && (
) : bodyPosition.dview.judged_status === 'Reject' ? ( ) : 'Un' } style={{ backgroundColor: bodyPosition.dview.judged_status === 'Accept' ? '#52c41a' : '#ff4d4f', borderRadius: '50%', display: 'flex', alignItems: 'center', justifyContent: 'center', }} />
)}
))}
{showAddButton && (
)}
); }; export default BodyPositionList;