Skip to content

Commit d19d3b4

Browse files
committed
fixbug: 算子库搜索,添加算子全选功能
1 parent 930b433 commit d19d3b4

File tree

10 files changed

+188
-43
lines changed

10 files changed

+188
-43
lines changed

frontend/src/mock/mock-seed/data-cleansing.cjs

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,10 @@ function operatorItem() {
1111
outputs: Mock.Random.integer(1, 5),
1212
settings: JSON.stringify({
1313
host: { type: "input", label: "主机地址", value: "localhost" },
14-
port: { type: "input", label: "端口", value: "3306" },
15-
database: { type: "input", label: "数据库名", value: "" },
16-
table: { type: "input", label: "表名", value: "" },
1714
limit: {
1815
type: "range",
1916
label: "读取行数",
20-
value: [1000],
17+
value: [1000, 2000],
2118
min: 100,
2219
max: 10000,
2320
step: 100,
@@ -35,6 +32,24 @@ function operatorItem() {
3532
value: [],
3633
options: ["feature1", "feature2", "feature3"],
3734
},
35+
repeatPhraseRatio: {
36+
name: "文档词重复率",
37+
description: "某个词的统计数/文档总词数 > 设定值,该文档被去除。",
38+
type: "slider",
39+
defaultVal: 0.5,
40+
min: 0,
41+
max: 1,
42+
step: 0.1,
43+
},
44+
hitStopwords: {
45+
name: "去除停用词",
46+
description: "统计重复词时,选择是否要去除停用词。",
47+
type: "switch",
48+
defaultVal: false,
49+
required: true,
50+
checkedLabel: "去除",
51+
unCheckedLabel: "不去除",
52+
},
3853
}),
3954
categories: [Mock.Random.pick([3, 4, 5, 6, 7, 8, 9])],
4055
isStar: Mock.Random.boolean(),
@@ -51,7 +66,13 @@ function cleaningTaskItem() {
5166
id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
5267
name: Mock.Random.ctitle(5, 20),
5368
description: Mock.Random.csentence(5, 30),
54-
status: Mock.Random.pick(["PENDING", "RUNNING", "COMPLETED", "FAILED", "STOPPED"]),
69+
status: Mock.Random.pick([
70+
"PENDING",
71+
"RUNNING",
72+
"COMPLETED",
73+
"FAILED",
74+
"STOPPED",
75+
]),
5576
srcDatasetId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),
5677
srcDatasetName: Mock.Random.ctitle(5, 15),
5778
destDatasetId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""),

frontend/src/pages/DataCleansing/Create/CreateTask.tsx

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
import { useState } from "react";
2-
import { Card, Steps, Button, message, Form } from "antd";
2+
import { Steps, Button, message, Form } from "antd";
33
import { SaveOutlined } from "@ant-design/icons";
44
import { Link, useNavigate } from "react-router";
55
import { ArrowLeft } from "lucide-react";
66
import { createCleaningTaskUsingPost } from "../cleansing.api";
77
import CreateTaskStepOne from "./components/CreateTaskStepOne";
88
import { useCreateStepTwo } from "./hooks/useCreateStepTwo";
9-
import {
10-
DatasetSubType,
11-
DatasetType,
12-
} from "@/pages/DataManagement/dataset.model";
9+
import { DatasetType } from "@/pages/DataManagement/dataset.model";
1310

1411
export default function CleansingTaskCreate() {
1512
const navigate = useNavigate();
@@ -43,7 +40,6 @@ export default function CleansingTaskCreate() {
4340
},
4441
})),
4542
};
46-
console.log("创建任务:", task);
4743
navigate("/data/cleansing");
4844
await createCleaningTaskUsingPost(task);
4945
message.success("任务已创建");

frontend/src/pages/DataCleansing/Create/components/OperatorLibrary.tsx

Lines changed: 70 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
import React, { useMemo, useState } from "react";
2-
import { Card, Input, Select, Tooltip, Collapse, Tag, Checkbox } from "antd";
2+
import {
3+
Card,
4+
Input,
5+
Select,
6+
Tooltip,
7+
Collapse,
8+
Tag,
9+
Checkbox,
10+
Button,
11+
} from "antd";
312
import { StarFilled, StarOutlined, SearchOutlined } from "@ant-design/icons";
413
import { CategoryI, OperatorI } from "@/pages/OperatorMarket/operator.model";
514
import { Layers } from "lucide-react";
@@ -76,6 +85,7 @@ interface OperatorLibraryProps {
7685
selectedOperators: OperatorI[];
7786
operatorList: OperatorI[];
7887
categoryOptions: CategoryI[];
88+
setSelectedOperators: (operators: OperatorI[]) => void;
7989
toggleOperator: (template: OperatorI) => void;
8090
handleDragStart: (
8191
e: React.DragEvent,
@@ -88,6 +98,7 @@ const OperatorLibrary: React.FC<OperatorLibraryProps> = ({
8898
selectedOperators,
8999
operatorList,
90100
categoryOptions,
101+
setSelectedOperators,
91102
toggleOperator,
92103
handleDragStart,
93104
}) => {
@@ -116,25 +127,40 @@ const OperatorLibrary: React.FC<OperatorLibraryProps> = ({
116127
}
117128
});
118129
}
119-
setExpandedCategories(new Set(Object.keys(groups)));
120-
return groups;
121-
}, [categoryOptions, selectedCategory]);
122130

