diff --git a/Makefile b/Makefile index bc3cc0c24..6b535fc24 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,7 @@ build-%: $(MAKE) $*-docker-build .PHONY: build -build: database-docker-build backend-docker-build frontend-docker-build runtime-docker-build +build: backend-docker-build frontend-docker-build runtime-docker-build backend-python-docker-build .PHONY: create-namespace create-namespace: @@ -117,9 +117,9 @@ frontend-docker-build: runtime-docker-build: docker build -t datamate-runtime:$(VERSION) . -f scripts/images/runtime/Dockerfile -.PHONY: label-studio-adapter-docker-build -label-studio-adapter-docker-build: - docker build -t label-studio-adapter:$(VERSION) . -f scripts/images/label-studio-adapter/Dockerfile +.PHONY: backend-python-docker-build +backend-python-docker-build: + docker build -t datamate-backend-python:$(VERSION) . -f scripts/images/datamate-python/Dockerfile .PHONY: deer-flow-docker-build deer-flow-docker-build: @@ -132,10 +132,6 @@ deer-flow-docker-build: mineru-docker-build: docker build -t datamate-mineru:$(VERSION) . -f scripts/images/mineru/Dockerfile -.PHONY: backend-python-docker-build -backend-python-docker-build: - docker build -t datamate-backend-python:$(VERSION) . -f scripts/images/datamate-python/Dockerfile - .PHONY: backend-docker-install backend-docker-install: cd deployment/docker/datamate && docker compose up -d backend diff --git a/frontend/src/hooks/useFetchData.ts b/frontend/src/hooks/useFetchData.ts index eb27d052e..6a7aad31b 100644 --- a/frontend/src/hooks/useFetchData.ts +++ b/frontend/src/hooks/useFetchData.ts @@ -110,7 +110,7 @@ export default function useFetchData( status: getFirstOfArray(filter?.status) || undefined, tags: filter?.tags?.length ? filter.tags.join(",") : undefined, page: current - pageOffset, - size: pageSize, + pageSize: pageSize, // Use camelCase for HTTP query params }), ...additionalPollingFuncs.map((func) => func()), ]; diff --git a/frontend/src/hooks/useTagConfig.ts b/frontend/src/hooks/useTagConfig.ts new file mode 100644 index 000000000..d547c54ac --- /dev/null +++ b/frontend/src/hooks/useTagConfig.ts @@ -0,0 +1,67 @@ +import { useState, useEffect } from "react"; +import { message } from "antd"; +import { getTagConfigUsingGet } from "../pages/DataAnnotation/annotation.api"; +import type { LabelStudioTagConfig } from "../pages/DataAnnotation/annotation.tagconfig"; +import { parseTagConfig, type TagOption } from "../pages/DataAnnotation/annotation.tagconfig"; + +interface UseTagConfigReturn { + config: LabelStudioTagConfig | null; + objectOptions: TagOption[]; + controlOptions: TagOption[]; + loading: boolean; + error: string | null; + refetch: () => Promise; +} + +/** + * Hook to fetch and manage Label Studio tag configuration + * @param includeLabelingOnly - If true, only include controls with category="labeling" (default: true) + */ +export function useTagConfig(includeLabelingOnly: boolean = true): UseTagConfigReturn { + const [config, setConfig] = useState(null); + const [objectOptions, setObjectOptions] = useState([]); + const [controlOptions, setControlOptions] = useState([]); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + const fetchConfig = async () => { + setLoading(true); + setError(null); + try { + const response = await getTagConfigUsingGet(); + if (response.code === 200 && response.data) { + const tagConfig: LabelStudioTagConfig = response.data; + setConfig(tagConfig); + + const { objectOptions: objects, controlOptions: controls } = + parseTagConfig(tagConfig, includeLabelingOnly); + setObjectOptions(objects); + setControlOptions(controls); + } else { + const errorMsg = response.message || "获取标签配置失败"; + setError(errorMsg); + message.error(errorMsg); + } + } catch (err: any) { + const errorMsg = err.message || "加载标签配置时出错"; + setError(errorMsg); + console.error("Failed to fetch tag config:", err); + message.error(errorMsg); + } finally { + setLoading(false); + } + }; + + useEffect(() => { + fetchConfig(); + }, []); + + return { + config, + objectOptions, + controlOptions, + loading, + error, + refetch: fetchConfig, + }; +} diff --git a/frontend/src/pages/DataAnnotation/Create/components/CreateAnnotationTaskDialog.tsx b/frontend/src/pages/DataAnnotation/Create/components/CreateAnnotationTaskDialog.tsx index 9f9ddbe87..8652fb1bf 100644 --- a/frontend/src/pages/DataAnnotation/Create/components/CreateAnnotationTaskDialog.tsx +++ b/frontend/src/pages/DataAnnotation/Create/components/CreateAnnotationTaskDialog.tsx @@ -29,16 +29,16 @@ export default function CreateAnnotationTask({ // Fetch datasets const { data: datasetData } = await queryDatasetsUsingGet({ page: 0, - size: 1000, + pageSize: 1000, // Use camelCase for HTTP params }); setDatasets(datasetData.content.map(mapDataset) || []); // Fetch templates const templateResponse = await queryAnnotationTemplatesUsingGet({ page: 1, - size: 100, // Backend max is 100 + size: 100, // Backend max is 100 (template API uses 'size' not 'pageSize') }); - + // The API returns: {code, message, data: {content, total, page, ...}} if (templateResponse.code === 200 && templateResponse.data) { const fetchedTemplates = templateResponse.data.content || []; @@ -68,7 +68,6 @@ export default function CreateAnnotationTask({ try { const values = await form.validateFields(); setSubmitting(true); - // Send templateId instead of labelingConfig const requestData = { name: values.name, @@ -76,7 +75,6 @@ export default function CreateAnnotationTask({ datasetId: values.datasetId, templateId: values.templateId, }; - await createAnnotationTaskUsingPost(requestData); message?.success?.("创建标注任务成功"); onClose(); @@ -154,7 +152,6 @@ export default function CreateAnnotationTask({ /> - {/* 描述变为可选 */}