diff --git a/frontend/src/hooks/useAuth.tsx b/frontend/src/hooks/useAuth.tsx index 74a33fb..9524caf 100644 --- a/frontend/src/hooks/useAuth.tsx +++ b/frontend/src/hooks/useAuth.tsx @@ -62,7 +62,7 @@ export const actionPermissionMap: Record = { 'ticket.delete': ['admin'], 'query.create': ['admin', 'dba', 'developer'], 'query.export': ['admin', 'dba', 'developer'], - 'instance.add': ['admin'], + 'instance.add': ['admin', 'dba'], 'instance.edit': ['admin', 'dba'], 'instance.delete': ['admin'], 'user.manage': ['admin'], diff --git a/frontend/src/pages/AuditRulesPage.tsx b/frontend/src/pages/AuditRulesPage.tsx index 7260f29..b024bf3 100644 --- a/frontend/src/pages/AuditRulesPage.tsx +++ b/frontend/src/pages/AuditRulesPage.tsx @@ -49,15 +49,15 @@ export default function AuditRulesPage() { if (filter.severity) params.set('severity', filter.severity); if (filter.is_enabled !== '') params.set('is_enabled', filter.is_enabled); const res = await request.get('/audit-rules', { params }); - setRules(res.data); - } catch { /* */ } finally { setLoading(false); } + setRules(Array.isArray(res.data) ? res.data : []); + } catch { setRules([]); } finally { setLoading(false); } } async function fetchStats() { try { const res = await request.get('/audit-rules/stats/summary'); - setStats(res.data); - } catch { /* */ } + setStats(res.data || null); + } catch { setStats(null); } } async function handleCreate() { diff --git a/frontend/src/pages/InstancePage.tsx b/frontend/src/pages/InstancePage.tsx index 918fb99..96b032b 100644 --- a/frontend/src/pages/InstancePage.tsx +++ b/frontend/src/pages/InstancePage.tsx @@ -38,6 +38,18 @@ const envLabel: Record = { production: '生产', staging: '预发', development: '开发', }; +const statusLabel: Record = { + connected: { text: '在线', online: true }, + online: { text: '在线', online: true }, + disconnected: { text: '离线', online: false }, + offline: { text: '离线', online: false }, + error: { text: '异常', online: false }, +}; + +function getStatusInfo(status: string) { + return statusLabel[status] || { text: '离线', online: false }; +} + export default function InstancePage() { const { type = 'mysql' } = useParams<{ type: string }>(); const canAdd = useActionPermission('instance.add'); @@ -78,8 +90,8 @@ export default function InstancePage() { }); const statusCounts = { - online: filtered.filter(i => i.status === 'online').length, - offline: filtered.filter(i => i.status === 'offline').length, + online: filtered.filter(i => getStatusInfo(i.status).online).length, + offline: filtered.filter(i => !getStatusInfo(i.status).online).length, total: filtered.length, }; @@ -164,7 +176,7 @@ export default function InstancePage() {
{envLabel[instance.env] || instance.env} -
+

{instance.name}

@@ -214,8 +226,8 @@ function InstanceDetail({ instance, onBack, config, canEdit, canDelete, onDelete

{instance.name} - - {instance.status === 'online' ? '在线' : '离线'} + + {getStatusInfo(instance.status).text}

{instance.host}:{instance.port} · {instance.version || '版本未知'}

@@ -264,7 +276,7 @@ function InstanceDetail({ instance, onBack, config, canEdit, canDelete, onDelete { label: '用户名', value: instance.username }, { label: '默认数据库', value: instance.database || '-' }, { label: '运行环境', value: envLabel[instance.env] || instance.env }, - { label: '状态', value: instance.status === 'online' ? '在线' : '离线' }, + { label: '状态', value: getStatusInfo(instance.status).text }, { label: '版本', value: instance.version || '-' }, { label: '描述', value: instance.description || '-' }, { label: '创建时间', value: new Date(instance.created_at).toLocaleString() },