内容库素材列表 + 编辑

This commit is contained in:
wong
2025-05-12 09:32:27 +08:00
parent 50cd82f5d3
commit bb20d5182c
8 changed files with 943 additions and 233 deletions

View File

@@ -4,38 +4,50 @@ import type React from "react"
import { useState } from "react"
import { useRouter } from "next/navigation"
import { ChevronLeft, Plus, X } from "lucide-react"
import { ChevronLeft, Plus, X, Image as ImageIcon, UploadCloud } from "lucide-react"
import { Card } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Textarea } from "@/components/ui/textarea"
import { Label } from "@/components/ui/label"
import { Badge } from "@/components/ui/badge"
import { toast } from "@/components/ui/use-toast"
import Image from "next/image"
export default function NewMaterialPage({ params }: { params: { id: string } }) {
const router = useRouter()
const [content, setContent] = useState("")
const [newTag, setNewTag] = useState("")
const [tags, setTags] = useState<string[]>([])
const [images, setImages] = useState<string[]>([])
const [previewUrls, setPreviewUrls] = useState<string[]>([])
const handleAddTag = () => {
if (newTag && !tags.includes(newTag)) {
setTags([...tags, newTag])
setNewTag("")
// 模拟上传图片
const handleUploadImage = () => {
// 这里应该是真实的图片上传逻辑
// 为了演示这里模拟添加一些示例图片URL
const mockImageUrls = [
"https://picsum.photos/id/237/200/300",
"https://picsum.photos/id/238/200/300",
"https://picsum.photos/id/239/200/300"
]
const randomIndex = Math.floor(Math.random() * mockImageUrls.length)
const newImage = mockImageUrls[randomIndex]
if (!images.includes(newImage)) {
setImages([...images, newImage])
setPreviewUrls([...previewUrls, newImage])
}
}
const handleRemoveTag = (tagToRemove: string) => {
setTags(tags.filter((tag) => tag !== tagToRemove))
const handleRemoveImage = (indexToRemove: number) => {
setImages(images.filter((_, index) => index !== indexToRemove))
setPreviewUrls(previewUrls.filter((_, index) => index !== indexToRemove))
}
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
if (!content) {
if (!content && images.length === 0) {
toast({
title: "错误",
description: "请输入素材内容",
description: "请输入素材内容或上传图片",
variant: "destructive",
})
return
@@ -87,36 +99,48 @@ export default function NewMaterialPage({ params }: { params: { id: string } })
</div>
<div>
<Label htmlFor="tags"></Label>
<div className="flex items-center mt-1">
<Input
id="tags"
value={newTag}
onChange={(e) => setNewTag(e.target.value)}
placeholder="输入标签"
className="flex-1"
/>
<Button type="button" onClick={handleAddTag} className="ml-2">
<Plus className="h-4 w-4" />
<Label></Label>
<div className="mt-2 border border-dashed border-gray-300 rounded-lg p-4 text-center">
<Button
type="button"
variant="outline"
onClick={handleUploadImage}
className="w-full py-8 flex flex-col items-center justify-center"
>
<UploadCloud className="h-8 w-8 mb-2 text-gray-400" />
<span></span>
<span className="text-xs text-gray-500 mt-1"> JPGPNG </span>
</Button>
</div>
<div className="flex flex-wrap gap-2 mt-2">
{tags.map((tag, index) => (
<Badge key={index} variant="secondary" className="flex items-center">
{tag}
<Button
type="button"
variant="ghost"
size="sm"
className="h-4 w-4 ml-1 p-0"
onClick={() => handleRemoveTag(tag)}
>
<X className="h-3 w-3" />
</Button>
</Badge>
))}
</div>
{previewUrls.length > 0 && (
<div className="mt-4">
<Label></Label>
<div className="grid grid-cols-2 md:grid-cols-3 gap-3 mt-2">
{previewUrls.map((url, index) => (
<div key={index} className="relative group">
<div className="aspect-square relative rounded-lg overflow-hidden border border-gray-200">
<Image
src={url}
alt={`图片 ${index + 1}`}
fill
className="object-cover"
/>
</div>
<Button
type="button"
variant="destructive"
size="sm"
className="absolute top-1 right-1 opacity-0 group-hover:opacity-100 transition-opacity h-6 w-6 p-0"
onClick={() => handleRemoveImage(index)}
>
<X className="h-3 w-3" />
</Button>
</div>
))}
</div>
</div>
)}
</div>
<Button type="submit" className="w-full">