fix: 全部页面 confirm() 替换为 ConfirmDialog 组件 — 9个页面统一回调模式
This commit is contained in:
1 parent
41dab3deab
commit
7f6a4bb6df
9 files changed
+132
-41
No files matched your search
@@ -1,6 +1,7 @@
|
|||||||
import { useState, useEffect, useCallback } from 'react';
|
import { useState, useEffect, useCallback } from 'react';
|
||||||
import request from '@/api/request';
|
import request from '@/api/request';
|
||||||
import { Megaphone, Plus, Edit2, Trash2, Eye, Clock, CheckCircle, X, Save } from 'lucide-react';
|
import { Megaphone, Plus, Edit2, Trash2, Eye, Clock, CheckCircle, X, Save } from 'lucide-react';
|
||||||
|
import { ConfirmDialog } from '@/components/ConfirmDialog';
|
||||||
|
|
||||||
/* ── types ── */
|
/* ── types ── */
|
||||||
interface Announcement {
|
interface Announcement {
|
||||||
@@ -56,6 +57,7 @@ export default function AnnouncementPage() {
|
|||||||
|
|
||||||
/* view preview */
|
/* view preview */
|
||||||
const [viewAnn, setViewAnn] = useState<Announcement | null>(null);
|
const [viewAnn, setViewAnn] = useState<Announcement | null>(null);
|
||||||
|
const [deleteConfirm, setDeleteConfirm] = useState<{msg: string; onConfirm: () => void} | null>(null);
|
||||||
|
|
||||||
const fetchList = useCallback(async () => {
|
const fetchList = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
@@ -118,13 +120,8 @@ export default function AnnouncementPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleDelete = async (id: number) => {
|
const handleDelete = async (id: number) => {
|
||||||
if (!confirm('确定删除此公告?')) return;
|
setDeleteConfirm({msg: '确定删除此公告?', onConfirm: async () => { try { await request.delete(`/announcements/${id}`); fetchList(); } catch {} }});
|
||||||
try {
|
return;
|
||||||
await request.delete(`/announcements/${id}`);
|
|
||||||
fetchList();
|
|
||||||
} catch {
|
|
||||||
/* ignore */
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ── render ── */
|
/* ── render ── */
|
||||||
@@ -344,6 +341,14 @@ export default function AnnouncementPage() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
<ConfirmDialog
|
||||||
|
open={!!deleteConfirm}
|
||||||
|
title={deleteConfirm?.msg || '确认操作'}
|
||||||
|
variant="danger"
|
||||||
|
confirmText="确定"
|
||||||
|
onConfirm={() => { deleteConfirm?.onConfirm(); }}
|
||||||
|
onCancel={() => setDeleteConfirm(null)}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -4,6 +4,7 @@ import { ArrowLeft, Database, Table2, Users, Cpu, Play, RefreshCw } from 'lucide
|
|||||||
import { instanceDetailApi } from '@/api/instanceDetail';
|
import { instanceDetailApi } from '@/api/instanceDetail';
|
||||||
import { instanceApi } from '@/api/instance';
|
import { instanceApi } from '@/api/instance';
|
||||||
import { queryApi } from '@/api/query';
|
import { queryApi } from '@/api/query';
|
||||||
|
import { ConfirmDialog } from '@/components/ConfirmDialog';
|
||||||
|
|
||||||
interface InstanceInfo {
|
interface InstanceInfo {
|
||||||
id: number; name: string; db_type: string; host: string; port: number;
|
id: number; name: string; db_type: string; host: string; port: number;
|
||||||
@@ -27,6 +28,7 @@ export default function InstanceDetailPage() {
|
|||||||
var [sqlText, setSqlText] = useState('');
|
var [sqlText, setSqlText] = useState('');
|
||||||
var [queryResult, setQueryResult] = useState<any>(null);
|
var [queryResult, setQueryResult] = useState<any>(null);
|
||||||
var [loading, setLoading] = useState(false);
|
var [loading, setLoading] = useState(false);
|
||||||
|
const [deleteConfirm, setDeleteConfirm] = useState<{msg: string; onConfirm: () => void} | null>(null);
|
||||||
|
|
||||||
var tabs: { key: TabKey; label: string; icon: React.ElementType }[] = [
|
var tabs: { key: TabKey; label: string; icon: React.ElementType }[] = [
|
||||||
{ key: 'overview', label: '概览', icon: Database },
|
{ key: 'overview', label: '概览', icon: Database },
|
||||||
@@ -81,12 +83,17 @@ export default function InstanceDetailPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var handleKill = function (pid: number) {
|
var handleKill = function (pid: number) {
|
||||||
if (!confirm('确定 Kill 进程 ' + pid + '?')) return;
|
setDeleteConfirm({
|
||||||
instanceDetailApi.killProcess(instanceId, pid).then(function () {
|
msg: '确定 Kill 进程 ' + pid + '?',
|
||||||
instanceDetailApi.getProcesslist(instanceId).then(function (res: any) {
|
onConfirm: () => {
|
||||||
|
instanceDetailApi.killProcess(instanceId, pid).then(() => {
|
||||||
|
instanceDetailApi.getProcesslist(instanceId).then((res: any) => {
|
||||||
setProcesses(res.processes || res || []);
|
setProcesses(res.processes || res || []);
|
||||||
});
|
});
|
||||||
}).catch(function () {});
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!instance) return <div className="p-10 text-center text-[var(--dg-text-muted)]">加载中...</div>;
|
if (!instance) return <div className="p-10 text-center text-[var(--dg-text-muted)]">加载中...</div>;
|
||||||
@@ -255,6 +262,15 @@ export default function InstanceDetailPage() {
|
|||||||
{processes.length === 0 && <div className="text-center py-8 text-[var(--dg-text-muted)]">暂无进程</div>}
|
{processes.length === 0 && <div className="text-center py-8 text-[var(--dg-text-muted)]">暂无进程</div>}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<ConfirmDialog
|
||||||
|
open={!!deleteConfirm}
|
||||||
|
title={deleteConfirm?.msg || '确认操作'}
|
||||||
|
variant="danger"
|
||||||
|
confirmText="确定"
|
||||||
|
onConfirm={() => { deleteConfirm?.onConfirm(); }}
|
||||||
|
onCancel={() => setDeleteConfirm(null)}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -8,6 +8,7 @@ import { instanceGroupApi, type InstanceGroup } from '@/api/instanceGroup';
|
|||||||
import { instanceApi } from '@/api/instance';
|
import { instanceApi } from '@/api/instance';
|
||||||
import { userApi } from '@/api/user';
|
import { userApi } from '@/api/user';
|
||||||
import { useActionPermission } from '@/hooks/useAuth';
|
import { useActionPermission } from '@/hooks/useAuth';
|
||||||
|
import { ConfirmDialog } from '@/components/ConfirmDialog';
|
||||||
|
|
||||||
/* ───────── Constants ───────── */
|
/* ───────── Constants ───────── */
|
||||||
|
|
||||||
@@ -109,6 +110,7 @@ export default function InstanceGroupPage() {
|
|||||||
const [showCreateModal, setShowCreateModal] = useState(false);
|
const [showCreateModal, setShowCreateModal] = useState(false);
|
||||||
const [showEditModal, setShowEditModal] = useState(false);
|
const [showEditModal, setShowEditModal] = useState(false);
|
||||||
const [showUserModal, setShowUserModal] = useState(false);
|
const [showUserModal, setShowUserModal] = useState(false);
|
||||||
|
const [deleteConfirm, setDeleteConfirm] = useState<{msg: string; onConfirm: () => void} | null>(null);
|
||||||
const canManage = useActionPermission('instance-group.manage');
|
const canManage = useActionPermission('instance-group.manage');
|
||||||
|
|
||||||
// Form state — shared by create & edit
|
// Form state — shared by create & edit
|
||||||
@@ -215,10 +217,11 @@ export default function InstanceGroupPage() {
|
|||||||
|
|
||||||
/* ── Delete ── */
|
/* ── Delete ── */
|
||||||
const handleDelete = async (id: number) => {
|
const handleDelete = async (id: number) => {
|
||||||
if (!confirm('确定删除该权限组?')) return;
|
setDeleteConfirm({msg: '确定删除该权限组?', onConfirm: async () => {
|
||||||
await instanceGroupApi.delete(id);
|
await instanceGroupApi.delete(id);
|
||||||
if (selectedId === id) setSelectedId(null);
|
if (selectedId === id) setSelectedId(null);
|
||||||
fetchGroups();
|
fetchGroups();
|
||||||
|
}});
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ── Assign Users ── */
|
/* ── Assign Users ── */
|
||||||
@@ -439,6 +442,15 @@ export default function InstanceGroupPage() {
|
|||||||
<FormModal mode="create" />
|
<FormModal mode="create" />
|
||||||
<FormModal mode="edit" />
|
<FormModal mode="edit" />
|
||||||
|
|
||||||
|
<ConfirmDialog
|
||||||
|
open={!!deleteConfirm}
|
||||||
|
title={deleteConfirm?.msg || '确认操作'}
|
||||||
|
variant="danger"
|
||||||
|
confirmText="确定"
|
||||||
|
onConfirm={() => { deleteConfirm?.onConfirm(); }}
|
||||||
|
onCancel={() => setDeleteConfirm(null)}
|
||||||
|
/>
|
||||||
|
|
||||||
{/* User Modal */}
|
{/* User Modal */}
|
||||||
{showUserModal && (
|
{showUserModal && (
|
||||||
<div className="fixed inset-0 z-[100] flex items-start justify-center pt-[10vh] bg-black/60 backdrop-blur-sm">
|
<div className="fixed inset-0 z-[100] flex items-start justify-center pt-[10vh] bg-black/60 backdrop-blur-sm">
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import PageHeader from '@/components/PageHeader';
|
|||||||
import EmptyState from '@/components/EmptyState';
|
import EmptyState from '@/components/EmptyState';
|
||||||
import { instanceApi } from '@/api/instance';
|
import { instanceApi } from '@/api/instance';
|
||||||
import EditInstanceDialog from '@/components/EditInstanceDialog';
|
import EditInstanceDialog from '@/components/EditInstanceDialog';
|
||||||
|
import { ConfirmDialog } from '@/components/ConfirmDialog';
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
/* Types */
|
/* Types */
|
||||||
@@ -189,29 +190,28 @@ export default function InstancePage() {
|
|||||||
}, [filtered]);
|
}, [filtered]);
|
||||||
|
|
||||||
const handleDelete = useCallback(async (id: number) => {
|
const handleDelete = useCallback(async (id: number) => {
|
||||||
if (!confirm('确定删除该实例?')) return;
|
setDeleteConfirm({
|
||||||
try {
|
msg: '确定删除该实例?',
|
||||||
await instanceApi.delete(id);
|
onConfirm: async () => {
|
||||||
fetchInstances();
|
try { await instanceApi.delete(id); fetchInstances(); } catch {}
|
||||||
} catch {
|
},
|
||||||
/* ignore */
|
});
|
||||||
}
|
|
||||||
}, [fetchInstances]);
|
}, [fetchInstances]);
|
||||||
|
|
||||||
const handleBatchDelete = useCallback(async () => {
|
const handleBatchDelete = useCallback(async () => {
|
||||||
if (selectedIds.size === 0) return;
|
if (selectedIds.size === 0) return;
|
||||||
if (!confirm(`确定删除选中的 ${selectedIds.size} 个实例?此操作不可恢复。`)) return;
|
setDeleteConfirm({
|
||||||
|
msg: `确定删除选中的 ${selectedIds.size} 个实例?此操作不可恢复。`,
|
||||||
|
onConfirm: async () => {
|
||||||
setBatchDeleting(true);
|
setBatchDeleting(true);
|
||||||
try {
|
try {
|
||||||
const ids = Array.from(selectedIds);
|
const ids = Array.from(selectedIds);
|
||||||
await Promise.all(ids.map(id => instanceApi.delete(id)));
|
await Promise.all(ids.map(i => instanceApi.delete(i)));
|
||||||
setSelectedIds(new Set());
|
setSelectedIds(new Set());
|
||||||
fetchInstances();
|
fetchInstances();
|
||||||
} catch {
|
} finally { setBatchDeleting(false); }
|
||||||
/* ignore */
|
},
|
||||||
} finally {
|
});
|
||||||
setBatchDeleting(false);
|
|
||||||
}
|
|
||||||
}, [selectedIds, fetchInstances]);
|
}, [selectedIds, fetchInstances]);
|
||||||
|
|
||||||
const toggleSelect = useCallback((id: number) => {
|
const toggleSelect = useCallback((id: number) => {
|
||||||
@@ -994,6 +994,7 @@ function CreateInstanceForm({ defaultType, onCancel, onCreated }: {
|
|||||||
const [error, setError] = useState('');
|
const [error, setError] = useState('');
|
||||||
const [testing, setTesting] = useState(false);
|
const [testing, setTesting] = useState(false);
|
||||||
const [testResult, setTestResult] = useState<{ success: boolean; message: string; version?: string } | null>(null);
|
const [testResult, setTestResult] = useState<{ success: boolean; message: string; version?: string } | null>(null);
|
||||||
|
const [deleteConfirm, setDeleteConfirm] = useState<{msg: string; onConfirm: () => void} | null>(null);
|
||||||
|
|
||||||
const isRedis = dbType === 'redis';
|
const isRedis = dbType === 'redis';
|
||||||
const needUsername = !isRedis;
|
const needUsername = !isRedis;
|
||||||
@@ -1447,6 +1448,14 @@ function CreateInstanceForm({ defaultType, onCancel, onCreated }: {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<ConfirmDialog
|
||||||
|
open={!!deleteConfirm}
|
||||||
|
title={deleteConfirm?.msg || '确认操作'}
|
||||||
|
variant="danger"
|
||||||
|
confirmText="确定"
|
||||||
|
onConfirm={() => { deleteConfirm?.onConfirm(); }}
|
||||||
|
onCancel={() => setDeleteConfirm(null)}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useState, useEffect, useCallback } from 'react';
|
import { useState, useEffect, useCallback } from 'react';
|
||||||
import request from '@/api/request';
|
import request from '@/api/request';
|
||||||
import { Plus, Trash2, Send, Bell, Mail, Settings, X } from 'lucide-react';
|
import { Plus, Trash2, Send, Bell, Mail, Settings, X } from 'lucide-react';
|
||||||
|
import { ConfirmDialog } from '@/components/ConfirmDialog';
|
||||||
|
|
||||||
/* ── types ── */
|
/* ── types ── */
|
||||||
type ChannelType = 'dingtalk' | 'webhook_feishu' | 'email';
|
type ChannelType = 'dingtalk' | 'webhook_feishu' | 'email';
|
||||||
@@ -62,6 +63,7 @@ export default function NotificationPage() {
|
|||||||
/* test */
|
/* test */
|
||||||
const [testingId, setTestingId] = useState<number | null>(null);
|
const [testingId, setTestingId] = useState<number | null>(null);
|
||||||
const [testResult, setTestResult] = useState<Record<number, { success: boolean; message: string } | null>>({});
|
const [testResult, setTestResult] = useState<Record<number, { success: boolean; message: string } | null>>({});
|
||||||
|
const [deleteConfirm, setDeleteConfirm] = useState<{msg: string; onConfirm: () => void} | null>(null);
|
||||||
|
|
||||||
const fetchList = useCallback(async () => {
|
const fetchList = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
@@ -128,13 +130,8 @@ export default function NotificationPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleDelete = async (id: number) => {
|
const handleDelete = async (id: number) => {
|
||||||
if (!confirm('确定删除此通知渠道?')) return;
|
setDeleteConfirm({msg: '确定删除此通知渠道?', onConfirm: async () => { try { await request.delete(`/notifications/${id}`); fetchList(); } catch {} }});
|
||||||
try {
|
return;
|
||||||
await request.delete(`/notifications/${id}`);
|
|
||||||
fetchList();
|
|
||||||
} catch {
|
|
||||||
/* ignore */
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleTest = async (id: number) => {
|
const handleTest = async (id: number) => {
|
||||||
@@ -451,6 +448,14 @@ export default function NotificationPage() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
<ConfirmDialog
|
||||||
|
open={!!deleteConfirm}
|
||||||
|
title={deleteConfirm?.msg || '确认操作'}
|
||||||
|
variant="danger"
|
||||||
|
confirmText="确定"
|
||||||
|
onConfirm={() => { deleteConfirm?.onConfirm(); }}
|
||||||
|
onCancel={() => setDeleteConfirm(null)}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@ import { useState, useEffect, useCallback } from 'react';
|
|||||||
import { Bell, Webhook, Check, Settings, TestTube, ToggleLeft, ToggleRight, Loader2, AlertCircle, Plus, Trash2 } from 'lucide-react';
|
import { Bell, Webhook, Check, Settings, TestTube, ToggleLeft, ToggleRight, Loader2, AlertCircle, Plus, Trash2 } from 'lucide-react';
|
||||||
import { Card, CardContent } from '@/components/ui/card';
|
import { Card, CardContent } from '@/components/ui/card';
|
||||||
import { notificationApi } from '@/api/notification';
|
import { notificationApi } from '@/api/notification';
|
||||||
|
import { ConfirmDialog } from '@/components/ConfirmDialog';
|
||||||
|
|
||||||
interface NotificationChannel {
|
interface NotificationChannel {
|
||||||
id: number;
|
id: number;
|
||||||
@@ -25,6 +26,7 @@ export default function NotificationsPage() {
|
|||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const [testingId, setTestingId] = useState<number | null>(null);
|
const [testingId, setTestingId] = useState<number | null>(null);
|
||||||
const [testResult, setTestResult] = useState<{ id: number; success: boolean; message: string } | null>(null);
|
const [testResult, setTestResult] = useState<{ id: number; success: boolean; message: string } | null>(null);
|
||||||
|
const [deleteConfirm, setDeleteConfirm] = useState<{msg: string; onConfirm: () => void} | null>(null);
|
||||||
|
|
||||||
const fetchChannels = useCallback(async () => {
|
const fetchChannels = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
@@ -67,11 +69,8 @@ export default function NotificationsPage() {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleDelete = useCallback(async (id: number) => {
|
const handleDelete = useCallback(async (id: number) => {
|
||||||
if (!confirm('确认删除该通知渠道?')) return;
|
setDeleteConfirm({msg: '确认删除该通知渠道?', onConfirm: async () => { try { await notificationApi.delete(id); setChannels(prev => prev.filter(c => c.id !== id)); } catch {} }});
|
||||||
try {
|
return;
|
||||||
await notificationApi.delete(id);
|
|
||||||
setChannels(prev => prev.filter(c => c.id !== id));
|
|
||||||
} catch {}
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
@@ -175,6 +174,14 @@ export default function NotificationsPage() {
|
|||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
<ConfirmDialog
|
||||||
|
open={!!deleteConfirm}
|
||||||
|
title={deleteConfirm?.msg || '确认操作'}
|
||||||
|
variant="danger"
|
||||||
|
confirmText="确定"
|
||||||
|
onConfirm={() => { deleteConfirm?.onConfirm(); }}
|
||||||
|
onCancel={() => setDeleteConfirm(null)}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@ import { useState, useEffect } from 'react';
|
|||||||
import { useParams, useNavigate } from 'react-router-dom';
|
import { useParams, useNavigate } from 'react-router-dom';
|
||||||
import { ArrowLeft, Key, Activity, Terminal, Gauge, Plus, RefreshCw, Search } from 'lucide-react';
|
import { ArrowLeft, Key, Activity, Terminal, Gauge, Plus, RefreshCw, Search } from 'lucide-react';
|
||||||
import { redisApi } from '@/api/redis';
|
import { redisApi } from '@/api/redis';
|
||||||
|
import { ConfirmDialog } from '@/components/ConfirmDialog';
|
||||||
|
|
||||||
type TabKey = 'keys' | 'monitor' | 'cli' | 'perf';
|
type TabKey = 'keys' | 'monitor' | 'cli' | 'perf';
|
||||||
|
|
||||||
@@ -24,6 +25,7 @@ export default function RedisDetailPage() {
|
|||||||
var [slowlog, setSlowlog] = useState<any[]>([]);
|
var [slowlog, setSlowlog] = useState<any[]>([]);
|
||||||
var [clients, setClients] = useState<any[]>([]);
|
var [clients, setClients] = useState<any[]>([]);
|
||||||
var [loading, setLoading] = useState(false);
|
var [loading, setLoading] = useState(false);
|
||||||
|
const [deleteConfirm, setDeleteConfirm] = useState<{msg: string; onConfirm: () => void} | null>(null);
|
||||||
|
|
||||||
var tabs: { key: TabKey; label: string; icon: React.ElementType }[] = [
|
var tabs: { key: TabKey; label: string; icon: React.ElementType }[] = [
|
||||||
{ key: 'keys', label: '键管理', icon: Key },
|
{ key: 'keys', label: '键管理', icon: Key },
|
||||||
@@ -54,8 +56,10 @@ export default function RedisDetailPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var handleDeleteKey = function (keyName: string) {
|
var handleDeleteKey = function (keyName: string) {
|
||||||
if (!confirm('确定删除键 ' + keyName + '?')) return;
|
setDeleteConfirm({msg: '确定删除该键?', onConfirm: async () => {
|
||||||
redisApi.deleteKey(instanceId, keyName, selectedDb).then(function () { fetchKeys(); }).catch(function () {});
|
redisApi.deleteKey(instanceId, keyName, selectedDb).then(function () { fetchKeys(); }).catch(function () {});
|
||||||
|
}});
|
||||||
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
var handleCommand = function () {
|
var handleCommand = function () {
|
||||||
@@ -304,6 +308,14 @@ export default function RedisDetailPage() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
<ConfirmDialog
|
||||||
|
open={!!deleteConfirm}
|
||||||
|
title={deleteConfirm?.msg || '确认操作'}
|
||||||
|
variant="danger"
|
||||||
|
confirmText="确定"
|
||||||
|
onConfirm={() => { deleteConfirm?.onConfirm(); }}
|
||||||
|
onCancel={() => setDeleteConfirm(null)}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -10,6 +10,7 @@ import { userApi, ldapApi } from '@/api/user';
|
|||||||
import { instanceGroupApi, type InstanceGroup } from '@/api/instanceGroup';
|
import { instanceGroupApi, type InstanceGroup } from '@/api/instanceGroup';
|
||||||
import { nameToUsername } from '@/utils/pinyin';
|
import { nameToUsername } from '@/utils/pinyin';
|
||||||
import { toast } from '@/hooks/useToast';
|
import { toast } from '@/hooks/useToast';
|
||||||
|
import { ConfirmDialog } from '@/components/ConfirmDialog';
|
||||||
|
|
||||||
/* ───────── Types ───────── */
|
/* ───────── Types ───────── */
|
||||||
|
|
||||||
@@ -134,6 +135,7 @@ export default function UsersPage() {
|
|||||||
const [selectedIds, setSelectedIds] = useState<Set<number>>(new Set());
|
const [selectedIds, setSelectedIds] = useState<Set<number>>(new Set());
|
||||||
const [showBatchMenu, setShowBatchMenu] = useState(false);
|
const [showBatchMenu, setShowBatchMenu] = useState(false);
|
||||||
const [showImport, setShowImport] = useState(false);
|
const [showImport, setShowImport] = useState(false);
|
||||||
|
const [deleteConfirm, setDeleteConfirm] = useState<{msg: string; onConfirm: () => void} | null>(null);
|
||||||
|
|
||||||
const fetchUsers = useCallback(async () => {
|
const fetchUsers = useCallback(async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
@@ -188,13 +190,15 @@ export default function UsersPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleDelete = async (id: number) => {
|
const handleDelete = async (id: number) => {
|
||||||
if (!confirm('确定删除该用户?此操作不可恢复。')) return;
|
setDeleteConfirm({msg: '确定删除该用户?此操作不可恢复。', onConfirm: async () => {
|
||||||
try {
|
try {
|
||||||
await userApi.delete(id);
|
await userApi.delete(id);
|
||||||
setSelectedIds(prev => { const n = new Set(prev); n.delete(id); return n; });
|
setSelectedIds(prev => { const n = new Set(prev); n.delete(id); return n; });
|
||||||
toast('success', '用户已删除');
|
toast('success', '用户已删除');
|
||||||
fetchUsers();
|
fetchUsers();
|
||||||
} catch { toast('error', '删除失败'); }
|
} catch { toast('error', '删除失败'); }
|
||||||
|
}});
|
||||||
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleBatchAction = async (action: string) => {
|
const handleBatchAction = async (action: string) => {
|
||||||
@@ -521,6 +525,14 @@ export default function UsersPage() {
|
|||||||
{showImport && (
|
{showImport && (
|
||||||
<BatchImportModal onClose={() => setShowImport(false)} onImported={() => { setShowImport(false); fetchUsers(); }} />
|
<BatchImportModal onClose={() => setShowImport(false)} onImported={() => { setShowImport(false); fetchUsers(); }} />
|
||||||
)}
|
)}
|
||||||
|
<ConfirmDialog
|
||||||
|
open={!!deleteConfirm}
|
||||||
|
title={deleteConfirm?.msg || '确认操作'}
|
||||||
|
variant="danger"
|
||||||
|
confirmText="确定"
|
||||||
|
onConfirm={() => { deleteConfirm?.onConfirm(); }}
|
||||||
|
onCancel={() => setDeleteConfirm(null)}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -888,6 +900,7 @@ function BatchImportModal({ onClose, onImported }: { onClose: () => void; onImpo
|
|||||||
const [newOuName, setNewOuName] = useState('');
|
const [newOuName, setNewOuName] = useState('');
|
||||||
const [newOuDesc, setNewOuDesc] = useState('');
|
const [newOuDesc, setNewOuDesc] = useState('');
|
||||||
const [creatingOu, setCreatingOu] = useState(false);
|
const [creatingOu, setCreatingOu] = useState(false);
|
||||||
|
const [deleteConfirm, setDeleteConfirm] = useState<{msg: string; onConfirm: () => void} | null>(null);
|
||||||
|
|
||||||
// Check LDAP readiness
|
// Check LDAP readiness
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
import { Card, CardContent } from '@/components/ui/card';
|
import { Card, CardContent } from '@/components/ui/card';
|
||||||
import { workflowApi } from '@/api/workflow';
|
import { workflowApi } from '@/api/workflow';
|
||||||
import { userApi } from '@/api/user';
|
import { userApi } from '@/api/user';
|
||||||
|
import { ConfirmDialog } from '@/components/ConfirmDialog';
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
/* Types */
|
/* Types */
|
||||||
@@ -470,6 +471,7 @@ export default function WorkflowPage() {
|
|||||||
const [expandedId, setExpandedId] = useState<number | null>(null);
|
const [expandedId, setExpandedId] = useState<number | null>(null);
|
||||||
const [previewWorkflow, setPreviewWorkflow] = useState<WorkflowDetail | null>(null);
|
const [previewWorkflow, setPreviewWorkflow] = useState<WorkflowDetail | null>(null);
|
||||||
const [editorWorkflow, setEditorWorkflow] = useState<WorkflowDetail | null | undefined>(undefined);
|
const [editorWorkflow, setEditorWorkflow] = useState<WorkflowDetail | null | undefined>(undefined);
|
||||||
|
const [deleteConfirm, setDeleteConfirm] = useState<{msg: string; onConfirm: () => void} | null>(null);
|
||||||
|
|
||||||
const fetchWorkflows = useCallback(async () => {
|
const fetchWorkflows = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
@@ -506,11 +508,13 @@ export default function WorkflowPage() {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleDelete = useCallback(async (id: number) => {
|
const handleDelete = useCallback(async (id: number) => {
|
||||||
if (!confirm('确认删除该审批流程?')) return;
|
setDeleteConfirm({msg: '确认删除该审批流程?', onConfirm: async () => {
|
||||||
try {
|
try {
|
||||||
await workflowApi.delete(id);
|
await workflowApi.delete(id);
|
||||||
setItems((prev) => prev.filter((w) => w.id !== id));
|
setItems((prev) => prev.filter((w) => w.id !== id));
|
||||||
} catch {}
|
} catch {}
|
||||||
|
}});
|
||||||
|
return;
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const setDefault = useCallback(async (id: number) => {
|
const setDefault = useCallback(async (id: number) => {
|
||||||
@@ -807,6 +811,14 @@ export default function WorkflowPage() {
|
|||||||
onSaved={() => { setEditorWorkflow(undefined); fetchWorkflows(); }}
|
onSaved={() => { setEditorWorkflow(undefined); fetchWorkflows(); }}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
<ConfirmDialog
|
||||||
|
open={!!deleteConfirm}
|
||||||
|
title={deleteConfirm?.msg || '确认操作'}
|
||||||
|
variant="danger"
|
||||||
|
confirmText="确定"
|
||||||
|
onConfirm={() => { deleteConfirm?.onConfirm(); }}
|
||||||
|
onCancel={() => setDeleteConfirm(null)}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user