增加团队管理页面
This commit is contained in:
parent
1dbb411e08
commit
10bfa7bcbd
@ -1,21 +1,21 @@
|
|||||||
import React, { useState, useEffect, useMemo } from 'react';
|
import React, {useState, useEffect, useMemo} from 'react';
|
||||||
import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card';
|
import {Card, CardHeader, CardTitle, CardContent} from '@/components/ui/card';
|
||||||
import { Table, TableHeader, TableBody, TableRow, TableHead, TableCell } from '@/components/ui/table';
|
import {Table, TableHeader, TableBody, TableRow, TableHead, TableCell} from '@/components/ui/table';
|
||||||
import { Badge } from '@/components/ui/badge';
|
import {Badge} from '@/components/ui/badge';
|
||||||
import { Button } from '@/components/ui/button';
|
import {Button} from '@/components/ui/button';
|
||||||
import { Input } from '@/components/ui/input';
|
import {Input} from '@/components/ui/input';
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
import {Select, SelectContent, SelectItem, SelectTrigger, SelectValue} from '@/components/ui/select';
|
||||||
import { DataTablePagination } from '@/components/ui/pagination';
|
import {DataTablePagination} from '@/components/ui/pagination';
|
||||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
import {Tabs, TabsContent, TabsList, TabsTrigger} from '@/components/ui/tabs';
|
||||||
import {
|
import {
|
||||||
Loader2, Plus, Search, Edit, Trash2, Play, Pause,
|
Loader2, Plus, Search, Edit, Trash2, Play, Pause,
|
||||||
Clock, Activity, CheckCircle2, XCircle, FolderKanban, PlayCircle, FileText, BarChart3, List
|
Clock, Activity, CheckCircle2, XCircle, FolderKanban, PlayCircle, FileText, BarChart3, List, Ban
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import { useToast } from '@/components/ui/use-toast';
|
import {useToast} from '@/components/ui/use-toast';
|
||||||
import { getScheduleJobs, getJobCategoryList, startJob, pauseJob, resumeJob, stopJob, triggerJob, deleteScheduleJob } from './service';
|
import {getScheduleJobs, getJobCategoryList, startJob, pauseJob, resumeJob, stopJob, triggerJob, disableJob, deleteScheduleJob, enableJob} from './service';
|
||||||
import type { ScheduleJobResponse, ScheduleJobQuery, JobCategoryResponse, JobStatus } from './types';
|
import type {ScheduleJobResponse, ScheduleJobQuery, JobCategoryResponse, JobStatus} from './types';
|
||||||
import type { Page } from '@/types/base';
|
import type {Page} from '@/types/base';
|
||||||
import { DEFAULT_PAGE_SIZE, DEFAULT_CURRENT } from '@/utils/page';
|
import {DEFAULT_PAGE_SIZE, DEFAULT_CURRENT} from '@/utils/page';
|
||||||
import CategoryManageDialog from './components/CategoryManageDialog';
|
import CategoryManageDialog from './components/CategoryManageDialog';
|
||||||
import JobLogDialog from './components/JobLogDialog';
|
import JobLogDialog from './components/JobLogDialog';
|
||||||
import JobEditDialog from './components/JobEditDialog';
|
import JobEditDialog from './components/JobEditDialog';
|
||||||
@ -36,7 +36,7 @@ import dayjs from 'dayjs';
|
|||||||
* 定时任务列表页
|
* 定时任务列表页
|
||||||
*/
|
*/
|
||||||
const ScheduleJobList: React.FC = () => {
|
const ScheduleJobList: React.FC = () => {
|
||||||
const { toast } = useToast();
|
const {toast} = useToast();
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [data, setData] = useState<Page<ScheduleJobResponse> | null>(null);
|
const [data, setData] = useState<Page<ScheduleJobResponse> | null>(null);
|
||||||
const [categories, setCategories] = useState<JobCategoryResponse[]>([]);
|
const [categories, setCategories] = useState<JobCategoryResponse[]>([]);
|
||||||
@ -88,7 +88,7 @@ const ScheduleJobList: React.FC = () => {
|
|||||||
|
|
||||||
// 搜索
|
// 搜索
|
||||||
const handleSearch = () => {
|
const handleSearch = () => {
|
||||||
setQuery(prev => ({ ...prev, pageNum: 0 }));
|
setQuery(prev => ({...prev, pageNum: 0}));
|
||||||
};
|
};
|
||||||
|
|
||||||
// 重置
|
// 重置
|
||||||
@ -236,6 +236,44 @@ const ScheduleJobList: React.FC = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 禁用任务
|
||||||
|
const handleDisable = async (record: ScheduleJobResponse) => {
|
||||||
|
try {
|
||||||
|
await disableJob(record.id);
|
||||||
|
toast({
|
||||||
|
title: '禁用成功',
|
||||||
|
description: `任务 "${record.jobName}" 已禁用`,
|
||||||
|
});
|
||||||
|
loadData();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('禁用失败:', error);
|
||||||
|
toast({
|
||||||
|
variant: 'destructive',
|
||||||
|
title: '禁用失败',
|
||||||
|
description: error instanceof Error ? error.message : '未知错误',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 启用(解除禁用)任务
|
||||||
|
const handleEnable = async (record: ScheduleJobResponse) => {
|
||||||
|
try {
|
||||||
|
await enableJob(record.id);
|
||||||
|
toast({
|
||||||
|
title: '启用成功',
|
||||||
|
description: `任务 "${record.jobName}" 已启用`,
|
||||||
|
});
|
||||||
|
loadData();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('启用失败:', error);
|
||||||
|
toast({
|
||||||
|
variant: 'destructive',
|
||||||
|
title: '启用失败',
|
||||||
|
description: error instanceof Error ? error.message : '未知错误',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// 查看日志
|
// 查看日志
|
||||||
const handleViewLog = (record: ScheduleJobResponse) => {
|
const handleViewLog = (record: ScheduleJobResponse) => {
|
||||||
setSelectedJob(record);
|
setSelectedJob(record);
|
||||||
@ -249,15 +287,15 @@ const ScheduleJobList: React.FC = () => {
|
|||||||
text: string;
|
text: string;
|
||||||
icon: React.ElementType
|
icon: React.ElementType
|
||||||
}> = {
|
}> = {
|
||||||
ENABLED: { variant: 'default', text: '启用', icon: CheckCircle2 },
|
ENABLED: {variant: 'default', text: '启用', icon: CheckCircle2},
|
||||||
DISABLED: { variant: 'secondary', text: '禁用', icon: XCircle },
|
DISABLED: {variant: 'secondary', text: '禁用', icon: XCircle},
|
||||||
PAUSED: { variant: 'outline', text: '暂停', icon: Pause },
|
PAUSED: {variant: 'outline', text: '暂停', icon: Pause},
|
||||||
};
|
};
|
||||||
const statusInfo = statusMap[status] || { variant: 'outline', text: status, icon: Clock };
|
const statusInfo = statusMap[status] || {variant: 'outline', text: status, icon: Clock};
|
||||||
const Icon = statusInfo.icon;
|
const Icon = statusInfo.icon;
|
||||||
return (
|
return (
|
||||||
<Badge variant={statusInfo.variant} className="inline-flex items-center gap-1">
|
<Badge variant={statusInfo.variant} className="inline-flex items-center gap-1">
|
||||||
<Icon className="h-3 w-3" />
|
<Icon className="h-3 w-3"/>
|
||||||
{statusInfo.text}
|
{statusInfo.text}
|
||||||
</Badge>
|
</Badge>
|
||||||
);
|
);
|
||||||
@ -268,7 +306,7 @@ const ScheduleJobList: React.FC = () => {
|
|||||||
const total = data?.totalElements || 0;
|
const total = data?.totalElements || 0;
|
||||||
const enabledCount = data?.content?.filter(d => d.status === 'ENABLED').length || 0;
|
const enabledCount = data?.content?.filter(d => d.status === 'ENABLED').length || 0;
|
||||||
const pausedCount = data?.content?.filter(d => d.status === 'PAUSED').length || 0;
|
const pausedCount = data?.content?.filter(d => d.status === 'PAUSED').length || 0;
|
||||||
return { total, enabledCount, pausedCount };
|
return {total, enabledCount, pausedCount};
|
||||||
}, [data]);
|
}, [data]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -284,11 +322,11 @@ const ScheduleJobList: React.FC = () => {
|
|||||||
<Tabs defaultValue="list" className="space-y-6">
|
<Tabs defaultValue="list" className="space-y-6">
|
||||||
<TabsList>
|
<TabsList>
|
||||||
<TabsTrigger value="list" className="gap-2">
|
<TabsTrigger value="list" className="gap-2">
|
||||||
<List className="h-4 w-4" />
|
<List className="h-4 w-4"/>
|
||||||
列表视图
|
列表视图
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
<TabsTrigger value="dashboard" className="gap-2">
|
<TabsTrigger value="dashboard" className="gap-2">
|
||||||
<BarChart3 className="h-4 w-4" />
|
<BarChart3 className="h-4 w-4"/>
|
||||||
仪表盘
|
仪表盘
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
</TabsList>
|
</TabsList>
|
||||||
@ -300,7 +338,7 @@ const ScheduleJobList: React.FC = () => {
|
|||||||
<Card className="bg-gradient-to-br from-blue-500/10 to-blue-500/5 border-blue-500/20">
|
<Card className="bg-gradient-to-br from-blue-500/10 to-blue-500/5 border-blue-500/20">
|
||||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||||
<CardTitle className="text-sm font-medium text-blue-700">总任务</CardTitle>
|
<CardTitle className="text-sm font-medium text-blue-700">总任务</CardTitle>
|
||||||
<Activity className="h-4 w-4 text-blue-500" />
|
<Activity className="h-4 w-4 text-blue-500"/>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="text-2xl font-bold">{stats.total}</div>
|
<div className="text-2xl font-bold">{stats.total}</div>
|
||||||
@ -310,7 +348,7 @@ const ScheduleJobList: React.FC = () => {
|
|||||||
<Card className="bg-gradient-to-br from-green-500/10 to-green-500/5 border-green-500/20">
|
<Card className="bg-gradient-to-br from-green-500/10 to-green-500/5 border-green-500/20">
|
||||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||||
<CardTitle className="text-sm font-medium text-green-700">运行中</CardTitle>
|
<CardTitle className="text-sm font-medium text-green-700">运行中</CardTitle>
|
||||||
<CheckCircle2 className="h-4 w-4 text-green-500" />
|
<CheckCircle2 className="h-4 w-4 text-green-500"/>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="text-2xl font-bold">{stats.enabledCount}</div>
|
<div className="text-2xl font-bold">{stats.enabledCount}</div>
|
||||||
@ -320,7 +358,7 @@ const ScheduleJobList: React.FC = () => {
|
|||||||
<Card className="bg-gradient-to-br from-yellow-500/10 to-yellow-500/5 border-yellow-500/20">
|
<Card className="bg-gradient-to-br from-yellow-500/10 to-yellow-500/5 border-yellow-500/20">
|
||||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||||
<CardTitle className="text-sm font-medium text-yellow-700">已暂停</CardTitle>
|
<CardTitle className="text-sm font-medium text-yellow-700">已暂停</CardTitle>
|
||||||
<Pause className="h-4 w-4 text-yellow-500" />
|
<Pause className="h-4 w-4 text-yellow-500"/>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="text-2xl font-bold">{stats.pausedCount}</div>
|
<div className="text-2xl font-bold">{stats.pausedCount}</div>
|
||||||
@ -334,11 +372,11 @@ const ScheduleJobList: React.FC = () => {
|
|||||||
<CardTitle>任务列表</CardTitle>
|
<CardTitle>任务列表</CardTitle>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Button variant="outline" onClick={() => setCategoryDialogOpen(true)}>
|
<Button variant="outline" onClick={() => setCategoryDialogOpen(true)}>
|
||||||
<FolderKanban className="h-4 w-4 mr-2" />
|
<FolderKanban className="h-4 w-4 mr-2"/>
|
||||||
分类管理
|
分类管理
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={handleCreate}>
|
<Button onClick={handleCreate}>
|
||||||
<Plus className="h-4 w-4 mr-2" />
|
<Plus className="h-4 w-4 mr-2"/>
|
||||||
新建任务
|
新建任务
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
@ -350,16 +388,16 @@ const ScheduleJobList: React.FC = () => {
|
|||||||
<Input
|
<Input
|
||||||
placeholder="搜索任务名称..."
|
placeholder="搜索任务名称..."
|
||||||
value={query.jobName}
|
value={query.jobName}
|
||||||
onChange={(e) => setQuery({ ...query, jobName: e.target.value })}
|
onChange={(e) => setQuery({...query, jobName: e.target.value})}
|
||||||
onKeyDown={(e) => e.key === 'Enter' && handleSearch()}
|
onKeyDown={(e) => e.key === 'Enter' && handleSearch()}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Select
|
<Select
|
||||||
value={query.categoryId?.toString() || 'all'}
|
value={query.categoryId?.toString() || 'all'}
|
||||||
onValueChange={(value) => setQuery({ ...query, categoryId: value !== 'all' ? Number(value) : undefined, pageNum: 0 })}
|
onValueChange={(value) => setQuery({...query, categoryId: value !== 'all' ? Number(value) : undefined, pageNum: 0})}
|
||||||
>
|
>
|
||||||
<SelectTrigger className="w-[200px]">
|
<SelectTrigger className="w-[200px]">
|
||||||
<SelectValue placeholder="全部分类" />
|
<SelectValue placeholder="全部分类"/>
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectItem value="all">全部分类</SelectItem>
|
<SelectItem value="all">全部分类</SelectItem>
|
||||||
@ -372,10 +410,10 @@ const ScheduleJobList: React.FC = () => {
|
|||||||
</Select>
|
</Select>
|
||||||
<Select
|
<Select
|
||||||
value={query.status || 'all'}
|
value={query.status || 'all'}
|
||||||
onValueChange={(value) => setQuery({ ...query, status: value !== 'all' ? value as JobStatus : undefined, pageNum: 0 })}
|
onValueChange={(value) => setQuery({...query, status: value !== 'all' ? value as JobStatus : undefined, pageNum: 0})}
|
||||||
>
|
>
|
||||||
<SelectTrigger className="w-[150px]">
|
<SelectTrigger className="w-[150px]">
|
||||||
<SelectValue placeholder="全部状态" />
|
<SelectValue placeholder="全部状态"/>
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectItem value="all">全部状态</SelectItem>
|
<SelectItem value="all">全部状态</SelectItem>
|
||||||
@ -385,7 +423,7 @@ const ScheduleJobList: React.FC = () => {
|
|||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
<Button onClick={handleSearch}>
|
<Button onClick={handleSearch}>
|
||||||
<Search className="h-4 w-4 mr-2" />
|
<Search className="h-4 w-4 mr-2"/>
|
||||||
查询
|
查询
|
||||||
</Button>
|
</Button>
|
||||||
<Button variant="outline" onClick={handleReset}>
|
<Button variant="outline" onClick={handleReset}>
|
||||||
@ -416,7 +454,7 @@ const ScheduleJobList: React.FC = () => {
|
|||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell colSpan={11} className="h-24 text-center">
|
<TableCell colSpan={11} className="h-24 text-center">
|
||||||
<div className="flex items-center justify-center gap-2">
|
<div className="flex items-center justify-center gap-2">
|
||||||
<Loader2 className="h-4 w-4 animate-spin" />
|
<Loader2 className="h-4 w-4 animate-spin"/>
|
||||||
<span className="text-muted-foreground">加载中...</span>
|
<span className="text-muted-foreground">加载中...</span>
|
||||||
</div>
|
</div>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
@ -457,18 +495,12 @@ const ScheduleJobList: React.FC = () => {
|
|||||||
<span className="text-muted-foreground">-</span>
|
<span className="text-muted-foreground">-</span>
|
||||||
)}
|
)}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell sticky width="240px">
|
<TableCell sticky width="280px">
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1">
|
||||||
<Button
|
{/* ENABLED 按钮控制 */}
|
||||||
variant="ghost"
|
|
||||||
size="icon"
|
|
||||||
className="h-7 w-7"
|
|
||||||
onClick={() => handleTrigger(record)}
|
|
||||||
title="立即触发"
|
|
||||||
>
|
|
||||||
<PlayCircle className="h-4 w-4" />
|
|
||||||
</Button>
|
|
||||||
{record.status === 'ENABLED' && (
|
{record.status === 'ENABLED' && (
|
||||||
|
<>
|
||||||
|
{/* 暂停 */}
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="icon"
|
size="icon"
|
||||||
@ -476,10 +508,34 @@ const ScheduleJobList: React.FC = () => {
|
|||||||
onClick={() => handlePause(record)}
|
onClick={() => handlePause(record)}
|
||||||
title="暂停"
|
title="暂停"
|
||||||
>
|
>
|
||||||
<Pause className="h-4 w-4" />
|
<Pause className="h-4 w-4"/>
|
||||||
</Button>
|
</Button>
|
||||||
|
{/* 禁用 */}
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
className="h-7 w-7 text-orange-600 hover:text-orange-700 hover:bg-orange-50 dark:text-orange-500 dark:hover:bg-orange-950/20"
|
||||||
|
onClick={() => handleDisable(record)}
|
||||||
|
title="禁用"
|
||||||
|
>
|
||||||
|
<Ban className="h-4 w-4"/>
|
||||||
|
</Button>
|
||||||
|
{/* 立即执行 */}
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
className="h-7 w-7 text-green-600 hover:text-green-700 hover:bg-green-50 dark:text-green-500 dark:hover:bg-green-950/20"
|
||||||
|
onClick={() => handleTrigger(record)}
|
||||||
|
title="立即执行"
|
||||||
|
>
|
||||||
|
<PlayCircle className="h-4 w-4"/>
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
|
{/* PAUSED 按钮控制 */}
|
||||||
{record.status === 'PAUSED' && (
|
{record.status === 'PAUSED' && (
|
||||||
|
<>
|
||||||
|
{/* 恢复 */}
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="icon"
|
size="icon"
|
||||||
@ -487,9 +543,42 @@ const ScheduleJobList: React.FC = () => {
|
|||||||
onClick={() => handleResume(record)}
|
onClick={() => handleResume(record)}
|
||||||
title="恢复"
|
title="恢复"
|
||||||
>
|
>
|
||||||
<Play className="h-4 w-4" />
|
<Play className="h-4 w-4"/>
|
||||||
|
</Button>
|
||||||
|
{/* 禁用 */}
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
className="h-7 w-7 text-orange-600 hover:text-orange-700 hover:bg-orange-50 dark:text-orange-500 dark:hover:bg-orange-950/20"
|
||||||
|
onClick={() => handleDisable(record)}
|
||||||
|
title="禁用"
|
||||||
|
>
|
||||||
|
<Ban className="h-4 w-4"/>
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{/* DISABLED 按钮控制 */}
|
||||||
|
{record.status === 'DISABLED' && (
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
className="h-7 w-7 text-blue-600 hover:text-blue-700 hover:bg-blue-50 dark:text-blue-400 dark:hover:bg-blue-950/20"
|
||||||
|
onClick={() => handleEnable(record)}
|
||||||
|
title="启用"
|
||||||
|
>
|
||||||
|
<CheckCircle2 className="h-4 w-4"/>
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
{/* 删除按钮 所有状态显示 */}
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
className="h-7 w-7 text-destructive hover:text-destructive"
|
||||||
|
onClick={() => handleDeleteClick(record)}
|
||||||
|
title="删除"
|
||||||
|
>
|
||||||
|
<Trash2 className="h-4 w-4"/>
|
||||||
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="icon"
|
size="icon"
|
||||||
@ -497,7 +586,7 @@ const ScheduleJobList: React.FC = () => {
|
|||||||
onClick={() => handleViewLog(record)}
|
onClick={() => handleViewLog(record)}
|
||||||
title="查看日志"
|
title="查看日志"
|
||||||
>
|
>
|
||||||
<FileText className="h-4 w-4" />
|
<FileText className="h-4 w-4"/>
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
@ -506,16 +595,7 @@ const ScheduleJobList: React.FC = () => {
|
|||||||
onClick={() => handleEdit(record)}
|
onClick={() => handleEdit(record)}
|
||||||
title="编辑"
|
title="编辑"
|
||||||
>
|
>
|
||||||
<Edit className="h-4 w-4" />
|
<Edit className="h-4 w-4"/>
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
variant="ghost"
|
|
||||||
size="icon"
|
|
||||||
className="h-7 w-7 text-destructive hover:text-destructive"
|
|
||||||
onClick={() => handleDeleteClick(record)}
|
|
||||||
title="删除"
|
|
||||||
>
|
|
||||||
<Trash2 className="h-4 w-4" />
|
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
@ -539,7 +619,7 @@ const ScheduleJobList: React.FC = () => {
|
|||||||
pageIndex={query.pageNum || 0}
|
pageIndex={query.pageNum || 0}
|
||||||
pageSize={query.pageSize || DEFAULT_PAGE_SIZE}
|
pageSize={query.pageSize || DEFAULT_PAGE_SIZE}
|
||||||
pageCount={data.totalPages}
|
pageCount={data.totalPages}
|
||||||
onPageChange={(pageIndex) => setQuery({ ...query, pageNum: pageIndex })}
|
onPageChange={(pageIndex) => setQuery({...query, pageNum: pageIndex})}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -623,7 +703,7 @@ const ScheduleJobList: React.FC = () => {
|
|||||||
|
|
||||||
{/* 仪表盘视图 */}
|
{/* 仪表盘视图 */}
|
||||||
<TabsContent value="dashboard">
|
<TabsContent value="dashboard">
|
||||||
<Dashboard />
|
<Dashboard/>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -122,6 +122,17 @@ export const stopJob = (id: number) =>
|
|||||||
export const triggerJob = (id: number) =>
|
export const triggerJob = (id: number) =>
|
||||||
request.post<void>(`${SCHEDULE_JOB_URL}/${id}/trigger`);
|
request.post<void>(`${SCHEDULE_JOB_URL}/${id}/trigger`);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 禁用任务
|
||||||
|
*/
|
||||||
|
export const disableJob = (id: number) =>
|
||||||
|
request.post<void>(`${SCHEDULE_JOB_URL}/${id}/disable`);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用任务(解除禁用)
|
||||||
|
*/
|
||||||
|
export const enableJob = (id: number) => request.post<void>(`${SCHEDULE_JOB_URL}/${id}/enable`);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新Cron表达式
|
* 更新Cron表达式
|
||||||
*/
|
*/
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user