菜单添加页面模板管理页面,增加一个纯图平铺模板,优化预览手机屏效果

This commit is contained in:
2026-04-17 08:35:45 +08:00
parent 9a6418eb93
commit 052195abab
36 changed files with 1534 additions and 708 deletions

View File

@@ -0,0 +1,55 @@
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import type { EditorProps } from "../../types"
export function PureImagePageEditor({
content,
canEdit,
onUpdate,
newImageUrl,
onNewImageUrlChange,
onAddImage,
onRemoveImage,
}: EditorProps) {
return (
<>
<div className="grid gap-2">
<label className="text-xs font-semibold tracking-wide text-muted-foreground uppercase"></label>
<Input value={content.title} disabled={!canEdit} onChange={(e) => onUpdate({ title: e.target.value })} />
</div>
<div className="grid gap-2">
<label className="text-xs font-semibold tracking-wide text-muted-foreground uppercase"></label>
<Input value={content.ctaText} disabled={!canEdit} onChange={(e) => onUpdate({ ctaText: e.target.value })} />
</div>
<div className="grid gap-2">
<label className="text-xs font-semibold tracking-wide text-muted-foreground uppercase"></label>
<div className="flex gap-2">
<Input
value={newImageUrl ?? ""}
disabled={!canEdit}
onChange={(e) => onNewImageUrlChange?.(e.target.value)}
placeholder="粘贴图片 URL"
/>
<Button variant="outline" disabled={!canEdit} onClick={() => onAddImage?.()}>
</Button>
</div>
<div className="grid grid-cols-2 gap-2">
{content.imageUrls.map((url, idx) => (
<div key={`${url}-${idx}`} className="rounded-lg border p-2">
<img src={url} alt={`${content.title}-${idx}`} className="aspect-video w-full rounded object-cover" />
<div className="mt-2 flex items-center justify-between gap-2">
<span className="truncate text-[11px] text-muted-foreground">{url}</span>
<Button size="sm" variant="ghost" disabled={!canEdit} onClick={() => onRemoveImage?.(idx)}>
</Button>
</div>
</div>
))}
</div>
</div>
</>
)
}

View File

@@ -0,0 +1,70 @@
import { ChevronLeft, MoreHorizontal, X } from "lucide-react"
import type { PreviewProps } from "../../types"
export function PureImagePagePreview({ content }: PreviewProps) {
const imageUrls = content.imageUrls.filter(Boolean)
return (
<div className="flex h-[780px] w-[360px] flex-col overflow-hidden rounded-[28px] border border-gray-200 bg-black text-white shadow-2xl">
<div className="flex h-11 items-end justify-between px-8 pb-2 text-[15px] font-semibold tracking-tight">
<span>9:41</span>
<div className="flex items-center gap-1.5 pb-1">
<svg width="17" height="11" viewBox="0 0 17 11" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<path d="M0 8.35L2.83 8.35L2.83 10.5H0V8.35ZM4.25 6.2H7.08V10.5H4.25V6.2ZM8.5 4.05H11.33V10.5H8.5V4.05ZM12.75 1.9H15.58V10.5H12.75V1.9Z" fill="white" />
</svg>
<svg width="16" height="12" viewBox="0 0 16 12" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<path d="M8 12L16 3.10931C11.5768 -0.493103 4.42323 -0.493103 0 3.10931L8 12Z" fill="white" />
</svg>
<div className="relative h-[11.33px] w-[24.33px] rounded-[3px] border border-white/35 p-[1px]">
<div className="h-full w-[18px] rounded-[1px] bg-white" />
<div className="absolute -right-[3px] top-[3px] h-[5px] w-[2px] rounded-r-[1px] bg-white/35" />
</div>
</div>
</div>
<header className="flex h-14 items-center justify-between bg-black/85 px-4 backdrop-blur-md">
<button className="p-2 text-white/90" type="button" aria-label="返回">
<ChevronLeft className="h-6 w-6" />
</button>
<h1 className="text-lg font-medium tracking-wide">{content.title || "E7X详情"}</h1>
<div className="flex h-8 items-center rounded-full border border-white/10 bg-black/40 px-1">
<button className="border-r border-white/10 px-2 text-white/90" type="button" aria-label="更多">
<MoreHorizontal className="h-4 w-4" />
</button>
<button className="px-2 text-white/90" type="button" aria-label="关闭">
<X className="h-4 w-4" />
</button>
</div>
</header>
<main className="min-h-0 flex-1 overflow-y-auto bg-black [scrollbar-width:none] [&::-webkit-scrollbar]:hidden">
{imageUrls.length > 0 ? (
imageUrls.map((url, idx) => (
<img
key={`${url}-${idx}`}
src={url}
alt={`${content.title || "E7X详情"}-${idx + 1}`}
className="block w-full"
/>
))
) : (
<div className="flex min-h-[480px] items-center justify-center bg-neutral-900 text-sm text-white/60">
</div>
)}
</main>
<footer className="shrink-0 bg-black px-5 py-3.5">
<button
type="button"
className="w-full border border-white bg-transparent py-2.5 text-sm font-medium text-white"
>
{content.ctaText || "预约体验"}
</button>
<div className="mt-3 flex justify-center">
<div className="h-1 w-24 rounded-full bg-white/20" />
</div>
</footer>
</div>
)
}