chore: format

This commit is contained in:
ryan
2026-08-16 21:39:25 +08:00
parent e5d2e4b6d5
commit 55c1fcd5f9
93 changed files with 544 additions and 439 deletions
@@ -66,22 +66,25 @@ export function CacheManager({ refreshTrigger }: CacheManagerProps) {
const [lruEnabled, setLruEnabled] = useState<boolean>(true);
// 获取磁盘缓存状态
const fetchCacheStatus = useCallback(async (isSilent = false) => {
if (!isSilent) setLoadingCache(true);
try {
const data = await services.adminCache.getCacheStatus();
setCacheStatus(data);
setMaxSizeMB(data.max_size_mb.toString());
setTtlMinutes(data.ttl_minutes.toString());
setLruEnabled(data.lru_enabled);
} catch (err) {
toast.error(t('fetchCacheStatusFailed'), {
description: err instanceof Error ? err.message : t('unknownError'),
});
} finally {
setLoadingCache(false);
}
}, [t]);
const fetchCacheStatus = useCallback(
async (isSilent = false) => {
if (!isSilent) setLoadingCache(true);
try {
const data = await services.adminCache.getCacheStatus();
setCacheStatus(data);
setMaxSizeMB(data.max_size_mb.toString());
setTtlMinutes(data.ttl_minutes.toString());
setLruEnabled(data.lru_enabled);
} catch (err) {
toast.error(t('fetchCacheStatusFailed'), {
description: err instanceof Error ? err.message : t('unknownError'),
});
} finally {
setLoadingCache(false);
}
},
[t],
);
// 保存配置
const handleSaveConfig = async (e: React.FormEvent) => {
@@ -349,9 +349,7 @@ export function SQLConsole({ dbType, onClose }: SQLConsoleProps) {
{!executingSQL && !sqlResult && !sqlError && (
<div className='flex flex-col items-center justify-center h-full py-10 text-muted-foreground opacity-60'>
<Terminal className='size-8 mb-2' />
<span className='text-xs'>
{t('editorReady')}
</span>
<span className='text-xs'>{t('editorReady')}</span>
</div>
)}
</div>
@@ -71,19 +71,22 @@ export function DatabasePageClient() {
const [refreshTrigger, setRefreshTrigger] = useState<number>(0);
// 1. 获取运行概览
const fetchOverview = useCallback(async (isSilent = false) => {
if (!isSilent) setLoadingOverview(true);
try {
const data = await services.dbManage.getOverview();
setOverview(data);
} catch (err) {
toast.error(t('fetchOverviewFailed'), {
description: err instanceof Error ? err.message : t('unknownError'),
});
} finally {
setLoadingOverview(false);
}
}, [t]);
const fetchOverview = useCallback(
async (isSilent = false) => {
if (!isSilent) setLoadingOverview(true);
try {
const data = await services.dbManage.getOverview();
setOverview(data);
} catch (err) {
toast.error(t('fetchOverviewFailed'), {
description: err instanceof Error ? err.message : t('unknownError'),
});
} finally {
setLoadingOverview(false);
}
},
[t],
);
// 2. 获取表列表
const fetchTables = useCallback(async () => {
@@ -77,9 +77,7 @@ export function DashboardTab() {
<span className='font-semibold text-foreground'>34</span>
</div>
</div>
<p className='text-[10px] text-muted-foreground'>
{t('dbStatus')}
</p>
<p className='text-[10px] text-muted-foreground'>{t('dbStatus')}</p>
</CardContent>
</Card>
</div>
@@ -478,9 +478,7 @@ export function FileList() {
<SheetContent className='w-full sm:max-w-md overflow-y-auto p-6'>
<SheetHeader className='border-b pb-4 px-0'>
<SheetTitle>{t('list.detailTitle')}</SheetTitle>
<SheetDescription>
{t('list.detailDesc')}
</SheetDescription>
<SheetDescription>{t('list.detailDesc')}</SheetDescription>
</SheetHeader>
{detailTarget && (
@@ -542,8 +540,7 @@ export function FileList() {
</span>
<span className='col-span-2 text-foreground/90'>
{formatFileSize(detailTarget.file_size)} (
{detailTarget.file_size.toLocaleString()} {t('list.bytes')}
)
{detailTarget.file_size.toLocaleString()} {t('list.bytes')})
</span>
</div>
@@ -397,8 +397,7 @@ export function AccessAnalytics() {
{user.nickname
? `(${user.nickname})`
: t('noNickname')}{' '}
|
ID: {user.user_id}
| ID: {user.user_id}
</div>
</div>
</div>
@@ -174,13 +174,16 @@ export function AppLogs() {
}, [logs, autoScroll]);
// ---- Data fetching ---------------------------------------------------
const fetchLogs = useCallback(async (cursor: number = 0) => {
try {
return await services.adminLog.getLogs(cursor);
} catch (err) {
throw err instanceof Error ? err : new Error(t('fetchFailed'));
}
}, [t]);
const fetchLogs = useCallback(
async (cursor: number = 0) => {
try {
return await services.adminLog.getLogs(cursor);
} catch (err) {
throw err instanceof Error ? err : new Error(t('fetchFailed'));
}
},
[t],
);
const loadHistory = useCallback(
async (cursor: number = 0) => {
@@ -315,7 +315,10 @@ export function EventsTab() {
</Button>
</div>
{eventsQuery.isLoading ? (
<LoadingStateWithBorder icon={Layers} description={t('loadingEvents')} />
<LoadingStateWithBorder
icon={Layers}
description={t('loadingEvents')}
/>
) : eventsQuery.isError ? (
<div className='p-8 border border-dashed rounded-xl bg-card'>
<ErrorInline
@@ -325,10 +328,7 @@ export function EventsTab() {
/>
</div>
) : (eventsQuery.data ?? []).length === 0 ? (
<EmptyStateWithBorder
icon={Layers}
description={t('noEvents')}
/>
<EmptyStateWithBorder icon={Layers} description={t('noEvents')} />
) : (
<div className='border border-dashed shadow-none rounded-lg overflow-hidden'>
<Table className='w-full caption-bottom text-sm min-w-full'>
@@ -492,9 +492,7 @@ export function EventsTab() {
<DialogContent className='sm:max-w-[550px] max-h-[85vh] overflow-y-auto'>
<DialogHeader>
<DialogTitle>{t('addEventDialogTitle')}</DialogTitle>
<DialogDescription>
{t('addEventDialogDesc')}
</DialogDescription>
<DialogDescription>{t('addEventDialogDesc')}</DialogDescription>
</DialogHeader>
<div className='space-y-4 py-4'>
@@ -534,7 +532,9 @@ export function EventsTab() {
{newEventType === 'builtin' ? (
<div className='space-y-1.5'>
<Label className='text-xs font-semibold'>{t('systemEvent')}</Label>
<Label className='text-xs font-semibold'>
{t('systemEvent')}
</Label>
{builtInEventsQuery.isLoading ? (
<div className='flex items-center gap-2 text-xs text-muted-foreground'>
<Loader2 className='size-3.5 animate-spin' />
@@ -724,7 +724,9 @@ export function EventsTab() {
<div className='flex items-center justify-between p-3 border rounded-lg bg-muted/10'>
<div className='space-y-0.5'>
<Label className='text-xs font-semibold'>{t('enableStatus')}</Label>
<Label className='text-xs font-semibold'>
{t('enableStatus')}
</Label>
<div className='text-[10px] text-muted-foreground'>
{t('enableStatusDesc')}
</div>
@@ -770,9 +772,7 @@ export function EventsTab() {
<DialogContent className='sm:max-w-[550px] max-h-[85vh] overflow-y-auto'>
<DialogHeader>
<DialogTitle>{t('editEventDialogTitle')}</DialogTitle>
<DialogDescription>
{t('editEventDialogDesc')}
</DialogDescription>
<DialogDescription>{t('editEventDialogDesc')}</DialogDescription>
</DialogHeader>
{selectedEvent && (
@@ -271,9 +271,7 @@ export function HistoriesTab() {
{historiesQuery.data && historiesQuery.data.total > 0 && (
<div className='flex justify-between items-center text-xs text-muted-foreground'>
<span>
{t('totalRecords', { total: historiesQuery.data.total })}
</span>
<span>{t('totalRecords', { total: historiesQuery.data.total })}</span>
<div className='flex items-center gap-1.5'>
<Button
variant='outline'
@@ -335,9 +335,7 @@ export function SettingsTab() {
className='size-8 mb-2 opacity-30 animate-spin'
style={{ animationDuration: '3s' }}
/>
<span className='text-xs font-medium'>
{t('noCustomChannels')}
</span>
<span className='text-xs font-medium'>{t('noCustomChannels')}</span>
</div>
) : (
<div className='border border-dashed shadow-none rounded-lg overflow-hidden'>
@@ -464,7 +462,9 @@ export function SettingsTab() {
<div className='space-y-4 py-4'>
<div className='space-y-1.5'>
<Label className='text-xs font-semibold'>{t('channelName')}</Label>
<Label className='text-xs font-semibold'>
{t('channelName')}
</Label>
<Input
type='text'
placeholder={t('channelNamePlaceholder')}
@@ -479,7 +479,9 @@ export function SettingsTab() {
</div>
<div className='space-y-1.5'>
<Label className='text-xs font-semibold'>{t('channelRemark')}</Label>
<Label className='text-xs font-semibold'>
{t('channelRemark')}
</Label>
<Input
type='text'
placeholder={t('channelRemarkPlaceholder')}
@@ -490,7 +492,9 @@ export function SettingsTab() {
</div>
<div className='space-y-1.5'>
<Label className='text-xs font-semibold'>{t('channelType')}</Label>
<Label className='text-xs font-semibold'>
{t('channelType')}
</Label>
<Select
value={channelType}
onValueChange={handleChannelTypeChange}
@@ -201,9 +201,7 @@ export function OpenFlareOpsSettings() {
};
if (optionsQuery.isLoading) {
return (
<LoadingStateWithBorder icon={Server} description={t('loading')} />
);
return <LoadingStateWithBorder icon={Server} description={t('loading')} />;
}
if (optionsQuery.isError) {
@@ -406,9 +404,7 @@ export function OpenFlareOpsSettings() {
<Card className='border-dashed shadow-none'>
<CardHeader className='flex flex-row items-center justify-between gap-4'>
<div>
<CardTitle className='text-base'>
{t('discovery.title')}
</CardTitle>
<CardTitle className='text-base'>{t('discovery.title')}</CardTitle>
<CardDescription>{t('discovery.description')}</CardDescription>
</div>
<div className='flex flex-wrap gap-2'>
@@ -60,38 +60,41 @@ export function SystemStatusManager() {
);
// 获取状态数据
const fetchStatus = useCallback(async (isSilent = false) => {
if (!isSilent) setWavelet(true);
try {
const data = await services.adminStatus.getSystemStatus();
const fetchStatus = useCallback(
async (isSilent = false) => {
if (!isSilent) setWavelet(true);
try {
const data = await services.adminStatus.getSystemStatus();
// 检测变化的字段用于微动画效果
if (prevStatusRef.current) {
const changes: Record<string, boolean> = {};
Object.keys(data).forEach((key) => {
const k = key as keyof SystemStatus;
if (prevStatusRef.current && prevStatusRef.current[k] !== data[k]) {
changes[k] = true;
}
// 检测变化的字段用于微动画效果
if (prevStatusRef.current) {
const changes: Record<string, boolean> = {};
Object.keys(data).forEach((key) => {
const k = key as keyof SystemStatus;
if (prevStatusRef.current && prevStatusRef.current[k] !== data[k]) {
changes[k] = true;
}
});
setChangedFields(changes);
// 1秒后清除变化状态
setTimeout(() => {
setChangedFields({});
}, 1000);
}
setStatus(data);
prevStatusRef.current = data;
} catch (err) {
toast.error(t('loadFailed'), {
description: err instanceof Error ? err.message : t('unknownError'),
});
setChangedFields(changes);
// 1秒后清除变化状态
setTimeout(() => {
setChangedFields({});
}, 1000);
} finally {
setLoading(false);
setWavelet(false);
}
setStatus(data);
prevStatusRef.current = data;
} catch (err) {
toast.error(t('loadFailed'), {
description: err instanceof Error ? err.message : t('unknownError'),
});
} finally {
setLoading(false);
setWavelet(false);
}
}, [t]);
},
[t],
);
// 轮询逻辑
useEffect(() => {
@@ -256,7 +256,9 @@ export function TaskExecutionsManager() {
<TableHead className='w-[110px]'>{t('colTrigger')}</TableHead>
<TableHead className='w-[120px]'>{t('colRetry')}</TableHead>
<TableHead className='w-[120px]'>{t('colDuration')}</TableHead>
<TableHead className='min-w-[220px]'>{t('colResult')}</TableHead>
<TableHead className='min-w-[220px]'>
{t('colResult')}
</TableHead>
<TableHead className='w-[170px]'>{t('colCreatedAt')}</TableHead>
</TableRow>
</TableHeader>
@@ -376,9 +378,8 @@ export function TaskExecutionsManager() {
{t('detailTrigger')}
</div>
<div className='mt-2 text-sm font-medium'>
{t(
TRIGGER_LABELS_KEYS[selectedExecution.triggered_by],
) || selectedExecution.triggered_by}
{t(TRIGGER_LABELS_KEYS[selectedExecution.triggered_by]) ||
selectedExecution.triggered_by}
</div>
</div>
<div className='rounded-lg border p-3'>
@@ -165,7 +165,11 @@ function DatePickerWithTime({
)}
>
<CalendarIcon className='mr-1 size-3' />
{date ? format(date, 'yyyy-MM-dd') : <span>{t('selectDate')}</span>}
{date ? (
format(date, 'yyyy-MM-dd')
) : (
<span>{t('selectDate')}</span>
)}
</Button>
</PopoverTrigger>
<PopoverContent className='w-auto p-0' align='start'>
@@ -213,7 +217,9 @@ export function TaskManager() {
const data = await services.adminTask.getTaskTypes();
setTaskTypes(data);
} catch (err) {
setError(err instanceof Error ? err : new Error(t('loadTaskTypesFailed')));
setError(
err instanceof Error ? err : new Error(t('loadTaskTypesFailed')),
);
} finally {
setLoading(false);
}
@@ -75,7 +75,9 @@ export function TaskSchedulesManager() {
setSchedules(schedulesData || []);
setTaskTypes(taskTypesData || []);
} catch (err) {
setError(err instanceof Error ? err : new Error(t('loadSchedulesFailed')));
setError(
err instanceof Error ? err : new Error(t('loadSchedulesFailed')),
);
} finally {
setLoading(false);
}
@@ -304,10 +306,7 @@ export function TaskSchedulesManager() {
description={t('loadingSchedules')}
/>
) : schedules.length === 0 ? (
<EmptyStateWithBorder
icon={Clock}
description={t('noSchedules')}
/>
<EmptyStateWithBorder icon={Clock} description={t('noSchedules')} />
) : (
<div className='rounded-lg border bg-card'>
<Table className='min-w-[800px]'>
@@ -395,9 +394,7 @@ export function TaskSchedulesManager() {
<DialogTitle>
{editingSchedule ? t('editSchedule') : t('addSchedule')}
</DialogTitle>
<DialogDescription>
{t('scheduleDialogDesc')}
</DialogDescription>
<DialogDescription>{t('scheduleDialogDesc')}</DialogDescription>
</DialogHeader>
<div className='grid gap-4 py-4'>
@@ -574,9 +571,7 @@ export function TaskSchedulesManager() {
<DialogContent className='sm:max-w-[400px]'>
<DialogHeader>
<DialogTitle>{t('deleteScheduleTitle')}</DialogTitle>
<DialogDescription>
{t('deleteScheduleDesc')}
</DialogDescription>
<DialogDescription>{t('deleteScheduleDesc')}</DialogDescription>
</DialogHeader>
<DialogFooter className='gap-2 sm:gap-0'>
<Button
@@ -218,7 +218,9 @@ export function EditUserModal({
<div className='flex items-center justify-between rounded-lg border border-dashed p-3 bg-muted/10'>
<div>
<div className='font-medium text-sm'>{t('adminPermission')}</div>
<div className='font-medium text-sm'>
{t('adminPermission')}
</div>
<div className='text-xs text-muted-foreground'>
{isSelf
? t('cannotRevokeSelfAdmin')
@@ -288,7 +290,9 @@ export function EditUserModal({
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel disabled={saving}>{t('cancel')}</AlertDialogCancel>
<AlertDialogCancel disabled={saving}>
{t('cancel')}
</AlertDialogCancel>
<AlertDialogAction
onClick={(e) => {
e.preventDefault();
@@ -172,7 +172,9 @@ export function UserDetailSheet({
</h4>
<div className='rounded-lg border divide-y bg-background/50'>
<div className='flex items-center justify-between p-3.5 text-sm'>
<span className='text-[10px]'>{t('accountStatus')}</span>
<span className='text-[10px]'>
{t('accountStatus')}
</span>
<Badge
variant={
selectedUser.is_active ? 'secondary' : 'outline'