feat(scan): 添加自定义扫描目录选择功能
- 在扫描页面添加目录输入框和选择按钮 - 实现文件系统浏览器,支持Windows盘符和目录浏览 - 添加扫描目录参数传递到后端服务 - 显示当前扫描目录路径信息 - 修复前端空数组访问错误 - 更新文档说明扫描功能变化
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
// Package api 提供服务器文件系统浏览接口,供前端目录选择器使用(只列出目录,不列文件)。
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// FsController 服务器文件系统浏览控制器
|
||||
type FsController struct{}
|
||||
|
||||
// NewFsController 创建文件系统浏览控制器
|
||||
func NewFsController() *FsController {
|
||||
return &FsController{}
|
||||
}
|
||||
|
||||
// FsListResult 目录浏览结果
|
||||
type FsListResult struct {
|
||||
Current string `json:"current"` // 当前目录绝对路径;盘符层为空
|
||||
Parent string `json:"parent"` // 父目录;根/盘符层时等于 Current
|
||||
Drives []string `json:"drives"` // Windows 盘符列表(非 Windows 为空)
|
||||
Dirs []FsDir `json:"dirs"` // 子目录列表(不含文件)
|
||||
}
|
||||
|
||||
// FsDir 子目录项
|
||||
type FsDir struct {
|
||||
Name string `json:"name"`
|
||||
Path string `json:"path"`
|
||||
}
|
||||
|
||||
// List GET /api/fs/list?dir= 列出指定目录的子目录(不含文件);
|
||||
// dir 为空时返回 Windows 盘符列表或 Unix 根目录。
|
||||
func (c *FsController) List(ctx *gin.Context) {
|
||||
dir := strings.TrimSpace(ctx.Query("dir"))
|
||||
|
||||
if dir == "" {
|
||||
if runtime.GOOS == "windows" {
|
||||
Success(ctx, FsListResult{Drives: listLogicalDrives()})
|
||||
return
|
||||
}
|
||||
dir = string(os.PathSeparator)
|
||||
}
|
||||
|
||||
abs, err := filepath.Abs(dir)
|
||||
if err != nil {
|
||||
Error(ctx, http.StatusBadRequest, "路径解析失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
st, err := os.Stat(abs)
|
||||
if err != nil || !st.IsDir() {
|
||||
Error(ctx, http.StatusBadRequest, "目录不存在或不可访问: "+abs)
|
||||
return
|
||||
}
|
||||
|
||||
entries, err := os.ReadDir(abs)
|
||||
if err != nil {
|
||||
Error(ctx, http.StatusBadRequest, "读取目录失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
parent := filepath.Dir(abs)
|
||||
if parent == abs {
|
||||
parent = abs
|
||||
}
|
||||
dirs := make([]FsDir, 0, len(entries))
|
||||
for _, e := range entries {
|
||||
if !e.IsDir() {
|
||||
continue
|
||||
}
|
||||
dirs = append(dirs, FsDir{Name: e.Name(), Path: filepath.Join(abs, e.Name())})
|
||||
}
|
||||
sort.Slice(dirs, func(i, j int) bool {
|
||||
return strings.ToLower(dirs[i].Name) < strings.ToLower(dirs[j].Name)
|
||||
})
|
||||
|
||||
Success(ctx, FsListResult{
|
||||
Current: abs,
|
||||
Parent: parent,
|
||||
Drives: nil,
|
||||
Dirs: dirs,
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
//go:build !windows
|
||||
|
||||
package api
|
||||
|
||||
// listLogicalDrives 非 Windows 平台无盘符概念,返回空
|
||||
func listLogicalDrives() []string {
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
//go:build windows
|
||||
|
||||
package api
|
||||
|
||||
import "golang.org/x/sys/windows"
|
||||
|
||||
// listLogicalDrives 返回 Windows 所有逻辑盘符(如 C:\、D:\)
|
||||
func listLogicalDrives() []string {
|
||||
bits, err := windows.GetLogicalDrives()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
drives := make([]string, 0, 26)
|
||||
for i := 0; i < 26; i++ {
|
||||
if bits&(1<<uint(i)) != 0 {
|
||||
drives = append(drives, string(rune('A'+i))+":\\")
|
||||
}
|
||||
}
|
||||
return drives
|
||||
}
|
||||
@@ -28,6 +28,9 @@ func NewRouter(st *store.Store) *gin.Engine {
|
||||
sc := NewScanController(service.NewScanService(st))
|
||||
apiGroup.POST("/scan/start", sc.Start)
|
||||
apiGroup.GET("/scan/status", sc.Status)
|
||||
|
||||
fc := NewFsController()
|
||||
apiGroup.GET("/fs/list", fc.List)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
@@ -18,9 +18,19 @@ func NewScanController(svc *service.ScanService) *ScanController {
|
||||
return &ScanController{service: svc}
|
||||
}
|
||||
|
||||
// scanStartReq 扫描启动请求;dir 为空时使用服务当前运行目录
|
||||
type scanStartReq struct {
|
||||
Dir string `json:"dir"`
|
||||
}
|
||||
|
||||
// Start POST /api/scan/start 触发一次扫描整理
|
||||
func (c *ScanController) Start(ctx *gin.Context) {
|
||||
if err := c.service.Start(); err != nil {
|
||||
var req scanStartReq
|
||||
if err := ctx.ShouldBindJSON(&req); err != nil {
|
||||
Error(ctx, http.StatusBadRequest, "请求参数错误:"+err.Error())
|
||||
return
|
||||
}
|
||||
if err := c.service.Start(req.Dir); err != nil {
|
||||
Error(ctx, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user