"use client" import { checkLabelDataSource, getProjectAdminList, getProjectTypeList, projectAdd, } from "@/components/label/api/project" import { getAllVersionByName, getLabelSchemeList, } from "@/components/label/api/scheme" import { usePermissionStore } from "@/components/label/store/auth" import { Alert, Button, Group, Modal, MultiSelect, Radio, Select, Stack, Switch, Text, TextInput, Textarea, } from "@mantine/core" import { useForm } from "@mantine/form" import { notifications } from "@mantine/notifications" import { IconAlertTriangle } from "@tabler/icons-react" import { useEffect, useMemo, useRef, useState } from "react" export default function NewProjectModal(props: { opened: boolean onCloseAction: (refresh?: boolean) => void }) { const { opened, onCloseAction } = props const userName = usePermissionStore((s) => s.user_name) const [typeOpts, setTypeOpts] = useState< Array<{ label: string; value: string }> >([]) const [labelSchemeOpts, setLabelSchemeOpts] = useState< Array<{ label: string; value: string }> >([]) const [versionOpts, setVersionOpts] = useState< Array<{ label: string; value: string }> >([]) const [adminUserOpts, setAdminUserOpts] = useState< Array<{ label: string; value: string }> >([]) const [dataSize, setDataSize] = useState(0) const debounceTimerRef = useRef | null>(null) const form = useForm({ initialValues: { project_name: "", project_type: "", is_dynamic: false, data_source_radio: "" as "" | "0" | "1", data_source: "", label_schema_name: "", label_schema_version: "", is_embedding: false, admin_user: [] as string[], remark: "", }, validate: { project_name: (v) => { if (!v) return "必填" if (/^\s*$/.test(v)) return "项目名称不能全为空格" return null }, project_type: (v) => (!v ? "必填" : null), label_schema_name: (v) => (!v ? "必填" : null), label_schema_version: (v) => (!v ? "必填" : null), admin_user: (v) => (v && v.length ? null : "必填"), }, }) const isDynamic = form.values.is_dynamic const projectType = form.values.project_type const labelSchema = form.values.label_schema_name useEffect(() => { if (!opened) return const initFormOpts = async () => { try { const [schemeRes, adminRes, typeRes] = await Promise.all([ getLabelSchemeList({ page_number: 1, page_size: 5000 } as any), getProjectAdminList(), getProjectTypeList(), ]) const schemes = (schemeRes as any)?.label_schema_list ?? [] setLabelSchemeOpts( schemes.map((item: any) => ({ label: item.name, value: item.name })) ) setAdminUserOpts( (adminRes ?? []).map((item: any) => ({ label: item.label, value: String(item.value), })) ) setTypeOpts( (typeRes ?? []).map((name) => ({ label: name, value: name })) ) } catch { setLabelSchemeOpts([]) setAdminUserOpts([]) setTypeOpts([]) } } initFormOpts() }, [opened]) useEffect(() => { if (!opened) return const run = async () => { form.setFieldValue("label_schema_version", "") setVersionOpts([]) if (!labelSchema) return try { const res = await getAllVersionByName(labelSchema) const list = (res as any)?.label_schema_version_list ?? [] setVersionOpts( list.map((item: any) => ({ label: item.version, value: item.version, })) ) } catch { setVersionOpts([]) } } run() // eslint-disable-next-line react-hooks/exhaustive-deps }, [labelSchema, opened]) useEffect(() => { if (!opened) return if (isDynamic) { form.setFieldValue("data_source_radio", "") form.setFieldValue("data_source", "") queueMicrotask(() => setDataSize(0)) form.clearFieldError("data_source") } // eslint-disable-next-line react-hooks/exhaustive-deps }, [isDynamic, opened]) const triggerCheckDataSource = (value: string) => { if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current) if (!value) { setDataSize(0) form.clearFieldError("data_source") return } const radio = form.values.data_source_radio if (!projectType) { setDataSize(0) form.setFieldError("data_source", "请先选择所属业务") return } if (radio !== "0" && radio !== "1") { setDataSize(0) form.setFieldError("data_source", "请先选择标注数据源对应来源类型") return } debounceTimerRef.current = setTimeout(async () => { try { const res = await checkLabelDataSource({ project_type: projectType, nfs_path: value, flag: Number(radio), }) const errorCode = (res as any)?.error_code const size = (res as any)?.data_size ?? 0 const errorMap = new Map([ [1, "nfs路径不存在"], [2, "nfs路径下不存在data目录"], [3, "nfs路径下不存在tag目录"], [4, "tag文件数量小于data文件数量"], [5, "pattern.json文件不存在"], [6, "clip.json文件不合法"], [7, "tag.json文件不合法"], [8, "pattern.json文件不合法"], ]) if (errorCode === 0) { setDataSize(size) form.clearFieldError("data_source") } else if (errorMap.has(errorCode)) { setDataSize(0) form.setFieldError( "data_source", errorMap.get(errorCode) || "标注数据源填写有误" ) } else { setDataSize(0) form.setFieldError("data_source", "标注数据源填写有误") } } catch (e) { setDataSize(0) form.setFieldError( "data_source", e instanceof Error ? e.message : "标注数据源校验失败" ) } }, 1000) } const canSubmit = useMemo(() => { if (!opened) return false if (!form.values.project_name || /^\s*$/.test(form.values.project_name)) return false if (!form.values.project_type) return false if (!form.values.label_schema_name || !form.values.label_schema_version) return false if (!form.values.admin_user.length) return false if (!form.values.is_dynamic) { if (!form.values.data_source_radio) return false if (!form.values.data_source) return false if (form.errors.data_source) return false } return true }, [form.errors.data_source, form.values, opened]) return ( onCloseAction()} title="新增标注任务" centered size="50%" closeOnClickOutside={false}> } title="提示"> 如标注数据需预标或辅助标注,请先前往数据中心MDS模块进行数据处理
{ if (!canSubmit) return const data: any = { ...values } data.is_dynamic = values.is_dynamic ? 1 : 0 data.is_embedding = values.is_embedding ? 1 : 0 data.data_source = values.data_source ?? "" data.create_user = userName ?? "" data.data_size = dataSize data.admin_user = values.admin_user .map((v) => Number(v)) .filter((n) => Number.isFinite(n)) data.remarks = values.remark || undefined delete data.remark delete data.data_source_radio try { await projectAdd(data) notifications.show({ color: "green", title: "项目创建成功", message: "已创建项目", }) form.reset() setDataSize(0) onCloseAction(true) } catch (e) { notifications.show({ color: "red", title: "创建失败", message: e instanceof Error ? e.message : "请求失败", }) } })}>
form.setFieldValue("label_schema_name", v ?? "") } error={form.errors.label_schema_name} />