diff --git a/pkg/storage/local.go b/pkg/storage/local.go index cb0cf59..7799e43 100644 --- a/pkg/storage/local.go +++ b/pkg/storage/local.go @@ -26,10 +26,20 @@ type LocalStorage struct { dir string } -func (l *LocalStorage) Move(src, dest string) error { - targetDir := filepath.Join(l.dir, dest) - os.MkdirAll(filepath.Dir(targetDir), os.ModePerm) - err := filepath.Walk(src, func(path string, info fs.FileInfo, err error) error { +func (l *LocalStorage) Move(src, destDir string) error { + os.MkdirAll(filepath.Join(l.dir, destDir), os.ModePerm) + + targetBase := filepath.Join(l.dir, destDir, filepath.Base(src)) //文件的场景,要加上文件名, move filename ./dir/ + info, err := os.Stat(src) + if err != nil { + return errors.Wrap(err, "read source dir") + } + if info.IsDir() { //如果是路径,则只移动路径里面的文件,不管当前路径, 行为类似 move dirname/* target_dir/ + targetBase = filepath.Join(l.dir, destDir) + } + + + err = filepath.Walk(src, func(path string, info fs.FileInfo, err error) error { if err != nil { return err } @@ -37,7 +47,7 @@ func (l *LocalStorage) Move(src, dest string) error { if err != nil { return errors.Wrapf(err, "relation between %s and %s", src, path) } - destName := filepath.Join(targetDir, rel) + destName := filepath.Join(targetBase, rel) if info.IsDir() { os.Mkdir(destName, os.ModePerm) diff --git a/pkg/storage/webdav.go b/pkg/storage/webdav.go index 632bde7..6abb790 100644 --- a/pkg/storage/webdav.go +++ b/pkg/storage/webdav.go @@ -30,13 +30,20 @@ func NewWebdavStorage(url, user, password, path string, changeMediaHash bool) (* }, nil } -func (w *WebdavStorage) Move(local, remote string) error { +func (w *WebdavStorage) Move(local, remoteDir string) error { - remoteBase := filepath.Join(w.dir,remote) + remoteBase := filepath.Join(w.dir,remoteDir, filepath.Base(local)) + info, err := os.Stat(local) + if err != nil { + return errors.Wrap(err, "read source dir") + } + if info.IsDir() { //如果是路径,则只移动路径里面的文件,不管当前路径, 行为类似 move dirname/* target_dir/ + remoteBase = filepath.Join(w.dir, remoteDir) + } //log.Infof("remove all content in %s", remoteBase) //w.fs.RemoveAll(remoteBase) - err := filepath.Walk(local, func(path string, info fs.FileInfo, err error) error { + err = filepath.Walk(local, func(path string, info fs.FileInfo, err error) error { if err != nil { return errors.Wrapf(err, "read file %v", path) } diff --git a/server/scheduler.go b/server/scheduler.go index 57bcbbd..77745d5 100644 --- a/server/scheduler.go +++ b/server/scheduler.go @@ -128,18 +128,10 @@ func (s *Server) moveCompletedTask(id int) (err1 error) { stImpl = storageImpl } - if r.EpisodeID == 0 { - //season package download - if err := stImpl.Move(filepath.Join(s.db.GetDownloadDir(), torrent.Name()), r.TargetDir); err != nil { - return errors.Wrap(err, "move file") - } - - } else { - if err := stImpl.Move(filepath.Join(s.db.GetDownloadDir(), torrent.Name()), filepath.Join(r.TargetDir, torrent.Name())); err != nil { - return errors.Wrap(err, "move file") - - } + //如果种子是路径,则会把路径展开,只移动文件,类似 move dir/* dir2/, 如果种子是文件,则会直接移动文件,类似 move file dir/ + if err := stImpl.Move(filepath.Join(s.db.GetDownloadDir(), torrent.Name()), r.TargetDir); err != nil { + return errors.Wrap(err, "move file") } log.Infof("move downloaded files to target dir success, file: %v, target dir: %v", torrent.Name(), r.TargetDir) diff --git a/server/watchlist.go b/server/watchlist.go index 723dc7d..c0effb8 100644 --- a/server/watchlist.go +++ b/server/watchlist.go @@ -60,7 +60,7 @@ type addWatchlistIn struct { TmdbID int `json:"tmdb_id" binding:"required"` StorageID int `json:"storage_id" ` Resolution string `json:"resolution" binding:"required"` - Folder string `json:"folder"` + Folder string `json:"folder" binding:"required"` DownloadHistoryEpisodes bool `json:"download_history_episodes"` //for tv } @@ -187,7 +187,7 @@ func (s *Server) AddMovie2Watchlist(c *gin.Context) (interface{}, error) { AirDate: detail.ReleaseDate, Resolution: media.Resolution(in.Resolution), StorageID: in.StorageID, - TargetDir: "./", + TargetDir: in.Folder, }, []int{epid}) if err != nil { return nil, errors.Wrap(err, "add to list") diff --git a/ui/lib/search.dart b/ui/lib/search.dart index 2a762a0..331807c 100644 --- a/ui/lib/search.dart +++ b/ui/lib/search.dart @@ -30,13 +30,15 @@ class _SearchPageState extends ConsumerState { List res = searchList.when( data: (data) { if (data.isEmpty) { - return [Container( - height: MediaQuery.of(context).size.height * 0.6, - alignment: Alignment.center, - child: const Text( - "啥都没有...", - style: TextStyle(fontSize: 16), - ))]; + return [ + Container( + height: MediaQuery.of(context).size.height * 0.6, + alignment: Alignment.center, + child: const Text( + "啥都没有...", + style: TextStyle(fontSize: 16), + )) + ]; } var cards = List.empty(growable: true); for (final item in data) { @@ -202,44 +204,39 @@ class _SearchPageState extends ConsumerState { }); }, ), - item.mediaType == "tv" - ? name.when( - data: (s) { - return storageSelected == 0 - ? const Text("") - : () { - final storage = v - .where((e) => - e.id == - storageSelected) - .first; - final path = storage - .settings!["tv_path"]; + name.when( + data: (s) { + return storageSelected == 0 + ? const Text("") + : () { + final storage = v + .where((e) => + e.id == storageSelected) + .first; + final path = item.mediaType == + "tv" + ? storage.settings!["tv_path"] + : storage + .settings!["movie_path"]; - pathController.text = s; - return SizedBox( - //width: 300, - child: TextField( - controller: - pathController, - decoration: - InputDecoration( - labelText: - "存储路径", - prefix: - Text(path)), - ), - ); - }(); - }, - error: (error, stackTrace) => - Text("$error"), - loading: () => - const MyProgressIndicator( - size: 20, - ), - ) - : Text(""), + pathController.text = s; + return SizedBox( + //width: 300, + child: TextField( + controller: pathController, + decoration: InputDecoration( + labelText: "存储路径", + prefix: Text(path)), + ), + ); + }(); + }, + error: (error, stackTrace) => + Text("$error"), + loading: () => const MyProgressIndicator( + size: 20, + ), + ), item.mediaType == "tv" ? SizedBox( width: 250,