From 182a58d0dbe6cd496e93c57022145e799d0d2921 Mon Sep 17 00:00:00 2001 From: jiangh277 Date: Wed, 6 Aug 2025 18:41:32 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E7=BC=A9=E7=95=A5=E5=9B=BE?= =?UTF-8?q?=E5=8A=A0=E8=BD=BD=EF=BC=8C=E6=95=85=E4=BA=8B=E9=A1=B9=E6=96=B0?= =?UTF-8?q?=E5=BB=BA=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Hooks/useFetchImageUrl.ts | 4 +- src/components/TimelineImage/index.tsx | 17 +- src/pages/gallery/components/GalleryTable.tsx | 6 +- src/pages/gallery/components/GridView.tsx | 12 +- src/pages/gallery/components/ListView.tsx | 5 +- src/pages/gallery/index.tsx | 247 ++++++++------- .../story/components/AddTimeLineItemModal.tsx | 295 +++++++++++++++--- .../components/TimelineItem/TimelineItem.tsx | 61 ++-- .../story/components/TimelineItemDrawer.tsx | 5 +- src/pages/story/detail.tsx | 17 +- src/services/file/api.ts | 8 +- 11 files changed, 448 insertions(+), 229 deletions(-) diff --git a/src/components/Hooks/useFetchImageUrl.ts b/src/components/Hooks/useFetchImageUrl.ts index 3f8aa4d..4f7e8d3 100644 --- a/src/components/Hooks/useFetchImageUrl.ts +++ b/src/components/Hooks/useFetchImageUrl.ts @@ -1,12 +1,12 @@ -import { fetchImage } from '@/pages/story/service'; import { useRequest } from '@umijs/max'; import { useEffect, useState } from 'react'; +import {fetchImageLowRes} from "@/services/file/api"; const useFetchImageUrl = (imageInstanceId: string) => { const [imageUrl, setImageUrl] = useState("error"); const { data: response, run, loading } = useRequest( () => { - return fetchImage(imageInstanceId); + return fetchImageLowRes(imageInstanceId); }, { manual: true, diff --git a/src/components/TimelineImage/index.tsx b/src/components/TimelineImage/index.tsx index 33db07c..d86a9b3 100644 --- a/src/components/TimelineImage/index.tsx +++ b/src/components/TimelineImage/index.tsx @@ -1,7 +1,6 @@ import useFetchImageUrl from '@/components/Hooks/useFetchImageUrl'; import { Image } from 'antd'; -import React, { useState, useEffect } from 'react'; -import { LoadingOutlined } from "@ant-design/icons"; +import React, { useState } from 'react'; interface ImageItem { instanceId: string; @@ -28,18 +27,18 @@ const TimelineImage: React.FC = (props) => { width = 200, height = 200, imageList = [], - currentIndex = 0 + currentIndex = 0, } = props; const { imageUrl, loading } = useFetchImageUrl(imageInstanceId ?? ''); const [previewVisible, setPreviewVisible] = useState(false); // 构建预览列表 - imageList.map(item => ({ + imageList.map((item) => ({ src: item.instanceId, - title: item.imageName + title: item.imageName, })); -// 预览配置 + // 预览配置 const previewConfig = { visible: previewVisible, onVisibleChange: (visible: boolean) => setPreviewVisible(visible), @@ -50,8 +49,10 @@ const TimelineImage: React.FC = (props) => {
{title} = ({ style={{ width: 100, height: 100, - backgroundImage: `url(/file/image/${record.instanceId})`, + backgroundImage: `url(/file/image-low-res/${record.instanceId})`, backgroundSize: 'cover', backgroundPosition: 'center', backgroundRepeat: 'no-repeat', diff --git a/src/pages/gallery/components/GridView.tsx b/src/pages/gallery/components/GridView.tsx index 5b6a73d..16a829e 100644 --- a/src/pages/gallery/components/GridView.tsx +++ b/src/pages/gallery/components/GridView.tsx @@ -77,6 +77,16 @@ const GridView: FC = ({ [imageList, onPreview, onDownload, onDelete], ); + // 根据视图模式确定图像 URL + const getImageUrl = (instanceId: string) => { + // 小图模式使用低分辨率图像 + if (viewMode === 'small') { + return `/file/image-low-res/${instanceId}`; + } + // 其他模式使用原图 + return `/file/image/${instanceId}`; + }; + return (
= ({ style={{ width: imageSize.width, height: imageSize.height, - backgroundImage: `url(/file/image/${item.instanceId})`, + backgroundImage: `url(${getImageUrl(item.instanceId)})`, backgroundSize: 'cover', backgroundPosition: 'center', backgroundRepeat: 'no-repeat', diff --git a/src/pages/gallery/components/ListView.tsx b/src/pages/gallery/components/ListView.tsx index e05dd79..2c3a385 100644 --- a/src/pages/gallery/components/ListView.tsx +++ b/src/pages/gallery/components/ListView.tsx @@ -1,10 +1,9 @@ -// src/pages/gallery/components/ListView.tsx +import { ImageItem } from '@/pages/gallery/typings'; import { formatBytes } from '@/utils/timelineUtils'; import { DeleteOutlined, DownloadOutlined, EyeOutlined } from '@ant-design/icons'; import { Button, Card, Checkbox, Spin } from 'antd'; import React, { FC } from 'react'; -import '../index.css' -import {ImageItem} from "@/pages/gallery/typings"; +import '../index.css'; interface ListViewProps { imageList: ImageItem[]; diff --git a/src/pages/gallery/index.tsx b/src/pages/gallery/index.tsx index 3dd5123..d6d3818 100644 --- a/src/pages/gallery/index.tsx +++ b/src/pages/gallery/index.tsx @@ -1,17 +1,17 @@ // src/pages/gallery/index.tsx -import React, { FC, useState, useMemo, useCallback, useEffect } from 'react'; -import { PageContainer } from "@ant-design/pro-components"; -import { useRequest } from "@umijs/max"; -import { getImagesList, deleteImage, uploadImage } from "@/services/file/api"; -import { Empty, Spin, Image, message, Modal } from 'antd'; +import { ImageItem } from '@/pages/gallery/typings'; +import { deleteImage, getImagesList, uploadImage } from '@/services/file/api'; +import { PageContainer } from '@ant-design/pro-components'; +import { useRequest } from '@umijs/max'; import type { RadioChangeEvent } from 'antd'; +import { Empty, Image, message, Modal, Spin } from 'antd'; import type { UploadFile } from 'antd/es/upload/interface'; +import React, { FC, useCallback, useEffect, useMemo, useState } from 'react'; +import GalleryTable from './components/GalleryTable'; import GalleryToolbar from './components/GalleryToolbar'; import GridView from './components/GridView'; import ListView from './components/ListView'; -import GalleryTable from './components/GalleryTable'; -import './index.css' -import { ImageItem } from "@/pages/gallery/typings"; +import './index.css'; const Gallery: FC = () => { const [viewMode, setViewMode] = useState<'small' | 'large' | 'list' | 'table'>('small'); @@ -21,28 +21,32 @@ const Gallery: FC = () => { const [selectedRowKeys, setSelectedRowKeys] = useState([]); const [batchMode, setBatchMode] = useState(false); const [uploading, setUploading] = useState(false); - const pageSize = 5; - const initPagination = { current: 1, pageSize: 5 } + const pageSize = 50; + const initPagination = { current: 1, pageSize: 5 }; // 表格模式使用不同的分页状态 const [tablePagination, setTablePagination] = useState(initPagination); // 非表格模式的数据请求 - const { data, loading, loadingMore, refresh } = useRequest(() => { - return getImagesList({ current: page, pageSize }); - }, { - loadMore: true, - refreshDeps: [page], - ready: viewMode !== 'table' // 非表格模式才启用 - }); + const { data, loading, loadingMore, refresh } = useRequest( + () => { + return getImagesList({ current: page, pageSize }); + }, + { + loadMore: true, + refreshDeps: [page], + ready: viewMode !== 'table', // 非表格模式才启用 + }, + ); // 表格模式的数据请求 - const { data: tableData, loading: tableLoading, run: fetchTableData } = useRequest( - async (params) => await getImagesList(params), - { - manual: true, - } - ); + const { + data: tableData, + loading: tableLoading, + run: fetchTableData, + } = useRequest(async (params) => await getImagesList(params), { + manual: true, + }); // 当视图模式改变时重置分页 const handleViewModeChange = (e: RadioChangeEvent) => { @@ -63,18 +67,21 @@ const Gallery: FC = () => { }; // 处理表格分页变化 - const handleTableChange = useCallback((pagination: any) => { - const { current, pageSize } = pagination; - setTablePagination({ current, pageSize }); - fetchTableData({ current: current, pageSize }); - }, [fetchTableData]); + const handleTableChange = useCallback( + (pagination: any) => { + const { current, pageSize } = pagination; + setTablePagination({ current, pageSize }); + fetchTableData({ current: current, pageSize }); + }, + [fetchTableData], + ); // 当表格分页变化时重新获取数据 useEffect(() => { if (viewMode === 'table') { fetchTableData({ current: tablePagination.current, - pageSize: tablePagination.pageSize + pageSize: tablePagination.pageSize, }); } }, [viewMode, tablePagination, fetchTableData]); @@ -86,17 +93,20 @@ const Gallery: FC = () => { return data?.list || []; }, [data, tableData, viewMode]); - const handleScroll = useCallback((e: React.UIEvent) => { - // 表格模式不需要滚动加载 - if (viewMode === 'table') return; + const handleScroll = useCallback( + (e: React.UIEvent) => { + // 表格模式不需要滚动加载 + if (viewMode === 'table') return; - const { scrollTop, scrollHeight, clientHeight } = e.currentTarget; - if (scrollTop + clientHeight >= scrollHeight - 10 && !loading && !loadingMore) { - if (data?.total && imageList.length < data.total) { - setPage(prev => prev + 1); + const { scrollTop, scrollHeight, clientHeight } = e.currentTarget; + if (scrollTop + clientHeight >= scrollHeight - 10 && !loading && !loadingMore) { + if (data?.total && imageList.length < data.total) { + setPage((prev) => prev + 1); + } } - } - }, [loading, loadingMore, data?.total, imageList.length, viewMode]); + }, + [loading, loadingMore, data?.total, imageList.length, viewMode], + ); // 处理图片预览 const handlePreview = useCallback((index: number) => { @@ -123,66 +133,75 @@ const Gallery: FC = () => { }, []); // 上传图片 - const handleUpload = useCallback(async (file: UploadFile) => { - // 检查文件类型 - if (!file.type?.startsWith('image/')) { - message.error('只能上传图片文件!'); - return; - } - - setUploading(true); - try { - const formData = new FormData(); - formData.append('image', file as any); - - // 调用上传API - await uploadImage(formData); - message.success(`${file.name} 上传成功`); - - // 上传成功后刷新列表 - if (viewMode === 'table') { - fetchTableData({ - current: tablePagination.current, - pageSize: tablePagination.pageSize - }); - } else { - refresh(); + const handleUpload = useCallback( + async (file: UploadFile) => { + // 检查文件类型 + if (!file.type?.startsWith('image/')) { + message.error('只能上传图片文件!'); + return; } - } catch (error) { - message.error(`${file.name} 上传失败`); - } finally { - setUploading(false); - } - }, [viewMode, tablePagination, fetchTableData, refresh]); + + setUploading(true); + try { + const formData = new FormData(); + formData.append('image', file as any); + + // 调用上传API + await uploadImage(formData); + message.success(`${file.name} 上传成功`); + + // 上传成功后刷新列表 + if (viewMode === 'table') { + fetchTableData({ + current: tablePagination.current, + pageSize: tablePagination.pageSize, + }); + } else { + refresh(); + } + } catch (error) { + message.error(`${file.name} 上传失败`); + } finally { + setUploading(false); + } + }, + [viewMode, tablePagination, fetchTableData, refresh], + ); // 删除图片确认 - const handleDelete = useCallback((instanceId: string, imageName: string) => { - Modal.confirm({ - title: '确认删除', - content: `确定要删除图片 "${imageName}" 吗?此操作不可恢复。`, - okText: '删除', - okType: 'danger', - cancelText: '取消', - onOk: async () => { - try { - await deleteImage({ instanceId }); - message.success('删除成功'); + const handleDelete = useCallback( + (instanceId: string, imageName: string) => { + Modal.confirm({ + title: '确认删除', + content: `确定要删除图片 "${imageName}" 吗?此操作不可恢复。`, + okText: '删除', + okType: 'danger', + cancelText: '取消', + onOk: async () => { + try { + await deleteImage({ instanceId }); + message.success('删除成功'); - // 表格模式也需要刷新数据 - if (viewMode === 'table') { - fetchTableData({ current: tablePagination.current, pageSize: tablePagination.pageSize }); - } else { - refresh(); + // 表格模式也需要刷新数据 + if (viewMode === 'table') { + fetchTableData({ + current: tablePagination.current, + pageSize: tablePagination.pageSize, + }); + } else { + refresh(); + } + + // 如果在批量选择中,也需要移除 + setSelectedRowKeys((prev) => prev.filter((key) => key !== instanceId)); + } catch (error) { + message.error('删除失败'); } - - // 如果在批量选择中,也需要移除 - setSelectedRowKeys(prev => prev.filter(key => key !== instanceId)); - } catch (error) { - message.error('删除失败'); - } - } - }); - }, [refresh, viewMode, tablePagination, fetchTableData]); + }, + }); + }, + [refresh, viewMode, tablePagination, fetchTableData], + ); // 批量删除 const handleBatchDelete = useCallback(() => { @@ -207,14 +226,17 @@ const Gallery: FC = () => { // 表格模式也需要刷新数据 if (viewMode === 'table') { - fetchTableData({ current: tablePagination.current, pageSize: tablePagination.pageSize }); + fetchTableData({ + current: tablePagination.current, + pageSize: tablePagination.pageSize, + }); } else { refresh(); } } catch (error) { message.error('批量删除失败'); } - } + }, }); }, [selectedRowKeys, refresh, viewMode, tablePagination, fetchTableData]); @@ -228,7 +250,7 @@ const Gallery: FC = () => { selectedRowKeys.forEach((id, index) => { // 添加延迟避免浏览器限制 setTimeout(() => { - const item = imageList.find(img => img.instanceId === id); + const item = imageList.find((img) => img.instanceId === id); if (item) { handleDownload(id, item.imageName); } @@ -240,23 +262,26 @@ const Gallery: FC = () => { // 切换选择 const handleSelect = useCallback((instanceId: string, checked: boolean) => { - setSelectedRowKeys(prev => { + setSelectedRowKeys((prev) => { if (checked) { return [...prev, instanceId]; } else { - return prev.filter(key => key !== instanceId); + return prev.filter((key) => key !== instanceId); } }); }, []); // 全选/取消全选 - const handleSelectAll = useCallback((checked: boolean) => { - if (checked) { - setSelectedRowKeys(imageList.map(item => item.instanceId)); - } else { - setSelectedRowKeys([]); - } - }, [imageList]); + const handleSelectAll = useCallback( + (checked: boolean) => { + if (checked) { + setSelectedRowKeys(imageList.map((item) => item.instanceId)); + } else { + setSelectedRowKeys([]); + } + }, + [imageList], + ); // 取消批量操作 const handleCancelBatch = useCallback(() => { @@ -347,7 +372,9 @@ const Gallery: FC = () => { /> } > - {currentLoading && ((viewMode === 'table' && tablePagination.current === 1) || (viewMode !== 'table' && page === 1)) ? ( + {currentLoading && + ((viewMode === 'table' && tablePagination.current === 1) || + (viewMode !== 'table' && page === 1)) ? (
@@ -357,7 +384,7 @@ const Gallery: FC = () => { renderView() )} - {/* 预览组件 */} + {/* 预览组件 - 根据视图模式决定使用哪种图像 */} { {imageList.map((item: ImageItem) => ( {item.imageName} diff --git a/src/pages/story/components/AddTimeLineItemModal.tsx b/src/pages/story/components/AddTimeLineItemModal.tsx index 108a56e..9fc9198 100644 --- a/src/pages/story/components/AddTimeLineItemModal.tsx +++ b/src/pages/story/components/AddTimeLineItemModal.tsx @@ -1,13 +1,29 @@ // src/pages/list/basic-list/components/AddTimeLineItemModal.tsx import chinaRegion, { code2Location } from '@/commonConstant/chinaRegion'; import { addStoryItem } from '@/pages/story/service'; -import { UploadOutlined } from '@ant-design/icons'; +import { getImagesList } from '@/services/file/api'; // 引入获取图库图片的API +import { PlusOutlined, SearchOutlined } from '@ant-design/icons'; import { useRequest } from '@umijs/max'; -import { Button, Cascader, DatePicker, Form, Input, message, Modal, Upload } from 'antd'; -import ImgCrop from 'antd-img-crop'; +import { + Button, + Card, + Cascader, + Checkbox, + DatePicker, + Form, + Image, + Input, + InputRef, + message, + Modal, + Pagination, + Spin, + Tabs, + Upload, +} from 'antd'; import dayjs from 'dayjs'; import moment from 'moment'; -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useRef, useState } from 'react'; interface ModalProps { visible: boolean; @@ -31,18 +47,61 @@ const AddTimeLineItemModal: React.FC = ({ const [form] = Form.useForm(); const [fileList, setFileList] = useState([]); const [imageList, setImageList] = useState(initialValues?.images || []); + const [galleryImages, setGalleryImages] = useState([]); // 图库图片列表 + const [selectedGalleryImages, setSelectedGalleryImages] = useState( + initialValues?.galleryImageIds || [], + ); // 选中的图库图片 + const [galleryLoading, setGalleryLoading] = useState(false); + const [activeTab, setActiveTab] = useState('upload'); // 图片选择标签页 + const [currentPage, setCurrentPage] = useState(1); + const [pageSize] = useState(20); + const [total, setTotal] = useState(0); + const [searchKeyword, setSearchKeyword] = useState(''); + const searchInputRef = useRef(null); + useEffect(() => { - if (initialValues && option === 'edit') { + if (initialValues && option.startsWith('edit')) { form.setFieldsValue({ title: initialValues.title, - storyItemTime: initialValues.date ? moment(initialValues.date) : undefined, + date: initialValues.storyItemTime ? moment(initialValues.storyItemTime) : undefined, location: initialValues.location, description: initialValues.description, - cover: initialValues.cover ? [{ url: initialValues.cover }] : [], - images: initialValues.images?.map((url) => ({ url })) || [], }); } }, [initialValues, option]); + + // 获取图库图片 + const fetchGalleryImages = async (page: number = 1, keyword: string = '') => { + if (visible) { + setGalleryLoading(true); + try { + const response = await getImagesList({ + current: page, + pageSize: pageSize, + keyword: keyword, + }); + 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); + setCurrentPage(page); + } catch (error) { + message.error('获取图库图片失败'); + } finally { + setGalleryLoading(false); + } + } + }; + + useEffect(() => { + if (visible && activeTab === 'gallery') { + fetchGalleryImages(1, searchKeyword); + } + }, [visible, activeTab, searchKeyword]); + const { run: submitItem, loading } = useRequest((newItem) => addStoryItem(newItem), { manual: true, onSuccess: (data) => { @@ -63,16 +122,17 @@ const AddTimeLineItemModal: React.FC = ({ const values = await form.validateFields(); const location = code2Location(values.location); const newItem = { - ...values, - id: initialValues?.id || Date.now(), storyItemTime: dayjs(values.date).format('YYYY-MM-DDTHH:mm:ss'), - masterItemId: initialValues.masterItemId, + title: values.title, + description: values.description, + masterItemId: initialValues?.masterItemId, subItems: initialValues?.subItems || [], storyInstanceId: storyId, location, + instanceId: initialValues?.instanceId, + // 添加选中的图库图片ID + relatedImageInstanceIds: selectedGalleryImages, }; - delete newItem.cover; - delete newItem.images; // 构建 FormData const formData = new FormData(); @@ -83,7 +143,8 @@ const AddTimeLineItemModal: React.FC = ({ if (fileList.length > 0 && fileList[0].originFileObj instanceof File) { formData.append('cover', fileList[0].originFileObj); } - console.log(imageList); + + // 添加上传的图片文件 if (imageList.length > 0) { imageList.forEach((file) => { if (file.originFileObj && file.originFileObj instanceof File) { @@ -91,6 +152,8 @@ const AddTimeLineItemModal: React.FC = ({ } }); } + + console.log(formData); // 提交 submitItem(formData); } catch (error) { @@ -99,26 +162,6 @@ const AddTimeLineItemModal: React.FC = ({ } }; - const uploadCoverProps = { - beforeUpload: (file) => { - // 确保 originFileObj 是真正的 File 对象 - return false; // 阻止自动上传 - }, - onChange: ({ fileList }) => { - // 确保 originFileObj 是真正的 File 对象 - const updatedFileList = fileList.map((file) => { - if (file.originFileObj && !(file.originFileObj instanceof File)) { - file.originFileObj = new File([file.originFileObj], file.name, { type: file.type }); - } - return file; - }); - setFileList(updatedFileList); - }, - listType: 'picture', - maxCount: 1, - defaultFileList: initialValues?.cover ? [{ url: initialValues.cover }] : [], - }; - const uploadImagesProps = { beforeUpload: () => false, onChange: ({ fileList }) => { @@ -135,14 +178,149 @@ const AddTimeLineItemModal: React.FC = ({ defaultFileList: initialValues?.images?.map((url) => ({ url })), }; + // 切换图库图片选择状态 + const toggleGalleryImageSelection = (instanceId: string) => { + setSelectedGalleryImages((prev) => { + if (prev.includes(instanceId)) { + return prev.filter((id) => id !== instanceId); + } else { + return [...prev, instanceId]; + } + }); + }; + + // 处理分页变化 + const handlePageChange = (page: number) => { + fetchGalleryImages(page, searchKeyword); + }; + + // 处理搜索 + const handleSearch = (value: string) => { + setSearchKeyword(value); + fetchGalleryImages(1, value); + }; + + // 渲染图库图片选择器 + const renderGallerySelector = () => ( +
+ {/* 搜索框 */} +
+ } + onPressEnter={(e) => handleSearch(e.currentTarget.value)} + style={{ width: 200 }} + allowClear + /> + +
+ + {galleryLoading ? ( +
+ +
+ ) : ( + <> +
+ {galleryImages.map((image) => ( + toggleGalleryImageSelection(image.instanceId)} + style={{ + border: selectedGalleryImages.includes(image.instanceId) + ? '2px solid #1890ff' + : '1px solid #f0f0f0', + position: 'relative', + }} + > +
+ {image.imageName} + e.stopPropagation()} + /> +
+
+ {image.imageName} +
+
+ ))} +
+ + {galleryImages.length === 0 && !galleryLoading && ( +
+ {searchKeyword ? '未找到相关图片' : '图库中暂无图片'} +
+ )} + + {/* 分页器 */} + {total > 0 && ( +
+ +
+ )} + + )} +
+ ); + return ( { form.resetFields(); + setSelectedGalleryImages([]); + setSearchKeyword(''); + setCurrentPage(1); + setGalleryImages([]); onCancel(); }} + width={800} footer={[ - - - - - {/* 新增:时刻图库 */} - - - - + {/* 时刻图库 */} + + { + setActiveTab(key); + if (key === 'gallery' && galleryImages.length === 0) { + fetchGalleryImages(1, searchKeyword); + } + }} + items={[ + { + key: 'upload', + label: '上传图片', + children: ( + +
+ +
上传图片
+
+
+ ), + }, + { + key: 'gallery', + label: `从图库选择${selectedGalleryImages.length > 0 ? ` (${selectedGalleryImages.length})` : ''}`, + children: renderGallerySelector(), + }, + ]} + />
diff --git a/src/pages/story/components/TimelineItem/TimelineItem.tsx b/src/pages/story/components/TimelineItem/TimelineItem.tsx index cdc9dd6..250bb1c 100644 --- a/src/pages/story/components/TimelineItem/TimelineItem.tsx +++ b/src/pages/story/components/TimelineItem/TimelineItem.tsx @@ -1,12 +1,17 @@ -import {DeleteOutlined, DownOutlined, EditOutlined, PlusOutlined, UpOutlined} from '@ant-design/icons'; -import {useIntl, useRequest} from '@umijs/max'; -import { Button, Card, Popconfirm, message } from 'antd'; -import React, {useState} from 'react'; -import {queryStoryItemImages, removeStoryItem} from '../../service'; -import useStyles from './index.style'; -import {StoryItem} from "@/pages/story/data"; -import TimelineImage from "@/components/TimelineImage"; +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 } from 'antd'; +import React, { useState } from 'react'; +import { queryStoryItemImages, removeStoryItem } from '../../service'; import TimelineItemDrawer from '../TimelineItemDrawer'; +import useStyles from './index.style'; const TimelineItem: React.FC<{ item: StoryItem; @@ -18,12 +23,10 @@ const TimelineItem: React.FC<{ const [expanded, setExpanded] = useState(false); const [showActions, setShowActions] = useState(false); const [subItemsExpanded, setSubItemsExpanded] = useState(false); - const [openDetail, setOpenDetail] = useState(false) - const { data: imagesList } = useRequest( - async () => { - return await queryStoryItemImages(item.instanceId); - }, - ); + const [openDetail, setOpenDetail] = useState(false); + const { data: imagesList } = useRequest(async () => { + return await queryStoryItemImages(item.instanceId); + }); const handleDelete = async () => { try { if (!item.instanceId) return; @@ -48,7 +51,8 @@ const TimelineItem: React.FC<{ const displayedDescription = expanded ? item.description - : item.description?.substring(0, 100) + (item.description && item.description.length > 100 ? '...' : ''); + : item.description?.substring(0, 100) + + (item.description && item.description.length > 100 ? '...' : ''); return ( setShowActions(true)} onMouseLeave={() => setShowActions(false)} - onClick={() => setOpenDetail(true)} extra={ -
+
{showActions && ( <>
-
- {subItem.description} -
+
{subItem.description}
))}
@@ -170,11 +169,7 @@ const TimelineItem: React.FC<{
)} - + ); }; diff --git a/src/pages/story/components/TimelineItemDrawer.tsx b/src/pages/story/components/TimelineItemDrawer.tsx index e81227d..25742c1 100644 --- a/src/pages/story/components/TimelineItemDrawer.tsx +++ b/src/pages/story/components/TimelineItemDrawer.tsx @@ -29,7 +29,6 @@ const TimelineItemDrawer = (props: Props) => { ); useEffect(() => { if (open) { - console.log(storyItem); run(storyItem.instanceId); } }, [open]); @@ -52,9 +51,7 @@ const TimelineItemDrawer = (props: Props) => { { - closeDrawer(); - }} + onClose={closeDrawer} open={open} title={storyItem.title} footer={ diff --git a/src/pages/story/detail.tsx b/src/pages/story/detail.tsx index f05b10c..7c17e4b 100644 --- a/src/pages/story/detail.tsx +++ b/src/pages/story/detail.tsx @@ -91,22 +91,7 @@ const Index = () => { { setCurrentOption('add'); - setCurrentItem({ - coverInstanceId: "", - createTime: "", - description: "", - id: 0, - images: [], - instanceId: "", - isRoot: 0, - location: "", - masterItemId: "", - storyInstanceId: "", - storyItemTime: "", - subItems: [], - title: "", - updateTime: "" - }); + setCurrentItem(); setOpenAddItemModal(true); }} /> { getResponse: true, }); } - +export async function fetchImageLowRes(imageInstanceId: string): Promise { + return request(`/file/image-low-res/${imageInstanceId}`, { + method: 'GET', + responseType: 'blob', + getResponse: true, + }); +} export async function getImagesList( params: { // query