From 06cba0e3bfd1055c31dd23dfe63a2b4e71da8cf3 Mon Sep 17 00:00:00 2001 From: GeorgeDong32 Date: Thu, 25 Sep 2025 12:48:32 +0800 Subject: [PATCH] style(backup): fix style --- .../settings/DataSettings/S3Settings.tsx | 31 +++++++++++++++++++ src/renderer/src/services/BackupService.ts | 23 +++++++++++--- 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/src/renderer/src/pages/settings/DataSettings/S3Settings.tsx b/src/renderer/src/pages/settings/DataSettings/S3Settings.tsx index ccf8b41ae9..d581612384 100644 --- a/src/renderer/src/pages/settings/DataSettings/S3Settings.tsx +++ b/src/renderer/src/pages/settings/DataSettings/S3Settings.tsx @@ -139,6 +139,37 @@ const S3Settings: FC = () => { {t('settings.data.s3.title.help')} + {/* 覆盖式单文件备份,仅在自动备份开启且保留份数=1时推荐启用 */} + + + {t('settings.data.backup.singleFileOverwrite.title') || '覆盖式单文件备份(同名覆盖)'} + + 0 && maxBackups === 1)} + /> + + + + {t('settings.data.backup.singleFileOverwrite.help') || + '当自动备份开启且保留份数为1时,使用固定文件名每次覆盖。S3 会直接覆盖同键对象。'} + + + + {t('settings.data.backup.singleFileName.title') || '自定义文件名(可选)'} + ..zip' + } + value={singleFileName} + onChange={(e) => setSingleFileName(e.target.value)} + onBlur={onSingleFileNameBlur} + style={{ width: 300 }} + disabled={!singleFileOverwrite || !(syncInterval > 0 && maxBackups === 1)} + /> + + {t('settings.data.s3.endpoint.label')} 0) { + // 覆盖式单文件备份启用时(且=1),不进行清理,避免误删历史。后续不会再增长。 + if ( + s3Config.maxBackups > 0 && + !(autoBackupProcess && s3Config.maxBackups === 1 && s3Config.singleFileOverwrite) + ) { try { // 获取所有备份文件 const files = await window.api.backup.listS3Files(s3Config) @@ -951,7 +955,9 @@ export async function backupToLocal({ const { localBackupDir: localBackupDirSetting, localBackupMaxBackups, - localBackupSkipBackupFile + localBackupSkipBackupFile, + localSingleFileOverwrite, + localSingleFileName } = store.getState().settings const localBackupDir = await window.api.resolvePath(localBackupDirSetting) let deviceType = 'unknown' @@ -963,7 +969,11 @@ export async function backupToLocal({ logger.error('Failed to get device type or hostname:', error as Error) } const timestamp = dayjs().format('YYYYMMDDHHmmss') - const backupFileName = customFileName || `cherry-studio.${timestamp}.${hostname}.${deviceType}.zip` + let backupFileName = customFileName || `cherry-studio.${timestamp}.${hostname}.${deviceType}.zip` + if (autoBackupProcess && localBackupMaxBackups === 1 && localSingleFileOverwrite) { + const base = (localSingleFileName || `cherry-studio.${hostname}.${deviceType}`).trim() + backupFileName = base.endsWith('.zip') ? base : `${base}.zip` + } const finalFileName = backupFileName.endsWith('.zip') ? backupFileName : `${backupFileName}.zip` const backupData = await getBackupData() @@ -993,8 +1003,11 @@ export async function backupToLocal({ }) } - // Clean up old backups if maxBackups is set - if (localBackupMaxBackups > 0) { + // 覆盖式单文件备份启用时(且=1),不进行清理 + if ( + localBackupMaxBackups > 0 && + !(autoBackupProcess && localBackupMaxBackups === 1 && localSingleFileOverwrite) + ) { try { // Get all backup files const files = await window.api.backup.listLocalBackupFiles(localBackupDir)