故事详情排版修改

This commit is contained in:
jiangh277
2025-08-08 17:42:07 +08:00
parent efd3f4a82c
commit 30e9e1c7b2
10 changed files with 501 additions and 172 deletions

View File

@@ -41,7 +41,6 @@ const AddTimeLineItemModal: React.FC<ModalProps> = ({
onOk,
storyId,
initialValues,
storyItemId,
option,
}) => {
const [form] = Form.useForm();
@@ -60,6 +59,7 @@ const AddTimeLineItemModal: React.FC<ModalProps> = ({
const searchInputRef = useRef<InputRef>(null);
useEffect(() => {
console.log(initialValues)
if (initialValues && option.startsWith('edit')) {
form.setFieldsValue({
title: initialValues.title,
@@ -68,7 +68,7 @@ const AddTimeLineItemModal: React.FC<ModalProps> = ({
description: initialValues.description,
});
}
}, [initialValues, option]);
}, [initialValues, option, visible]);
// 获取图库图片
const fetchGalleryImages = async (page: number = 1, keyword: string = '') => {
@@ -80,13 +80,13 @@ const AddTimeLineItemModal: React.FC<ModalProps> = ({
pageSize: pageSize,
keyword: keyword,
});
const images = response.data.list.map((img: any) => ({
const images = response?.data?.list.map((img: any) => ({
instanceId: img.instanceId,
imageName: img.imageName,
url: `/file/image-low-res/${img.instanceId}`,
}));
})) ?? [];
setGalleryImages(images);
setTotal(response.data.total);
setTotal(response?.data?.total ?? 0);
setCurrentPage(page);
} catch (error) {
message.error('获取图库图片失败');
@@ -321,6 +321,7 @@ const AddTimeLineItemModal: React.FC<ModalProps> = ({
onCancel();
}}
width={800}
zIndex={1001}
footer={[
<Button key="back" onClick={onCancel}>

View File

@@ -1,11 +1,7 @@
// TimelineItem.tsx
import TimelineImage from '@/components/TimelineImage';
import { StoryItem } from '@/pages/story/data';
import {
DeleteOutlined,
DownOutlined,
EditOutlined,
UpOutlined,
} from '@ant-design/icons';
import { DeleteOutlined, DownOutlined, EditOutlined, UpOutlined } from '@ant-design/icons';
import { useIntl, useRequest } from '@umijs/max';
import { Button, Card, message, Popconfirm } from 'antd';
import React, { useState } from 'react';
@@ -135,6 +131,7 @@ const TimelineItem: React.FC<{
key={imageInstanceId + index}
title={imageInstanceId}
imageInstanceId={imageInstanceId}
style={{ maxWidth: '100%', height: 'auto' }} // 添加响应式样式
/>
))}
</div>
@@ -169,7 +166,13 @@ const TimelineItem: React.FC<{
</div>
)}
</div>
<TimelineItemDrawer storyItem={item} open={openDetail} setOpen={setOpenDetail} />
<TimelineItemDrawer
storyItem={item}
open={openDetail}
setOpen={setOpenDetail}
handleDelete={handleDelete}
handOption={handleOption}
/>
</Card>
);
};

View File

@@ -1,3 +1,4 @@
// index.style.ts
import { createStyles } from 'antd-style';
const useStyles = createStyles(({ token }) => {
@@ -11,6 +12,17 @@ const useStyles = createStyles(({ token }) => {
'&:hover': {
boxShadow: token.boxShadowSecondary,
},
position: 'relative',
padding: '20px',
maxWidth: '100%',
textAlign: 'left',
maxHeight: '80vh',
scrollBehavior: 'smooth',
scrollbarWidth: 'none',
borderBottom: '1px solid #eee',
[`@media (max-width: 768px)`]: {
padding: '10px',
},
},
actions: {
display: 'flex',
@@ -84,6 +96,23 @@ const useStyles = createStyles(({ token }) => {
flex: 1,
color: token.colorText,
},
timelineItemImages: {
display: 'flex',
flexWrap: 'wrap',
gap: '10px',
marginBottom: '20px',
},
timelineImage: {
maxWidth: '100%',
height: 'auto',
borderRadius: '4px',
overflow: 'hidden',
img: {
width: '100%',
height: 'auto',
objectFit: 'cover',
},
},
};
});

View File

@@ -1,24 +1,24 @@
// src/pages/story/components/TimelineItemDrawer.tsx
import TimelineImage from '@/components/TimelineImage';
import AddTimeLineItemModal from '@/pages/story/components/AddTimeLineItemModal';
import SubTimeLineItemModal from '@/pages/story/components/SubTimeLineItemModal';
import { StoryItem } from '@/pages/story/data';
import { queryStoryItemImages } from '@/pages/story/service';
import { EditOutlined, PlusCircleOutlined } from '@ant-design/icons';
import { useRequest } from '@umijs/max';
import { Button, Drawer, Space } from 'antd';
import { DeleteOutlined, EditOutlined } from '@ant-design/icons';
import { useIntl, useRequest } from '@umijs/max';
import { Button, Divider, Drawer, Popconfirm, Space } from 'antd';
import React, { useEffect } from 'react';
interface Props {
storyItem: StoryItem;
open: boolean;
setOpen: React.Dispatch<React.SetStateAction<boolean>>;
handleDelete: () => void;
handOption: (item: StoryItem, option: 'add' | 'edit' | 'addSubItem' | 'editSubItem') => void;
}
const TimelineItemDrawer = (props: Props) => {
const { storyItem, open, setOpen } = props;
const [editModalVisible, setEditModalVisible] = React.useState(false);
const [openAddSubItemModal, setOpenAddSubItemModal] = React.useState(false);
const [openEditMainItemModal, setOpenEditMainItemModal] = React.useState(false);
const TimelineItemDrawer: React.FC<Props> = (props) => {
const { storyItem, open, setOpen, handleDelete, handOption } = props;
const intl = useIntl();
const { data: imagesList, run } = useRequest(
async (itemId) => {
return await queryStoryItemImages(itemId);
@@ -27,107 +27,144 @@ const TimelineItemDrawer = (props: Props) => {
manual: true,
},
);
useEffect(() => {
if (open) {
run(storyItem.instanceId);
}
}, [open]);
const closeDrawer = () => {
setOpen(false);
};
const handleEditMainItem = (updatedItem: any) => {
const mergedEvent = {
...storyItem,
...updatedItem,
};
setOpenEditMainItemModal(false);
};
const handleAddSubItem = () => {
setOpenAddSubItemModal(false);
// 格式化日期显示
const formatDate = (dateString: string) => {
if (!dateString) return '';
const date = new Date(dateString);
return date.toLocaleString('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
});
};
return (
<div>
{/* 主时间点详情抽屉 */}
<Drawer
width={1000}
width={800}
placement="right"
onClose={closeDrawer}
open={open}
title={storyItem.title}
zIndex={1000}
title={
<div>
<h2 style={{ margin: 0 }}>{storyItem.title}</h2>
<div style={{ fontSize: '14px', color: '#888', marginTop: '4px' }}>
{storyItem.storyItemTime} {storyItem.location ? `${storyItem.location}` : ''}
</div>
</div>
}
footer={
<div style={{ textAlign: 'right' }}>
<Space>
<Button
icon={<PlusCircleOutlined />}
type="primary"
onClick={() => setOpenAddSubItemModal(true)}
icon={<EditOutlined />}
onClick={() => {
return handOption(storyItem, 'edit');
}}
>
</Button>
<Button icon={<EditOutlined />} onClick={() => setEditModalVisible(true)}>
</Button>
<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>
<Button onClick={closeDrawer}></Button>
</Space>
</div>
}
>
<p>
<strong></strong> {storyItem.description}
</p>
<p>
<strong></strong> {storyItem.storyItemTime}
</p>
<p>
<strong></strong> {storyItem.location}
</p>
{/* 封面图 */}
{storyItem.coverInstanceId && (
<>
<p>
<strong></strong>
</p>
<TimelineImage
title={storyItem.title + 'cover'}
imageInstanceId={storyItem.coverInstanceId}
/>
</>
)}
<div style={{ padding: '0 24px' }}>
<div style={{ marginBottom: '24px' }}>
<h3></h3>
<p style={{ fontSize: '16px', lineHeight: '1.6' }}>{storyItem.description}</p>
</div>
{/* 时刻图库 */}
{imagesList && imagesList.length > 0 && (
<>
<p>
<strong></strong>
</p>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '10px', marginBottom: '20px' }}>
{imagesList.map((imageInstanceId, index) => (
<TimelineImage
key={imageInstanceId + index}
title={imageInstanceId}
imageInstanceId={imageInstanceId}
/>
))}
<Divider />
{/* 时刻图库 */}
{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 />
{/* 添加子时间点模态框 */}
<AddTimeLineItemModal
visible={openAddSubItemModal}
onOk={handleAddSubItem}
onCancel={() => setOpenAddSubItemModal(false)}
lineId={storyItem.storyInstanceId}
storyItemId={storyItem.instanceId}
/>
{/* 编辑主时间点模态框 */}
<SubTimeLineItemModal
visible={openEditMainItemModal}
onOk={handleEditMainItem}
onCancel={() => setOpenEditMainItemModal(false)}
initialValues={storyItem}
/>
{/* 创建和更新信息 */}
<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>
<div style={{ flex: '1', minWidth: '200px' }}>
<div style={{ color: '#888', marginBottom: '4px' }}></div>
<div style={{ fontSize: '16px' }}></div>
</div>
</div>
</div>
</div>
</Drawer>
</div>
);