feat(ui): 添加删除操作延迟确认功能

增强用户体验,防止误删除操作:

1. MessageModal 组件增强
   - 添加 confirmDelay 属性(秒)
   - 确认按钮倒计时功能
   - 倒计时期间禁用确认按钮
   - 按钮显示剩余秒数 (例如: "删除 (4s)")

2. 删除操作应用延迟确认(4秒)
   -  文档类型删除 (document-types._index.tsx)
   -  文档删除和批量删除 (documents.list.tsx)
   -  入口模块删除 (entry-modules._index.tsx)
   -  提示词删除 (prompts._index.tsx)
   -  规则组删除 (rule-groups._index.tsx)

技术实现:
- 使用 useEffect + setInterval 实现倒计时
- 倒计时结束自动清理定时器
- 按钮禁用状态控制(disabled + opacity + cursor)

用户体验提升:
- 防止误操作:4秒思考时间
- 视觉反馈:倒计时提示
- 操作可逆:倒计时期间可取消

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-25 18:17:52 +08:00
parent be529d2f2a
commit 7c47b11ec7
7 changed files with 192 additions and 125 deletions
+62 -49
View File
@@ -16,7 +16,7 @@ import {
batchUpdateRuleGroupStatus,
batchDeleteRuleGroups
} from "~/api/evaluation_points/rule-groups";
import { toastService } from "~/components/ui";
import { toastService, messageService } from "~/components/ui";
export function links() {
return [{ rel: "stylesheet", href: indexStyles }];
@@ -230,42 +230,49 @@ export default function RuleGroupsIndex() {
// 处理删除分组
const handleDeleteGroup = async (groupId: string) => {
if (confirm("确定要删除该分组吗?此操作将同时删除该分组下的所有评查点,且不可恢复。")) {
try {
const result = await deleteRuleGroup(groupId, frontendJWT);
if (result.success) {
// 从本地状态中移除被删除的分组
setGroups(prev => {
// 如果是一级分组,直接过滤掉
const filteredGroups = prev.filter(g => g.id !== groupId);
// 如果是二级分组,需要从父分组的 children 中移除
return filteredGroups.map(group => {
if (group.children) {
return {
...group,
children: group.children.filter(child => child.id !== groupId)
};
}
return group;
messageService.show({
title: "确认删除",
message: "确定要删除该分组吗?此操作将同时删除该分组下的所有评查点,且不可恢复。",
type: "warning",
confirmText: "删除",
cancelText: "取消",
confirmDelay: 4,
onConfirm: async () => {
try {
const result = await deleteRuleGroup(groupId, frontendJWT);
if (result.success) {
// 从本地状态中移除被删除的分组
setGroups(prev => {
// 如果是一级分组,直接过滤掉
const filteredGroups = prev.filter(g => g.id !== groupId);
// 如果是二级分组,需要从父分组的 children 中移除
return filteredGroups.map(group => {
if (group.children) {
return {
...group,
children: group.children.filter(child => child.id !== groupId)
};
}
return group;
});
});
});
// 如果被删除的分组当前是展开状态,从展开列表中移除
setExpandedGroups(prev => prev.filter(id => id !== groupId));
// 显示成功消息
// alert('删除成功');
toastService.success('删除成功')
} else {
toastService.error(`删除失败: ${result.error}`);
console.error(`删除失败: ${result.error}`);
// 如果被删除的分组当前是展开状态,从展开列表中移除
setExpandedGroups(prev => prev.filter(id => id !== groupId));
// 显示成功消息
toastService.success('删除成功')
} else {
toastService.error(`删除失败: ${result.error}`);
console.error(`删除失败: ${result.error}`);
}
} catch (error) {
console.error('删除分组失败:', error);
toastService.error('删除分组失败,请稍后重试');
}
} catch (error) {
console.error('删除分组失败:', error);
toastService.error('删除分组失败,请稍后重试');
}
}
});
};
// 🆕 批量启用/禁用
@@ -297,22 +304,28 @@ export default function RuleGroupsIndex() {
return;
}
if (!confirm(`确定要删除选中的 ${selectedIds.length} 个分组吗?此操作不可恢复。`)) {
return;
}
try {
const result = await batchDeleteRuleGroups(selectedIds, frontendJWT);
toastService.success(`成功删除 ${result.deleted_count} 个分组`);
if (result.failed_ids.length > 0) {
toastService.warning(`${result.failed_ids.length} 个分组删除失败`);
messageService.show({
title: "确认批量删除",
message: `确定要删除选中的 ${selectedIds.length} 个分组吗?此操作不可恢复。`,
type: "warning",
confirmText: "删除",
cancelText: "取消",
confirmDelay: 4,
onConfirm: async () => {
try {
const result = await batchDeleteRuleGroups(selectedIds, frontendJWT);
toastService.success(`成功删除 ${result.deleted_count} 个分组`);
if (result.failed_ids.length > 0) {
toastService.warning(`${result.failed_ids.length} 个分组删除失败`);
}
// 刷新页面以重新加载数据
window.location.reload();
} catch (error) {
console.error('批量删除失败:', error);
toastService.error('批量删除失败,请稍后重试');
}
}
// 刷新页面以重新加载数据
window.location.reload();
} catch (error) {
console.error('批量删除失败:', error);
toastService.error('批量删除失败,请稍后重试');
}
});
};
// 🆕 处理全选/取消全选