0.6.0.0
This commit is contained in:
@@ -2,10 +2,10 @@
|
||||
|
||||
import { useState, useEffect } from "react"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Card } from "@/components/ui/card"
|
||||
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog"
|
||||
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from "@/components/ui/dialog"
|
||||
import { Input } from "@/components/ui/input"
|
||||
import { Label } from "@/components/ui/label"
|
||||
import { Switch } from "@/components/ui/switch"
|
||||
import { X, Upload, Image as ImageIcon, Plus, ZoomIn, Edit2 } from "lucide-react"
|
||||
import { useDialog } from "@/components/ui/alert-dialog-custom"
|
||||
import imageCompression from "browser-image-compression"
|
||||
@@ -27,17 +27,25 @@ export function PhotoGallery({ photos: propPhotos = [], photoIds = [], onChange,
|
||||
const [isUploading, setIsUploading] = useState(false)
|
||||
const [editingPhoto, setEditingPhoto] = useState<FamilyPhoto | null>(null)
|
||||
const [editCaption, setEditCaption] = useState("")
|
||||
const [pendingVisibilityUrl, setPendingVisibilityUrl] = useState<string | null>(null)
|
||||
|
||||
// 加载照片 - 兼容新旧格式
|
||||
useEffect(() => {
|
||||
// 优先使用新格式 photos
|
||||
if (propPhotos && propPhotos.length > 0) {
|
||||
setPhotos(propPhotos)
|
||||
const normalized = propPhotos.map(photo => ({
|
||||
...photo,
|
||||
visibleInOverview: photo.visibleInOverview ?? false,
|
||||
adminVisibleOverride: photo.adminVisibleOverride ?? true,
|
||||
}))
|
||||
setPhotos(normalized)
|
||||
} else if (photoIds && photoIds.length > 0) {
|
||||
// 兼容旧格式:将 string[] 转换为 FamilyPhoto[]
|
||||
const convertedPhotos: FamilyPhoto[] = photoIds.map(url => ({
|
||||
url,
|
||||
uploadedAt: new Date().toISOString() // 旧数据没有时间,用当前时间
|
||||
uploadedAt: new Date().toISOString(), // 旧数据没有时间,用当前时间
|
||||
visibleInOverview: false,
|
||||
adminVisibleOverride: true,
|
||||
}))
|
||||
setPhotos(convertedPhotos)
|
||||
} else {
|
||||
@@ -82,7 +90,9 @@ export function PhotoGallery({ photos: propPhotos = [], photoIds = [], onChange,
|
||||
const { url } = await response.json()
|
||||
newPhotos.push({
|
||||
url,
|
||||
uploadedAt: new Date().toISOString()
|
||||
uploadedAt: new Date().toISOString(),
|
||||
visibleInOverview: false,
|
||||
adminVisibleOverride: true,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -104,6 +114,25 @@ export function PhotoGallery({ photos: propPhotos = [], photoIds = [], onChange,
|
||||
}
|
||||
}
|
||||
|
||||
const handleToggleOverview = async (photo: FamilyPhoto, value: boolean) => {
|
||||
if (readonly) return
|
||||
setPendingVisibilityUrl(photo.url)
|
||||
const previous = photos
|
||||
const updatedPhotos = photos.map(p =>
|
||||
p.url === photo.url ? { ...p, visibleInOverview: value } : p
|
||||
)
|
||||
setPhotos(updatedPhotos)
|
||||
try {
|
||||
await onChange(updatedPhotos)
|
||||
} catch (error) {
|
||||
console.error('更新照片展示状态失败:', error)
|
||||
setPhotos(previous)
|
||||
await showAlert('更新照片展示状态失败,请重试', '错误')
|
||||
} finally {
|
||||
setPendingVisibilityUrl(null)
|
||||
}
|
||||
}
|
||||
|
||||
const handleEditCaption = (photo: FamilyPhoto) => {
|
||||
setEditingPhoto(photo)
|
||||
setEditCaption(photo.caption || "")
|
||||
@@ -177,6 +206,14 @@ export function PhotoGallery({ photos: propPhotos = [], photoIds = [], onChange,
|
||||
{photo.caption && (
|
||||
<div className="text-foreground mt-1 line-clamp-2">{photo.caption}</div>
|
||||
)}
|
||||
<div className="mt-2 flex items-center justify-between gap-2 text-[11px] text-muted-foreground">
|
||||
<span>展示到总览</span>
|
||||
<Switch
|
||||
checked={photo.visibleInOverview ?? false}
|
||||
onCheckedChange={(checked) => handleToggleOverview(photo, checked)}
|
||||
disabled={readonly || pendingVisibilityUrl === photo.url}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{/* 操作按钮 */}
|
||||
{!readonly && (
|
||||
@@ -222,11 +259,14 @@ export function PhotoGallery({ photos: propPhotos = [], photoIds = [], onChange,
|
||||
|
||||
{/* 照片预览对话框 */}
|
||||
<Dialog open={!!selectedPhoto} onOpenChange={() => setSelectedPhoto(null)}>
|
||||
<DialogContent className="max-w-4xl" aria-describedby={undefined}>
|
||||
<DialogContent className="max-w-4xl" aria-describedby="photo-preview-desc">
|
||||
<DialogHeader>
|
||||
<DialogTitle>
|
||||
{selectedPhoto?.caption || "照片预览"}
|
||||
</DialogTitle>
|
||||
<DialogDescription id="photo-preview-desc" className="sr-only">
|
||||
家族照片预览弹窗,可查看大图与上传时间
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
{selectedPhoto && (
|
||||
<div className="space-y-2">
|
||||
@@ -245,9 +285,12 @@ export function PhotoGallery({ photos: propPhotos = [], photoIds = [], onChange,
|
||||
|
||||
{/* 编辑说明对话框 */}
|
||||
<Dialog open={!!editingPhoto} onOpenChange={() => setEditingPhoto(null)}>
|
||||
<DialogContent aria-describedby={undefined}>
|
||||
<DialogContent aria-describedby="photo-edit-desc">
|
||||
<DialogHeader>
|
||||
<DialogTitle>编辑照片说明</DialogTitle>
|
||||
<DialogDescription id="photo-edit-desc" className="sr-only">
|
||||
修改当前照片的备注文字并保存
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="space-y-4">
|
||||
<div className="space-y-2">
|
||||
|
||||
Reference in New Issue
Block a user