feat(backup): GFS 分层保留策略(祖父-父-子)+ 任务表单配置 (#85)

新增 GFS 分层保留:按天/周/月/年保留代表性备份,各层级并集;任一>0 启用、全0 维持原策略(兼容),锁定记录豁免。后端 retention 算法+任务字段贯通,前端任务表单 GFS 配置。go test、tsc+vite 通过。
This commit is contained in:
Wu Qing
2026-05-27 15:36:58 +08:00
committed by GitHub
parent 386f12a11b
commit 992fc24150
6 changed files with 244 additions and 35 deletions

View File

@@ -65,6 +65,10 @@ function createEmptyDraft(storageTargets?: StorageTargetSummary[]): BackupTaskPa
compression: 'gzip',
encrypt: false,
maxBackups: 10,
keepDaily: 0,
keepWeekly: 0,
keepMonthly: 0,
keepYearly: 0,
extraConfig: undefined,
verifyEnabled: false,
verifyCronExpr: '',
@@ -134,6 +138,10 @@ export function BackupTaskFormDrawer({ visible, loading, initialValue, storageTa
compression: initialValue.compression,
encrypt: initialValue.encrypt,
maxBackups: initialValue.maxBackups,
keepDaily: initialValue.keepDaily ?? 0,
keepWeekly: initialValue.keepWeekly ?? 0,
keepMonthly: initialValue.keepMonthly ?? 0,
keepYearly: initialValue.keepYearly ?? 0,
extraConfig: initialValue.extraConfig,
verifyEnabled: initialValue.verifyEnabled ?? false,
verifyCronExpr: initialValue.verifyCronExpr ?? '',
@@ -588,6 +596,25 @@ export function BackupTaskFormDrawer({ visible, loading, initialValue, storageTa
<Typography.Text></Typography.Text>
<InputNumber style={{ width: '100%' }} value={draft.maxBackups} min={0} onChange={(value) => updateDraft({ maxBackups: Number(value ?? 0) })} />
</div>
<div>
<Typography.Text type="secondary" style={{ fontSize: 12 }}>
GFS &gt; 0 ////
</Typography.Text>
<Grid.Row gutter={8} style={{ marginTop: 4 }}>
<Grid.Col span={6}>
<InputNumber style={{ width: '100%' }} placeholder="日" prefix="日" min={0} value={draft.keepDaily} onChange={(value) => updateDraft({ keepDaily: Number(value ?? 0) })} />
</Grid.Col>
<Grid.Col span={6}>
<InputNumber style={{ width: '100%' }} placeholder="周" prefix="周" min={0} value={draft.keepWeekly} onChange={(value) => updateDraft({ keepWeekly: Number(value ?? 0) })} />
</Grid.Col>
<Grid.Col span={6}>
<InputNumber style={{ width: '100%' }} placeholder="月" prefix="月" min={0} value={draft.keepMonthly} onChange={(value) => updateDraft({ keepMonthly: Number(value ?? 0) })} />
</Grid.Col>
<Grid.Col span={6}>
<InputNumber style={{ width: '100%' }} placeholder="年" prefix="年" min={0} value={draft.keepYearly} onChange={(value) => updateDraft({ keepYearly: Number(value ?? 0) })} />
</Grid.Col>
</Grid.Row>
</div>
<div>
<Typography.Text></Typography.Text>
<Input

View File

@@ -21,6 +21,10 @@ export interface BackupTaskSummary {
compression: BackupCompression
encrypt: boolean
maxBackups: number
keepDaily: number
keepWeekly: number
keepMonthly: number
keepYearly: number
lastRunAt?: string
lastStatus: BackupTaskStatus
verifyEnabled: boolean
@@ -73,6 +77,10 @@ export interface BackupTaskPayload {
compression: BackupCompression
encrypt: boolean
maxBackups: number
keepDaily: number
keepWeekly: number
keepMonthly: number
keepYearly: number
/** 类型特有的扩展配置(如 SAP HANA 的 backupLevel/backupChannels 等) */
extraConfig?: Record<string, unknown>
verifyEnabled: boolean