You've already forked DataMate
change settings page and add ratio task detail page (#77)
* feat: Update site name to DataMate and refine text for AI data processing * feat: Refactor settings page and implement model access functionality - Created a new ModelAccess component for managing model configurations. - Removed the old Settings component and replaced it with a new SettingsPage component that integrates ModelAccess, SystemConfig, and WebhookConfig. - Added SystemConfig component for managing system settings. - Implemented WebhookConfig component for managing webhook configurations. - Updated API functions for model management in settings.apis.ts. - Adjusted routing to point to the new SettingsPage component. * feat: Implement Data Collection Page with Task Management and Execution Log - Created DataCollectionPage component to manage data collection tasks. - Added TaskManagement and ExecutionLog components for task handling and logging. - Integrated task operations including start, stop, edit, and delete functionalities. - Implemented filtering and searching capabilities in task management. - Introduced SimpleCronScheduler for scheduling tasks with cron expressions. - Updated CreateTask component to utilize new scheduling and template features. - Enhanced BasicInformation component to conditionally render fields based on visibility settings. - Refactored ImportConfiguration component to remove NAS import section. * feat: Update task creation API endpoint and enhance task creation form with new fields and validation * Refactor file upload and operator management components - Removed unnecessary console logs from file download and export functions. - Added size property to TaskItem interface for better task management. - Simplified TaskUpload component by utilizing useFileSliceUpload hook for file upload logic. - Enhanced OperatorPluginCreate component to handle file uploads and parsing more efficiently. - Updated ConfigureStep component to use Ant Design Form for better data handling and validation. - Improved PreviewStep component to navigate back to the operator market. - Added support for additional file types in UploadStep component. - Implemented delete operator functionality in OperatorMarketPage with confirmation prompts. - Cleaned up unused API functions in operator.api.ts to streamline the codebase. - Fixed number formatting utility to handle zero values correctly. * Refactor Knowledge Generation to Knowledge Base - Created new API service for Knowledge Base operations including querying, creating, updating, and deleting knowledge bases and files. - Added constants for Knowledge Base status and type mappings. - Defined models for Knowledge Base and related files. - Removed obsolete Knowledge Base creation and home components, replacing them with new implementations under the Knowledge Base structure. - Updated routing to reflect the new Knowledge Base paths. - Adjusted menu items to align with the new Knowledge Base terminology. - Modified ModelAccess interface to include modelName and type properties. * feat: Implement Knowledge Base Page with CRUD operations and data management - Added KnowledgeBasePage component for displaying and managing knowledge bases. - Integrated search and filter functionalities with SearchControls component. - Implemented CreateKnowledgeBase component for creating and editing knowledge bases. - Enhanced AddDataDialog for file uploads and dataset selections. - Introduced TableTransfer component for managing data transfers between tables. - Updated API functions for knowledge base operations, including file management. - Refactored knowledge base model to include file status and metadata. - Adjusted routing to point to the new KnowledgeBasePage. * feat: enhance OperatorPluginCreate and ConfigureStep for better upload handling and UI updates * refactor: remove unused components and clean up API logging in KnowledgeBase * feat: update icons in various components and improve styling for better UI consistency * fix: adjust upload step handling and improve error display in configuration step * feat: Add RatioTransfer component for dataset selection and configuration - Implemented RatioTransfer component to manage dataset selection and ratio configuration. - Integrated dataset fetching with search and filter capabilities. - Added RatioConfig component for displaying and updating selected datasets' configurations. - Enhanced SelectDataset component with improved UI and functionality for dataset selection. - Updated RatioTasksPage to utilize new ratio task status mapping and improved error handling for task deletion. - Refactored ratio model and constants for better type safety and clarity. - Changed Vite configuration to use local backend service for development. * feat: Add .editorconfig and enhance SystemConfig with table for settings display * feat: Enhance parameter configuration for range inputs and update default values * feat: Update site name to DataMate and refine text for AI data processing * Refactor file upload and operator management components - Removed unnecessary console logs from file download and export functions. - Added size property to TaskItem interface for better task management. - Simplified TaskUpload component by utilizing useFileSliceUpload hook for file upload logic. - Enhanced OperatorPluginCreate component to handle file uploads and parsing more efficiently. - Updated ConfigureStep component to use Ant Design Form for better data handling and validation. - Improved PreviewStep component to navigate back to the operator market. - Added support for additional file types in UploadStep component. - Implemented delete operator functionality in OperatorMarketPage with confirmation prompts. - Cleaned up unused API functions in operator.api.ts to streamline the codebase. - Fixed number formatting utility to handle zero values correctly. * Refactor Knowledge Generation to Knowledge Base - Created new API service for Knowledge Base operations including querying, creating, updating, and deleting knowledge bases and files. - Added constants for Knowledge Base status and type mappings. - Defined models for Knowledge Base and related files. - Removed obsolete Knowledge Base creation and home components, replacing them with new implementations under the Knowledge Base structure. - Updated routing to reflect the new Knowledge Base paths. - Adjusted menu items to align with the new Knowledge Base terminology. - Modified ModelAccess interface to include modelName and type properties. * feat: Implement Knowledge Base Page with CRUD operations and data management - Added KnowledgeBasePage component for displaying and managing knowledge bases. - Integrated search and filter functionalities with SearchControls component. - Implemented CreateKnowledgeBase component for creating and editing knowledge bases. - Enhanced AddDataDialog for file uploads and dataset selections. - Introduced TableTransfer component for managing data transfers between tables. - Updated API functions for knowledge base operations, including file management. - Refactored knowledge base model to include file status and metadata. - Adjusted routing to point to the new KnowledgeBasePage. * feat: enhance OperatorPluginCreate and ConfigureStep for better upload handling and UI updates * feat: update icons in various components and improve styling for better UI consistency * fix: adjust upload step handling and improve error display in configuration step * feat: Update site name to DataMate and refine text for AI data processing * Refactor file upload and operator management components - Removed unnecessary console logs from file download and export functions. - Added size property to TaskItem interface for better task management. - Simplified TaskUpload component by utilizing useFileSliceUpload hook for file upload logic. - Enhanced OperatorPluginCreate component to handle file uploads and parsing more efficiently. - Updated ConfigureStep component to use Ant Design Form for better data handling and validation. - Improved PreviewStep component to navigate back to the operator market. - Added support for additional file types in UploadStep component. - Implemented delete operator functionality in OperatorMarketPage with confirmation prompts. - Cleaned up unused API functions in operator.api.ts to streamline the codebase. - Fixed number formatting utility to handle zero values correctly. * Refactor Knowledge Generation to Knowledge Base - Created new API service for Knowledge Base operations including querying, creating, updating, and deleting knowledge bases and files. - Added constants for Knowledge Base status and type mappings. - Defined models for Knowledge Base and related files. - Removed obsolete Knowledge Base creation and home components, replacing them with new implementations under the Knowledge Base structure. - Updated routing to reflect the new Knowledge Base paths. - Adjusted menu items to align with the new Knowledge Base terminology. - Modified ModelAccess interface to include modelName and type properties. * feat: Implement Knowledge Base Page with CRUD operations and data management - Added KnowledgeBasePage component for displaying and managing knowledge bases. - Integrated search and filter functionalities with SearchControls component. - Implemented CreateKnowledgeBase component for creating and editing knowledge bases. - Enhanced AddDataDialog for file uploads and dataset selections. - Introduced TableTransfer component for managing data transfers between tables. - Updated API functions for knowledge base operations, including file management. - Refactored knowledge base model to include file status and metadata. - Adjusted routing to point to the new KnowledgeBasePage. * feat: enhance OperatorPluginCreate and ConfigureStep for better upload handling and UI updates * feat: update icons in various components and improve styling for better UI consistency * fix: adjust upload step handling and improve error display in configuration step * feat: add settings drawer and integrate SettingsPage component * feat: add ratio task management features including detail view and API integration
This commit is contained in:
@@ -209,7 +209,9 @@ function CardView<T extends BaseCardDataType>(props: CardViewProps<T>) {
|
||||
{item?.status && (
|
||||
<Tag color={item?.status?.color}>
|
||||
<div className="flex items-center gap-2 text-xs py-0.5">
|
||||
<span>{item?.status?.icon}</span>
|
||||
{item?.status?.icon && (
|
||||
<span>{item?.status?.icon}</span>
|
||||
)}
|
||||
<span>{item?.status?.label}</span>
|
||||
</div>
|
||||
</Tag>
|
||||
|
||||
@@ -92,6 +92,17 @@ const MockAPI = {
|
||||
deleteInstructionTemplateByIdUsingDelete: "/synthesis/templates/:templateId", // 删除指令模板
|
||||
instructionTuningUsingPost: "/synthesis/instruction-tuning", // 指令微调
|
||||
cotDistillationUsingPost: "/synthesis/cot-distillation", // Cot蒸馏
|
||||
|
||||
// 数据配比接口
|
||||
createRatioTaskUsingPost: "/synthesis/ratio-task", // 创建配比任务
|
||||
queryRatioTasksUsingGet: "/synthesis/ratio-task", // 获取配比任务列表
|
||||
queryRatioTaskByIdUsingGet: "/synthesis/ratio-task/:taskId", // 根据ID获取配比任务详情
|
||||
deleteRatioTaskByIdUsingDelete: "/synthesis/ratio-task/:taskId", // 删除配比任务
|
||||
updateRatioTaskByIdUsingPut: "/synthesis/ratio-task/:taskId", // 更新配比任务
|
||||
executeRatioTaskByIdUsingPost: "/synthesis/ratio-task/:taskId/execute", // 执行配比任务
|
||||
stopRatioTaskByIdUsingPost: "/synthesis/ratio-task/:taskId/stop", // 停止配比任务
|
||||
queryRatioJobStatusUsingGet: "/synthesis/ratio-task/:taskId/status", // 获取配比任务状态
|
||||
queryRatioModelsUsingGet: "/synthesis/ratio-models", // 获取配比模型列表
|
||||
|
||||
// 数据评测接口
|
||||
queryEvaluationTasksUsingPost: "/evaluation/tasks", // 获取评测任务列表
|
||||
|
||||
@@ -443,7 +443,6 @@ module.exports = function (router) {
|
||||
const { id } = req.params;
|
||||
const operator = operatorList.find((op) => op.id === id);
|
||||
console.log("获取算子详情:", id, operator);
|
||||
|
||||
if (operator) {
|
||||
// 增加浏览次数模拟
|
||||
operator.viewCount = (operator.viewCount || 0) + 1;
|
||||
|
||||
220
frontend/src/mock/mock-seed/data-ratio.cjs
Normal file
220
frontend/src/mock/mock-seed/data-ratio.cjs
Normal file
@@ -0,0 +1,220 @@
|
||||
|
||||
const Mock = require("mockjs");
|
||||
const API = require("../mock-apis.cjs");
|
||||
|
||||
function ratioJobItem() {
|
||||
return {
|
||||
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
name: Mock.Random.ctitle(5, 15),
|
||||
description: Mock.Random.csentence(10, 30),
|
||||
status: Mock.Random.pick(["PENDING", "RUNNING", "COMPLETED", "FAILED", "PAUSED"]),
|
||||
totals: Mock.Random.integer(1000, 10000),
|
||||
ratio_method: Mock.Random.pick(["DATASET", "TAG"]),
|
||||
target_dataset_id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
target_dataset_name: Mock.Random.ctitle(3, 8),
|
||||
config: [
|
||||
{
|
||||
datasetId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
counts: Mock.Random.integer(100, 1000).toString(),
|
||||
filter_conditions: "",
|
||||
},
|
||||
{
|
||||
datasetId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
counts: Mock.Random.integer(100, 1000).toString(),
|
||||
filter_conditions: "",
|
||||
},
|
||||
],
|
||||
created_at: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
updated_at: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"),
|
||||
};
|
||||
}
|
||||
|
||||
const ratioJobList = new Array(20).fill(null).map(ratioJobItem);
|
||||
|
||||
|
||||
module.exports = function (router) {
|
||||
// 获取配比任务列表
|
||||
router.get(API.queryRatioTasksUsingGet, (req, res) => {
|
||||
const { page = 0, size = 10, status } = req.query;
|
||||
let filteredJobs = ratioJobList;
|
||||
if (status) {
|
||||
filteredJobs = ratioJobList.filter((job) => job.status === status);
|
||||
}
|
||||
const startIndex = page * size;
|
||||
const endIndex = startIndex + parseInt(size);
|
||||
const pageData = filteredJobs.slice(startIndex, endIndex);
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: {
|
||||
content: pageData,
|
||||
totalElements: filteredJobs.length,
|
||||
totalPages: Math.ceil(filteredJobs.length / size),
|
||||
size: parseInt(size),
|
||||
number: parseInt(page),
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// 创建配比任务
|
||||
router.post(API.createRatioTaskUsingPost, (req, res) => {
|
||||
const newJob = {
|
||||
...ratioJobItem(),
|
||||
...req.body,
|
||||
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
status: "PENDING",
|
||||
createdAt: new Date().toISOString(),
|
||||
};
|
||||
ratioJobList.push(newJob);
|
||||
res.status(201).send({
|
||||
code: "0",
|
||||
msg: "Ratio job created successfully",
|
||||
data: newJob,
|
||||
});
|
||||
});
|
||||
|
||||
// 获取配比任务详情
|
||||
router.get(API.queryRatioTaskByIdUsingGet, (req, res) => {
|
||||
const { taskId } = req.params;
|
||||
const job = ratioJobList.find((j) => j.id === taskId);
|
||||
if (job) {
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: job,
|
||||
});
|
||||
} else {
|
||||
res.status(404).send({
|
||||
code: "1",
|
||||
msg: "Ratio job not found",
|
||||
data: null,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 删除配比任务
|
||||
router.delete(API.deleteRatioTaskByIdUsingDelete, (req, res) => {
|
||||
const { taskId } = req.params;
|
||||
const index = ratioJobList.findIndex((j) => j.id === taskId);
|
||||
if (index !== -1) {
|
||||
ratioJobList.splice(index, 1);
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Ratio job deleted successfully",
|
||||
data: null,
|
||||
});
|
||||
} else {
|
||||
res.status(404).send({
|
||||
code: "1",
|
||||
msg: "Ratio job not found",
|
||||
data: null,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 更新配比任务
|
||||
router.put(API.updateRatioTaskByIdUsingPut, (req, res) => {
|
||||
const { taskId } = req.params;
|
||||
const index = ratioJobList.findIndex((j) => j.id === taskId);
|
||||
if (index !== -1) {
|
||||
ratioJobList[index] = {
|
||||
...ratioJobList[index],
|
||||
...req.body,
|
||||
updatedAt: new Date().toISOString(),
|
||||
};
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Ratio job updated successfully",
|
||||
data: ratioJobList[index],
|
||||
});
|
||||
} else {
|
||||
res.status(404).send({
|
||||
code: "1",
|
||||
msg: "Ratio job not found",
|
||||
data: null,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 执行配比任务
|
||||
router.post(API.executeRatioTaskByIdUsingPost, (req, res) => {
|
||||
const { taskId } = req.params;
|
||||
const job = ratioJobList.find((j) => j.id === taskId);
|
||||
if (job) {
|
||||
job.status = "RUNNING";
|
||||
job.startedAt = new Date().toISOString();
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Ratio job execution started",
|
||||
data: {
|
||||
executionId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
|
||||
status: "RUNNING",
|
||||
message: "Job execution started successfully",
|
||||
},
|
||||
});
|
||||
} else {
|
||||
res.status(404).send({
|
||||
code: "1",
|
||||
msg: "Ratio job not found",
|
||||
data: null,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 停止配比任务
|
||||
router.post(API.stopRatioTaskByIdUsingPost, (req, res) => {
|
||||
const { taskId } = req.params;
|
||||
const job = ratioJobList.find((j) => j.id === taskId);
|
||||
if (job) {
|
||||
job.status = "STOPPED";
|
||||
job.finishedAt = new Date().toISOString();
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Ratio job stopped successfully",
|
||||
data: null,
|
||||
});
|
||||
} else {
|
||||
res.status(404).send({
|
||||
code: "1",
|
||||
msg: "Ratio job not found",
|
||||
data: null,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 获取配比任务状态
|
||||
router.get(API.queryRatioJobStatusUsingGet, (req, res) => {
|
||||
const { taskId } = req.params;
|
||||
const job = ratioJobList.find((j) => j.id === taskId);
|
||||
if (job) {
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: {
|
||||
status: job.status,
|
||||
progress: job.progress,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
res.status(404).send({
|
||||
code: "1",
|
||||
msg: "Ratio job not found",
|
||||
data: null,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 获取配比模型列表
|
||||
router.get(API.queryRatioModelsUsingGet, (req, res) => {
|
||||
const models = [
|
||||
{ id: "model1", name: "均匀分配模型", description: "将目标数量均匀分配到各数据集。" },
|
||||
{ id: "model2", name: "标签优先模型", description: "优先满足标签配比需求。" },
|
||||
{ id: "model3", name: "自定义模型", description: "支持自定义分配逻辑。" },
|
||||
];
|
||||
res.send({
|
||||
code: "0",
|
||||
msg: "Success",
|
||||
data: models,
|
||||
});
|
||||
});
|
||||
};
|
||||
@@ -1,5 +1,5 @@
|
||||
import { memo, useEffect, useState } from "react";
|
||||
import { Button, Menu, Popover } from "antd";
|
||||
import { Button, Drawer, Menu, Popover } from "antd";
|
||||
import {
|
||||
CloseOutlined,
|
||||
MenuOutlined,
|
||||
@@ -9,6 +9,7 @@ import { ClipboardList, Sparkles, X } from "lucide-react";
|
||||
import { menuItems } from "@/pages/Layout/menu";
|
||||
import { NavLink, useLocation, useNavigate } from "react-router";
|
||||
import TaskUpload from "./TaskUpload";
|
||||
import SettingsPage from "../SettingsPage/SettingsPage";
|
||||
|
||||
const AsiderAndHeaderLayout = () => {
|
||||
const { pathname } = useLocation();
|
||||
@@ -16,6 +17,7 @@ const AsiderAndHeaderLayout = () => {
|
||||
const [activeItem, setActiveItem] = useState<string>("");
|
||||
const [sidebarOpen, setSidebarOpen] = useState(true);
|
||||
const [taskCenterVisible, setTaskCenterVisible] = useState(false);
|
||||
const [settingVisible, setSettingVisible] = useState(false);
|
||||
|
||||
// Initialize active item based on current pathname
|
||||
const initActiveItem = () => {
|
||||
@@ -137,11 +139,8 @@ const AsiderAndHeaderLayout = () => {
|
||||
</Popover>
|
||||
<Button
|
||||
block
|
||||
color={pathname === "/data/settings" ? "primary" : "default"}
|
||||
variant={pathname === "/data/settings" ? "filled" : "outlined"}
|
||||
onClick={() => {
|
||||
setActiveItem("");
|
||||
navigate("/data/settings");
|
||||
setSettingVisible(true);
|
||||
}}
|
||||
>
|
||||
设置
|
||||
@@ -167,11 +166,8 @@ const AsiderAndHeaderLayout = () => {
|
||||
</div>
|
||||
<Button
|
||||
block
|
||||
color={pathname === "/data/settings" ? "primary" : "default"}
|
||||
variant={pathname === "/data/settings" ? "filled" : "outlined"}
|
||||
onClick={() => {
|
||||
setActiveItem("");
|
||||
navigate("/data/settings");
|
||||
setSettingVisible(true);
|
||||
}}
|
||||
>
|
||||
<SettingOutlined />
|
||||
@@ -179,7 +175,17 @@ const AsiderAndHeaderLayout = () => {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<Drawer
|
||||
title="设置"
|
||||
placement="bottom"
|
||||
width="100%"
|
||||
height="100%"
|
||||
open={settingVisible}
|
||||
onClose={() => setSettingVisible(false)}
|
||||
bodyStyle={{ padding: 0 }}
|
||||
>
|
||||
<SettingsPage></SettingsPage>
|
||||
</Drawer>
|
||||
{/* 添加遮罩层,点击外部区域时关闭 */}
|
||||
{taskCenterVisible && (
|
||||
<div
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {Alert, Input, Form} from "antd";
|
||||
import { Alert, Input, Form } from "antd";
|
||||
import TextArea from "antd/es/input/TextArea";
|
||||
import React, {useEffect} from "react";
|
||||
import React, { useEffect } from "react";
|
||||
import ParamConfig from "@/pages/DataCleansing/Create/components/ParamConfig.tsx";
|
||||
|
||||
export default function ConfigureStep({
|
||||
@@ -22,14 +22,14 @@ export default function ConfigureStep({
|
||||
setParsedInfo((op) =>
|
||||
op.id === operatorId
|
||||
? {
|
||||
...op,
|
||||
overrides: {
|
||||
...(op?.overrides || op?.defaultParams),
|
||||
[paramKey]: value,
|
||||
},
|
||||
}
|
||||
...op,
|
||||
overrides: {
|
||||
...(op?.overrides || op?.defaultParams),
|
||||
[paramKey]: value,
|
||||
},
|
||||
}
|
||||
: op
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -52,32 +52,40 @@ export default function ConfigureStep({
|
||||
layout="vertical"
|
||||
initialValues={parsedInfo}
|
||||
onValuesChange={(_, allValues) => {
|
||||
setParsedInfo({...parsedInfo, ...allValues});
|
||||
setParsedInfo({ ...parsedInfo, ...allValues });
|
||||
}}
|
||||
>
|
||||
{/* 基本信息 */}
|
||||
<h3 className="text-lg font-semibold text-gray-900">基本信息</h3>
|
||||
<Form.Item label="ID" name="id" rules={[{required: true}]}>
|
||||
<Input value={parsedInfo.id} readOnly/>
|
||||
<Form.Item label="ID" name="id" rules={[{ required: true }]}>
|
||||
<Input value={parsedInfo.id} readOnly />
|
||||
</Form.Item>
|
||||
<Form.Item label="名称" name="name" rules={[{required: true}]}>
|
||||
<Input value={parsedInfo.name}/>
|
||||
<Form.Item label="名称" name="name" rules={[{ required: true }]}>
|
||||
<Input value={parsedInfo.name} />
|
||||
</Form.Item>
|
||||
<Form.Item label="版本" name="version" rules={[{required: true}]}>
|
||||
<Input value={parsedInfo.version}/>
|
||||
<Form.Item label="版本" name="version" rules={[{ required: true }]}>
|
||||
<Input value={parsedInfo.version} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label="描述"
|
||||
name="description"
|
||||
rules={[{required: false}]}
|
||||
rules={[{ required: false }]}
|
||||
>
|
||||
<TextArea value={parsedInfo.description}/>
|
||||
<TextArea value={parsedInfo.description} />
|
||||
</Form.Item>
|
||||
<Form.Item label="输入类型" name="inputs" rules={[{required: true}]}>
|
||||
<Input value={parsedInfo.inputs}/>
|
||||
<Form.Item
|
||||
label="输入类型"
|
||||
name="inputs"
|
||||
rules={[{ required: true }]}
|
||||
>
|
||||
<Input value={parsedInfo.inputs} />
|
||||
</Form.Item>
|
||||
<Form.Item label="输出类型" name="outputs" rules={[{required: true}]}>
|
||||
<Input value={parsedInfo.outputs}/>
|
||||
<Form.Item
|
||||
label="输出类型"
|
||||
name="outputs"
|
||||
rules={[{ required: true }]}
|
||||
>
|
||||
<Input value={parsedInfo.outputs} />
|
||||
</Form.Item>
|
||||
|
||||
{parsedInfo.configs && Object.keys(parsedInfo.configs).length > 0 && (
|
||||
@@ -85,19 +93,17 @@ export default function ConfigureStep({
|
||||
<h3 className="text-lg font-semibold text-gray-900 mt-10 mb-2">
|
||||
高级配置
|
||||
</h3>
|
||||
<div className="border p-4 rounded-lg grid grid-cols-2 gap-4">
|
||||
<Form layout="vertical">
|
||||
{Object.entries(parsedInfo?.configs).map(([key, param]) =>
|
||||
<ParamConfig
|
||||
key={key}
|
||||
operator={parsedInfo}
|
||||
paramKey={key}
|
||||
param={param}
|
||||
onParamChange={handleConfigChange}
|
||||
/>
|
||||
)}
|
||||
</Form>
|
||||
</div>
|
||||
<Form layout="vertical">
|
||||
{Object.entries(parsedInfo?.configs).map(([key, param]) => (
|
||||
<ParamConfig
|
||||
key={key}
|
||||
operator={parsedInfo}
|
||||
paramKey={key}
|
||||
param={param}
|
||||
onParamChange={handleConfigChange}
|
||||
/>
|
||||
))}
|
||||
</Form>
|
||||
</>
|
||||
)}
|
||||
|
||||
|
||||
312
frontend/src/pages/RatioTask/Detail/RatioTaskDetail.tsx
Normal file
312
frontend/src/pages/RatioTask/Detail/RatioTaskDetail.tsx
Normal file
@@ -0,0 +1,312 @@
|
||||
import { useEffect, useMemo, useState, useCallback } from "react";
|
||||
import {
|
||||
Breadcrumb,
|
||||
App,
|
||||
Tabs,
|
||||
Button,
|
||||
Card,
|
||||
Progress,
|
||||
Badge,
|
||||
Descriptions,
|
||||
DescriptionsProps,
|
||||
} from "antd";
|
||||
import { ReloadOutlined, DeleteOutlined } from "@ant-design/icons";
|
||||
import DetailHeader from "@/components/DetailHeader";
|
||||
import { Link, useNavigate, useParams } from "react-router";
|
||||
import {
|
||||
getRatioTaskByIdUsingGet,
|
||||
deleteRatioTasksUsingDelete,
|
||||
} from "@/pages/RatioTask/ratio.api";
|
||||
import { post } from "@/utils/request";
|
||||
import type { RatioTaskItem } from "@/pages/RatioTask/ratio.model";
|
||||
import { mapRatioTask } from "../ratio.const";
|
||||
import { Copy, Pause, PlayIcon } from "lucide-react";
|
||||
|
||||
const tabList = [
|
||||
{
|
||||
key: "overview",
|
||||
label: "概览",
|
||||
},
|
||||
{
|
||||
key: "analysis",
|
||||
label: "配比分析",
|
||||
},
|
||||
{
|
||||
key: "config",
|
||||
label: "配比配置",
|
||||
},
|
||||
];
|
||||
|
||||
export default function RatioTaskDetail() {
|
||||
const { id } = useParams();
|
||||
const navigate = useNavigate();
|
||||
const [activeTab, setActiveTab] = useState("overview");
|
||||
const { message } = App.useApp();
|
||||
const [ratioTask, setRatioTask] = useState<RatioTaskItem>(
|
||||
{} as RatioTaskItem
|
||||
);
|
||||
|
||||
const navigateItems = useMemo(
|
||||
() => [
|
||||
{
|
||||
title: <Link to="/data/synthesis/ratio-task">首页</Link>,
|
||||
},
|
||||
{
|
||||
title: ratioTask.name || "配比任务详情",
|
||||
},
|
||||
],
|
||||
[ratioTask]
|
||||
);
|
||||
|
||||
const fetchRatioTask = useCallback(async () => {
|
||||
const { data } = await getRatioTaskByIdUsingGet(id as string);
|
||||
setRatioTask(mapRatioTask(data));
|
||||
}, [id]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchRatioTask();
|
||||
}, []);
|
||||
|
||||
const handleRefresh = useCallback(
|
||||
async (showMessage = true) => {
|
||||
await fetchRatioTask();
|
||||
if (showMessage) message.success({ content: "任务数据刷新成功" });
|
||||
},
|
||||
[fetchRatioTask, message]
|
||||
);
|
||||
|
||||
const handleDelete = async () => {
|
||||
await deleteRatioTasksUsingDelete(id as string);
|
||||
navigate("/ratio/task");
|
||||
message.success("配比任务删除成功");
|
||||
};
|
||||
|
||||
const handleExecute = async () => {
|
||||
await post(`/api/synthesis/ratio-task/${id}/execute`);
|
||||
handleRefresh();
|
||||
message.success("任务已启动");
|
||||
};
|
||||
|
||||
const handleStop = async () => {
|
||||
await post(`/api/synthesis/ratio-task/${id}/stop`);
|
||||
handleRefresh();
|
||||
message.success("任务已停止");
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const refreshData = () => {
|
||||
handleRefresh(false);
|
||||
};
|
||||
window.addEventListener("update:ratio-task", refreshData);
|
||||
return () => {
|
||||
window.removeEventListener("update:ratio-task", refreshData);
|
||||
};
|
||||
}, [handleRefresh]);
|
||||
|
||||
// 操作列表
|
||||
const operations = [
|
||||
{
|
||||
key: "execute",
|
||||
label: "启动",
|
||||
icon: <PlayIcon className="w-4 h-4 text-gray-500" />,
|
||||
onClick: handleExecute,
|
||||
disabled: ratioTask.status === "RUNNING",
|
||||
},
|
||||
{
|
||||
key: "stop",
|
||||
label: "停止",
|
||||
icon: <Pause className="w-4 h-4 text-gray-500" />,
|
||||
onClick: handleStop,
|
||||
disabled: ratioTask.status !== "RUNNING",
|
||||
},
|
||||
{
|
||||
key: "refresh",
|
||||
label: "刷新",
|
||||
icon: <ReloadOutlined />,
|
||||
onClick: handleRefresh,
|
||||
},
|
||||
{
|
||||
key: "delete",
|
||||
label: "删除",
|
||||
danger: true,
|
||||
confirm: {
|
||||
title: "确认删除该配比任务?",
|
||||
description: "删除后该任务将无法恢复,请谨慎操作。",
|
||||
okText: "删除",
|
||||
cancelText: "取消",
|
||||
okType: "danger",
|
||||
},
|
||||
icon: <DeleteOutlined />,
|
||||
onClick: handleDelete,
|
||||
},
|
||||
];
|
||||
|
||||
// 基本信息
|
||||
const items: DescriptionsProps["items"] = [
|
||||
{
|
||||
key: "id",
|
||||
label: "ID",
|
||||
children: ratioTask.id,
|
||||
},
|
||||
{
|
||||
key: "name",
|
||||
label: "名称",
|
||||
children: ratioTask.name,
|
||||
},
|
||||
{
|
||||
key: "dataset",
|
||||
label: "目标数据集",
|
||||
children: (
|
||||
<Link to={`/data/management/detail/${ratioTask.target_dataset_id}`}>
|
||||
{ratioTask.target_dataset_name}
|
||||
</Link>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "status",
|
||||
label: "数据大小",
|
||||
children: (
|
||||
<Badge color={ratioTask.status?.color} text={ratioTask.status?.label} />
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "type",
|
||||
label: "类型",
|
||||
children: ratioTask.type || "未知",
|
||||
},
|
||||
{
|
||||
key: "status",
|
||||
label: "状态",
|
||||
children: ratioTask?.status?.label || "未知",
|
||||
},
|
||||
{
|
||||
key: "createdBy",
|
||||
label: "创建者",
|
||||
children: ratioTask.createdBy || "未知",
|
||||
},
|
||||
{
|
||||
key: "targetLocation",
|
||||
label: "输出路径",
|
||||
children: ratioTask.targetLocation || "未知",
|
||||
},
|
||||
{
|
||||
key: "createdAt",
|
||||
label: "创建时间",
|
||||
children: ratioTask.createdAt,
|
||||
},
|
||||
{
|
||||
key: "updatedAt",
|
||||
label: "更新时间",
|
||||
children: ratioTask.updatedAt,
|
||||
},
|
||||
{
|
||||
key: "description",
|
||||
label: "描述",
|
||||
children: ratioTask.description || "无",
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="h-full flex flex-col gap-4">
|
||||
<Breadcrumb items={navigateItems} />
|
||||
{/* Header */}
|
||||
<DetailHeader
|
||||
data={ratioTask}
|
||||
statistics={ratioTask?.statistics || []}
|
||||
operations={operations}
|
||||
/>
|
||||
<div className="flex-overflow-auto p-6 pt-2 bg-white rounded-md shadow">
|
||||
<Tabs activeKey={activeTab} items={tabList} onChange={setActiveTab} />
|
||||
<div className="h-full overflow-auto">
|
||||
{activeTab === "overview" && (
|
||||
<>
|
||||
<Descriptions
|
||||
title="基本信息"
|
||||
layout="vertical"
|
||||
size="small"
|
||||
items={items}
|
||||
column={5}
|
||||
/>
|
||||
<h2 className="text-base font-semibold mt-8 mb-4">配比详情</h2>
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
{/* 目标配比 */}
|
||||
<Card title="目标配比">
|
||||
<div className="space-y-4">
|
||||
{ratioTask.targetRatio &&
|
||||
Object.entries(ratioTask.targetRatio).map(
|
||||
([category, ratio]) => (
|
||||
<div key={category} className="space-y-2">
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-sm font-medium text-gray-700">
|
||||
{category}
|
||||
</span>
|
||||
<span className="text-sm font-semibold text-blue-600">
|
||||
{ratioTask.ratio}%
|
||||
</span>
|
||||
</div>
|
||||
<Progress value={ratio} className="h-2" />
|
||||
</div>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* 当前配比 */}
|
||||
<Card title="当前配比">
|
||||
<div className="space-y-4">
|
||||
{ratioTask.currentRatio &&
|
||||
Object.entries(ratioTask.currentRatio).length > 0 ? (
|
||||
Object.entries(ratioTask.currentRatio)?.map(
|
||||
([category, ratio]) => (
|
||||
<div key={category} className="space-y-2">
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-sm font-medium text-gray-700">
|
||||
{category}
|
||||
</span>
|
||||
<span className="text-sm font-semibold text-green-600">
|
||||
{ratioTask.ratio}%
|
||||
</span>
|
||||
</div>
|
||||
<Progress value={ratio} className="h-2" />
|
||||
</div>
|
||||
)
|
||||
)
|
||||
) : (
|
||||
<p className="text-sm text-gray-500">等待处理开始</p>
|
||||
)}
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{activeTab === "analysis" && (
|
||||
<div className="text-center py-20 text-gray-500">
|
||||
配比分析功能正在开发中,敬请期待!
|
||||
</div>
|
||||
)}
|
||||
{activeTab === "config" && (
|
||||
<div className="bg-gray-50 rounded-lg p-4 font-mono text-xs overflow-x-auto">
|
||||
<pre className="text-gray-700 whitespace-pre-wrap break-words">
|
||||
{JSON.stringify(
|
||||
{
|
||||
id: ratioTask.id,
|
||||
name: ratioTask.name,
|
||||
type: ratioTask.type,
|
||||
status: ratioTask.status,
|
||||
strategy: ratioTask.strategy,
|
||||
sourceDatasets: ratioTask.sourceDatasets,
|
||||
targetRatio: ratioTask.targetRatio,
|
||||
outputPath: ratioTask.outputPath,
|
||||
createdAt: ratioTask.createdAt,
|
||||
},
|
||||
null,
|
||||
2
|
||||
)}
|
||||
</pre>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useState } from "react";
|
||||
import { Button, Card, Table, Tooltip, App } from "antd";
|
||||
import { Button, Card, Table, App, Badge, Popconfirm } from "antd";
|
||||
import { Plus } from "lucide-react";
|
||||
import { DeleteOutlined } from "@ant-design/icons";
|
||||
import type { RatioTaskItem } from "@/pages/RatioTask/ratio.model";
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
queryRatioTasksUsingGet,
|
||||
} from "../ratio.api";
|
||||
import useFetchData from "@/hooks/useFetchData";
|
||||
import { mapRatioTask, ratioTaskStatusMap } from "../ratio.const";
|
||||
import { mapRatioTask } from "../ratio.const";
|
||||
|
||||
export default function RatioTasksPage() {
|
||||
const { message } = App.useApp();
|
||||
@@ -68,6 +68,8 @@ export default function RatioTasksPage() {
|
||||
title: "任务名称",
|
||||
dataIndex: "name",
|
||||
key: "name",
|
||||
width: 200,
|
||||
fixed: "left" as const,
|
||||
render: (text: string, record: RatioTaskItem) => (
|
||||
<a
|
||||
onClick={() =>
|
||||
@@ -82,17 +84,28 @@ export default function RatioTasksPage() {
|
||||
title: "状态",
|
||||
dataIndex: "status",
|
||||
key: "status",
|
||||
render: (status) => ratioTaskStatusMap[status]?.label,
|
||||
width: 120,
|
||||
render: (status) => {
|
||||
return (
|
||||
<Badge
|
||||
color={status?.color}
|
||||
icon={status?.icon}
|
||||
text={status?.label}
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "配比方式",
|
||||
dataIndex: "ratio_method",
|
||||
key: "ratio_method",
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
title: "目标数量",
|
||||
dataIndex: "totals",
|
||||
key: "totals",
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
title: "目标数据集",
|
||||
@@ -112,21 +125,35 @@ export default function RatioTasksPage() {
|
||||
title: "创建时间",
|
||||
dataIndex: "created_at",
|
||||
key: "created_at",
|
||||
width: 180,
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
key: "actions",
|
||||
width: 120,
|
||||
fixed: "right" as const,
|
||||
render: (_: any, task: RatioTaskItem) => (
|
||||
<div className="flex items-center gap-2">
|
||||
{operations.map((op) => (
|
||||
<Tooltip key={op.key} title={op.label}>
|
||||
{operations.map((op) => {
|
||||
if (op.confirm) {
|
||||
<Popconfirm
|
||||
title={op.confirm.title}
|
||||
description={op.confirm.description}
|
||||
onConfirm={() => op.onClick(task)}
|
||||
>
|
||||
<Button type="text" icon={op.icon} />
|
||||
</Popconfirm>;
|
||||
}
|
||||
return (
|
||||
<Button
|
||||
key={op.key}
|
||||
type="text"
|
||||
icon={op.icon}
|
||||
danger={op.danger}
|
||||
onClick={() => op.onClick(task)}
|
||||
/>
|
||||
</Tooltip>
|
||||
))}
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
),
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { formatDate } from "@/utils/unit";
|
||||
import { RatioTaskItem, RatioStatus } from "./ratio.model";
|
||||
import { BarChart3 } from "lucide-react";
|
||||
import { BarChart3, Calendar, Database } from "lucide-react";
|
||||
import { Link } from "react-router";
|
||||
|
||||
export const ratioTaskStatusMap: Record<
|
||||
@@ -9,22 +9,23 @@ export const ratioTaskStatusMap: Record<
|
||||
value: RatioStatus;
|
||||
label: string;
|
||||
color: string;
|
||||
icon?: React.ReactNode;
|
||||
}
|
||||
> = {
|
||||
[RatioStatus.PENDING]: {
|
||||
value: RatioStatus.PENDING,
|
||||
label: "等待中",
|
||||
color: "blue",
|
||||
color: "gray",
|
||||
},
|
||||
[RatioStatus.RUNNING]: {
|
||||
value: RatioStatus.RUNNING,
|
||||
label: "运行中",
|
||||
color: "green",
|
||||
color: "blue",
|
||||
},
|
||||
[RatioStatus.COMPLETED]: {
|
||||
value: RatioStatus.COMPLETED,
|
||||
label: "已完成",
|
||||
color: "gray",
|
||||
color: "green",
|
||||
},
|
||||
[RatioStatus.FAILED]: {
|
||||
value: RatioStatus.FAILED,
|
||||
@@ -41,20 +42,22 @@ export const ratioTaskStatusMap: Record<
|
||||
export function mapRatioTask(task: Partial<RatioTaskItem>): RatioTaskItem {
|
||||
return {
|
||||
...task,
|
||||
status: ratioTaskStatusMap[task.status || RatioStatus.PENDING]?.value,
|
||||
status: ratioTaskStatusMap[task.status || RatioStatus.PENDING],
|
||||
createdAt: formatDate(task.created_at),
|
||||
updatedAt: formatDate(task.updated_at),
|
||||
description:
|
||||
task.ratio_method === "DATASET" ? "按数据集配比" : "按标签配比",
|
||||
icon: <BarChart3 className="w-6 h-6" />,
|
||||
icon: <BarChart3 />,
|
||||
iconColor: task.ratio_method === "DATASET" ? "bg-blue-100" : "bg-green-100",
|
||||
statistics: [
|
||||
{
|
||||
label: "目标数量",
|
||||
icon: <BarChart3 className="w-4 h-4 text-gray-500" />,
|
||||
value: (task.totals ?? 0).toLocaleString(),
|
||||
},
|
||||
{
|
||||
label: "目标数据集",
|
||||
icon: <Database className="w-4 h-4 text-gray-500" />,
|
||||
value: task.target_dataset_name ? (
|
||||
<Link to={`/data/management/detail/${task.target_dataset_id}`}>
|
||||
{task.target_dataset_name}
|
||||
@@ -65,8 +68,20 @@ export function mapRatioTask(task: Partial<RatioTaskItem>): RatioTaskItem {
|
||||
},
|
||||
{
|
||||
label: "创建时间",
|
||||
icon: <Calendar className="w-4 h-4 text-gray-500" />,
|
||||
value: task.created_at || "-",
|
||||
},
|
||||
],
|
||||
type: "balance",
|
||||
progress: 100,
|
||||
sourceDatasets: ["sentiment_dataset", "news_classification"],
|
||||
targetRatio: { 正面: 33, 负面: 33, 中性: 34 },
|
||||
currentRatio: { 正面: 33, 负面: 33, 中性: 34 },
|
||||
totalRecords: 15000,
|
||||
processedRecords: 15000,
|
||||
estimatedTime: "已完成",
|
||||
quality: 95,
|
||||
strategy: "随机下采样",
|
||||
outputPath: "/data/balanced/sentiment_balanced_20250120",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,60 +1,56 @@
|
||||
import { useState } from "react";
|
||||
import { Tabs } from "antd";
|
||||
import { Button, Menu } from "antd";
|
||||
import { SettingOutlined, ApiOutlined } from "@ant-design/icons";
|
||||
import WebhookConfig from "./WebhookConfig";
|
||||
import ModelAccess from "./ModelAccess";
|
||||
import { Component, X } from "lucide-react";
|
||||
import { useNavigate } from "react-router";
|
||||
import SystemConfig from "./SystemConfig";
|
||||
import { Component } from "lucide-react";
|
||||
import ModelAccess from "./ModelAccess";
|
||||
import WebhookConfig from "./WebhookConfig";
|
||||
|
||||
export default function SettingsPage() {
|
||||
const [activeTab, setActiveTab] = useState("modelAccess");
|
||||
const navigate = useNavigate();
|
||||
const [activeTab, setActiveTab] = useState("model-access");
|
||||
|
||||
return (
|
||||
<div className="h-full flex flex-col gap-4">
|
||||
{/* Header */}
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<h1 className="text-xl font-bold text-gray-900">系统设置</h1>
|
||||
<div className="h-screen flex">
|
||||
<div className="border-right h-full">
|
||||
{/* <h1 className="min-w-[200px] w-full border-bottom flex gap-2 text-lg font-bold text-gray-900 p-4">
|
||||
<Button icon={<X />} type="text" onClick={() => navigate(-1)} />
|
||||
设置中心
|
||||
</h1> */}
|
||||
<div className="h-full">
|
||||
<Menu
|
||||
mode="inline"
|
||||
items={[
|
||||
{
|
||||
key: "system-config",
|
||||
icon: <SettingOutlined />,
|
||||
label: "系统设置",
|
||||
},
|
||||
{
|
||||
key: "model-access",
|
||||
icon: <Component className="w-4 h-4" />,
|
||||
label: "模型接入",
|
||||
},
|
||||
{
|
||||
key: "webhook-config",
|
||||
icon: <ApiOutlined />,
|
||||
label: "Webhook",
|
||||
},
|
||||
]}
|
||||
selectedKeys={[activeTab]}
|
||||
onClick={({ key }) => {
|
||||
setActiveTab(key);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Settings Tabs */}
|
||||
<Tabs
|
||||
activeKey={activeTab}
|
||||
onChange={setActiveTab}
|
||||
items={[
|
||||
// {
|
||||
// key: "system",
|
||||
// label: (
|
||||
// <span>
|
||||
// <SettingOutlined className="mr-1" />
|
||||
// 系统设置
|
||||
// </span>
|
||||
// ),
|
||||
// children: <SystemConfig />,
|
||||
// },
|
||||
{
|
||||
key: "modelAccess",
|
||||
label: (
|
||||
<span className="flex items-center">
|
||||
<Component className="w-4 h-4 mr-1" />
|
||||
模型接入
|
||||
</span>
|
||||
),
|
||||
children: <ModelAccess key="modelAccess" />,
|
||||
},
|
||||
// {
|
||||
// key: "webhook",
|
||||
// label: (
|
||||
// <span>
|
||||
// <ApiOutlined className="mr-1" />
|
||||
// Webhook
|
||||
// </span>
|
||||
// ),
|
||||
// children: <WebhookConfig />,
|
||||
// },
|
||||
]}
|
||||
/>
|
||||
<div className="flex-1 h-full p-4">
|
||||
{/* 内容区域,根据 activeTab 渲染不同的组件 */}
|
||||
{activeTab === "system-config" && <SystemConfig />}
|
||||
{activeTab === "model-access" && <ModelAccess />}
|
||||
{activeTab === "webhook-config" && <WebhookConfig />}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -37,9 +37,9 @@ import RatioTasksPage from "@/pages/RatioTask/Home/RatioTask.tsx";
|
||||
import CreateRatioTask from "@/pages/RatioTask/Create/CreateRatioTask.tsx";
|
||||
import OrchestrationPage from "@/pages/Orchestration/Orchestration";
|
||||
import WorkflowEditor from "@/pages/Orchestration/WorkflowEditor";
|
||||
import SettingsPage from "@/pages/SettingsPage/SettingsPage";
|
||||
import { withErrorBoundary } from "@/components/ErrorBoundary";
|
||||
import AgentPage from "@/pages/Agent/Agent.tsx";
|
||||
import RatioTaskDetail from "@/pages/RatioTask/Detail/RatioTaskDetail";
|
||||
|
||||
const router = createBrowserRouter([
|
||||
{
|
||||
@@ -165,6 +165,10 @@ const router = createBrowserRouter([
|
||||
path: "create",
|
||||
Component: CreateRatioTask,
|
||||
},
|
||||
{
|
||||
path: "detail/:id",
|
||||
Component: RatioTaskDetail,
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -225,10 +229,6 @@ const router = createBrowserRouter([
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "settings",
|
||||
Component: SettingsPage,
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
Reference in New Issue
Block a user