Merge branch 'ModelEngine-Group:main' into develop_label_tool

This commit is contained in:
Jinglong Wang
2025-10-22 16:51:40 +08:00
committed by GitHub
41 changed files with 224 additions and 238 deletions

View File

@@ -168,12 +168,12 @@ function CardView<T extends BaseCardDataType>(props: CardViewProps<T>) {
const ops = (item) => const ops = (item) =>
typeof operations === "function" ? operations(item) : operations; typeof operations === "function" ? operations(item) : operations;
return ( return (
<div className="flex-1 flex flex-col overflow-auto"> <div className="flex-overflow-hidden">
<div className="overflow-auto grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4 gap-4"> <div className="flex-overflow-auto grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4 gap-4">
{data.map((item) => ( {data.map((item) => (
<div <div
key={item.id} key={item.id}
className="border border-gray-100 rounded-lg p-4 bg-white hover:shadow-lg transition-shadow duration-200" className="border-card p-4 bg-white hover:shadow-lg transition-shadow duration-200"
> >
<div className="flex flex-col space-y-4 h-full"> <div className="flex flex-col space-y-4 h-full">
{/* Header */} {/* Header */}

View File

@@ -48,7 +48,7 @@ function DetailHeader<T>({
<div className="flex items-start justify-between"> <div className="flex items-start justify-between">
<div className="flex items-start gap-4 flex-1"> <div className="flex items-start gap-4 flex-1">
<div <div
className={`w-16 h-16 text-white rounded-xl flex items-center justify-center shadow-lg ${ className={`w-16 h-16 text-white rounded-lg flex-center shadow-lg ${
data?.iconColor data?.iconColor
? data.iconColor ? data.iconColor
: "bg-gradient-to-br from-blue-100 to-blue-200" : "bg-gradient-to-br from-blue-100 to-blue-200"

View File

@@ -1,14 +1,15 @@
import { Button } from "antd"; import { Button } from "antd";
const DevelopmentInProgress = ({ showHome = true, showTime = "" }) => {
const DevelopmentInProgress = ({ showHome = true }) => {
return ( return (
<div className="mt-40 flex flex-col items-center justify-center"> <div className="mt-40 flex flex-col items-center justify-center">
<div className="hero-icon">🚧</div> <div className="hero-icon">🚧</div>
<h1 className="text-2xl font-bold"></h1> <h1 className="text-2xl font-bold"></h1>
<p className="mt-4"> {showTime && (
<b>2025.10.30</b> <p className="mt-4">
<b>{showTime}</b>
</p>
</p>
)}
{showHome && ( {showHome && (
<Button <Button
type="primary" type="primary"

View File

@@ -32,7 +32,7 @@ const RadioCard: React.FC<RadioCardProps> = ({
{options.map((option) => ( {options.map((option) => (
<div <div
key={option.value} key={option.value}
className="border border-gray-200 rounded-lg hover:shadow-lg p-4 text-center" className="border-card hover:shadow-lg p-4 text-center"
style={{ style={{
borderColor: value === option.value ? "#1677ff" : undefined, borderColor: value === option.value ? "#1677ff" : undefined,
background: value === option.value ? "#e6f7ff" : undefined, background: value === option.value ? "#e6f7ff" : undefined,

View File

@@ -30,7 +30,7 @@ function CustomTag({
return ( return (
<div <div
key={tag.id} key={tag.id}
className="flex items-center justify-between px-4 py-2 border border-gray-100 rounded-md hover:bg-gray-50" className="flex items-center justify-between px-4 py-2 border-card hover:bg-gray-50"
> >
{editingTag?.id === tag.id ? ( {editingTag?.id === tag.id ? (
<div className="flex gap-2 flex-1"> <div className="flex gap-2 flex-1">
@@ -92,17 +92,6 @@ function CustomTag({
); );
} }
export const mockPreparedTags = [
{ id: "1", name: "重要" },
{ id: "2", name: "待处理" },
{ id: "3", name: "已完成" },
{ id: "4", name: "审核中" },
{ id: "5", name: "高优先级" },
{ id: "6", name: "低优先级" },
{ id: "7", name: "客户A" },
{ id: "8", name: "客户B" },
];
const TagManager: React.FC = ({ const TagManager: React.FC = ({
onFetch, onFetch,
onCreate, onCreate,
@@ -112,7 +101,7 @@ const TagManager: React.FC = ({
onFetch: () => Promise<any>; onFetch: () => Promise<any>;
onCreate: (tag: Pick<TagItem, "name">) => Promise<{ ok: boolean }>; onCreate: (tag: Pick<TagItem, "name">) => Promise<{ ok: boolean }>;
onDelete: (tagId: number) => Promise<{ ok: boolean }>; onDelete: (tagId: number) => Promise<{ ok: boolean }>;
onUpdate: (oldTagId: number, newTag: string) => Promise<{ ok: boolean }>; onUpdate: (tag: TagItem) => Promise<{ ok: boolean }>;
}) => { }) => {
const [showTagManager, setShowTagManager] = useState(false); const [showTagManager, setShowTagManager] = useState(false);
const { message } = App.useApp(); const { message } = App.useApp();
@@ -121,9 +110,6 @@ const TagManager: React.FC = ({
const [editingTag, setEditingTag] = useState<string | null>(null); const [editingTag, setEditingTag] = useState<string | null>(null);
const [editingTagValue, setEditingTagValue] = useState(""); const [editingTagValue, setEditingTagValue] = useState("");
// 预置标签
const [preparedTags, setPreparedTags] = useState(mockPreparedTags);
// 获取标签列表 // 获取标签列表
const fetchTags = async () => { const fetchTags = async () => {
if (!onFetch) return; if (!onFetch) return;
@@ -161,7 +147,7 @@ const TagManager: React.FC = ({
const updateTag = async (oldTag: TagItem, newTag: string) => { const updateTag = async (oldTag: TagItem, newTag: string) => {
try { try {
await onUpdate?.(oldTag.id, { ...oldTag, name: newTag }); await onUpdate?.({ ...oldTag, name: newTag });
fetchTags(); fetchTags();
message.success("标签更新成功"); message.success("标签更新成功");
} catch (error) { } catch (error) {
@@ -213,55 +199,48 @@ const TagManager: React.FC = ({
title="标签管理" title="标签管理"
width={500} width={500}
> >
<div className="space-y-4"> <div className="space-y-4 flex-overflow">
{/* Add New Tag */} {/* Add New Tag */}
<div className="space-y-2"> <div className="flex gap-2">
<div className="flex gap-2"> <Input
<Input placeholder="输入标签名称..."
placeholder="输入标签名称..." value={newTag}
value={newTag} allowClear
allowClear onChange={(e) => setNewTag(e.target.value)}
onChange={(e) => setNewTag(e.target.value)} onKeyPress={(e) => {
onKeyPress={(e) => { if (e.key === "Enter") {
if (e.key === "Enter") { addTag(e.target.value);
addTag(e.target.value); }
} }}
}} />
/> <Button
<Button type="primary"
type="primary" onClick={handleCreateNewTag}
onClick={handleCreateNewTag} disabled={!newTag.trim()}
disabled={!newTag.trim()} icon={<PlusOutlined />}
icon={<PlusOutlined />} >
>
</Button>
</Button> </div>
<div className="flex-overflow">
<div className="overflow-auto grid grid-cols-2 gap-2">
{tags.map((tag) => (
<CustomTag
isEditable
key={tag.id}
tag={tag}
editingTag={editingTag}
editingTagValue={editingTagValue}
setEditingTag={setEditingTag}
setEditingTagValue={setEditingTagValue}
handleEditTag={handleEditTag}
handleCancelEdit={handleCancelEdit}
handleDeleteTag={handleDeleteTag}
/>
))}
</div> </div>
</div> </div>
<h2 className="font-large font-bold w-full"></h2>
<div className="grid grid-cols-2 gap-2">
{preparedTags.length > 0 &&
preparedTags.map((tag) => <CustomTag key={tag.id} tag={tag} />)}
</div>
<h2 className="font-large font-bold w-full"></h2>
<div className="grid grid-cols-2 gap-2 mt-4">
{tags.map((tag) => (
<CustomTag
isEditable
key={tag.id}
tag={tag}
editingTag={editingTag}
editingTagValue={editingTagValue}
setEditingTag={setEditingTag}
setEditingTagValue={setEditingTagValue}
handleEditTag={handleEditTag}
handleCancelEdit={handleCancelEdit}
handleDeleteTag={handleDeleteTag}
/>
))}
</div>
</div> </div>
</Drawer> </Drawer>
</> </>

View File

@@ -89,7 +89,7 @@ export default function TaskPopover() {
{tasks.map((task) => ( {tasks.map((task) => (
<div <div
key={task.id} key={task.id}
className="p-3 border border-gray-100 rounded-lg hover:bg-gray-50" className="p-3 border-card hover:bg-gray-50"
> >
<div className="space-y-2"> <div className="space-y-2">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">

View File

@@ -42,4 +42,28 @@
opacity: 100%; opacity: 100%;
visibility: visible; visibility: visible;
transform: translateX(0); transform: translateX(0);
} }
@layer components {
.flex-center {
@apply flex items-center justify-center;
}
.flex-overflow-auto {
@apply flex-1 flex flex-col overflow-auto h-full;
}
.flex-overflow-hidden {
@apply flex flex-col h-full overflow-hidden;
}
.border-card {
@apply border border-[#f0f0f0] rounded-lg bg-white;
}
.border {
@apply border border-gray-100;
}
.border-bottom {
@apply border-b border-gray-100;
}
.border-top {
@apply border-t border-gray-100;
}
}

View File

@@ -429,7 +429,7 @@ export default function ImageAnnotationWorkspace({
}`} }`}
onClick={() => setSelectedImageIndex(index)} onClick={() => setSelectedImageIndex(index)}
> >
<div className="w-8 h-8 bg-gray-200 rounded flex items-center justify-center text-sm font-medium mr-3"> <div className="w-8 h-8 bg-gray-200 rounded flex-center text-sm font-medium mr-3">
{index + 1} {index + 1}
</div> </div>
<img <img
@@ -462,7 +462,7 @@ export default function ImageAnnotationWorkspace({
</div> </div>
</div> </div>
<div className="flex-1 border rounded-lg overflow-hidden bg-gray-100 relative"> <div className="flex-1 border-card overflow-hidden bg-gray-100 relative">
<canvas <canvas
ref={canvasRef} ref={canvasRef}
width={800} width={800}

View File

@@ -123,7 +123,7 @@ export default function AnnotationTaskCreate() {
}; };
return ( return (
<div className="h-full flex flex-col overflow-auto"> <div className="flex-overflow-auto">
{/* Header */} {/* Header */}
<div className="flex items-center mb-2"> <div className="flex items-center mb-2">
<Link to="/data/annotation"> <Link to="/data/annotation">
@@ -134,7 +134,7 @@ export default function AnnotationTaskCreate() {
<h1 className="text-xl font-bold bg-clip-text"></h1> <h1 className="text-xl font-bold bg-clip-text"></h1>
</div> </div>
<div className="h-full flex-1 overflow-y-auto flex flex-col bg-white rounded-lg shadow-sm"> <div className="flex-overflow-auto bg-white rounded-lg shadow-sm">
<div className="flex-1 overflow-y-auto p-6"> <div className="flex-1 overflow-y-auto p-6">
<Form <Form
form={form} form={form}

View File

@@ -1,5 +1,8 @@
import { queryDatasetsUsingGet } from "@/pages/DataManagement/dataset.api"; import { queryDatasetsUsingGet } from "@/pages/DataManagement/dataset.api";
import { datasetTypeMap } from "@/pages/DataManagement/dataset.const"; import {
datasetTypeMap,
mapDataset,
} from "@/pages/DataManagement/dataset.const";
import { Button, Form, Input, Modal, Select } from "antd"; import { Button, Form, Input, Modal, Select } from "antd";
import TextArea from "antd/es/input/TextArea"; import TextArea from "antd/es/input/TextArea";
import { Database } from "lucide-react"; import { Database } from "lucide-react";
@@ -26,7 +29,7 @@ export default function CreateAnnotationTask({
page: 0, page: 0,
size: 1000, size: 1000,
}); });
setDatasets(data.content || []); setDatasets(data.content.map(mapDataset) || []);
}; };
fetchDatasets(); fetchDatasets();
}, [open]); }, [open]);
@@ -74,22 +77,20 @@ export default function CreateAnnotationTask({
> >
<Select <Select
placeholder="请选择数据集" placeholder="请选择数据集"
options={datasets.map((dataset) => ({ options={datasets.map((dataset) => {
label: ( return {
<div className="flex items-center justify-between gap-3 py-2"> label: (
<div className="flex items-center font-sm text-gray-900"> <div className="flex items-center justify-between gap-3 py-2">
<span> <div className="flex items-center font-sm text-gray-900">
{dataset.icon || <Database className="w-4 h-4 mr-2" />} <span className="mr-2">{dataset.icon}</span>
</span> <span>{dataset.name}</span>
<span>{dataset.name}</span> </div>
<div className="text-xs text-gray-500">{dataset.size}</div>
</div> </div>
<div className="text-xs text-gray-500"> ),
{datasetTypeMap[dataset?.datasetType]?.label} value: dataset.id,
</div> };
</div> })}
),
value: dataset.id,
}))}
/> />
</Form.Item> </Form.Item>
</Form> </Form>

View File

@@ -19,8 +19,10 @@ import {
import { mapAnnotationTask } from "../annotation.const"; import { mapAnnotationTask } from "../annotation.const";
import CreateAnnotationTask from "../Create/components/CreateAnnptationTaskDialog"; import CreateAnnotationTask from "../Create/components/CreateAnnptationTaskDialog";
import { ColumnType } from "antd/es/table"; import { ColumnType } from "antd/es/table";
import DevelopmentInProgress from "@/components/DevelopmentInProgress";
export default function DataAnnotation() { export default function DataAnnotation() {
return <DevelopmentInProgress showTime="2025.10.30" />;
const navigate = useNavigate(); const navigate = useNavigate();
const [viewMode, setViewMode] = useState<"list" | "card">("list"); const [viewMode, setViewMode] = useState<"list" | "card">("list");
const [showCreateDialog, setShowCreateDialog] = useState(false); const [showCreateDialog, setShowCreateDialog] = useState(false);

View File

@@ -2,7 +2,7 @@ import { get, post, put, del, download } from "@/utils/request";
// 标注任务管理相关接口 // 标注任务管理相关接口
export function queryAnnotationTasksUsingGet(params?: any) { export function queryAnnotationTasksUsingGet(params?: any) {
return get("/api/project/mappings/list", params); return get("/project/mappings/list", params);
} }
export function createAnnotationTaskUsingPost(data: any) { export function createAnnotationTaskUsingPost(data: any) {

View File

@@ -101,9 +101,9 @@ export default function CleansingTaskCreate() {
</div> </div>
</div> </div>
{/* Step Content */} {/* Step Content */}
<div className="h-full mb-4 flex flex-col overflow-auto flex-1 bg-white rounded shadow-sm"> <div className="flex-overflow-auto bg-white border-card">
<div className="flex-1 overflow-auto m-6">{renderStepContent()}</div> <div className="flex-1 overflow-auto m-6">{renderStepContent()}</div>
<div className="flex justify-end p-6 gap-3 border-t border-gray-200"> <div className="flex justify-end p-6 gap-3 border-top">
<Button onClick={() => navigate("/data/cleansing")}></Button> <Button onClick={() => navigate("/data/cleansing")}></Button>
{currentStep > 1 && <Button onClick={handlePrev}></Button>} {currentStep > 1 && <Button onClick={handlePrev}></Button>}
{currentStep === 2 ? ( {currentStep === 2 ? (

View File

@@ -90,9 +90,9 @@ export default function CleansingTemplateCreate() {
</div> </div>
</div> </div>
<div className="h-full mb-4 flex flex-col overflow-auto flex-1 bg-white rounded shadow-sm"> <div className="flex-overflow-auto border-card">
<div className="flex-1 overflow-auto m-6">{renderStepContent()}</div> <div className="flex-1 overflow-auto m-6">{renderStepContent()}</div>
<div className="flex justify-end p-6 gap-3 border-t border-gray-200"> <div className="flex justify-end p-6 gap-3 border-top">
<Button onClick={() => navigate("/data/cleansing")}></Button> <Button onClick={() => navigate("/data/cleansing")}></Button>
{currentStep > 1 && <Button onClick={handlePrev}></Button>} {currentStep > 1 && <Button onClick={handlePrev}></Button>}
{currentStep === 2 ? ( {currentStep === 2 ? (

View File

@@ -3,6 +3,7 @@ import { queryDatasetsUsingGet } from "@/pages/DataManagement/dataset.api";
import { import {
datasetTypeMap, datasetTypeMap,
datasetTypes, datasetTypes,
mapDataset,
} from "@/pages/DataManagement/dataset.const"; } from "@/pages/DataManagement/dataset.const";
import { import {
Dataset, Dataset,
@@ -34,7 +35,7 @@ export default function CreateTaskStepOne({
const fetchDatasets = async () => { const fetchDatasets = async () => {
const { data } = await queryDatasetsUsingGet({ page: 0, size: 1000 }); const { data } = await queryDatasetsUsingGet({ page: 0, size: 1000 });
setDatasets(data.content || []); setDatasets(data.content.map(mapDataset) || []);
}; };
useEffect(() => { useEffect(() => {
@@ -76,22 +77,20 @@ export default function CreateTaskStepOne({
<Form.Item label="源数据集" name="srcDatasetId" required> <Form.Item label="源数据集" name="srcDatasetId" required>
<Select <Select
placeholder="请选择源数据集" placeholder="请选择源数据集"
options={datasets.map((dataset) => ({ options={datasets.map((dataset) => {
label: ( return {
<div className="flex items-center justify-between gap-3 py-2"> label: (
<div className="flex items-center font-sm text-gray-900"> <div className="flex items-center justify-between gap-3 py-2">
<span> <div className="flex items-center font-sm text-gray-900">
{dataset.icon || <Database className="w-4 h-4 mr-2" />} <span className="mr-2">{dataset.icon}</span>
</span> <span>{dataset.name}</span>
<span>{dataset.name}</span> </div>
<div className="text-xs text-gray-500">{dataset.size}</div>
</div> </div>
<div className="text-xs text-gray-500"> ),
{datasetTypeMap[dataset?.datasetType]?.label} value: dataset.id,
</div> };
</div> })}
),
value: dataset.id,
}))}
/> />
</Form.Item> </Form.Item>
<Form.Item label="目标数据集名称" name="destDatasetName" required> <Form.Item label="目标数据集名称" name="destDatasetName" required>

View File

@@ -105,7 +105,7 @@ const OperatorFlow: React.FC<OperatorFlowProps> = ({
</div> </div>
{/* 编排区域 */} {/* 编排区域 */}
<div <div
className="flex-1 overflow-auto p-4 flex flex-col gap-2" className="flex-overflow-auto p-4 gap-2"
onDragOver={(e) => e.preventDefault()} onDragOver={(e) => e.preventDefault()}
onDragLeave={handleContainerDragLeave} onDragLeave={handleContainerDragLeave}
onDrop={handleDropToContainer} onDrop={handleDropToContainer}

View File

@@ -56,7 +56,7 @@ export default function ProcessFlowDiagram() {
]; ];
return ( return (
<div className="rounded-xl border border-gray-200 p-6 bg-white"> <div className="border-card p-6">
<div className="w-full flex items-center justify-center"> <div className="w-full flex items-center justify-center">
<div className="w-full flex items-center space-x-12"> <div className="w-full flex items-center space-x-12">
{flowSteps.map((step, index) => { {flowSteps.map((step, index) => {

View File

@@ -16,7 +16,11 @@ export interface CleansingTask {
color: string; color: string;
}; };
startedAt: string; startedAt: string;
progress: number; progress: {
finishedFileNum: number;
process: 100,
totalFileNum: number;
};
operators: OperatorI[]; operators: OperatorI[];
createdAt: string; createdAt: string;
updatedAt: string; updatedAt: string;

View File

@@ -59,7 +59,7 @@ const defaultTemplates = [
]; ];
export default function CollectionTaskCreate() { export default function CollectionTaskCreate() {
return <DevelopmentInProgress />; return <DevelopmentInProgress showTime="2025.10.30" />;
const navigate = useNavigate(); const navigate = useNavigate();
const [form] = Form.useForm(); const [form] = Form.useForm();

View File

@@ -10,7 +10,7 @@ export default function DataCollection() {
const navigate = useNavigate(); const navigate = useNavigate();
const [activeTab, setActiveTab] = useState("task-management"); const [activeTab, setActiveTab] = useState("task-management");
return <DevelopmentInProgress />; return <DevelopmentInProgress showTime="2025.10.30" />;
return ( return (
<div> <div>

View File

@@ -180,9 +180,7 @@ export default function DataEvaluationPage() {
setTasks(tasks.filter((task) => task.id !== taskId)); setTasks(tasks.filter((task) => task.id !== taskId));
}; };
return ( return <DevelopmentInProgress showTime="2025.11.30" />;
<DevelopmentInProgress />
);
// 主列表界面 // 主列表界面
return ( return (
<div> <div>

View File

@@ -56,7 +56,7 @@ export default function DatasetCreate() {
</div> </div>
{/* form */} {/* form */}
<div className="h-full flex flex-col flex-1 overflow-auto bg-white border-gray-200 rounded shadow-sm"> <div className="flex-overflow-auto border-card">
<div className="flex-1 p-6 overflow-auto"> <div className="flex-1 p-6 overflow-auto">
<Form <Form
form={form} form={form}
@@ -67,7 +67,7 @@ export default function DatasetCreate() {
<BasicInformation data={newDataset} setData={setNewDataset} /> <BasicInformation data={newDataset} setData={setNewDataset} />
</Form> </Form>
</div> </div>
<div className="flex gap-2 justify-end p-6 border-t border-gray-200"> <div className="flex gap-2 justify-end p-6 border-top">
<Button onClick={() => navigate("/data/management")}></Button> <Button onClick={() => navigate("/data/management")}></Button>
<Button type="primary" onClick={handleSubmit}> <Button type="primary" onClick={handleSubmit}>

View File

@@ -2,7 +2,6 @@ import RadioCard from "@/components/RadioCard";
import { Input, Select, Form } from "antd"; import { Input, Select, Form } from "antd";
import { datasetTypes } from "../../dataset.const"; import { datasetTypes } from "../../dataset.const";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { mockPreparedTags } from "@/components/TagManagement";
import { queryDatasetTagsUsingGet } from "../../dataset.api"; import { queryDatasetTagsUsingGet } from "../../dataset.api";
export default function BasicInformation({ export default function BasicInformation({
@@ -26,26 +25,11 @@ export default function BasicInformation({
const fetchTags = async () => { const fetchTags = async () => {
try { try {
const { data } = await queryDatasetTagsUsingGet(); const { data } = await queryDatasetTagsUsingGet();
const preparedTags = mockPreparedTags.map((tag) => ({
label: tag.name,
value: tag.name,
}));
const customTags = data.map((tag) => ({ const customTags = data.map((tag) => ({
label: tag.name, label: tag.name,
value: tag.name, value: tag.name,
})); }));
setTagOptions([ setTagOptions(customTags);
{
label: <span></span>,
title: "prepared",
options: preparedTags,
},
{
label: <span></span>,
title: "custom",
options: customTags,
},
]);
} catch (error) { } catch (error) {
console.error("Error fetching tags: ", error); console.error("Error fetching tags: ", error);
} }

View File

@@ -121,7 +121,7 @@ export default function DatasetDetail() {
{ {
icon: <Clock className="text-blue-400 w-4 h-4" />, icon: <Clock className="text-blue-400 w-4 h-4" />,
key: "time", key: "time",
value: dataset?.createdAt, value: dataset?.updatedAt,
}, },
]; ];
@@ -200,7 +200,7 @@ export default function DatasetDetail() {
}, },
}} }}
/> />
<div className="h-full flex flex-col flex-1 overflow-auto p-6 pt-2 bg-white rounded-md shadow"> <div className="flex-overflow-auto p-6 pt-2 bg-white rounded-md shadow">
<Tabs activeKey={activeTab} items={tabList} onChange={setActiveTab} /> <Tabs activeKey={activeTab} items={tabList} onChange={setActiveTab} />
<div className="h-full overflow-auto"> <div className="h-full overflow-auto">
{activeTab === "overview" && ( {activeTab === "overview" && (

View File

@@ -20,8 +20,8 @@ import {
deleteDatasetByIdUsingDelete, deleteDatasetByIdUsingDelete,
createDatasetTagUsingPost, createDatasetTagUsingPost,
queryDatasetTagsUsingGet, queryDatasetTagsUsingGet,
updateDatasetTagByIdUsingPut, deleteDatasetTagUsingDelete,
deleteDatasetTagByIdUsingDelete, updateDatasetTagUsingPut,
} from "../dataset.api"; } from "../dataset.api";
import { formatBytes } from "@/utils/unit"; import { formatBytes } from "@/utils/unit";
import EditDataset from "../Create/EditDataset"; import EditDataset from "../Create/EditDataset";
@@ -295,8 +295,8 @@ export default function DatasetManagementPage() {
{/* tasks */} {/* tasks */}
<TagManager <TagManager
onCreate={createDatasetTagUsingPost} onCreate={createDatasetTagUsingPost}
onDelete={deleteDatasetTagByIdUsingDelete} onDelete={(ids: string) => deleteDatasetTagUsingDelete({ ids })}
onUpdate={updateDatasetTagByIdUsingPut} onUpdate={updateDatasetTagUsingPut}
onFetch={queryDatasetTagsUsingGet} onFetch={queryDatasetTagsUsingGet}
/> />
<Link to="/data/management/create"> <Link to="/data/management/create">

View File

@@ -97,13 +97,13 @@ export function createDatasetTagUsingPost(data: any) {
} }
// 更新数据集标签 // 更新数据集标签
export function updateDatasetTagByIdUsingPut(id: string | number, data: any) { export function updateDatasetTagUsingPut(data: any) {
return put(`/api/data-management/tags/${id}`, data); return put(`/api/data-management/tags`, data);
} }
// 删除数据集标签 // 删除数据集标签
export function deleteDatasetTagByIdUsingDelete(id: string | number) { export function deleteDatasetTagUsingDelete(data: any) {
return del(`/api/data-management/tags/${id}`); return del(`/api/data-management/tags`, data);
} }
// 数据集质量检查 // 数据集质量检查

View File

@@ -23,6 +23,8 @@ import {
Music, Music,
Videotape, Videotape,
Database, Database,
Image,
ScanText,
} from "lucide-react"; } from "lucide-react";
export const datasetTypeMap: Record< export const datasetTypeMap: Record<
@@ -41,8 +43,8 @@ export const datasetTypeMap: Record<
value: DatasetType.TEXT, value: DatasetType.TEXT,
label: "文本", label: "文本",
order: 1, order: 1,
icon: FileText, icon: ScanText,
iconColor: "#3b82f6", iconColor: "blue",
children: [ children: [
DatasetSubType.TEXT_DOCUMENT, DatasetSubType.TEXT_DOCUMENT,
DatasetSubType.TEXT_WEB, DatasetSubType.TEXT_WEB,
@@ -54,8 +56,8 @@ export const datasetTypeMap: Record<
value: DatasetType.IMAGE, value: DatasetType.IMAGE,
label: "图像", label: "图像",
order: 2, order: 2,
icon: FileImage, icon: Image,
iconColor: "#3b82f6", iconColor: "green",
children: [DatasetSubType.IMAGE_IMAGE, DatasetSubType.IMAGE_CAPTION], children: [DatasetSubType.IMAGE_IMAGE, DatasetSubType.IMAGE_CAPTION],
description: "用于处理和分析图像数据的数据集", description: "用于处理和分析图像数据的数据集",
}, },
@@ -64,7 +66,7 @@ export const datasetTypeMap: Record<
label: "音频", label: "音频",
order: 3, order: 3,
icon: Music, icon: Music,
iconColor: "#3b82f6", iconColor: "orange",
children: [DatasetSubType.AUDIO_AUDIO, DatasetSubType.AUDIO_JSONL], children: [DatasetSubType.AUDIO_AUDIO, DatasetSubType.AUDIO_JSONL],
description: "用于处理和分析音频数据的数据集", description: "用于处理和分析音频数据的数据集",
}, },
@@ -73,7 +75,7 @@ export const datasetTypeMap: Record<
label: "视频", label: "视频",
order: 3, order: 3,
icon: Video, icon: Video,
iconColor: "#3b82f6", iconColor: "purple",
children: [DatasetSubType.VIDEO_VIDEO, DatasetSubType.VIDEO_JSONL], children: [DatasetSubType.VIDEO_VIDEO, DatasetSubType.VIDEO_JSONL],
description: "用于处理和分析视频数据的数据集", description: "用于处理和分析视频数据的数据集",
}, },
@@ -193,14 +195,22 @@ export const dataSourceMap: Record<string, { label: string; value: string }> = {
export const dataSourceOptions = Object.values(dataSourceMap); export const dataSourceOptions = Object.values(dataSourceMap);
export function mapDataset(dataset: Dataset) { export function mapDataset(dataset: Dataset) {
const IconComponent = datasetTypeMap[dataset?.datasetType]?.icon || null; const { icon: IconComponent, iconColor } =
datasetTypeMap[dataset?.datasetType] || {};
return { return {
...dataset, ...dataset,
type: datasetTypeMap[dataset.datasetType]?.label || "未知", type: datasetTypeMap[dataset.datasetType]?.label || "未知",
size: formatBytes(dataset.totalSize || 0), size: formatBytes(dataset.totalSize || 0),
createdAt: formatDateTime(dataset.createdAt) || "--", createdAt: formatDateTime(dataset.createdAt) || "--",
updatedAt: formatDateTime(dataset?.updatedAt) || "--", updatedAt: formatDateTime(dataset?.updatedAt) || "--",
icon: IconComponent ? <IconComponent className="w-4 h-4" /> : <Database />, icon: IconComponent ? (
<IconComponent
className="w-5 h-5 text-gray-500"
// style={{ color: iconColor }}
/>
) : (
<Database />
),
status: datasetStatusMap[dataset.status], status: datasetStatusMap[dataset.status],
statistics: [ statistics: [
{ label: "文件数", value: dataset.fileCount || 0 }, { label: "文件数", value: dataset.fileCount || 0 },

View File

@@ -37,7 +37,7 @@ const { TextArea } = Input;
const { Option } = Select; const { Option } = Select;
const KnowledgeBaseCreatePage: React.FC = () => { const KnowledgeBaseCreatePage: React.FC = () => {
return <DevelopmentInProgress />; return <DevelopmentInProgress showTime="2025.10.30" />;
const navigate = useNavigate(); const navigate = useNavigate();
const [form] = Form.useForm(); const [form] = Form.useForm();
const [knowledgeBases, setKnowledgeBases] = const [knowledgeBases, setKnowledgeBases] =

View File

@@ -11,22 +11,12 @@ import {
FileText, FileText,
Download, Download,
} from "lucide-react"; } from "lucide-react";
import { import { Card, Button, Badge, Input, Tabs, Modal, Breadcrumb, Tag } from "antd";
Card, import { mockChunks, mockQAPairs, sliceOperators } from "@/mock/knowledgeBase";
Button, import type {
Badge, KnowledgeBase,
Input, KBFile,
Tabs, } from "@/pages/KnowledgeGeneration/knowledge-base.model";
Modal,
Breadcrumb,
Tag,
} from "antd";
import {
mockChunks,
mockQAPairs,
sliceOperators,
} from "@/mock/knowledgeBase";
import type { KnowledgeBase, KBFile } from "@/pages/KnowledgeGeneration/knowledge-base.model";
import { Link, useNavigate } from "react-router"; import { Link, useNavigate } from "react-router";
import DetailHeader from "@/components/DetailHeader"; import DetailHeader from "@/components/DetailHeader";
import DevelopmentInProgress from "@/components/DevelopmentInProgress"; import DevelopmentInProgress from "@/components/DevelopmentInProgress";
@@ -59,7 +49,7 @@ const getStatusColor = (status: string) => {
}; };
const KnowledgeBaseFileDetail: React.FC = () => { const KnowledgeBaseFileDetail: React.FC = () => {
return <DevelopmentInProgress />; return <DevelopmentInProgress showTime="2025.10.30" />;
const navigate = useNavigate(); const navigate = useNavigate();
// 假设通过 props 或路由参数获取 selectedFile/selectedKB // 假设通过 props 或路由参数获取 selectedFile/selectedKB
const [selectedFile] = useState<KBFile>( const [selectedFile] = useState<KBFile>(

View File

@@ -20,7 +20,7 @@ import CardView from "@/components/CardView";
import DevelopmentInProgress from "@/components/DevelopmentInProgress"; import DevelopmentInProgress from "@/components/DevelopmentInProgress";
export default function KnowledgeGenerationPage() { export default function KnowledgeGenerationPage() {
return <DevelopmentInProgress />; return <DevelopmentInProgress showTime="2025.10.30" />;
const navigate = useNavigate(); const navigate = useNavigate();
const [knowledgeBases, setKnowledgeBases] = const [knowledgeBases, setKnowledgeBases] =
useState<KnowledgeBase[]>(mockKnowledgeBases); useState<KnowledgeBase[]>(mockKnowledgeBases);

View File

@@ -9,9 +9,9 @@ const MainLayout = () => {
{/* Sidebar */} {/* Sidebar */}
<Sidebar /> <Sidebar />
{/* Main Content */} {/* Main Content */}
<div className="flex-1 flex flex-col overflow-auto p-6"> <div className="flex-overflow-auto p-6">
{/* Content Area */} {/* Content Area */}
<div className="flex-1 flex flex-col overflow-auto"> <div className="flex-overflow-auto">
<Outlet /> <Outlet />
</div> </div>
</div> </div>

View File

@@ -1,4 +1,4 @@
import React, { memo, useEffect, useState } from "react"; import { memo, useEffect, useState } from "react";
import { Button, Menu, Popover } from "antd"; import { Button, Menu, Popover } from "antd";
import { import {
CloseOutlined, CloseOutlined,
@@ -105,7 +105,6 @@ const AsiderAndHeaderLayout = () => {
defaultOpenKeys={["synthesis"]} defaultOpenKeys={["synthesis"]}
onClick={({ key }) => { onClick={({ key }) => {
setActiveItem(key); setActiveItem(key);
console.log(`/data/${key}`);
navigate(`/data/${key}`); navigate(`/data/${key}`);
}} }}
/> />
@@ -169,10 +168,7 @@ const AsiderAndHeaderLayout = () => {
<div <div
className="fixed inset-0 z-40" className="fixed inset-0 z-40"
onClick={() => { onClick={() => {
console.log("clicked outside");
setTaskCenterVisible(false); setTaskCenterVisible(false);
toggleShowTaskPopover(false);
}} }}
/> />
)} )}

View File

@@ -123,7 +123,7 @@ export default function OperatorPluginCreate() {
}; };
return ( return (
<div className="h-full flex flex-col overflow-auto bg-gray-50"> <div className="flex-overflow-auto bg-gray-50">
{/* Header */} {/* Header */}
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
@@ -167,8 +167,8 @@ export default function OperatorPluginCreate() {
</div> </div>
{/* Content */} {/* Content */}
<div className="h-full flex flex-col flex-1 overflow-y-auto p-6 mt-4 bg-white rounded-md shadow"> <div className="flex-overflow-auto p-6 mt-4 bg-white border-card">
<div className="h-full w-full flex flex-col flex-1 overflow-y-auto"> <div className="flex-overflow-auto">
{uploadStep === "upload" && ( {uploadStep === "upload" && (
<UploadStep onUpload={handleFileUpload} isUploading={isUploading} /> <UploadStep onUpload={handleFileUpload} isUploading={isUploading} />
)} )}

View File

@@ -115,9 +115,9 @@ export default function OperatorMarketPage() {
</div> */} </div> */}
</div> </div>
{/* Main Content */} {/* Main Content */}
<div className="flex flex-1 overflow-auto h-full bg-white rounded-lg"> <div className="flex-overflow-auto flex-row border-card">
<div <div
className={`border-r border-gray-200 transition-all duration-300 ${ className={`border-r border-gray-100 transition-all duration-300 ${
showFilters showFilters
? "translate-x-0 w-56" ? "translate-x-0 w-56"
: "-translate-x-full w-0 opacity-0" : "-translate-x-full w-0 opacity-0"
@@ -130,7 +130,7 @@ export default function OperatorMarketPage() {
setSelectedFilters={setSelectedFilters} setSelectedFilters={setSelectedFilters}
/> />
</div> </div>
<div className="flex-1 bg-yellow flex flex-col px-4 my-4"> <div className="flex-overflow-auto p-6 ">
<div className="flex w-full items-top gap-4 border-b border-gray-200 mb-4"> <div className="flex w-full items-top gap-4 border-b border-gray-200 mb-4">
{!showFilters && ( {!showFilters && (
<Button <Button
@@ -139,9 +139,8 @@ export default function OperatorMarketPage() {
onClick={() => setShowFilters(true)} onClick={() => setShowFilters(true)}
/> />
)} )}
<div className="flex-1"> <div className="flex-1 mb-4">
<SearchControls <SearchControls
className="mb-4"
searchTerm={searchParams.keyword} searchTerm={searchParams.keyword}
onSearchChange={(keyword) => onSearchChange={(keyword) =>
setSearchParams({ ...searchParams, keyword }) setSearchParams({ ...searchParams, keyword })

View File

@@ -129,7 +129,7 @@ const Filters: React.FC<FiltersProps> = ({
); );
return ( return (
<div className="p-4 space-y-4 h-full overflow-y-auto"> <div className="p-6 space-y-4 h-full overflow-y-auto">
{/* Filter Header */} {/* Filter Header */}
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<h3 className="text-sm font-medium text-gray-900 flex items-center gap-2"> <h3 className="text-sm font-medium text-gray-900 flex items-center gap-2">
@@ -142,7 +142,7 @@ const Filters: React.FC<FiltersProps> = ({
className="cursor-pointer hover:text-blue-500" className="cursor-pointer hover:text-blue-500"
></Button> ></Button>
</Tooltip> </Tooltip>
<h4></h4>
</h3> </h3>
{hasActiveFilters && ( {hasActiveFilters && (
<span <span

View File

@@ -1,6 +1,6 @@
import { Button, Avatar, List, Tag, Badge } from "antd"; import { Button, List, Tag, Badge } from "antd";
import { DeleteOutlined, EditOutlined, StarFilled } from "@ant-design/icons"; import { DeleteOutlined, EditOutlined, StarFilled } from "@ant-design/icons";
import { Brain, Code, Cpu, Package, Zap, Settings, X } from "lucide-react"; import { Zap, Settings, X } from "lucide-react";
import { useState } from "react"; import { useState } from "react";
import { useNavigate } from "react-router"; import { useNavigate } from "react-router";
import { Operator } from "../../operator.model"; import { Operator } from "../../operator.model";
@@ -49,20 +49,10 @@ export function ListView({ operators, pagination }) {
statusConfig[status as keyof typeof statusConfig] || statusConfig.active statusConfig[status as keyof typeof statusConfig] || statusConfig.active
); );
}; };
const getTypeIcon = (type: string) => {
const iconMap = {
preprocessing: Code,
training: Brain,
inference: Cpu,
postprocessing: Package,
};
const IconComponent = iconMap[type as keyof typeof iconMap] || Code;
return <IconComponent className="w-4 h-4" />;
};
return ( return (
<List <List
className="p-4 overflow-auto mx-4" className="p-4 flex-1 overflow-auto mx-4"
dataSource={operators} dataSource={operators}
pagination={pagination} pagination={pagination}
renderItem={(operator) => ( renderItem={(operator) => (

View File

@@ -31,8 +31,8 @@ const { TextArea } = Input;
const { Option } = Select; const { Option } = Select;
export default function CreateRatioTask() { export default function CreateRatioTask() {
return <DevelopmentInProgress />; return <DevelopmentInProgress showTime="2025.11.30" />;
const navigate = useNavigate(); const navigate = useNavigate();
const [form] = Form.useForm(); const [form] = Form.useForm();
// 配比任务相关状态 // 配比任务相关状态

View File

@@ -28,7 +28,7 @@ import { SearchControls } from "@/components/SearchControls";
import DevelopmentInProgress from "@/components/DevelopmentInProgress"; import DevelopmentInProgress from "@/components/DevelopmentInProgress";
export default function RatioTasksPage() { export default function RatioTasksPage() {
return <DevelopmentInProgress />; return <DevelopmentInProgress showTime="2025.11.30" />;
const navigate = useNavigate(); const navigate = useNavigate();
const [searchQuery, setSearchQuery] = useState(""); const [searchQuery, setSearchQuery] = useState("");
const [filterStatus, setFilterStatus] = useState("all"); const [filterStatus, setFilterStatus] = useState("all");

View File

@@ -41,7 +41,7 @@ import DevelopmentInProgress from "@/components/DevelopmentInProgress";
const { TextArea } = Input; const { TextArea } = Input;
export default function SynthesisTaskCreate() { export default function SynthesisTaskCreate() {
return <DevelopmentInProgress />; return <DevelopmentInProgress showTime="2025.11.30" />;
const navigate = useNavigate(); const navigate = useNavigate();
const [form] = Form.useForm(); const [form] = Form.useForm();
const [searchQuery, setSearchQuery] = useState(""); const [searchQuery, setSearchQuery] = useState("");

View File

@@ -1,15 +1,15 @@
import { useState, useRef } from "react"; import { useState, useRef } from "react";
import { Card, Select, Input, Button, Badge, Divider, Form, message } from "antd";
import { import {
Plus, Card,
ArrowLeft, Select,
Play, Input,
Save, Button,
RefreshCw, Badge,
FileText, Divider,
Code, Form,
X, message,
} from "lucide-react"; } from "antd";
import { Plus, ArrowLeft, Play, Save, RefreshCw, Code, X } from "lucide-react";
import { useNavigate } from "react-router"; import { useNavigate } from "react-router";
import { mockTemplates } from "@/mock/annotation"; import { mockTemplates } from "@/mock/annotation";
import DevelopmentInProgress from "@/components/DevelopmentInProgress"; import DevelopmentInProgress from "@/components/DevelopmentInProgress";
@@ -17,9 +17,11 @@ import DevelopmentInProgress from "@/components/DevelopmentInProgress";
const { TextArea } = Input; const { TextArea } = Input;
export default function InstructionTemplateCreate() { export default function InstructionTemplateCreate() {
return <DevelopmentInProgress />; return <DevelopmentInProgress showTime="2025.11.30" />;
const navigate = useNavigate(); const navigate = useNavigate();
const [selectedTemplate, setSelectedTemplate] = useState<Template | null>(null); const [selectedTemplate, setSelectedTemplate] = useState<Template | null>(
null
);
const [isTestingTemplate, setIsTestingTemplate] = useState(false); const [isTestingTemplate, setIsTestingTemplate] = useState(false);
const [templates, setTemplates] = useState<Template[]>(mockTemplates); const [templates, setTemplates] = useState<Template[]>(mockTemplates);
const [variables, setVariables] = useState<string[]>([]); const [variables, setVariables] = useState<string[]>([]);
@@ -131,10 +133,7 @@ export default function InstructionTemplateCreate() {
{/* Header */} {/* Header */}
<div className="flex items-center justify-between mb-2"> <div className="flex items-center justify-between mb-2">
<div className="flex items-center"> <div className="flex items-center">
<Button <Button onClick={() => navigate("/data/synthesis/task")} type="text">
onClick={() => navigate("/data/synthesis/task")}
type="text"
>
<ArrowLeft className="w-4 h-4 mr-2" /> <ArrowLeft className="w-4 h-4 mr-2" />
</Button> </Button>
<h1 className="text-xl font-bold bg-clip-text"> <h1 className="text-xl font-bold bg-clip-text">
@@ -177,7 +176,9 @@ export default function InstructionTemplateCreate() {
<Form.Item label="模板描述" name="description"> <Form.Item label="模板描述" name="description">
<Input placeholder="简要描述模板的用途和特点" /> <Input placeholder="简要描述模板的用途和特点" />
</Form.Item> </Form.Item>
<h2 className="font-medium text-gray-900 text-lg mt-6 mb-2">Prompt内容</h2> <h2 className="font-medium text-gray-900 text-lg mt-6 mb-2">
Prompt内容
</h2>
<Form.Item <Form.Item
label="Prompt内容" label="Prompt内容"
name="prompt" name="prompt"
@@ -194,7 +195,9 @@ export default function InstructionTemplateCreate() {
使 {"{变量名}"} {"{text}"} {"{input}"} 使 {"{变量名}"} {"{text}"} {"{input}"}
</p> </p>
<div className="mb-4"> <div className="mb-4">
<span className="text-sm font-semibold text-gray-700"></span> <span className="text-sm font-semibold text-gray-700">
</span>
<div className="flex flex-wrap gap-2 min-h-[50px] p-3 border rounded-xl bg-gray-50 mt-2"> <div className="flex flex-wrap gap-2 min-h-[50px] p-3 border rounded-xl bg-gray-50 mt-2">
{variables.map((variable, index) => ( {variables.map((variable, index) => (
<Badge <Badge
@@ -226,13 +229,19 @@ export default function InstructionTemplateCreate() {
className="h-8 text-sm" className="h-8 text-sm"
onPressEnter={handleAddVariable} onPressEnter={handleAddVariable}
/> />
<Button onClick={handleAddVariable} type="default" className="px-4 text-sm"> <Button
onClick={handleAddVariable}
type="default"
className="px-4 text-sm"
>
<Plus className="w-3 h-3 mr-1" /> <Plus className="w-3 h-3 mr-1" />
</Button> </Button>
</div> </div>
</div> </div>
<h2 className="font-medium text-gray-900 text-lg mb-2 pt-2"></h2> <h2 className="font-medium text-gray-900 text-lg mb-2 pt-2">
</h2>
<div className="grid grid-cols-2 gap-4"> <div className="grid grid-cols-2 gap-4">
<Form.Item label="测试输入" name="testInput"> <Form.Item label="测试输入" name="testInput">
<TextArea <TextArea

View File

@@ -1,5 +1,5 @@
import { useState } from "react"; import { useState } from "react";
import { Tabs, Button, Card } from "antd"; import { Tabs, Button } from "antd";
import { Plus, ArrowRight } from "lucide-react"; import { Plus, ArrowRight } from "lucide-react";
import DataAnnotation from "../DataAnnotation/Annotate/components/TextAnnotation"; import DataAnnotation from "../DataAnnotation/Annotate/components/TextAnnotation";
import { useNavigate } from "react-router"; import { useNavigate } from "react-router";
@@ -8,7 +8,7 @@ import SynthesisTaskTab from "./components/SynthesisTaskTab";
import DevelopmentInProgress from "@/components/DevelopmentInProgress"; import DevelopmentInProgress from "@/components/DevelopmentInProgress";
export default function DataSynthesisPage() { export default function DataSynthesisPage() {
return <DevelopmentInProgress />; return <DevelopmentInProgress showTime="2025.11.30" />;
const navigate = useNavigate(); const navigate = useNavigate();
const [activeTab, setActiveTab] = useState("tasks"); const [activeTab, setActiveTab] = useState("tasks");