// TimelineItem.tsx import TimelineImage from '@/components/TimelineImage'; import { StoryItem } from '@/pages/story/data'; import { DeleteOutlined, DownOutlined, EditOutlined, UpOutlined } from '@ant-design/icons'; import { useIntl, useRequest } from '@umijs/max'; import { Button, Card, message, Popconfirm, Tag, Space } from 'antd'; import React, { useState } from 'react'; import { queryStoryItemImages, removeStoryItem } from '../../service'; import TimelineItemDrawer from '../TimelineItemDrawer'; import useStyles from './index.style'; import ResponsiveGrid from '@/components/ResponsiveGrid'; // 格式化时间数组为易读格式 const formatTimeArray = (time: string | number[] | undefined): string => { if (!time) return ''; // 如果是数组格式 [2025, 12, 23, 8, 55, 39] if (Array.isArray(time)) { const [year, month, day, hour, minute, second] = time; return `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')} ${String(hour).padStart(2, '0')}:${String(minute).padStart(2, '0')}:${String(second).padStart(2, '0')}`; } // 如果已经是字符串格式,直接返回 return String(time); }; const TimelineItem: React.FC<{ item: StoryItem; handleOption: (item: StoryItem, option: 'add' | 'edit' | 'addSubItem' | 'editSubItem') => void; refresh: () => void; disableEdit?: boolean; }> = ({ item, handleOption, refresh, disableEdit }) => { const { styles, cx, isMobile } = useStyles(); const intl = useIntl(); const [expanded, setExpanded] = useState(false); const [showActions, setShowActions] = useState(false); const [subItemsExpanded, setSubItemsExpanded] = useState(false); const [openDetail, setOpenDetail] = useState(false); const [hovered, setHovered] = useState(false); const { data: imagesList } = useRequest(async () => { return await queryStoryItemImages(item.instanceId); }, { refreshDeps: [item.instanceId] }); const handleDelete = async () => { try { if (!item.instanceId) return; const response = await removeStoryItem(item.instanceId); if (response.code === 200) { message.success(intl.formatMessage({ id: 'story.deleteSuccess' })); refresh(); } else { message.error(intl.formatMessage({ id: 'story.deleteFailed' })); } } catch (error) { message.error(intl.formatMessage({ id: 'story.deleteFailed' })); } }; const toggleDescription = () => { setExpanded(!expanded); }; const toggleSubItems = () => { setSubItemsExpanded(!subItemsExpanded); }; const displayedDescription = expanded ? item.description : item.description?.substring(0, 100) + (item.description && item.description.length > 100 ? '...' : ''); return (
{item.title}
{item.createName && ( 创建: {item.createName} )} {item.updateName && item.updateName !== item.createName && ( 更新: {item.updateName} )} } onMouseEnter={() => { setShowActions(true); setHovered(true); }} onMouseLeave={() => { setShowActions(false); setHovered(false); }} extra={
{(showActions || isMobile) && !disableEdit && ( <>
} hoverable >
setOpenDetail(true)}> {formatTimeArray(item.storyItemTime)} {item.location && 📍 {item.location}}
setOpenDetail(true)}> {displayedDescription} {item.description && item.description.length > 100 && ( )}
{imagesList && imagesList.length > 0 && (
{imagesList.map((imageInstanceId, index) => ( ))}
)} {item.subItems && item.subItems.length > 0 && (
{ e.stopPropagation(); toggleSubItems(); }} > {intl.formatMessage({ id: 'story.subItems' })} ({item.subItems.length}) {subItemsExpanded ? : }
{subItemsExpanded && (
{item.subItems.map((subItem) => (
{formatTimeArray(item.storyItemTime)} {item.location ? `创建于${item.location}` : ''}
{subItem.description}
))}
)}
)}
); }; export default TimelineItem;