revert: 移除任务列表批量删除功能

- 还原 TasksPage/App/app.css 至 1bb28e3 状态(5795c39 及其未提交的布局调整一并撤销)
- 应用户要求移除复选框/全选/删除所选
This commit is contained in:
yu 2026-11-02 15:33:00 +08:00
parent 5795c39a6f
commit 56d00fba49
3 changed files with 2 additions and 87 deletions

View File

@ -175,26 +175,6 @@ export function App() {
}
};
const deleteTasks = async (ids: string[]) => {
if (!ids.length) return;
if (ids.length >= flows.length) {
showToast("至少保留一个任务", "error");
return;
}
if (!window.confirm(`确定删除选中的 ${ids.length} 个任务吗?删除后不可恢复。`)) return;
try {
for (const id of ids) await window.rpa.flows.delete(id);
await refreshFlows();
if (activeFlowId && ids.includes(activeFlowId)) {
setActiveFlowId(null);
setPage("tasks");
}
showToast(`已删除 ${ids.length} 个任务`);
} catch (deleteError) {
showToast(deleteError instanceof Error ? deleteError.message : String(deleteError), "error");
}
};
const runTask = async (id: string) => {
try {
const flow = await window.rpa.flows.get(id);
@ -280,7 +260,6 @@ export function App() {
onOpenEditor={(id) => void openEditor(id)}
onRun={(id) => void runTask(id)}
onDelete={(id) => void deleteTask(id)}
onDeleteMany={(ids) => void deleteTasks(ids)}
onRefresh={() => refreshFlows()}
onToast={showToast}
/>

View File

@ -23,7 +23,6 @@ interface TasksPageProps {
onOpenEditor: (id: string) => void;
onRun: (id: string) => void;
onDelete: (id: string) => void;
onDeleteMany: (ids: string[]) => void;
onRefresh: () => void | Promise<void>;
onToast: (message: string, kind?: "ok" | "error") => void;
}
@ -47,10 +46,9 @@ function formatDuration(value?: number): string {
const RUN_LABEL = { succeeded: "成功", failed: "失败", cancelled: "已取消", never: "未运行" } as const;
export function TasksPage({ flows, onCreate, onCreateExamples, onOpenEditor, onRun, onDelete, onDeleteMany, onRefresh, onToast }: TasksPageProps) {
export function TasksPage({ flows, onCreate, onCreateExamples, onOpenEditor, onRun, onDelete, onRefresh, onToast }: TasksPageProps) {
const [query, setQuery] = useState("");
const [selectedId, setSelectedId] = useState<string | null>(flows[0]?.id || null);
const [checkedIds, setCheckedIds] = useState<string[]>([]);
const [refreshing, setRefreshing] = useState(false);
const handleRefresh = async () => {
@ -72,30 +70,12 @@ export function TasksPage({ flows, onCreate, onCreateExamples, onOpenEditor, onR
if (!selectedId || !flows.some((flow) => flow.id === selectedId)) setSelectedId(flows[0].id);
}, [flows, selectedId]);
// 勾选集合随任务列表变化裁剪,避免残留已删除任务的 id
useEffect(() => {
setCheckedIds((previous) => {
const alive = new Set(flows.map((flow) => flow.id));
const next = previous.filter((id) => alive.has(id));
return next.length === previous.length ? previous : next;
});
}, [flows]);
const filtered = useMemo(() => {
const keyword = query.trim().toLowerCase();
if (!keyword) return flows;
return flows.filter((flow) => flow.name.toLowerCase().includes(keyword));
}, [flows, query]);
const toggleChecked = (id: string) => {
setCheckedIds((previous) => (previous.includes(id) ? previous.filter((item) => item !== id) : [...previous, id]));
};
const allFilteredChecked = filtered.length > 0 && filtered.every((flow) => checkedIds.includes(flow.id));
const toggleAllFiltered = () => {
setCheckedIds(allFilteredChecked ? [] : filtered.map((flow) => flow.id));
};
const selected = flows.find((flow) => flow.id === selectedId) || filtered[0] || null;
const enabledCount = flows.filter((flow) => flow.enabled !== false).length;
const failedCount = flows.filter((flow) => flow.lastRunStatus === "failed").length;
@ -132,11 +112,6 @@ export function TasksPage({ flows, onCreate, onCreateExamples, onOpenEditor, onR
<strong>任务列表</strong>
<span className="panel-subtitle">按最近修改时间排序</span>
</div>
{checkedIds.length > 0 && (
<button type="button" className="btn btn-danger task-batch-delete" onClick={() => onDeleteMany(checkedIds)}>
<Trash2 className="icon" /> 删除所选({checkedIds.length})
</button>
)}
<label className="task-search">
<Search className="icon" />
<input value={query} onChange={(event) => setQuery(event.target.value)} placeholder="搜索任务" aria-label="搜索任务" />
@ -153,16 +128,7 @@ export function TasksPage({ flows, onCreate, onCreateExamples, onOpenEditor, onR
</div>
<div className="task-table-head" aria-hidden="true">
<span className="task-name-head">
<input
type="checkbox"
className="task-check"
checked={allFilteredChecked}
onChange={toggleAllFiltered}
title="全选"
/>
任务
</span>
<span>任务</span>
<span>状态</span>
<span>触发方式</span>
<span>最近运行</span>
@ -182,14 +148,6 @@ export function TasksPage({ flows, onCreate, onCreateExamples, onOpenEditor, onR
}}
>
<div className="task-name-cell">
<input
type="checkbox"
className="task-check"
checked={checkedIds.includes(flow.id)}
onChange={() => toggleChecked(flow.id)}
onClick={(event) => event.stopPropagation()}
aria-label={`选择任务 ${flow.name}`}
/>
<span className="task-icon"><ListChecks className="icon" /></span>
<span className="task-copy"><strong>{flow.name}</strong><small>{flow.nodeCount} 个节点</small></span>
</div>

View File

@ -2860,28 +2860,6 @@ textarea:focus-visible {
box-shadow: inset 3px 0 0 var(--blue);
}
/* 任务列表勾选框(单选/全选) */
.task-check {
width: 15px;
height: 15px;
flex: none;
margin: 0;
accent-color: var(--blue);
cursor: pointer;
}
.task-name-head {
display: flex;
align-items: center;
gap: 7px;
}
.task-batch-delete {
margin-left: 12px;
padding: 5px 12px;
font-size: 12.5px;
}
.task-name-cell,
.task-trigger,
.task-updated,