Files
ozon-seller-kit/studio/src/pages/ai-image/components/ElementPropsPanel.tsx
T
2026-08-14 18:27:45 +08:00

167 lines
7.1 KiB
TypeScript

import { ColorPicker, Empty, Input, InputNumber, Select, Slider, Switch } from 'antd';
import type { AnnotationElement } from '@/types/annotation';
import { FONT_FAMILIES } from '@/utils/annotation';
interface ElementPropsPanelProps {
element: AnnotationElement | null;
onUpdate: (id: number, patch: Partial<AnnotationElement>) => void;
}
const FONT_OPTIONS = FONT_FAMILIES.map((f) => ({ value: f, label: f }));
const ElementPropsPanel = ({ element, onUpdate }: ElementPropsPanelProps) => {
if (!element) {
return (
<div className="props-empty">
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description="未选中元素" />
<p className="props-hint">点击画布上的文字或标尺进行编辑</p>
</div>
);
}
const update = (patch: Partial<AnnotationElement>) => onUpdate(element.id, patch);
return (
<div className="props-panel">
{element.type === 'text' ? (
<>
<div className="prop-row">
<span className="prop-label">内容</span>
<Input.TextArea
value={element.content}
autoSize={{ minRows: 1, maxRows: 4 }}
onChange={(e) => update({ content: e.target.value })}
/>
</div>
<div className="prop-row">
<span className="prop-label">字体</span>
<Select
value={element.fontFamily}
options={FONT_OPTIONS}
onChange={(v) => update({ fontFamily: v })}
style={{ flex: 1 }}
/>
</div>
<div className="prop-row">
<span className="prop-label">字号</span>
<InputNumber
value={element.fontSize}
min={8}
onChange={(v) => update({ fontSize: v ?? 18 })}
style={{ flex: 1 }}
/>
</div>
<div className="prop-row">
<span className="prop-label">加粗</span>
<Switch checked={element.bold} onChange={(v) => update({ bold: v })} />
</div>
<div className="prop-row">
<span className="prop-label">文字颜色</span>
<ColorPicker
value={element.color}
onChange={(c) => update({ color: c.toHexString() })}
/>
</div>
<div className="prop-row">
<span className="prop-label">描边颜色</span>
<ColorPicker
value={element.strokeColor}
onChange={(c) => update({ strokeColor: c.toHexString() })}
/>
</div>
<div className="prop-row">
<span className="prop-label">描边宽度</span>
<InputNumber
value={element.strokeWidth}
min={0}
onChange={(v) => update({ strokeWidth: v ?? 0 })}
style={{ flex: 1 }}
/>
</div>
</>
) : (
<>
<div className="prop-row">
<span className="prop-label">长度(px)</span>
<InputNumber
value={Math.round(element.length)}
min={4}
onChange={(v) => update({ length: v ?? 50 })}
style={{ flex: 1 }}
/>
</div>
<div className="prop-row">
<span className="prop-label">线色</span>
<ColorPicker
value={element.lineColor}
onChange={(c) => update({ lineColor: c.toHexString() })}
/>
</div>
<div className="prop-row">
<span className="prop-label">线宽</span>
<InputNumber
value={element.lineWidth}
min={1}
onChange={(v) => update({ lineWidth: v ?? 2 })}
style={{ flex: 1 }}
/>
</div>
<div className="prop-row">
<span className="prop-label">T字大小</span>
<InputNumber
value={Math.round(element.tSize)}
min={4}
onChange={(v) => update({ tSize: v ?? 14 })}
style={{ flex: 1 }}
/>
</div>
<div className="prop-row">
<span className="prop-label">标签文字</span>
<Input value={element.label} onChange={(e) => update({ label: e.target.value })} />
</div>
<div className="prop-row">
<span className="prop-label">标签颜色</span>
<ColorPicker
value={element.labelColor}
onChange={(c) => update({ labelColor: c.toHexString() })}
/>
</div>
<div className="prop-row">
<span className="prop-label">标签字号</span>
<InputNumber
value={Math.round(element.labelFontSize)}
min={8}
onChange={(v) => update({ labelFontSize: v ?? 14 })}
style={{ flex: 1 }}
/>
</div>
</>
)}
<div className="prop-row">
<span className="prop-label">透明度</span>
<Slider
min={0.05}
max={1}
step={0.05}
value={element.opacity}
onChange={(v) => update({ opacity: v })}
style={{ flex: 1 }}
/>
</div>
<div className="prop-row">
<span className="prop-label">旋转(°)</span>
<InputNumber
value={Math.round(element.rotation)}
min={0}
max={360}
onChange={(v) => update({ rotation: (v ?? 0) % 360 })}
style={{ flex: 1 }}
/>
</div>
</div>
);
};
export default ElementPropsPanel;