Compare commits
1 Commits
main
...
feature/v0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1331552cfc |
@ -15,6 +15,7 @@
|
|||||||
"axios": "^1.11.0",
|
"axios": "^1.11.0",
|
||||||
"i18next": "^25.3.2",
|
"i18next": "^25.3.2",
|
||||||
"i18next-browser-languagedetector": "^8.2.0",
|
"i18next-browser-languagedetector": "^8.2.0",
|
||||||
|
"lodash": "^4.17.21",
|
||||||
"react": "^19.1.0",
|
"react": "^19.1.0",
|
||||||
"react-dom": "^19.1.0",
|
"react-dom": "^19.1.0",
|
||||||
"react-i18next": "^15.6.0",
|
"react-i18next": "^15.6.0",
|
||||||
@ -23,6 +24,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.30.1",
|
"@eslint/js": "^9.30.1",
|
||||||
|
"@types/lodash": "^4.17.20",
|
||||||
"@types/node": "^24.0.14",
|
"@types/node": "^24.0.14",
|
||||||
"@types/react": "^19.1.8",
|
"@types/react": "^19.1.8",
|
||||||
"@types/react-dom": "^19.1.6",
|
"@types/react-dom": "^19.1.6",
|
||||||
|
|||||||
@ -23,18 +23,21 @@ export const dataGenerationApi = {
|
|||||||
return request.post(`${baseUrl}`, params);
|
return request.post(`${baseUrl}`, params);
|
||||||
},
|
},
|
||||||
stopTask: (params: {
|
stopTask: (params: {
|
||||||
task_id: number;
|
task_id: number | string;
|
||||||
}) => {
|
}) => {
|
||||||
return request.post(`${baseUrl}/${params.task_id}/stop`);
|
return request.post(`${baseUrl}/${params.task_id}/stop`);
|
||||||
},
|
},
|
||||||
deleteTask: (params: {
|
deleteTask: (params: {
|
||||||
task_id: number;
|
task_id: number | string;
|
||||||
}) => {
|
}) => {
|
||||||
return request.delete(`${baseUrl}/${params.task_id}`);
|
return request.delete(`${baseUrl}/${params.task_id}`);
|
||||||
},
|
},
|
||||||
getLogs: (params: {
|
getLogs: (params: {
|
||||||
task_id: number;
|
task_id: number | string;
|
||||||
}) => {
|
}) => {
|
||||||
return request.get(`${baseUrl}/${params.task_id}/logs`);
|
return request.get(`${baseUrl}/${params.task_id}/logs`);
|
||||||
},
|
},
|
||||||
|
getOptions: () => {
|
||||||
|
return request.get(`${baseUrl}/options`);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -13,7 +13,7 @@ export const datasetApi = {
|
|||||||
},
|
},
|
||||||
createDataset: (params: {
|
createDataset: (params: {
|
||||||
name: string;
|
name: string;
|
||||||
description: string;
|
description?: string;
|
||||||
}) => {
|
}) => {
|
||||||
return request.post(`${baseUrl}`, params);
|
return request.post(`${baseUrl}`, params);
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { datasetApi } from "@/api/dataset";
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Divider,
|
Divider,
|
||||||
@ -5,6 +6,7 @@ import {
|
|||||||
Form,
|
Form,
|
||||||
Input,
|
Input,
|
||||||
InputNumber,
|
InputNumber,
|
||||||
|
message,
|
||||||
Modal,
|
Modal,
|
||||||
Select,
|
Select,
|
||||||
Space,
|
Space,
|
||||||
@ -12,11 +14,18 @@ import {
|
|||||||
} from "antd";
|
} from "antd";
|
||||||
import React, { useEffect } from "react";
|
import React, { useEffect } from "react";
|
||||||
|
|
||||||
|
// 生成简短的UUID
|
||||||
|
const generateShortUUID = () => {
|
||||||
|
return Math.random().toString(36).substring(2, 8);
|
||||||
|
};
|
||||||
|
|
||||||
interface CreateTaskModalProps {
|
interface CreateTaskModalProps {
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
onCancel: () => void;
|
onCancel: () => void;
|
||||||
onConfirm: (values: any) => void; // 修改onConfirm的类型以接收表单值
|
onConfirm: (values: any) => void; // 修改onConfirm的类型以接收表单值
|
||||||
datasetList: { id: number; name: string; description: string }[] | undefined;
|
datasetList: { id: number; name: string; description: string }[] | undefined;
|
||||||
|
taskTypeOptions?: { value: string; label: string }[];
|
||||||
|
onDatasetCreate?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CreateTaskModal: React.FC<CreateTaskModalProps> = ({
|
const CreateTaskModal: React.FC<CreateTaskModalProps> = ({
|
||||||
@ -24,11 +33,45 @@ const CreateTaskModal: React.FC<CreateTaskModalProps> = ({
|
|||||||
onCancel,
|
onCancel,
|
||||||
onConfirm,
|
onConfirm,
|
||||||
datasetList,
|
datasetList,
|
||||||
|
taskTypeOptions,
|
||||||
|
onDatasetCreate
|
||||||
}) => {
|
}) => {
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const [datasetName, setDatasetName] = React.useState("");
|
const [datasetName, setDatasetName] = React.useState("");
|
||||||
const [loading, setLoading] = React.useState(false);
|
const [loading, setLoading] = React.useState(false);
|
||||||
|
|
||||||
|
// 监听表单字段变化,自动生成数据集名称
|
||||||
|
useEffect(() => {
|
||||||
|
const simulator = form.getFieldValue('simulator');
|
||||||
|
const taskType = form.getFieldValue('task_type');
|
||||||
|
const camera = form.getFieldValue('camera');
|
||||||
|
|
||||||
|
if (simulator && taskType && camera) {
|
||||||
|
const uuid = generateShortUUID();
|
||||||
|
const generatedName = `${simulator}-${taskType}-${camera}-${uuid}`;
|
||||||
|
setDatasetName(generatedName);
|
||||||
|
}
|
||||||
|
}, [form]);
|
||||||
|
|
||||||
|
// 监听表单字段变化
|
||||||
|
const handleFormChange = () => {
|
||||||
|
const taskType = form.getFieldValue('task_type');
|
||||||
|
const camera = form.getFieldValue('camera');
|
||||||
|
|
||||||
|
if (taskType && camera) {
|
||||||
|
const uuid = generateShortUUID();
|
||||||
|
const generatedName = `${taskType}-${camera}-${uuid}`;
|
||||||
|
setDatasetName(generatedName);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const simulationOptions = [
|
||||||
|
{ value: "robotwin", label: "robotwin" },
|
||||||
|
];
|
||||||
|
const cameraTypeOptions = [
|
||||||
|
{ value: "D435", label: "D435" },
|
||||||
|
{ value: "D515", label: "D515" },
|
||||||
|
];
|
||||||
|
|
||||||
const handleOk = async () => {
|
const handleOk = async () => {
|
||||||
try {
|
try {
|
||||||
const values = await form.validateFields();
|
const values = await form.validateFields();
|
||||||
@ -41,7 +84,18 @@ const CreateTaskModal: React.FC<CreateTaskModalProps> = ({
|
|||||||
|
|
||||||
const handleCreateDataset = async () => {
|
const handleCreateDataset = async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
await datasetApi.createDataset({
|
||||||
|
name: datasetName,
|
||||||
|
});
|
||||||
|
message.success("创建数据集成功");
|
||||||
|
setLoading(false);
|
||||||
|
setDatasetName("");
|
||||||
|
onDatasetCreate?.();
|
||||||
|
} catch (error) {
|
||||||
|
setLoading(false);
|
||||||
|
message.error("创建数据集失败");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -50,21 +104,16 @@ const CreateTaskModal: React.FC<CreateTaskModalProps> = ({
|
|||||||
closable={false}
|
closable={false}
|
||||||
open={visible}
|
open={visible}
|
||||||
onCancel={onCancel}
|
onCancel={onCancel}
|
||||||
onOk={handleOk} // 修改为handleOk
|
onOk={handleOk}
|
||||||
destroyOnHidden
|
destroyOnHidden
|
||||||
>
|
>
|
||||||
<Form form={form} layout="vertical">
|
<Form form={form} layout="vertical" onValuesChange={handleFormChange}>
|
||||||
<Form.Item label="任务名称" name="task_name">
|
|
||||||
<Input placeholder="请输入任务名称(可选)" />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="仿真器"
|
label="仿真器"
|
||||||
name="simulator"
|
name="simulator"
|
||||||
rules={[{ required: true, message: "请选择仿真器!" }]}
|
rules={[{ required: true, message: "请选择仿真器!" }]}
|
||||||
>
|
>
|
||||||
<Select placeholder="请选择仿真器">
|
<Select placeholder="请选择仿真器" options={simulationOptions}>
|
||||||
<Select.Option value="robotwin">robotwin</Select.Option>
|
|
||||||
{/* 可以根据实际情况添加更多仿真器选项 */}
|
|
||||||
</Select>
|
</Select>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
@ -72,11 +121,7 @@ const CreateTaskModal: React.FC<CreateTaskModalProps> = ({
|
|||||||
name="task_type"
|
name="task_type"
|
||||||
rules={[{ required: true, message: "请选择任务类型!" }]}
|
rules={[{ required: true, message: "请选择任务类型!" }]}
|
||||||
>
|
>
|
||||||
<Select placeholder="请选择任务类型">
|
<Select placeholder="请选择任务类型" options={taskTypeOptions}>
|
||||||
<Select.Option value="beat_block_hammer">
|
|
||||||
beat_block_hammer
|
|
||||||
</Select.Option>
|
|
||||||
{/* 可以根据实际情况添加更多任务类型选项 */}
|
|
||||||
</Select>
|
</Select>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
@ -84,9 +129,7 @@ const CreateTaskModal: React.FC<CreateTaskModalProps> = ({
|
|||||||
name="camera"
|
name="camera"
|
||||||
rules={[{ required: true, message: "请选择相机类型!" }]}
|
rules={[{ required: true, message: "请选择相机类型!" }]}
|
||||||
>
|
>
|
||||||
<Select placeholder="请选择相机类型">
|
<Select placeholder="请选择相机类型" options={cameraTypeOptions}>
|
||||||
<Select.Option value="D435">D435</Select.Option>
|
|
||||||
{/* 可以根据实际情况添加更多相机类型选项 */}
|
|
||||||
</Select>
|
</Select>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
@ -101,6 +144,9 @@ const CreateTaskModal: React.FC<CreateTaskModalProps> = ({
|
|||||||
placeholder="请输入轨迹条数 (1-10000)"
|
placeholder="请输入轨迹条数 (1-10000)"
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item label="任务名称" name="task_name">
|
||||||
|
<Input placeholder="请输入任务名称(可选)" />
|
||||||
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="数据集"
|
label="数据集"
|
||||||
name="dataset_id"
|
name="dataset_id"
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import ColLayout from "@/components/ColLayout";
|
import ColLayout from "@/components/ColLayout";
|
||||||
import { Button, Flex, Pagination, Table } from "antd";
|
import { Button, Flex, message, Pagination, Popconfirm, Table } from "antd";
|
||||||
import { createStyles } from "antd-style";
|
import { createStyles } from "antd-style";
|
||||||
import ButtonGroup from "antd/es/button/button-group";
|
import ButtonGroup from "antd/es/button/button-group";
|
||||||
import Search from "antd/es/input/Search";
|
import Search from "antd/es/input/Search";
|
||||||
@ -9,6 +9,8 @@ import { datasetApi } from "@/api/dataset";
|
|||||||
import useToken from "antd/es/theme/useToken";
|
import useToken from "antd/es/theme/useToken";
|
||||||
import { dataGenerationApi } from "@/api/data-generation";
|
import { dataGenerationApi } from "@/api/data-generation";
|
||||||
import { preciseInterval } from "@/utils";
|
import { preciseInterval } from "@/utils";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import { debounce } from "lodash";
|
||||||
|
|
||||||
// 假设的任务类型接口,如果已存在请忽略
|
// 假设的任务类型接口,如果已存在请忽略
|
||||||
interface TaskItem {
|
interface TaskItem {
|
||||||
@ -17,7 +19,7 @@ interface TaskItem {
|
|||||||
type: string;
|
type: string;
|
||||||
create_time: string;
|
create_time: string;
|
||||||
update_time: string;
|
update_time: string;
|
||||||
// 其他可能的字段
|
id: number | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DataGenerationPageProps {}
|
interface DataGenerationPageProps {}
|
||||||
@ -37,6 +39,10 @@ const DataGenerationPage: React.FC<DataGenerationPageProps> = () => {
|
|||||||
const [, token] = useToken();
|
const [, token] = useToken();
|
||||||
const PollyRef = useRef<any>(null);
|
const PollyRef = useRef<any>(null);
|
||||||
const refreshTime = 5000;
|
const refreshTime = 5000;
|
||||||
|
const [taskTypeOptions, setTaskTypeOptions] = useState<
|
||||||
|
{ value: string; label: string }[]
|
||||||
|
>([]);
|
||||||
|
const [searchKeyword, setSearchKeyword] = useState<string>("");
|
||||||
|
|
||||||
const HeaderSlot = (
|
const HeaderSlot = (
|
||||||
<div>
|
<div>
|
||||||
@ -66,7 +72,7 @@ const DataGenerationPage: React.FC<DataGenerationPageProps> = () => {
|
|||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
title: "任务名称",
|
title: "任务名称",
|
||||||
dataIndex: "name",
|
dataIndex: "task_name",
|
||||||
key: "name",
|
key: "name",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -76,78 +82,126 @@ const DataGenerationPage: React.FC<DataGenerationPageProps> = () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "任务类型",
|
title: "任务类型",
|
||||||
dataIndex: "type",
|
dataIndex: "task_type",
|
||||||
key: "type",
|
key: "type",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "任务创建时间",
|
title: "任务创建时间",
|
||||||
dataIndex: "create_time",
|
dataIndex: "created_at",
|
||||||
key: "create_time",
|
key: "created_at",
|
||||||
|
render: (text: string) => dayjs(text).format("YYYY-MM-DD HH:mm:ss"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "任务更新时间",
|
title: "任务更新时间",
|
||||||
dataIndex: "update_time",
|
dataIndex: "updated_at",
|
||||||
key: "update_time",
|
key: "updated_at",
|
||||||
|
render: (text: string) => dayjs(text).format("YYYY-MM-DD HH:mm:ss"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "操作",
|
title: "操作",
|
||||||
key: "action",
|
key: "action",
|
||||||
render: (_: any, record: TaskItem) => (
|
render: (_: any, record: TaskItem) => (
|
||||||
<ButtonGroup>
|
<span>
|
||||||
{record.status === "running" ? ( // 假设 "running" 表示执行中
|
{record.status === "running" ? ( // 假设 "running" 表示执行中
|
||||||
<>
|
<Flex gap={16}>
|
||||||
<Button type="primary">停止</Button>
|
<Popconfirm
|
||||||
|
title="确定停止吗?"
|
||||||
|
onConfirm={() => onOperate?.("stop", record)}
|
||||||
|
>
|
||||||
|
<Button type="primary" danger>
|
||||||
|
停止
|
||||||
|
</Button>
|
||||||
|
</Popconfirm>
|
||||||
<Button type="primary">日志</Button>
|
<Button type="primary">日志</Button>
|
||||||
</>
|
</Flex>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<Flex gap={16}>
|
||||||
<Button type="primary">删除</Button>
|
<Button type="primary" danger>删除</Button>
|
||||||
<Button type="primary">日志</Button>
|
<Button type="primary">日志</Button>
|
||||||
</>
|
</Flex>
|
||||||
)}
|
)}
|
||||||
</ButtonGroup>
|
</span>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const getDatasetList = async (
|
const onOperate = async (type: "stop" | "delete", record: TaskItem) => {
|
||||||
page: number,
|
try {
|
||||||
pageSize: number,
|
if (type === "stop") {
|
||||||
) => {
|
await dataGenerationApi.stopTask({ task_id: record.id });
|
||||||
const { data } = await datasetApi.getDatasetList({
|
} else if (type === "delete") {
|
||||||
current_page: page,
|
await dataGenerationApi.deleteTask({ task_id: record.id });
|
||||||
page_size: pageSize,
|
}
|
||||||
});
|
setSearchKeyword('');
|
||||||
setDatasetList(data.list);
|
setPage(1);
|
||||||
|
getTaskList(1, pageSize, '');
|
||||||
|
message.success("操作成功");
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getTaskList = async (page: number, pageSize: number, keyword?: string) => {
|
const getDatasetList = async () => {
|
||||||
|
const { data } = await datasetApi.getDatasetList({
|
||||||
|
current_page: 1,
|
||||||
|
page_size: 100,
|
||||||
|
});
|
||||||
|
setDatasetList(data.items);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getTaskList = async (
|
||||||
|
page: number,
|
||||||
|
pageSize: number,
|
||||||
|
keyword?: string
|
||||||
|
) => {
|
||||||
const { data } = await dataGenerationApi.getTaskList({
|
const { data } = await dataGenerationApi.getTaskList({
|
||||||
current_page: page,
|
current_page: page,
|
||||||
page_size: pageSize,
|
page_size: pageSize,
|
||||||
search_keyword: keyword
|
search_keyword: keyword,
|
||||||
});
|
});
|
||||||
setDataSource(data.items);
|
setDataSource(data.items);
|
||||||
setTotal(data.total);
|
setTotal(data.total);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getOptions = async () => {
|
||||||
|
const { data } = await dataGenerationApi.getOptions();
|
||||||
|
setTaskTypeOptions(
|
||||||
|
data.options.robotwin.task_types.map((item: any) => ({
|
||||||
|
value: item,
|
||||||
|
label: item,
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const clearPolling = () => {
|
const clearPolling = () => {
|
||||||
PollyRef.current?.cancel();
|
PollyRef.current?.cancel();
|
||||||
PollyRef.current = null;
|
PollyRef.current = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const startPolling = () => {
|
const startPolling = (page: number, pageSize: number, keyword?: string) => {
|
||||||
PollyRef.current = preciseInterval(() => {
|
PollyRef.current = preciseInterval(() => {
|
||||||
getTaskList(page, pageSize);
|
getTaskList(page, pageSize, keyword);
|
||||||
}, refreshTime);
|
}, refreshTime);
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
clearPolling();
|
clearPolling();
|
||||||
getDatasetList(1, 10000)
|
getDatasetList();
|
||||||
startPolling();
|
getOptions();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const debounceStartPolling = debounce(
|
||||||
|
(page: number, pageSize: number, keyword?: string) => {
|
||||||
|
clearPolling();
|
||||||
|
startPolling(page, pageSize, keyword);
|
||||||
|
},
|
||||||
|
500
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
debounceStartPolling(page, pageSize, searchKeyword);
|
||||||
|
}, [page, pageSize, searchKeyword]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ColLayout HeaderSlot={HeaderSlot} FooterSlot={FooterSlot}>
|
<ColLayout HeaderSlot={HeaderSlot} FooterSlot={FooterSlot}>
|
||||||
@ -155,7 +209,10 @@ const DataGenerationPage: React.FC<DataGenerationPageProps> = () => {
|
|||||||
<Flex justify="space-between" align="center" className="operate">
|
<Flex justify="space-between" align="center" className="operate">
|
||||||
<Search
|
<Search
|
||||||
placeholder="请输入任务名称模糊搜索"
|
placeholder="请输入任务名称模糊搜索"
|
||||||
onSearch={(value) => getTaskList(page, pageSize, value)}
|
onSearch={(value) => {
|
||||||
|
setSearchKeyword(value);
|
||||||
|
getTaskList(page, pageSize, value);
|
||||||
|
}}
|
||||||
style={{ width: "300px" }}
|
style={{ width: "300px" }}
|
||||||
/>
|
/>
|
||||||
<ButtonGroup>
|
<ButtonGroup>
|
||||||
@ -176,6 +233,8 @@ const DataGenerationPage: React.FC<DataGenerationPageProps> = () => {
|
|||||||
onCancel={() => setCreateTaskModalVisible(false)}
|
onCancel={() => setCreateTaskModalVisible(false)}
|
||||||
onConfirm={() => setCreateTaskModalVisible(false)}
|
onConfirm={() => setCreateTaskModalVisible(false)}
|
||||||
datasetList={datasetList}
|
datasetList={datasetList}
|
||||||
|
taskTypeOptions={taskTypeOptions}
|
||||||
|
onDatasetCreate={() => getDatasetList()}
|
||||||
></CreateTaskModal>
|
></CreateTaskModal>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import useToken from "antd/es/theme/useToken";
|
|||||||
import React, { useEffect, useRef, useState } from "react";
|
import React, { useEffect, useRef, useState } from "react";
|
||||||
import DatasetForm, { DatasetFormRef } from "./DatasetForm";
|
import DatasetForm, { DatasetFormRef } from "./DatasetForm";
|
||||||
import { Dataset } from "@/types/dataset";
|
import { Dataset } from "@/types/dataset";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
interface DatasetCardProps {
|
interface DatasetCardProps {
|
||||||
DatasetDetail: Dataset;
|
DatasetDetail: Dataset;
|
||||||
@ -27,9 +28,12 @@ const DatasetCard: React.FC<DatasetCardProps> = ({
|
|||||||
className="dataset_card_header"
|
className="dataset_card_header"
|
||||||
justify="space-between"
|
justify="space-between"
|
||||||
align="center"
|
align="center"
|
||||||
|
wrap={false}
|
||||||
>
|
>
|
||||||
<span>{DatasetDetail.name}</span>
|
<Tooltip title={DatasetDetail.name}>
|
||||||
<span>{DatasetDetail.data_count} / 条 数据</span>
|
<span className="ellipsis" style={{flex: 1}}>{DatasetDetail.name}</span>
|
||||||
|
</Tooltip>
|
||||||
|
<span style={{ maxWidth: '180px' }}>{`${DatasetDetail.data_count} / 条 数据`}</span>
|
||||||
</Flex>
|
</Flex>
|
||||||
<div className="dataset_card_content">
|
<div className="dataset_card_content">
|
||||||
<div className="dataset_card_content_description">
|
<div className="dataset_card_content_description">
|
||||||
@ -45,7 +49,7 @@ const DatasetCard: React.FC<DatasetCardProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
<div className="dataset_card_content_description">
|
<div className="dataset_card_content_description">
|
||||||
<p className="description">创建时间:</p>
|
<p className="description">创建时间:</p>
|
||||||
<p className="ellipsis">{DatasetDetail.created_at}</p>
|
<p className="ellipsis">{dayjs(DatasetDetail.created_at).format('YYYY-MM-DD HH:mm:ss')}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Flex
|
<Flex
|
||||||
@ -114,6 +118,7 @@ const useStyles = createStyles(({ token }) => {
|
|||||||
color: token.colorText,
|
color: token.colorText,
|
||||||
width: "100%",
|
width: "100%",
|
||||||
marginBottom: "16px",
|
marginBottom: "16px",
|
||||||
|
overflow: "hidden",
|
||||||
},
|
},
|
||||||
"& .dataset_card_content": {
|
"& .dataset_card_content": {
|
||||||
"& .dataset_card_content_description": {
|
"& .dataset_card_content_description": {
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import ColLayout from "@/components/ColLayout";
|
import ColLayout from "@/components/ColLayout";
|
||||||
import React, { useEffect, useRef, useState } from "react";
|
import React, { Fragment, useEffect, useRef, useState } from "react";
|
||||||
import DatasetCard from "./components/DatasetCard";
|
import DatasetCard from "./components/DatasetCard";
|
||||||
import { Form, Input, message, Pagination, Spin } from "antd";
|
import { Empty, Flex, Form, Input, message, Pagination, Spin } from "antd";
|
||||||
import { datasetApi } from "@/api/dataset";
|
import { datasetApi } from "@/api/dataset";
|
||||||
import { preciseInterval } from "@/utils";
|
import { preciseInterval } from "@/utils";
|
||||||
import useToken from "antd/es/theme/useToken";
|
import useToken from "antd/es/theme/useToken";
|
||||||
@ -22,21 +22,7 @@ const DatasetPage: React.FC<DatasetPageProps> = (props: DatasetPageProps) => {
|
|||||||
const refreshTime = 5000;
|
const refreshTime = 5000;
|
||||||
const [searchKeyword, setSearchKeyword] = useState("");
|
const [searchKeyword, setSearchKeyword] = useState("");
|
||||||
const [operateFormVisible, setOperateFormVisible] = useState(false);
|
const [operateFormVisible, setOperateFormVisible] = useState(false);
|
||||||
const [datasetList, setDatasetList] = useState<Dataset[]>([
|
const [datasetList, setDatasetList] = useState<Dataset[]>([]);
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
name: "数据集1",
|
|
||||||
description: "数据集1描述",
|
|
||||||
task_count: 1,
|
|
||||||
simulator: "simulator1",
|
|
||||||
task: "task1",
|
|
||||||
camera: "camera1",
|
|
||||||
storage_time: "2024-01-01",
|
|
||||||
created_at: "2024-01-01",
|
|
||||||
updated_at: "2024-01-01",
|
|
||||||
data_count: 1,
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
const HeaderSlot = (
|
const HeaderSlot = (
|
||||||
@ -65,7 +51,7 @@ const DatasetPage: React.FC<DatasetPageProps> = (props: DatasetPageProps) => {
|
|||||||
getDatasetList(newPage, newPageSize);
|
getDatasetList(newPage, newPageSize);
|
||||||
PollyRef.current = preciseInterval(() => {
|
PollyRef.current = preciseInterval(() => {
|
||||||
getDatasetList(newPage, newPageSize);
|
getDatasetList(newPage, newPageSize);
|
||||||
}, refreshTime);
|
}, 5000);
|
||||||
}}
|
}}
|
||||||
showSizeChanger
|
showSizeChanger
|
||||||
></Pagination>
|
></Pagination>
|
||||||
@ -79,28 +65,14 @@ const DatasetPage: React.FC<DatasetPageProps> = (props: DatasetPageProps) => {
|
|||||||
) => {
|
) => {
|
||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
// const { data } = await datasetApi.getDatasetList({
|
const { data } = await datasetApi.getDatasetList({
|
||||||
// current_page: page,
|
current_page: page,
|
||||||
// page_size: pageSize,
|
page_size: pageSize,
|
||||||
// search_keyword: name,
|
search_keyword: name,
|
||||||
// });
|
});
|
||||||
// setTotal(data.total);
|
setTotal(data.total);
|
||||||
setDatasetList([
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
name: "数据集1",
|
|
||||||
description: "数据集1描述",
|
|
||||||
task_count: 1,
|
|
||||||
simulator: "simulator1",
|
|
||||||
task: "task1",
|
|
||||||
camera: "camera1",
|
|
||||||
storage_time: "2024-01-01",
|
|
||||||
created_at: "2024-01-01",
|
|
||||||
updated_at: "2024-01-01",
|
|
||||||
data_count: 1,
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
|
setDatasetList(data?.items || []);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
message.error("获取数据集列表失败");
|
message.error("获取数据集列表失败");
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
@ -161,7 +133,7 @@ const DatasetPage: React.FC<DatasetPageProps> = (props: DatasetPageProps) => {
|
|||||||
getDatasetList(page, pageSize);
|
getDatasetList(page, pageSize);
|
||||||
PollyRef.current = preciseInterval(() => {
|
PollyRef.current = preciseInterval(() => {
|
||||||
getDatasetList(page, pageSize);
|
getDatasetList(page, pageSize);
|
||||||
}, refreshTime);
|
}, 5000);
|
||||||
return () => {
|
return () => {
|
||||||
clearPolling();
|
clearPolling();
|
||||||
};
|
};
|
||||||
@ -169,18 +141,24 @@ const DatasetPage: React.FC<DatasetPageProps> = (props: DatasetPageProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<ColLayout HeaderSlot={HeaderSlot} FooterSlot={FooterSlot}>
|
<ColLayout HeaderSlot={HeaderSlot} FooterSlot={FooterSlot}>
|
||||||
{loading ? (
|
|
||||||
<Spin />
|
|
||||||
) : (
|
|
||||||
<div
|
<div
|
||||||
className={styles.container}
|
className={styles.container}
|
||||||
onClick={() => setOperateFormVisible(false)}
|
onClick={() => setOperateFormVisible(false)}
|
||||||
>
|
>
|
||||||
<Search className="search" placeholder="请输入数据集名称" onChange={(e) => {
|
<Search
|
||||||
|
className="search"
|
||||||
|
placeholder="请输入数据集名称"
|
||||||
|
onChange={(e) => {
|
||||||
setSearchKeyword(e.target.value);
|
setSearchKeyword(e.target.value);
|
||||||
getDatasetList(page, pageSize, e.target.value)
|
getDatasetList(page, pageSize, e.target.value);
|
||||||
}} />
|
}}
|
||||||
|
/>
|
||||||
|
{datasetList.length === 0 ? (
|
||||||
|
<Empty />
|
||||||
|
) : (
|
||||||
|
<Flex wrap gap={16}>
|
||||||
{datasetList.map((item) => (
|
{datasetList.map((item) => (
|
||||||
|
<Fragment key={item.id}>
|
||||||
<DatasetCard
|
<DatasetCard
|
||||||
key={item.id}
|
key={item.id}
|
||||||
DatasetDetail={item}
|
DatasetDetail={item}
|
||||||
@ -188,9 +166,11 @@ const DatasetPage: React.FC<DatasetPageProps> = (props: DatasetPageProps) => {
|
|||||||
handleOperate(type, dataset as Dataset)
|
handleOperate(type, dataset as Dataset)
|
||||||
}
|
}
|
||||||
></DatasetCard>
|
></DatasetCard>
|
||||||
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
</div>
|
</Flex>
|
||||||
)}
|
)}
|
||||||
|
</div>
|
||||||
</ColLayout>
|
</ColLayout>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -203,7 +183,7 @@ const useStyles = createStyles(({ token }) => {
|
|||||||
"& .search": {
|
"& .search": {
|
||||||
width: "300px",
|
width: "300px",
|
||||||
marginBottom: token.margin,
|
marginBottom: token.margin,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
@ -10,4 +10,13 @@ export default defineConfig({
|
|||||||
"@": join(__dirname, "./src"),
|
"@": join(__dirname, "./src"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
server: {
|
||||||
|
proxy: {
|
||||||
|
"/api": {
|
||||||
|
target: "http://120.48.128.161:30030",
|
||||||
|
changeOrigin: true,
|
||||||
|
rewrite: (path) => path.replace(/^\/api/, ""),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user