You've already forked DataMate
feat(annotation): 添加标注任务预览功能
- 新增 previewTaskData 状态管理预览数据 - 实现 generateExampleData 函数根据对象配置生成示例数据 - 支持多种数据类型(图片、音频、视频、文本等)的示例生成 - 优化预览按钮逻辑,自动生成适配的示例数据 - 移除固定示例数据,使用动态生成的数据进行预览 - 调整模板列表组件的分页参数以修复数据获取问题
This commit is contained in:
@@ -120,6 +120,7 @@ export default function CreateAnnotationTask({
|
|||||||
// Custom template state
|
// Custom template state
|
||||||
const [customXml, setCustomXml] = useState("");
|
const [customXml, setCustomXml] = useState("");
|
||||||
const [showPreview, setShowPreview] = useState(false);
|
const [showPreview, setShowPreview] = useState(false);
|
||||||
|
const [previewTaskData, setPreviewTaskData] = useState<Record<string, any>>({});
|
||||||
const [configMode, setConfigMode] = useState<"template" | "custom">("template");
|
const [configMode, setConfigMode] = useState<"template" | "custom">("template");
|
||||||
const [templateEditTab, setTemplateEditTab] = useState<"visual" | "xml">("visual");
|
const [templateEditTab, setTemplateEditTab] = useState<"visual" | "xml">("visual");
|
||||||
|
|
||||||
@@ -174,6 +175,7 @@ export default function CreateAnnotationTask({
|
|||||||
setImageFileCount(0);
|
setImageFileCount(0);
|
||||||
setCustomXml("");
|
setCustomXml("");
|
||||||
setShowPreview(false);
|
setShowPreview(false);
|
||||||
|
setPreviewTaskData({});
|
||||||
setConfigMode("template");
|
setConfigMode("template");
|
||||||
setTemplateEditTab("visual");
|
setTemplateEditTab("visual");
|
||||||
}
|
}
|
||||||
@@ -234,6 +236,58 @@ export default function CreateAnnotationTask({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 根据 objects 配置生成预览用的示例数据
|
||||||
|
const generateExampleData = (objects: any[]) => {
|
||||||
|
const exampleUrls: Record<string, string> = {
|
||||||
|
Image: "https://labelstud.io/images/opa-header.png",
|
||||||
|
Audio: "https://labelstud.io/files/sample.wav",
|
||||||
|
Video: "https://labelstud.io/files/sample.mp4",
|
||||||
|
};
|
||||||
|
const exampleTexts: Record<string, string> = {
|
||||||
|
Text: "这是示例文本,用于预览标注界面。",
|
||||||
|
HyperText: "<p>这是示例 HTML 内容</p>",
|
||||||
|
Header: "示例标题",
|
||||||
|
Paragraphs: "段落一\n\n段落二\n\n段落三",
|
||||||
|
};
|
||||||
|
|
||||||
|
const data: Record<string, any> = {};
|
||||||
|
|
||||||
|
if (!objects || objects.length === 0) {
|
||||||
|
// 默认数据
|
||||||
|
return {
|
||||||
|
image: exampleUrls.Image,
|
||||||
|
text: exampleTexts.Text,
|
||||||
|
audio: exampleUrls.Audio,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
objects.forEach((obj: any) => {
|
||||||
|
if (!obj?.name || !obj?.value) return;
|
||||||
|
// 变量名从 $varName 中提取
|
||||||
|
const varName = obj.value.startsWith("$") ? obj.value.slice(1) : obj.name;
|
||||||
|
|
||||||
|
if (exampleUrls[obj.type]) {
|
||||||
|
data[varName] = exampleUrls[obj.type];
|
||||||
|
} else if (exampleTexts[obj.type]) {
|
||||||
|
data[varName] = exampleTexts[obj.type];
|
||||||
|
} else {
|
||||||
|
// 未知类型,尝试根据名称猜测
|
||||||
|
const lowerName = varName.toLowerCase();
|
||||||
|
if (lowerName.includes("image") || lowerName.includes("img")) {
|
||||||
|
data[varName] = exampleUrls.Image;
|
||||||
|
} else if (lowerName.includes("audio") || lowerName.includes("sound")) {
|
||||||
|
data[varName] = exampleUrls.Audio;
|
||||||
|
} else if (lowerName.includes("video")) {
|
||||||
|
data[varName] = exampleUrls.Video;
|
||||||
|
} else {
|
||||||
|
data[varName] = exampleTexts.Text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
// 当选择模板时,加载模板配置到表单
|
// 当选择模板时,加载模板配置到表单
|
||||||
const handleTemplateSelect = (value: string, option: any) => {
|
const handleTemplateSelect = (value: string, option: any) => {
|
||||||
if (option && option.config) {
|
if (option && option.config) {
|
||||||
@@ -494,18 +548,19 @@ export default function CreateAnnotationTask({
|
|||||||
type="link"
|
type="link"
|
||||||
size="small"
|
size="small"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
// 如果在可视化模式,先同步生成 XML
|
|
||||||
if (configMode === 'template' && templateEditTab === 'visual') {
|
|
||||||
syncFormToXml();
|
|
||||||
} else if (configMode === 'custom') {
|
|
||||||
// 自定义模式也从表单生成
|
|
||||||
const objects = manualForm.getFieldValue("objects");
|
const objects = manualForm.getFieldValue("objects");
|
||||||
const labels = manualForm.getFieldValue("labels");
|
const labels = manualForm.getFieldValue("labels");
|
||||||
|
|
||||||
|
// 生成 XML
|
||||||
if (objects && objects.length > 0) {
|
if (objects && objects.length > 0) {
|
||||||
const xml = generateXmlFromConfig(objects, labels || []);
|
const xml = generateXmlFromConfig(objects, labels || []);
|
||||||
setCustomXml(xml);
|
setCustomXml(xml);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// 生成适配的示例数据
|
||||||
|
const exampleData = generateExampleData(objects);
|
||||||
|
setPreviewTaskData(exampleData);
|
||||||
|
|
||||||
setShowPreview(true);
|
setShowPreview(true);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -717,11 +772,7 @@ export default function CreateAnnotationTask({
|
|||||||
config={customXml}
|
config={customXml}
|
||||||
task={{
|
task={{
|
||||||
id: 1,
|
id: 1,
|
||||||
data: {
|
data: previewTaskData,
|
||||||
image: "https://labelstud.io/images/opa-header.png",
|
|
||||||
text: "这是示例文本,用于预览标注界面。",
|
|
||||||
audio: "https://labelstud.io/files/sample.wav"
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ const TemplateList: React.FC = () => {
|
|||||||
fetchData,
|
fetchData,
|
||||||
handleFiltersChange,
|
handleFiltersChange,
|
||||||
handleKeywordChange,
|
handleKeywordChange,
|
||||||
} = useFetchData(queryAnnotationTemplatesUsingGet, undefined, undefined, undefined, undefined, 0);
|
} = useFetchData(queryAnnotationTemplatesUsingGet, undefined, undefined, undefined, undefined);
|
||||||
|
|
||||||
const handleCreate = () => {
|
const handleCreate = () => {
|
||||||
setFormMode("create");
|
setFormMode("create");
|
||||||
|
|||||||
Reference in New Issue
Block a user