2025-08-08 17:42:07 +08:00
|
|
|
// src/pages/story/components/TimelineItemDrawer.tsx
|
2025-07-22 22:52:55 +08:00
|
|
|
import TimelineImage from '@/components/TimelineImage';
|
2025-08-05 19:02:14 +08:00
|
|
|
import { StoryItem } from '@/pages/story/data';
|
|
|
|
|
import { queryStoryItemImages } from '@/pages/story/service';
|
2025-08-08 17:42:07 +08:00
|
|
|
import { DeleteOutlined, EditOutlined } from '@ant-design/icons';
|
|
|
|
|
import { useIntl, useRequest } from '@umijs/max';
|
2025-12-26 15:12:49 +08:00
|
|
|
import { Button, Divider, Drawer, Popconfirm, Space, Tag } from 'antd';
|
2025-07-22 22:52:55 +08:00
|
|
|
import React, { useEffect } from 'react';
|
|
|
|
|
|
2025-12-26 15:12:49 +08:00
|
|
|
// 格式化时间数组为易读格式
|
|
|
|
|
const formatTimeArray = (time: string | number[] | undefined): string => {
|
|
|
|
|
if (!time) return '';
|
2025-12-31 14:30:03 +08:00
|
|
|
|
2025-12-26 15:12:49 +08:00
|
|
|
// 如果是数组格式 [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')}`;
|
|
|
|
|
}
|
2025-12-31 14:30:03 +08:00
|
|
|
|
2025-12-26 15:12:49 +08:00
|
|
|
// 如果已经是字符串格式,直接返回
|
|
|
|
|
return String(time);
|
|
|
|
|
};
|
|
|
|
|
|
2025-07-22 22:52:55 +08:00
|
|
|
interface Props {
|
|
|
|
|
storyItem: StoryItem;
|
|
|
|
|
open: boolean;
|
|
|
|
|
setOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
2025-08-08 17:42:07 +08:00
|
|
|
handleDelete: () => void;
|
|
|
|
|
handOption: (item: StoryItem, option: 'add' | 'edit' | 'addSubItem' | 'editSubItem') => void;
|
2025-12-31 14:30:03 +08:00
|
|
|
disableEdit?: boolean;
|
2025-07-22 22:52:55 +08:00
|
|
|
}
|
|
|
|
|
|
2025-08-08 17:42:07 +08:00
|
|
|
const TimelineItemDrawer: React.FC<Props> = (props) => {
|
|
|
|
|
const { storyItem, open, setOpen, handleDelete, handOption } = props;
|
|
|
|
|
const intl = useIntl();
|
|
|
|
|
|
2025-07-22 22:52:55 +08:00
|
|
|
const { data: imagesList, run } = useRequest(
|
|
|
|
|
async (itemId) => {
|
|
|
|
|
return await queryStoryItemImages(itemId);
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
manual: true,
|
|
|
|
|
},
|
|
|
|
|
);
|
2025-08-08 17:42:07 +08:00
|
|
|
|
2025-07-22 22:52:55 +08:00
|
|
|
useEffect(() => {
|
|
|
|
|
if (open) {
|
2025-08-05 19:02:14 +08:00
|
|
|
run(storyItem.instanceId);
|
2025-07-22 22:52:55 +08:00
|
|
|
}
|
|
|
|
|
}, [open]);
|
2025-08-08 17:42:07 +08:00
|
|
|
|
2025-07-22 22:52:55 +08:00
|
|
|
const closeDrawer = () => {
|
|
|
|
|
setOpen(false);
|
|
|
|
|
};
|
2025-08-08 17:42:07 +08:00
|
|
|
|
|
|
|
|
// 格式化日期显示
|
2025-12-26 15:12:49 +08:00
|
|
|
const formatDate = (dateString: string | number[] | undefined) => {
|
2025-08-08 17:42:07 +08:00
|
|
|
if (!dateString) return '';
|
2025-12-31 14:30:03 +08:00
|
|
|
|
2025-12-26 15:12:49 +08:00
|
|
|
const formattedTime = formatTimeArray(dateString);
|
|
|
|
|
const date = new Date(formattedTime);
|
2025-08-08 17:42:07 +08:00
|
|
|
return date.toLocaleString('zh-CN', {
|
|
|
|
|
year: 'numeric',
|
|
|
|
|
month: '2-digit',
|
|
|
|
|
day: '2-digit',
|
|
|
|
|
hour: '2-digit',
|
|
|
|
|
minute: '2-digit',
|
|
|
|
|
second: '2-digit',
|
|
|
|
|
});
|
2025-07-22 22:52:55 +08:00
|
|
|
};
|
2025-08-08 17:42:07 +08:00
|
|
|
|
2025-07-22 22:52:55 +08:00
|
|
|
return (
|
|
|
|
|
<div>
|
|
|
|
|
{/* 主时间点详情抽屉 */}
|
|
|
|
|
<Drawer
|
2025-08-08 17:42:07 +08:00
|
|
|
width={800}
|
2025-07-22 22:52:55 +08:00
|
|
|
placement="right"
|
2025-08-06 18:41:32 +08:00
|
|
|
onClose={closeDrawer}
|
2025-07-22 22:52:55 +08:00
|
|
|
open={open}
|
2025-08-08 17:42:07 +08:00
|
|
|
zIndex={1000}
|
|
|
|
|
title={
|
|
|
|
|
<div>
|
2025-12-26 15:12:49 +08:00
|
|
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
|
|
|
|
<h2 style={{ margin: 0 }}>{storyItem.title}</h2>
|
|
|
|
|
<div style={{ display: 'flex', gap: '8px' }}>
|
|
|
|
|
{storyItem.createName && (
|
|
|
|
|
<Tag color="blue">
|
|
|
|
|
创建: {storyItem.createName}
|
|
|
|
|
</Tag>
|
|
|
|
|
)}
|
|
|
|
|
{storyItem.updateName && storyItem.updateName !== storyItem.createName && (
|
|
|
|
|
<Tag color="green">
|
|
|
|
|
更新: {storyItem.updateName}
|
|
|
|
|
</Tag>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2025-08-08 17:42:07 +08:00
|
|
|
<div style={{ fontSize: '14px', color: '#888', marginTop: '4px' }}>
|
2025-12-26 15:12:49 +08:00
|
|
|
{formatTimeArray(storyItem.storyItemTime)} {storyItem.location ? `于${storyItem.location}` : ''}
|
2025-08-08 17:42:07 +08:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
}
|
2025-12-31 14:30:03 +08:00
|
|
|
footer={ {disableEdit ??
|
2025-07-22 22:52:55 +08:00
|
|
|
<div style={{ textAlign: 'right' }}>
|
|
|
|
|
<Space>
|
|
|
|
|
<Button
|
2025-08-08 17:42:07 +08:00
|
|
|
icon={<EditOutlined />}
|
|
|
|
|
onClick={() => {
|
|
|
|
|
return handOption(storyItem, 'edit');
|
|
|
|
|
}}
|
2025-07-22 22:52:55 +08:00
|
|
|
>
|
|
|
|
|
编辑
|
|
|
|
|
</Button>
|
2025-08-08 17:42:07 +08:00
|
|
|
<Popconfirm
|
|
|
|
|
title={intl.formatMessage({ id: 'story.deleteConfirm' })}
|
|
|
|
|
description={intl.formatMessage({ id: 'story.deleteConfirmDescription' })}
|
|
|
|
|
onConfirm={(e) => {
|
|
|
|
|
e?.stopPropagation();
|
|
|
|
|
handleDelete();
|
|
|
|
|
}}
|
|
|
|
|
okText={intl.formatMessage({ id: 'story.yes' })}
|
|
|
|
|
cancelText={intl.formatMessage({ id: 'story.no' })}
|
|
|
|
|
>
|
|
|
|
|
<Button
|
|
|
|
|
icon={<DeleteOutlined />}
|
|
|
|
|
danger
|
|
|
|
|
onClick={(e) => e.stopPropagation()}
|
|
|
|
|
aria-label={intl.formatMessage({ id: 'story.delete' })}
|
|
|
|
|
>
|
|
|
|
|
删除
|
|
|
|
|
</Button>
|
|
|
|
|
</Popconfirm>
|
2025-07-22 22:52:55 +08:00
|
|
|
<Button onClick={closeDrawer}>关闭</Button>
|
|
|
|
|
</Space>
|
|
|
|
|
</div>
|
2025-12-31 14:30:03 +08:00
|
|
|
>}}
|
2025-08-08 17:42:07 +08:00
|
|
|
<div style={{ padding: '0 24px' }}>
|
|
|
|
|
<div style={{ marginBottom: '24px' }}>
|
|
|
|
|
<h3>描述</h3>
|
|
|
|
|
<p style={{ fontSize: '16px', lineHeight: '1.6' }}>{storyItem.description}</p>
|
|
|
|
|
</div>
|
2025-07-22 22:52:55 +08:00
|
|
|
|
2025-08-08 17:42:07 +08:00
|
|
|
<Divider />
|
2025-07-22 22:52:55 +08:00
|
|
|
|
2025-08-08 17:42:07 +08:00
|
|
|
{/* 时刻图库 */}
|
|
|
|
|
{imagesList && imagesList.length > 0 && (
|
|
|
|
|
<div style={{ marginBottom: '24px' }}>
|
|
|
|
|
<h3>时刻图库</h3>
|
|
|
|
|
<div
|
|
|
|
|
style={{
|
|
|
|
|
display: 'grid',
|
|
|
|
|
gridTemplateColumns: 'repeat(auto-fill, minmax(150px, 1fr))',
|
|
|
|
|
gap: '16px',
|
|
|
|
|
marginTop: '16px',
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
{imagesList.map((imageInstanceId, index) => (
|
|
|
|
|
<div
|
|
|
|
|
key={imageInstanceId + index}
|
|
|
|
|
style={{
|
|
|
|
|
borderRadius: '8px',
|
|
|
|
|
overflow: 'hidden',
|
|
|
|
|
boxShadow: '0 2px 8px rgba(0,0,0,0.1)',
|
|
|
|
|
aspectRatio: '1/1',
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<TimelineImage
|
|
|
|
|
title={imageInstanceId}
|
|
|
|
|
imageInstanceId={imageInstanceId}
|
|
|
|
|
style={{ width: '100%', height: '100%', objectFit: 'cover' }}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
<Divider />
|
2025-07-22 22:52:55 +08:00
|
|
|
|
2025-08-08 17:42:07 +08:00
|
|
|
{/* 创建和更新信息 */}
|
|
|
|
|
<div style={{ marginBottom: '24px' }}>
|
|
|
|
|
<h3>记录信息</h3>
|
|
|
|
|
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '16px', marginTop: '16px' }}>
|
|
|
|
|
<div style={{ flex: '1', minWidth: '200px' }}>
|
|
|
|
|
<div style={{ color: '#888', marginBottom: '4px' }}>创建时间</div>
|
|
|
|
|
<div style={{ fontSize: '16px' }}>{formatDate(storyItem.createTime)}</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div style={{ flex: '1', minWidth: '200px' }}>
|
|
|
|
|
<div style={{ color: '#888', marginBottom: '4px' }}>更新时间</div>
|
|
|
|
|
<div style={{ fontSize: '16px' }}>{formatDate(storyItem.updateTime)}</div>
|
|
|
|
|
</div>
|
2025-12-26 15:12:49 +08:00
|
|
|
<div style={{ flex: '1', minWidth: '200px' }}>
|
|
|
|
|
<div style={{ color: '#888', marginBottom: '4px' }}>创建人</div>
|
|
|
|
|
<div style={{ fontSize: '16px' }}>{storyItem.createName || '系统用户'}</div>
|
|
|
|
|
</div>
|
2025-08-08 17:42:07 +08:00
|
|
|
<div style={{ flex: '1', minWidth: '200px' }}>
|
|
|
|
|
<div style={{ color: '#888', marginBottom: '4px' }}>更新人</div>
|
2025-12-26 15:12:49 +08:00
|
|
|
<div style={{ fontSize: '16px' }}>{storyItem.updateName || storyItem.createName || '系统用户'}</div>
|
2025-08-08 17:42:07 +08:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2025-07-22 22:52:55 +08:00
|
|
|
</Drawer>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
2025-12-31 14:30:03 +08:00
|
|
|
export default TimelineItemDrawer;
|