重构消息通知弹窗

This commit is contained in:
dengqichen 2025-11-27 18:47:19 +08:00
parent cbe701a5af
commit e09d8d4be2
2 changed files with 53 additions and 19 deletions

View File

@ -22,8 +22,10 @@ export function useDeploymentData(options: UseDeploymentDataOptions = {}) {
const [currentEnvId, setCurrentEnvId] = useState<number | null>(null); const [currentEnvId, setCurrentEnvId] = useState<number | null>(null);
const [deploying, setDeploying] = useState<Set<number>>(new Set()); const [deploying, setDeploying] = useState<Set<number>>(new Set());
const [isInitialLoad, setIsInitialLoad] = useState(true); const [isInitialLoad, setIsInitialLoad] = useState(true);
const [recentlyCompleted, setRecentlyCompleted] = useState(false); // 刚完成部署,保持较短轮询间隔
const intervalRef = useRef<NodeJS.Timeout | null>(null); const intervalRef = useRef<NodeJS.Timeout | null>(null);
const recentlyCompletedTimerRef = useRef<NodeJS.Timeout | null>(null);
const optionsRef = useRef(options); const optionsRef = useRef(options);
const toastRef = useRef(toast); const toastRef = useRef(toast);
@ -110,6 +112,23 @@ export function useDeploymentData(options: UseDeploymentDataOptions = {}) {
}); });
}); });
// 部署完成后:立即刷新 + 保持较短轮询间隔一段时间
if (hasChanges && newDeploying.size === 0) {
// 立即刷新一次
setTimeout(() => {
loadData(false);
}, 1000);
// 设置"刚完成部署"状态保持10秒轮询间隔30秒后恢复正常
setRecentlyCompleted(true);
if (recentlyCompletedTimerRef.current) {
clearTimeout(recentlyCompletedTimerRef.current);
}
recentlyCompletedTimerRef.current = setTimeout(() => {
setRecentlyCompleted(false);
}, 30000);
}
return hasChanges ? newDeploying : prevDeploying; return hasChanges ? newDeploying : prevDeploying;
}); });
} }
@ -146,7 +165,14 @@ export function useDeploymentData(options: UseDeploymentDataOptions = {}) {
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, []); }, []);
// 定时刷新数据(智能轮询) - 简化版 // 计算轮询间隔部署中5秒刚完成10秒空闲30秒
const getPollingInterval = useCallback(() => {
if (deploying.size > 0) return 5000;
if (recentlyCompleted) return 10000;
return 30000;
}, [deploying.size, recentlyCompleted]);
// 定时刷新数据(智能轮询)
useEffect(() => { useEffect(() => {
// 初始加载时不启动轮询 // 初始加载时不启动轮询
if (isInitialLoad) return; if (isInitialLoad) return;
@ -169,8 +195,7 @@ export function useDeploymentData(options: UseDeploymentDataOptions = {}) {
if (intervalRef.current) { if (intervalRef.current) {
clearInterval(intervalRef.current); clearInterval(intervalRef.current);
} }
// 智能间隔有部署时5秒无部署时30秒 const interval = getPollingInterval();
const interval = deploying.size > 0 ? 5000 : 30000;
intervalRef.current = setInterval(() => { intervalRef.current = setInterval(() => {
loadData(false); loadData(false);
}, interval); }, interval);
@ -178,7 +203,7 @@ export function useDeploymentData(options: UseDeploymentDataOptions = {}) {
}; };
// 启动轮询 - 智能间隔 // 启动轮询 - 智能间隔
const interval = deploying.size > 0 ? 5000 : 30000; const interval = getPollingInterval();
intervalRef.current = setInterval(() => { intervalRef.current = setInterval(() => {
loadData(false); loadData(false);
}, interval); }, interval);
@ -192,7 +217,16 @@ export function useDeploymentData(options: UseDeploymentDataOptions = {}) {
} }
document.removeEventListener('visibilitychange', handleVisibilityChange); document.removeEventListener('visibilitychange', handleVisibilityChange);
}; };
}, [isInitialLoad, deploying.size, loadData]); }, [isInitialLoad, deploying.size, recentlyCompleted, loadData, getPollingInterval]);
// 清理 recentlyCompletedTimer
useEffect(() => {
return () => {
if (recentlyCompletedTimerRef.current) {
clearTimeout(recentlyCompletedTimerRef.current);
}
};
}, []);
// 切换团队 // 切换团队
const handleTeamChange = useCallback((teamId: string) => { const handleTeamChange = useCallback((teamId: string) => {

View File

@ -414,13 +414,13 @@ const WorkflowDefinitionList: React.FC = () => {
<Table minWidth="1000px"> <Table minWidth="1000px">
<TableHeader> <TableHeader>
<TableRow> <TableRow>
<TableHead width="180px"></TableHead> <TableHead minWidth="180px"></TableHead>
<TableHead width="140px"></TableHead> <TableHead minWidth="160px"></TableHead>
<TableHead width="100px"></TableHead> <TableHead minWidth="100px"></TableHead>
<TableHead width="140px"></TableHead> <TableHead minWidth="140px"></TableHead>
<TableHead width="70px"></TableHead> <TableHead minWidth="70px"></TableHead>
<TableHead width="100px"></TableHead> <TableHead minWidth="100px"></TableHead>
<TableHead width="150px"></TableHead> <TableHead minWidth="160px"></TableHead>
<TableHead width="180px" sticky></TableHead> <TableHead width="180px" sticky></TableHead>
</TableRow> </TableRow>
</TableHeader> </TableHeader>
@ -441,20 +441,20 @@ const WorkflowDefinitionList: React.FC = () => {
const categoryInfo = record.category || categories.find(c => c.id === record.categoryId); const categoryInfo = record.category || categories.find(c => c.id === record.categoryId);
return ( return (
<TableRow key={record.id} className="hover:bg-muted/50"> <TableRow key={record.id} className="hover:bg-muted/50">
<TableCell width="180px" className="font-medium">{record.name}</TableCell> <TableCell minWidth="180px" className="font-medium whitespace-nowrap">{record.name}</TableCell>
<TableCell width="140px"> <TableCell minWidth="160px" className="whitespace-nowrap">
<code className="relative rounded bg-muted px-[0.3rem] py-[0.2rem] font-mono text-sm font-semibold"> <code className="relative rounded bg-muted px-[0.3rem] py-[0.2rem] font-mono text-sm font-semibold">
{record.key} {record.key}
</code> </code>
</TableCell> </TableCell>
<TableCell width="100px"> <TableCell minWidth="100px" className="whitespace-nowrap">
{categoryInfo ? ( {categoryInfo ? (
<Badge variant="outline">{categoryInfo.name}</Badge> <Badge variant="outline">{categoryInfo.name}</Badge>
) : ( ) : (
<Badge variant="outline"></Badge> <Badge variant="outline"></Badge>
)} )}
</TableCell> </TableCell>
<TableCell width="140px"> <TableCell minWidth="140px" className="whitespace-nowrap">
{record.formDefinitionName ? ( {record.formDefinitionName ? (
<Badge variant="secondary" className="font-normal"> <Badge variant="secondary" className="font-normal">
{record.formDefinitionName} {record.formDefinitionName}
@ -463,11 +463,11 @@ const WorkflowDefinitionList: React.FC = () => {
<span className="text-xs text-muted-foreground"></span> <span className="text-xs text-muted-foreground"></span>
)} )}
</TableCell> </TableCell>
<TableCell width="70px"> <TableCell minWidth="70px" className="whitespace-nowrap">
<span className="font-mono text-sm">{record.flowVersion || 1}</span> <span className="font-mono text-sm">{record.flowVersion || 1}</span>
</TableCell> </TableCell>
<TableCell width="100px">{getStatusBadge(record.status || 'DRAFT')}</TableCell> <TableCell minWidth="100px" className="whitespace-nowrap">{getStatusBadge(record.status || 'DRAFT')}</TableCell>
<TableCell width="150px"> <TableCell minWidth="160px" className="whitespace-nowrap">
<span className="text-xs text-muted-foreground"> <span className="text-xs text-muted-foreground">
{record.createTime ? new Date(record.createTime).toLocaleString('zh-CN', { {record.createTime ? new Date(record.createTime).toLocaleString('zh-CN', {
year: 'numeric', year: 'numeric',