123-
// 过滤算子
124-
const filteredOperators = useMemo(() => {
125-
let filtered = operatorList;
126131
if (searchTerm) {
127-
filtered = filtered.filter(
128-
(operator) =>
129-
operator.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
130-
operator.description.toLowerCase().includes(searchTerm.toLowerCase())
131-
);
132+
Object.keys(groups).forEach((key) => {
133+
groups[key].operators = groups[key].operators.filter((operator) =>
134+
operator.name.toLowerCase().includes(searchTerm.toLowerCase())
135+
);
136+
if (groups[key].operators.length === 0) {
137+
delete groups[key];
138+
}
139+
});
132140
}
141+
133142
if (showFavorites) {
134-
filtered = filtered.filter((operator) => favorites.has(operator.id));
143+
Object.keys(groups).forEach((key) => {
144+
groups[key].operators = groups[key].operators.filter((operator) =>
145+
favorites.has(operator.id)
146+
);
147+
if (groups[key].operators.length === 0) {
148+
delete groups[key];
149+
}
150+
});
135151
}
152+
153+
setExpandedCategories(new Set(Object.keys(groups)));
154+
return groups;
155+
}, [categoryOptions, selectedCategory, searchTerm, showFavorites]);
156+
157+
// 过滤算子
158+
const filteredOperators = useMemo(() => {
159+
const filtered = Object.values(groupedOperators).flatMap(
160+
(category) => category.operators
161+
);
136162
return filtered;
137-
}, [groupedOperators, searchTerm, showFavorites, favorites]);
163+
}, [groupedOperators]);
138164

