"use client" import { useState, useRef, useEffect } from "react" import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog" import { Card, CardFooter } from "@/components/ui/card" import { Upload, PenTool, Type, QrCode, ChevronRight, ArrowRight, Smartphone, Monitor, Tablet, Save, Share2, Eye, } from "lucide-react" import { Switch } from "@/components/ui/switch" import { cn } from "@/lib/utils" const DEFAULT_TEMPLATES = [ { id: "register", name: "点击报名", src: "https://hebbkx1anhila5yf.public.blob.vercel-storage.com/%E7%80%9B%E6%A8%BA%EE%85%B9%E7%80%B9%E6%BF%87%E6%8D%A3%E9%8E%B6_%E9%90%90%E7%91%B0%E5%9A%AE%E9%8E%B6%E3%83%A5%E6%82%95-vJDCYhJ9ENr8jN3YGP9jVeQ5Ub3czl.gif", color: "#d32121", textColor: "#ffffff", }, { id: "claim", name: "点击领取", src: "https://hebbkx1anhila5yf.public.blob.vercel-storage.com/%E7%80%9B%E6%A8%BA%EE%85%B9%E7%80%B9%E6%BF%87%E6%8D%A3%E9%8E%B6_%E9%90%90%E7%91%B0%E5%9A%AE%E6%A3%B0%E5%97%97%E5%BD%871-cskUmYR6oO0n4uHdZVeB4naKUSUilb.gif", color: "#d32121", textColor: "#ffffff", }, { id: "consult", name: "点击咨询", src: "https://hebbkx1anhila5yf.public.blob.vercel-storage.com/%E7%80%9B%E6%A8%BA%EE%85%B9%E7%80%B9%E6%BF%87%E6%8D%A3%E9%8E%B6_%E9%90%90%E7%91%B0%E5%9A%AE%E9%8D%9C%E3%84%A8%EE%87%97-OUtJxwRbr4ydYRjt8FLOCMELC16Vw6.gif", color: "#d32121", textColor: "#ffffff", }, { id: "checkin", name: "点击签到", src: "https://hebbkx1anhila5yf.public.blob.vercel-storage.com/%E7%80%9B%E6%A8%BA%EE%85%B9%E7%80%B9%E6%BF%87%E6%8D%A3%E9%8E%B6_%E9%90%90%E7%91%B0%E5%9A%AE%E7%BB%9B%E6%83%A7%E5%9F%8C-bYcTocSdNrcykfBXmt51q6D4Yzh26h.gif", color: "#d32121", textColor: "#ffffff", }, { id: "cooperation", name: "点击合作", src: "https://hebbkx1anhila5yf.public.blob.vercel-storage.com/%E7%80%9B%E6%A8%BA%EE%85%B9%E7%80%B9%E6%BF%87%E6%8D%A3%E9%8E%B6_%E9%90%90%E7%91%B0%E5%9A%AE%E9%8D%9A%E5%A0%9C%E7%B6%94-kisPT3kV9A0aB7YpxO6AHUZ8aHvFLT.gif", color: "#d32121", textColor: "#ffffff", }, { id: "learn", name: "点击了解", src: "https://hebbkx1anhila5yf.public.blob.vercel-storage.com/%E7%80%9B%E6%A8%BA%EE%85%B9%E7%80%B9%E6%BF%87%E6%8D%A3%E9%8E%B6_%E9%90%90%E7%91%B0%E5%9A%AE%E6%B5%9C%E5%97%9A%D0%92-iE654sFFuO1PuvwmccV67yVLQZoLcx.gif", color: "#d32121", textColor: "#ffffff", }, { id: "claim_static", name: "点击领取(静态)", src: "https://hebbkx1anhila5yf.public.blob.vercel-storage.com/%E7%80%9B%E6%A8%BA%EE%85%B9%E7%80%B9%E6%BF%87%E6%8D%A3%E9%8E%B6_%E9%90%90%E7%91%B0%E5%9A%AE%E6%A3%B0%E5%97%97%E5%BD%87-jO6FPRCCzz6Irkm5suKeNkUDd98Y0f.png", color: "#d32121", textColor: "#ffffff", }, ] export function PosterEditor({ onChange, initialValue = null, }: { onChange: (value: any) => void initialValue?: any }) { const [selectedTemplate, setSelectedTemplate] = useState(initialValue?.template || DEFAULT_TEMPLATES[0]) const [customText, setCustomText] = useState(initialValue?.customText || selectedTemplate.name) const [mainColor, setMainColor] = useState(initialValue?.mainColor || selectedTemplate.color) const [textColor, setTextColor] = useState(initialValue?.textColor || selectedTemplate.textColor) const [hasQrCode, setHasQrCode] = useState(initialValue?.hasQrCode || false) const [qrCodeUrl, setQrCodeUrl] = useState(initialValue?.qrCodeUrl || "") const [offerText, setOfferText] = useState(initialValue?.offerText || "") const [previewDevice, setPreviewDevice] = useState("mobile") const [isTemplateDialogOpen, setIsTemplateDialogOpen] = useState(false) const canvasRef = useRef(null) // 当任何相关状态变化时更新父组件 useEffect(() => { onChange({ template: selectedTemplate, customText, mainColor, textColor, hasQrCode, qrCodeUrl, offerText, }) }, [selectedTemplate, customText, mainColor, textColor, hasQrCode, qrCodeUrl, offerText, onChange]) // 预览海报的渲染 useEffect(() => { const canvas = canvasRef.current if (!canvas) return const ctx = canvas.getContext("2d") if (!ctx) return // 清空画布 ctx.clearRect(0, 0, canvas.width, canvas.height) // 获取原始海报图像 const img = new Image() img.crossOrigin = "anonymous" img.src = selectedTemplate.src img.onload = () => { // 绘制原始海报 ctx.drawImage(img, 0, 0, canvas.width, canvas.height) // 自定义文本 if (customText !== selectedTemplate.name) { // 首先绘制一个半透明背景,盖住原文字 ctx.fillStyle = "rgba(255, 255, 255, 0.85)" ctx.fillRect(20, 30, canvas.width - 40, 150) // 绘制自定义文字 ctx.fillStyle = mainColor ctx.font = "bold 42px sans-serif" ctx.textAlign = "center" ctx.textBaseline = "middle" ctx.fillText(customText, canvas.width / 2, 100) } // 如果添加了二维码 if (hasQrCode) { // 添加一个二维码占位背景 ctx.fillStyle = "#ffffff" ctx.fillRect(canvas.width - 120, canvas.height - 120, 100, 100) ctx.strokeStyle = "#dddddd" ctx.lineWidth = 1 ctx.strokeRect(canvas.width - 120, canvas.height - 120, 100, 100) // 添加二维码图标占位 ctx.fillStyle = "#888888" ctx.fillRect(canvas.width - 100, canvas.height - 100, 60, 60) // 添加"扫码获取"文本 ctx.fillStyle = "#333333" ctx.font = "14px sans-serif" ctx.textAlign = "center" ctx.fillText("扫码获取", canvas.width - 70, canvas.height - 20) } // 如果添加了优惠文本 if (offerText) { // 添加一个醒目的优惠信息标签 ctx.fillStyle = "#ffeb3b" ctx.beginPath() ctx.moveTo(0, canvas.height - 200) ctx.lineTo(200, canvas.height - 200) ctx.lineTo(170, canvas.height - 150) ctx.lineTo(0, canvas.height - 150) ctx.closePath() ctx.fill() // 添加优惠文本 ctx.fillStyle = "#d32121" ctx.font = "bold 18px sans-serif" ctx.textAlign = "left" ctx.fillText(offerText, 15, canvas.height - 175) } } }, [selectedTemplate, customText, mainColor, hasQrCode, offerText]) return (

海报编辑器

设计 内容 互动 预览
{selectedTemplate && ( {selectedTemplate.name} )}

{selectedTemplate?.name || "请选择模板"}

点击右侧按钮选择其他模板

选择海报模板
{DEFAULT_TEMPLATES.map((template) => ( { setSelectedTemplate(template) setCustomText(template.name) setMainColor(template.color) setTextColor(template.textColor) setIsTemplateDialogOpen(false) }} >
{template.name}

{template.name}

))}

上传自定义模板

自定义上传

setMainColor(e.target.value)} className="rounded-l-none" />
setTextColor(e.target.value)} className="rounded-l-none" />
setCustomText(e.target.value)} className="mt-2" />
setOfferText(e.target.value)} className="mt-2" placeholder="例如: 限时8.5折 | 新人专享" />

添加醒目的优惠信息,提升用户点击欲望

{["限时特惠", "新人专享", "首单立减", "买一送一", "折扣优惠", "免费领取"].map((tag) => ( ))}

添加二维码提高用户转化率

{hasQrCode && (
setQrCodeUrl(e.target.value)} className="mt-2" placeholder="输入链接或小程序路径" />

上传自定义二维码

)}

点击行为

设置用户点击海报后的行为

) }