feat(story): 支持多视频上传与展示
Some checks failed
test/timeline-frontend/pipeline/head There was a failure building this commit
Some checks failed
test/timeline-frontend/pipeline/head There was a failure building this commit
1. 在文件服务 API 中新增 `batchGetFileInfo` 接口,支持批量获取文件详情。 2. 优化 `AddTimeLineItemModal` 组件,支持多视频选择、预览、批量上传及进度展示。 3. 改进 `TimelineGridItem` 组件,支持在时间轴列表中展示多个视频及对应的缩略图。 4. 增强视频上传流程,自动生成视频首帧作为缩略图并保存元数据。
This commit is contained in:
@@ -1,11 +1,12 @@
|
||||
// TimelineGridItem.tsx - Grid card layout for timeline items
|
||||
import TimelineImage from '@/components/TimelineImage';
|
||||
import { StoryItem } from '@/pages/story/data';
|
||||
import { batchGetFileInfo, queryStoryItemImages } from '@/services/file/api';
|
||||
import { DeleteOutlined, EditOutlined } from '@ant-design/icons';
|
||||
import { useIntl, useRequest } from '@umijs/max';
|
||||
import { Button, message, Popconfirm, Tag, theme } from 'antd';
|
||||
import React, { useEffect } from 'react';
|
||||
import { queryStoryItemImages, removeStoryItem } from '../service';
|
||||
import { removeStoryItem } from '../service';
|
||||
import TimelineVideo from './TimelineVideo';
|
||||
|
||||
// 格式化时间数组为易读格式
|
||||
@@ -60,9 +61,16 @@ const TimelineGridItem: React.FC<{
|
||||
root.style.setProperty('--timeline-more-color', token.colorWhite);
|
||||
}, [token]);
|
||||
|
||||
const { data: imagesList } = useRequest(
|
||||
const { data: filesInfo } = useRequest(
|
||||
async () => {
|
||||
return await queryStoryItemImages(item.instanceId);
|
||||
const idsResponse = await queryStoryItemImages(item.instanceId);
|
||||
// @ts-ignore
|
||||
const ids = idsResponse.data || idsResponse || [];
|
||||
if (Array.isArray(ids) && ids.length > 0) {
|
||||
const res = await batchGetFileInfo(ids);
|
||||
return res.data || [];
|
||||
}
|
||||
return [];
|
||||
},
|
||||
{
|
||||
refreshDeps: [item.instanceId],
|
||||
@@ -86,7 +94,7 @@ const TimelineGridItem: React.FC<{
|
||||
|
||||
// 动态计算卡片大小(1-4格)
|
||||
const calculateCardSize = () => {
|
||||
const imageCount = imagesList?.length || 0;
|
||||
const imageCount = filesInfo?.length || 0;
|
||||
const descriptionLength = item.description?.length || 0;
|
||||
|
||||
// 根据图片数量和描述长度决定卡片大小
|
||||
@@ -175,30 +183,39 @@ const TimelineGridItem: React.FC<{
|
||||
<p>{truncateText(item.description, descriptionMaxLength)}</p>
|
||||
|
||||
{/* Images preview - 固定间隔,单行展示,多余折叠 */}
|
||||
{item.videoUrl ? (
|
||||
{item.videoUrl || (filesInfo && filesInfo.length > 0) ? (
|
||||
<div className="item-images-container" style={{ marginTop: '10px' }}>
|
||||
<TimelineVideo videoInstanceId={item.videoUrl} thumbnailInstanceId={item.thumbnailUrl} />
|
||||
</div>
|
||||
) : (
|
||||
imagesList &&
|
||||
imagesList.length > 0 && (
|
||||
<div className="item-images-container">
|
||||
{item.videoUrl && (
|
||||
<div style={{ marginBottom: 10 }}>
|
||||
<TimelineVideo
|
||||
videoInstanceId={item.videoUrl}
|
||||
thumbnailInstanceId={item.thumbnailUrl}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{filesInfo && filesInfo.length > 0 && (
|
||||
<div className="item-images-row">
|
||||
{imagesList
|
||||
.filter((imageInstanceId) => imageInstanceId && imageInstanceId.trim() !== '')
|
||||
{filesInfo
|
||||
.slice(0, 6) // 最多显示6张图片
|
||||
.map((imageInstanceId, index) => (
|
||||
<div key={imageInstanceId + index} className="item-image-wrapper">
|
||||
<TimelineImage title={imageInstanceId} imageInstanceId={imageInstanceId} />
|
||||
.map((file, index) => (
|
||||
<div key={file.instanceId + index} className="item-image-wrapper">
|
||||
{file.contentType && file.contentType.startsWith('video') ? (
|
||||
<TimelineVideo
|
||||
videoInstanceId={file.instanceId}
|
||||
thumbnailInstanceId={file.thumbnailInstanceId}
|
||||
/>
|
||||
) : (
|
||||
<TimelineImage title={file.imageName} imageInstanceId={file.instanceId} />
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
{imagesList.length > 6 && (
|
||||
<div className="more-images-indicator">+{imagesList.length - 6}</div>
|
||||
{filesInfo.length > 6 && (
|
||||
<div className="more-images-indicator">+{filesInfo.length - 6}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
)}
|
||||
)}
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{/* Location badge */}
|
||||
{item.location && <span className="timeline-location-badge">📍 {item.location}</span>}
|
||||
|
||||
Reference in New Issue
Block a user