139165
// 收藏切换
140166
const toggleFavorite = (operatorId: string) => {
@@ -147,21 +173,33 @@ const OperatorLibrary: React.FC<OperatorLibraryProps> = ({
147173
setFavorites(newFavorites);
148174
};
149175

176+
// 全选分类算子
177+
const handleSelectAll = (operators: OperatorI[]) => {
178+
const newSelected = [...selectedOperators];
179+
operators.forEach((operator) => {
180+
if (!newSelected.some((op) => op.id === operator.id)) {
181+
newSelected.push(operator);
182+
}
183+
});
184+
setSelectedOperators(newSelected);
185+
};
186+
150187
return (
151188
<div className="w-1/4 h-full min-w-3xs flex flex-col">
152189
<div className="pb-4 border-b border-gray-200">
153190
<span className="flex items-center font-semibold text-base">
154191
<Layers className="w-4 h-4 mr-2" />
155-
算子库({operatorList.length})
192+
算子库({filteredOperators.length})
156193
</span>
157194
</div>
158195
<div className="flex flex-col h-full pt-4 pr-4 overflow-hidden">
159196
{/* 过滤器 */}
160197
<div className="flex flex-wrap gap-2 border-b border-gray-100 pb-4">
161198
<Input
162199
prefix={<SearchOutlined />}
163-
placeholder="搜索算子..."
200+
placeholder="搜索算子名称..."
164201
value={searchTerm}
202+
allowClear
165203
onChange={(e) => setSearchTerm(e.target.value)}
166204
/>
167205
<Select
@@ -200,10 +238,22 @@ const OperatorLibrary: React.FC<OperatorLibraryProps> = ({
200238
<Collapse.Panel
201239
key={key}
202240
header={
203-
<span className="flex items-center gap-2">
204-
<span>{category.name}</span>
205-
<Tag>{category.operators.length}</Tag>
206-
</span>
241+
<div className="flex items-center justify-between w-full">
242+
<span className="flex items-center gap-2">
243+
<span>{category.name}</span>
244+
<Tag>{category.operators.length}</Tag>
245+
</span>
246+
<Button
247+
type="link"
248+
size="small"
249+
onClick={(e) => {
250+
e.stopPropagation();
251+
handleSelectAll(category.operators);
252+
}}
253+
>
254+
全选
255+
</Button>
256+
</div>
207257
}
208258
>
209259
<OperatorList

frontend/src/pages/DataCleansing/Create/components/ParamConfig.tsx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
import React from "react";
2-
import { Input, Select, Radio, Checkbox, Form, InputNumber, Slider } from "antd";
2+
import {
3+
Input,
4+
Select,
5+
Radio,
6+
Checkbox,
7+
Form,
8+
InputNumber,
9+
Slider,
10+
} from "antd";
311
import { OperatorI } from "@/pages/OperatorMarket/operator.model";
412

513
interface ParamConfigProps {
@@ -28,6 +36,7 @@ const ParamConfig: React.FC<ParamConfigProps> = ({
2836
value={value}
2937
onChange={(e) => updateValue(e.target.value)}
3038
placeholder={`请输入${param.label}`}
39+
className="w-full"
3140
/>
3241
</Form.Item>
3342
);
@@ -92,6 +101,7 @@ const ParamConfig: React.FC<ParamConfigProps> = ({
92101
min={param.min || 0}
93102
max={param.max || 100}
94103
step={param.step || 1}
104+
className="flex-1"
95105
/>
96106
<InputNumber
97107
min={param.min || 0}
@@ -122,6 +132,7 @@ const ParamConfig: React.FC<ParamConfigProps> = ({
122132
min={param.min || 0}
123133
max={param.max || 100}
124134
step={param.step || 1}
135+
className="w-full"
125136
/>
126137
</Form.Item>
127138
);

frontend/src/pages/DataCleansing/Create/hooks/useCreateStepTwo.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export function useCreateStepTwo() {
4444
categoryOptions={categoryOptions}
4545
selectedOperators={selectedOperators}
4646
operatorList={operators}
47+
setSelectedOperators={setSelectedOperators}
4748
toggleOperator={toggleOperator}
4849
handleDragStart={handleDragStart}
4950
/>

frontend/src/pages/DataCleansing/Home/components/TaskList.tsx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,30 @@ export default function TaskList() {
177177
<Progress percent={progress} size="small" />
178178
),
179179
},
180+
{
181+
title: "创建时间",
182+
dataIndex: "createdAt",
183+
key: "createdAt",
184+
width: 180,
185+
},
186+
{
187+
title: "执行耗时",
188+
dataIndex: "duration",
189+
key: "duration",
190+
width: 180,
191+
},
192+
{
193+
title: "数据量变化",
194+
dataIndex: "dataSizeChange",
195+
key: "dataSizeChange",
196+
width: 180,
197+
render: (_: any, record: CleansingTask) => {
198+
if (record.before !== undefined && record.after !== undefined) {
199+
return `${record.before}${record.after}`;
200+
}
201+
return "-";
202+
},
203+
},
180204
{
181205
title: "操作",
182206
key: "action",

frontend/src/pages/DataCleansing/cleansing.const.tsx

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@ import {
44
TaskStatus,
55
TemplateType,
66
} from "@/pages/DataCleansing/cleansing.model";
7-
import { formatDateTime } from "@/utils/unit";
7+
import {
8+
formatBytes,
9+
formatDateTime,
10+
formatExecutionDuration,
11+
} from "@/utils/unit";
812
import {
913
ClockCircleOutlined,
1014
PlayCircleOutlined,
@@ -82,15 +86,39 @@ export const TaskStatusMap = {
8286
};
8387

8488
export const mapTask = (task: CleansingTask) => {
89+
const duration = formatExecutionDuration(task.startedAt, task.finishedAt);
90+
const before = formatBytes(task.beforeSize);
91+
const after = formatBytes(task.afterSize);
92+
const status = TaskStatusMap[task.status];
93+
const finishedAt = formatDateTime(task.finishedAt);
94+
const startedAt = formatDateTime(task.startedAt);
95+
const createdAt = formatDateTime(task.createdAt);
8596
return {
8697
...task,
87-
createdAt: formatDateTime(task.createdAt),
88-
startedAt: formatDateTime(task.startedAt),
89-
endedAt: formatDateTime(task.endedAt),
98+
createdAt,
99+
startedAt,
100+
finishedAt,
90101
icon: <DatabaseOutlined style={{ color: "#1677ff" }} />,
91102
iconColor: "bg-blue-100",
92-
status: TaskStatusMap[task.status],
93-
statistics: [{ label: "进度", value: `${task.progress}%` }],
103+
status,
104+
duration,
105+
before,
106+
after,
107+
statistics: [
108+
{ label: "进度", value: `${task.progress || 0}%` },
109+
{
110+
label: "执行耗时",
111+
value: duration,
112+
},
113+
{
114+
label: "处理前数据大小",
115+
value: task.beforeSize ? formatBytes(task.beforeSize) : "--",
116+
},
117+
{
118+
label: "处理后数据大小",
119+
value: task.afterSize ? formatBytes(task.afterSize) : "--",
120+
},
121+
],
94122
lastModified: formatDateTime(task.createdAt),
95123
};
96124
};

frontend/src/pages/DataCleansing/cleansing.model.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ export interface CleansingTask {
2020
operators: OperatorI[];
2121
createdAt: string;
2222
updatedAt: string;
23+
finishedAt: string;
24+
beforeSize?: number;
25+
afterSize?: number;
2326
}
2427

2528
export interface CleansingTemplate {

frontend/src/pages/DataManagement/Create/EditDataset.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,10 @@ export default function EditDataset({
7171
return (
7272
<Drawer
7373
title={`编辑数据集${data?.name}`}
74-
closable={{ "aria-label": "Close Button" }}
7574
onClose={onClose}
7675
open={open}
7776
width={600}
77+
maskClosable={false}
7878
footer={
7979
<div className="flex gap-2 justify-end p-6">
8080
<Button onClick={onClose}>取消</Button>

0 commit comments

Comments
 (0)