= ({
+ visible,
+ onClose,
+ image,
+ onSuccess
+}) => {
+ const [form] = Form.useForm();
+ const [submitting, setSubmitting] = useState(false);
+
+ // 当图片信息变化时重置表单
+ useEffect(() => {
+ if (visible && image) {
+ form.setFieldsValue({
+ name: image.name,
+ description: image.description,
+ tags: image.tags || []
+ });
+ }
+ }, [visible, image, form]);
+
+ // 提交表单
+ const handleSubmit = async () => {
+ if (!image) return;
+
+ try {
+ const values = await form.validateFields();
+ setSubmitting(true);
+
+ const result = await updatePicture({
+ id: image.id,
+ name: values.name,
+ description: values.description,
+ tags: values.tags
+ });
+
+ if (result.success) {
+ message.success('图片信息已成功更新');
+ if (onSuccess) {
+ onSuccess(result.data!);
+ }
+ onClose();
+ } else {
+ // 根据错误信息判断提示内容
+ if (result.message && result.message.includes('向量')) {
+ message.warning('图片信息已更新,但AI索引生成失败。您的图片可能在高级搜索中不可见,但基本功能不受影响。');
+ // 尽管AI索引失败,但其他信息已更新,所以仍然调用成功回调
+ if (onSuccess && result.data) {
+ onSuccess(result.data);
+ }
+ onClose();
+ } else {
+ message.error(result.message || '更新图片失败');
+ }
+ }
+ } catch (error) {
+ if (error instanceof Error) {
+ // 解析常见错误消息并提供友好提示
+ const errorMsg = error.message;
+ if (errorMsg.includes('401') || errorMsg.includes('Unauthorized')) {
+ message.error('AI服务授权失败,请检查服务配置');
+ } else if (errorMsg.includes('vector') || errorMsg.includes('dimension')) {
+ message.error('AI索引生成失败,请稍后重试');
+ } else {
+ message.error(`提交失败: ${errorMsg}`);
+ }
+ } else {
+ message.error('提交失败,请检查表单');
+ }
+ } finally {
+ setSubmitting(false);
+ }
+ };
+
+ // 自定义标签选择
+ const tagRender = (props: any) => {
+ const { label, closable, onClose } = props;
+ return (
+
+ #{label}
+ {closable && (
+ ×
+ )}
+
+ );
+ };
+
+ if (!image) return null;
+
+ return (
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default EditImageDialog;
diff --git a/Web/src/components/image/ImageGrid.tsx b/Web/src/components/image/ImageGrid.tsx
index ba9a3a0..7ef8832 100644
--- a/Web/src/components/image/ImageGrid.tsx
+++ b/Web/src/components/image/ImageGrid.tsx
@@ -8,6 +8,7 @@ import type { PictureResponse } from '../../api';
import { favoritePicture, unfavoritePicture, getPictures, deleteMultiplePictures } from '../../api';
import ImageViewer from './ImageViewer';
import ShareImageDialog from './ShareImageDialog';
+import EditImageDialog from './EditImageDialog';
import './ImageGrid.css';
import { useAuth } from '../../api/AuthContext';
@@ -159,6 +160,15 @@ const ImageGrid: React.FC = ({
y: 0,
});
+ // 添加编辑对话框状态
+ const [editDialogState, setEditDialogState] = useState<{
+ visible: boolean;
+ image: PictureResponse | null;
+ }>({
+ visible: false,
+ image: null
+ });
+
// 简化标志变量
const isUsingExternalData = !!dataSource;
@@ -354,7 +364,33 @@ const ImageGrid: React.FC = ({
});
};
- // 修改handleMenuAction中的分享处理
+ // 处理编辑图片
+ const handleEditImage = (image: PictureResponse) => {
+ setEditDialogState({
+ visible: true,
+ image
+ });
+ };
+
+ // 关闭编辑对话框
+ const handleCloseEditDialog = () => {
+ setEditDialogState({
+ ...editDialogState,
+ visible: false
+ });
+ };
+
+ // 处理图片更新成功
+ const handleImageUpdateSuccess = (updatedImage: PictureResponse) => {
+ // 更新本地图片列表中对应的图片
+ setImages(prevImages =>
+ prevImages.map(img =>
+ img.id === updatedImage.id ? { ...img, ...updatedImage } : img
+ )
+ );
+ };
+
+ // 修改handleMenuAction中的编辑处理
const handleMenuAction = (action: string) => {
if (!contextMenu.image) return;
@@ -366,7 +402,7 @@ const ImageGrid: React.FC = ({
handleDeleteImage(contextMenu.image);
break;
case 'edit':
- onEdit?.(contextMenu.image);
+ handleEditImage(contextMenu.image);
break;
case 'download':
onDownload?.(contextMenu.image);
@@ -497,7 +533,11 @@ const ImageGrid: React.FC = ({
className="custom-card-action-item"
onClick={(e) => {
e.stopPropagation();
- onEdit && onEdit(image);
+ if (onEdit) {
+ onEdit(image);
+ } else {
+ handleEditImage(image);
+ }
}}
>
@@ -686,6 +726,13 @@ const ImageGrid: React.FC = ({
onClose={handleCloseShareDialog}
image={shareDialogState.image}
/>
+
+
>
);
};