重构消息通知弹窗
This commit is contained in:
parent
763d14f3d3
commit
f66524bac6
@ -174,6 +174,7 @@ export function ConfirmDialog<T = any>({
|
|||||||
|
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
onCancel?.();
|
onCancel?.();
|
||||||
|
onOpenChange(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 按钮样式映射
|
// 按钮样式映射
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState, useMemo, useRef } from 'react';
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
@ -7,23 +7,16 @@ import {
|
|||||||
DialogFooter,
|
DialogFooter,
|
||||||
DialogBody,
|
DialogBody,
|
||||||
} from '@/components/ui/dialog';
|
} from '@/components/ui/dialog';
|
||||||
import {
|
|
||||||
Table,
|
|
||||||
TableBody,
|
|
||||||
TableCell,
|
|
||||||
TableHead,
|
|
||||||
TableHeader,
|
|
||||||
TableRow,
|
|
||||||
} from '@/components/ui/table';
|
|
||||||
import { ConfirmDialog } from '@/components/ui/confirm-dialog';
|
import { ConfirmDialog } from '@/components/ui/confirm-dialog';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { useToast } from '@/components/ui/use-toast';
|
import { useToast } from '@/components/ui/use-toast';
|
||||||
import { Plus, Edit, Trash2, Loader2 } from 'lucide-react';
|
import { PaginatedTable, type ColumnDef, type PaginatedTableRef } from '@/components/ui/paginated-table';
|
||||||
|
import { Plus, Edit, Trash2 } from 'lucide-react';
|
||||||
import type { Environment } from '@/pages/Deploy/Environment/List/types';
|
import type { Environment } from '@/pages/Deploy/Environment/List/types';
|
||||||
import type { TeamApplication, Application } from '../types';
|
import type { TeamApplication, Application } from '../types';
|
||||||
import type { WorkflowDefinition } from '@/pages/Workflow/Definition/List/types';
|
import type { WorkflowDefinition } from '@/pages/Workflow/Definition/List/types';
|
||||||
import {
|
import {
|
||||||
getTeamApplications,
|
getTeamApplicationsPage,
|
||||||
deleteTeamApplication,
|
deleteTeamApplication,
|
||||||
getApplicationList,
|
getApplicationList,
|
||||||
getJenkinsSystems,
|
getJenkinsSystems,
|
||||||
@ -48,7 +41,7 @@ export const TeamApplicationManageDialog: React.FC<
|
|||||||
TeamApplicationManageDialogProps
|
TeamApplicationManageDialogProps
|
||||||
> = ({ open, onOpenChange, teamId, environmentId, environments, onSuccess }) => {
|
> = ({ open, onOpenChange, teamId, environmentId, environments, onSuccess }) => {
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const [loading, setLoading] = useState(false);
|
const tableRef = useRef<PaginatedTableRef<TeamApplication>>(null);
|
||||||
const [teamApplications, setTeamApplications] = useState<TeamApplication[]>([]);
|
const [teamApplications, setTeamApplications] = useState<TeamApplication[]>([]);
|
||||||
// 如果从环境管理进入,只显示该环境的应用;否则显示所有应用
|
// 如果从环境管理进入,只显示该环境的应用;否则显示所有应用
|
||||||
const selectedEnvironmentId = environmentId || null;
|
const selectedEnvironmentId = environmentId || null;
|
||||||
@ -68,13 +61,12 @@ export const TeamApplicationManageDialog: React.FC<
|
|||||||
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
||||||
const [deletingApp, setDeletingApp] = useState<TeamApplication | null>(null);
|
const [deletingApp, setDeletingApp] = useState<TeamApplication | null>(null);
|
||||||
|
|
||||||
// 加载基础数据和应用列表
|
// 加载基础数据
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (open) {
|
if (open) {
|
||||||
loadTeamApplications();
|
|
||||||
loadBaseData();
|
loadBaseData();
|
||||||
}
|
}
|
||||||
}, [open, teamId, selectedEnvironmentId]);
|
}, [open]);
|
||||||
|
|
||||||
const loadBaseData = async () => {
|
const loadBaseData = async () => {
|
||||||
try {
|
try {
|
||||||
@ -95,23 +87,15 @@ export const TeamApplicationManageDialog: React.FC<
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 后端已经根据 selectedEnvironmentId 筛选了数据,前端不需要再次筛选
|
// 包装 fetchFn
|
||||||
|
const fetchData = async (query: any) => {
|
||||||
const loadTeamApplications = async () => {
|
const result = await getTeamApplicationsPage({
|
||||||
setLoading(true);
|
...query,
|
||||||
try {
|
teamId,
|
||||||
// 如果指定了环境ID,只加载该环境的应用;否则加载所有
|
environmentId: selectedEnvironmentId || undefined,
|
||||||
const data = await getTeamApplications(teamId, selectedEnvironmentId || undefined);
|
|
||||||
setTeamApplications(data);
|
|
||||||
} catch (error: any) {
|
|
||||||
toast({
|
|
||||||
title: '加载失败',
|
|
||||||
description: error.message || '无法加载应用列表',
|
|
||||||
variant: 'destructive',
|
|
||||||
});
|
});
|
||||||
} finally {
|
setTeamApplications(result.content || []);
|
||||||
setLoading(false);
|
return result;
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleOpenAddAppDialog = () => {
|
const handleOpenAddAppDialog = () => {
|
||||||
@ -166,7 +150,7 @@ export const TeamApplicationManageDialog: React.FC<
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 刷新应用列表
|
// 刷新应用列表
|
||||||
await loadTeamApplications();
|
tableRef.current?.refresh();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleLoadBranches = async (_appId: number, app: Application) => {
|
const handleLoadBranches = async (_appId: number, app: Application) => {
|
||||||
@ -202,6 +186,90 @@ export const TeamApplicationManageDialog: React.FC<
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 列定义
|
||||||
|
const columns: ColumnDef<TeamApplication>[] = useMemo(() => [
|
||||||
|
{
|
||||||
|
key: 'applicationName',
|
||||||
|
title: '应用名称',
|
||||||
|
width: '200px',
|
||||||
|
render: (_, app) => (
|
||||||
|
<span className="font-medium">
|
||||||
|
{app.applicationName && app.applicationCode
|
||||||
|
? `${app.applicationName}(${app.applicationCode})`
|
||||||
|
: app.applicationName || app.applicationCode || `应用 ${app.applicationId}`}
|
||||||
|
</span>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'environmentId',
|
||||||
|
title: '环境',
|
||||||
|
width: '100px',
|
||||||
|
render: (_, app) => getEnvironmentName(app.environmentId),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'buildType',
|
||||||
|
title: '构建类型',
|
||||||
|
width: '120px',
|
||||||
|
render: (_, app) =>
|
||||||
|
app.buildType === 'JENKINS' ? 'Jenkins构建' : app.buildType === 'NATIVE' ? '脚本部署' : '-',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'branch',
|
||||||
|
title: '分支',
|
||||||
|
dataIndex: 'branch',
|
||||||
|
width: '100px',
|
||||||
|
render: (value) => value || '-',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'deploySystemName',
|
||||||
|
title: 'Jenkins系统',
|
||||||
|
width: '150px',
|
||||||
|
render: (_, app) =>
|
||||||
|
app.buildType === 'JENKINS'
|
||||||
|
? (app.deploySystemName || (app.deploySystemId ? `系统 ${app.deploySystemId}` : '-'))
|
||||||
|
: '-',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'deployJob',
|
||||||
|
title: 'Jenkins Job',
|
||||||
|
width: '150px',
|
||||||
|
render: (_, app) => (app.buildType === 'JENKINS' ? (app.deployJob || '-') : '-'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'workflowDefinitionName',
|
||||||
|
title: '工作流',
|
||||||
|
dataIndex: 'workflowDefinitionName',
|
||||||
|
width: '180px',
|
||||||
|
render: (value) => value || '-',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'actions',
|
||||||
|
title: '操作',
|
||||||
|
width: '100px',
|
||||||
|
sticky: true,
|
||||||
|
render: (_, app) => (
|
||||||
|
<div className="flex items-center justify-end gap-1">
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
className="h-8 w-8 p-0"
|
||||||
|
onClick={() => handleOpenEditAppDialog(app)}
|
||||||
|
>
|
||||||
|
<Edit className="h-3.5 w-3.5" />
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
className="h-8 w-8 p-0"
|
||||||
|
onClick={() => handleOpenDeleteDialog(app)}
|
||||||
|
>
|
||||||
|
<Trash2 className="h-3.5 w-3.5 text-destructive" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
], [environments]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||||
@ -221,84 +289,14 @@ export const TeamApplicationManageDialog: React.FC<
|
|||||||
|
|
||||||
{/* 应用列表表格 */}
|
{/* 应用列表表格 */}
|
||||||
<div className="border rounded-lg">
|
<div className="border rounded-lg">
|
||||||
{loading ? (
|
<PaginatedTable<TeamApplication, any>
|
||||||
<div className="flex items-center justify-center h-64">
|
ref={tableRef}
|
||||||
<Loader2 className="h-8 w-8 animate-spin text-muted-foreground" />
|
fetchFn={fetchData}
|
||||||
</div>
|
columns={columns}
|
||||||
) : teamApplications.length === 0 ? (
|
rowKey="id"
|
||||||
<div className="flex flex-col items-center justify-center h-64 text-muted-foreground">
|
minWidth="1000px"
|
||||||
<p>暂无应用配置</p>
|
pageSize={10}
|
||||||
<Button
|
/>
|
||||||
variant="link"
|
|
||||||
onClick={handleOpenAddAppDialog}
|
|
||||||
className="mt-2"
|
|
||||||
>
|
|
||||||
立即添加
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<Table>
|
|
||||||
<TableHeader>
|
|
||||||
<TableRow>
|
|
||||||
<TableHead className="whitespace-nowrap" style={{ minWidth: '150px' }}>应用名称</TableHead>
|
|
||||||
<TableHead className="whitespace-nowrap" style={{ minWidth: '80px' }}>环境</TableHead>
|
|
||||||
<TableHead className="whitespace-nowrap" style={{ minWidth: '100px' }}>构建类型</TableHead>
|
|
||||||
<TableHead className="whitespace-nowrap" style={{ minWidth: '80px' }}>分支</TableHead>
|
|
||||||
<TableHead className="whitespace-nowrap" style={{ minWidth: '120px' }}>Jenkins系统</TableHead>
|
|
||||||
<TableHead className="whitespace-nowrap" style={{ minWidth: '120px' }}>Jenkins Job</TableHead>
|
|
||||||
<TableHead className="whitespace-nowrap" style={{ minWidth: '150px' }}>工作流</TableHead>
|
|
||||||
<TableHead className="text-right sticky right-0 bg-background" style={{ width: '80px' }}>操作</TableHead>
|
|
||||||
</TableRow>
|
|
||||||
</TableHeader>
|
|
||||||
<TableBody>
|
|
||||||
{teamApplications.map((app) => (
|
|
||||||
<TableRow key={app.id}>
|
|
||||||
<TableCell className="font-medium whitespace-nowrap">
|
|
||||||
{app.applicationName && app.applicationCode
|
|
||||||
? `${app.applicationName}(${app.applicationCode})`
|
|
||||||
: app.applicationName || app.applicationCode || `应用 ${app.applicationId}`}
|
|
||||||
</TableCell>
|
|
||||||
<TableCell className="whitespace-nowrap">
|
|
||||||
{getEnvironmentName(app.environmentId)}
|
|
||||||
</TableCell>
|
|
||||||
<TableCell className="whitespace-nowrap">
|
|
||||||
{app.buildType === 'JENKINS' ? 'Jenkins构建' : app.buildType === 'NATIVE' ? '脚本部署' : '-'}
|
|
||||||
</TableCell>
|
|
||||||
<TableCell className="whitespace-nowrap">{app.branch || '-'}</TableCell>
|
|
||||||
<TableCell className="whitespace-nowrap">
|
|
||||||
{app.buildType === 'JENKINS'
|
|
||||||
? (app.deploySystemName || (app.deploySystemId ? `系统 ${app.deploySystemId}` : '-'))
|
|
||||||
: '-'}
|
|
||||||
</TableCell>
|
|
||||||
<TableCell className="whitespace-nowrap">
|
|
||||||
{app.buildType === 'JENKINS' ? (app.deployJob || '-') : '-'}
|
|
||||||
</TableCell>
|
|
||||||
<TableCell className="whitespace-nowrap">
|
|
||||||
{app.workflowDefinitionName || '-'}
|
|
||||||
</TableCell>
|
|
||||||
<TableCell className="text-right sticky right-0 bg-background">
|
|
||||||
<div className="flex items-center justify-end gap-2">
|
|
||||||
<Button
|
|
||||||
variant="ghost"
|
|
||||||
size="sm"
|
|
||||||
onClick={() => handleOpenEditAppDialog(app)}
|
|
||||||
>
|
|
||||||
<Edit className="h-4 w-4" />
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
variant="ghost"
|
|
||||||
size="sm"
|
|
||||||
onClick={() => handleOpenDeleteDialog(app)}
|
|
||||||
>
|
|
||||||
<Trash2 className="h-4 w-4 text-destructive" />
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
))}
|
|
||||||
</TableBody>
|
|
||||||
</Table>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</DialogBody>
|
</DialogBody>
|
||||||
|
|
||||||
@ -353,7 +351,7 @@ export const TeamApplicationManageDialog: React.FC<
|
|||||||
description: '应用配置已删除',
|
description: '应用配置已删除',
|
||||||
});
|
});
|
||||||
setDeletingApp(null);
|
setDeletingApp(null);
|
||||||
loadTeamApplications();
|
tableRef.current?.refresh();
|
||||||
onSuccess?.();
|
onSuccess?.();
|
||||||
}}
|
}}
|
||||||
variant="destructive"
|
variant="destructive"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user