import { useState } from 'react'; import type { CSSProperties } from 'react'; import { Typography } from 'antd'; import type { WatermarkPosition } from '@atlas/contracts'; import type { WatermarkTemplateConfig } from '@atlas/contracts'; /** 九宫格位置选项,顺序与编辑器 3x3 网格一致 */ export const WATERMARK_POSITION_OPTIONS: Array<{ value: WatermarkPosition; label: string; row: 0 | 1 | 2; col: 0 | 1 | 2; }> = [ { value: 'top_left', label: '左上角', row: 0, col: 0 }, { value: 'top_center', label: '上居中', row: 0, col: 1 }, { value: 'top_right', label: '右上角', row: 0, col: 2 }, { value: 'middle_left', label: '左居中', row: 1, col: 0 }, { value: 'center', label: '正居中', row: 1, col: 1 }, { value: 'middle_right', label: '右居中', row: 1, col: 2 }, { value: 'bottom_left', label: '左下角', row: 2, col: 0 }, { value: 'bottom_center', label: '下居中', row: 2, col: 1 }, { value: 'bottom_right', label: '右下角', row: 2, col: 2 }, ]; export const watermarkPositionLabel = (position: string): string => WATERMARK_POSITION_OPTIONS.find((option) => option.value === position)?.label ?? position; const POSITION_FLEX: Record< WatermarkPosition, Pick > = { top_left: { justifyContent: 'flex-start', alignItems: 'flex-start' }, top_center: { justifyContent: 'center', alignItems: 'flex-start' }, top_right: { justifyContent: 'flex-end', alignItems: 'flex-start' }, middle_left: { justifyContent: 'flex-start', alignItems: 'center' }, center: { justifyContent: 'center', alignItems: 'center' }, middle_right: { justifyContent: 'flex-end', alignItems: 'center' }, bottom_left: { justifyContent: 'flex-start', alignItems: 'flex-end' }, bottom_center: { justifyContent: 'center', alignItems: 'flex-end' }, bottom_right: { justifyContent: 'flex-end', alignItems: 'flex-end' }, }; interface WatermarkPreviewProps { /** 允许传入部分字段:编辑弹窗按当前表单值实时渲染 */ config: Partial; width?: number; height?: number; } /** * 按模板 config 在内置演示底图上实时渲染水印效果(docs/api/watermarks-and-assets.md §3.1), * 不调用服务端渲染;图片使用响应中的短时 preview_url,过期时提示重新读取。 */ const WatermarkPreview = ({ config, width = 320, height = 420 }: WatermarkPreviewProps) => { const [imageBroken, setImageBroken] = useState(false); const position = config.position ?? 'bottom_right'; const flex = POSITION_FLEX[position] ?? POSITION_FLEX.bottom_right; const previewUrl = config.image_asset?.preview_url; return (
{config.image_asset ? ( imageBroken || !previewUrl ? ( 图片预览已过期或不可用 ) : ( 水印图片 setImageBroken(true)} /> ) ) : ( {config.text_content || '文字水印'} )}
); }; export default WatermarkPreview;