From a581c4f30bce18d1c45eadecc4e49b479d988fbf Mon Sep 17 00:00:00 2001 From: Awuqing <3184394176@qq.com> Date: Wed, 1 Apr 2026 00:06:08 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D:=20=E5=AD=98=E5=82=A8?= =?UTF-8?q?=E7=9B=AE=E6=A0=87=E5=88=9B=E5=BB=BA/=E8=BF=9E=E6=8E=A5?= =?UTF-8?q?=E6=B5=8B=E8=AF=95/=E7=B1=BB=E5=9E=8B=E9=80=89=E6=8B=A9?= =?UTF-8?q?=E4=B8=89=E4=B8=AA=E5=85=B3=E9=94=AE=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 修复 oneof 白名单仅含 4 种类型,阿里云/腾讯/七牛/FTP/Rclone 类型的存储目标无法创建(binding 验证直接拒绝) 2. 修复本地磁盘 TestConnection 报 "directory not found", 在 List 前先 Mkdir 确保目录存在 3. 前端存储类型选项明确标注 Rclone 支持 SFTP/Azure/Dropbox 等 --- server/internal/service/storage_target_service.go | 2 +- server/internal/storage/rclone/provider.go | 6 +++++- web/src/components/storage-targets/field-config.ts | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/server/internal/service/storage_target_service.go b/server/internal/service/storage_target_service.go index 563d9b9..2e9ec4c 100644 --- a/server/internal/service/storage_target_service.go +++ b/server/internal/service/storage_target_service.go @@ -21,7 +21,7 @@ import ( type StorageTargetUpsertInput struct { Name string `json:"name" binding:"required,min=1,max=128"` - Type string `json:"type" binding:"required,oneof=local_disk google_drive s3 webdav"` + Type string `json:"type" binding:"required,oneof=local_disk google_drive s3 webdav aliyun_oss tencent_cos qiniu_kodo ftp rclone"` Description string `json:"description" binding:"max=255"` Enabled bool `json:"enabled"` Config map[string]any `json:"config" binding:"required"` diff --git a/server/internal/storage/rclone/provider.go b/server/internal/storage/rclone/provider.go index 2126ee2..92b8256 100644 --- a/server/internal/storage/rclone/provider.go +++ b/server/internal/storage/rclone/provider.go @@ -26,8 +26,12 @@ func newProvider(providerType storage.ProviderType, rfs fs.Fs) *Provider { func (p *Provider) Type() storage.ProviderType { return p.providerType } -// TestConnection 通过列出根目录验证连通性。 +// TestConnection 验证连通性。对本地磁盘会先确保目录存在。 func (p *Provider) TestConnection(ctx context.Context) error { + // 确保根目录存在(本地磁盘等后端需要预创建) + if err := p.rfs.Mkdir(ctx, ""); err != nil { + return fmt.Errorf("rclone test connection (mkdir): %w", err) + } _, err := p.rfs.List(ctx, "") if err != nil { return fmt.Errorf("rclone test connection: %w", err) diff --git a/web/src/components/storage-targets/field-config.ts b/web/src/components/storage-targets/field-config.ts index e95713f..54c0e72 100644 --- a/web/src/components/storage-targets/field-config.ts +++ b/web/src/components/storage-targets/field-config.ts @@ -301,5 +301,5 @@ export const storageTargetTypeOptions = [ { label: 'Google Drive', value: 'google_drive' }, { label: 'WebDAV', value: 'webdav' }, { label: 'FTP', value: 'ftp' }, - { label: 'Rclone (70+ 后端)', value: 'rclone' }, + { label: 'Rclone — SFTP / Azure / Dropbox / OneDrive 等 70+ 后端', value: 'rclone' }, ] as const