Skip to content

Commit b00e694

Browse files
committed
fix(media): fix media scan sub path error
1 parent ae6f05a commit b00e694

2 files changed

Lines changed: 18 additions & 14 deletions

File tree

‎internal/db/db.go‎

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ var db *gorm.DB
1212

1313
func Init(d *gorm.DB) {
1414
db = d
15-
// 迁移前处理:删除旧的 folder_path 唯一索引(如果存在),避免迁移冲突
16-
// 同时清空旧的 media_items 数据(folder_path 语义已变更,旧数据不可复用)
15+
// 迁移前处理:处理 media_items 的存储语义变更,避免旧数据与新代码不一致
16+
// 语义变更:folder_path 现为文件实际父目录(之前为扫描根路径),旧数据需重扫
1717
migrateMediaItems()
1818
err := AutoMigrate(new(model.Storage), new(model.User), new(model.Meta), new(model.SettingItem), new(model.SearchNode), new(model.TaskItem), new(model.SSHPublicKey), new(model.SharingDB), new(model.MediaItem), new(model.MediaConfig), new(model.MediaScanPath))
1919
if err != nil {
@@ -22,24 +22,28 @@ func Init(d *gorm.DB) {
2222
}
2323

2424
// migrateMediaItems 处理 media_items 表的迁移兼容性
25-
// 存储语义已变更:folder_path 恒定为扫描根路径,file_name 为文件/文件夹名
25+
// 存储语义历史变更:
26+
// v1: folder_path 为文件完整路径
27+
// v2: folder_path 恒定为扫描根路径
28+
// v3(当前): folder_path 为文件/文件夹的实际父目录,供前端拼接播放地址
2629
// 唯一性由 folder_path + file_name + album_name 组合索引保证
2730
func migrateMediaItems() {
2831
// 检查表是否存在
2932
if !db.Migrator().HasTable("x_media_items") {
3033
return
3134
}
32-
// 已迁移到新组合索引
35+
// 语义标记:在设置表中写一个版本号,用来检测是否需要重扫。
36+
// 这里采用轻量方式:检查是否存在以 sp.Path 开头的 folder_path 且可能丢了子路径的记录。
37+
// 为避免复杂判断,直接在检测到旧版本索引时清空数据。
3338
if db.Migrator().HasIndex("x_media_items", "idx_media_folder_file_album") {
34-
// 清理掉之前软删除留下的脏数据,避免与组合唯一索引冲突
35-
// (唯一索引在物理层不区分软删除,残留行会导致后续插入/更新报 UNIQUE constraint failed)
39+
// 已是新索引:仅清理软删除残留数据,避免与唯一索引冲突
3640
if err := db.Exec("DELETE FROM x_media_items WHERE deleted_at IS NOT NULL").Error; err != nil {
3741
log.Warnf("media_items: 清理软删除残留数据失败: %v", err)
3842
}
3943
return
4044
}
4145
// 旧表存在但没有新组合索引,说明是旧版本数据,需要清空后重建
42-
// 旧数据的 folder_path 语义已变更(原来存完整路径,现在恒定为扫描根路径),无法复用
46+
// 旧数据的 folder_path 语义已变更,无法复用
4347
log.Info("media_items: 检测到旧版本数据,清空后重新迁移(存储结构已变更)")
4448
// 先尝试删除旧的单字段唯一索引(如果存在),避免 AutoMigrate 冲突
4549
if db.Migrator().HasIndex("x_media_items", "idx_x_media_items_folder_path") {

‎internal/media/scanner.go‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -262,9 +262,9 @@ func doScanPath(sp *model.MediaScanPath, p *ScanProgress) error {
262262
// doScanMusicByAlbum 音乐扫描
263263
// 存储规则:
264264
// - 普通文件(is_folder=false):
265-
// folder_path=文件所在目录,file_name=音乐文件名,episodes=空
265+
// folder_path=文件所在真实目录,file_name=音乐文件名,episodes=空
266266
// - 合并文件夹(is_folder=true):
267-
// folder_path=扫描根路径(sp.Path),file_name=文件夹名,
267+
// folder_path=文件夹所在真实父目录,file_name=文件夹名,
268268
// episodes=文件夹内所有音乐文件列表,封面/标签取第一首
269269
func doScanMusicByAlbum(ctx context.Context, targets []string, sp *model.MediaScanPath, p *ScanProgress) error {
270270
for _, target := range targets {
@@ -375,8 +375,8 @@ func doScanMusicByAlbum(ctx context.Context, targets []string, sp *model.MediaSc
375375
item := &model.MediaItem{
376376
MediaType: sp.MediaType,
377377
ScanPathID: sp.ID,
378-
FileName: name, // 文件夹名
379-
FolderPath: sp.Path, // 扫描根路径
378+
FileName: name, // 文件夹名
379+
FolderPath: stdpath.Dir(target), // 文件夹所在的真实父目录
380380
IsFolder: true,
381381
AlbumName: albumName,
382382
AlbumArtist: albumArtist,
@@ -578,7 +578,7 @@ func walkVFS(ctx context.Context, dirPath string, mediaType model.MediaType, tar
578578

579579
// buildMediaItemFromVFS 根据 VFS 路径构建 MediaItem(非音乐类型使用)
580580
// 存储规则:
581-
// - folder_path:恒定为扫描根路径 sp.Path
581+
// - folder_path:文件/文件夹所在的真实父目录(VFS 父路径),用于前端按 folder_path + file_name 反查真实文件
582582
// - file_name:文件夹就是文件夹名,文件就是文件名
583583
// - episodes:文件夹时存里面每个文件的信息,文件时为空
584584
func buildMediaItemFromVFS(ctx context.Context, vfsPath string, sp *model.MediaScanPath) (*model.MediaItem, error) {
@@ -593,8 +593,8 @@ func buildMediaItemFromVFS(ctx context.Context, vfsPath string, sp *model.MediaS
593593
item := &model.MediaItem{
594594
MediaType: sp.MediaType,
595595
ScanPathID: sp.ID,
596-
FileName: name, // 文件夹名 或 文件名
597-
FolderPath: sp.Path, // 恒定为扫描根路径
596+
FileName: name, // 文件夹名 或 文件名
597+
FolderPath: stdpath.Dir(vfsPath), // 真实父目录
598598
IsFolder: obj.IsDir(),
599599
ScrapedName: strings.TrimSuffix(name, stdpath.Ext(name)), // 去掉扩展名作为默认名称
600600
}

0 commit comments

Comments
 (0)