package backend import ( "ant-chrome/backend/internal/logger" "fmt" "os" "os/exec" "path/filepath" goruntime "runtime" "strings" ) // OpenUserDataDir 在资源管理器中打开用户数据目录 func (a *App) OpenUserDataDir(userDataDir string) error { log := logger.New("Browser") userDataDir = strings.TrimSpace(userDataDir) if userDataDir == "" { return fmt.Errorf("用户数据目录不能为空") } var fullPath string if filepath.IsAbs(userDataDir) { fullPath = userDataDir } else { root := strings.TrimSpace(a.config.Browser.UserDataRoot) if root == "" { root = "data" } root = a.resolveAppPath(root) fullPath = filepath.Join(root, userDataDir) } if _, err := os.Stat(fullPath); os.IsNotExist(err) { if err := os.MkdirAll(fullPath, 0755); err != nil { log.Error("创建用户数据目录失败", logger.F("path", fullPath), logger.F("error", err)) return fmt.Errorf("创建目录失败: %v", err) } } absPath, err := filepath.Abs(fullPath) if err != nil { log.Error("获取绝对路径失败", logger.F("path", fullPath), logger.F("error", err)) return err } if err := openPathInFileManager(absPath); err != nil { log.Error("打开资源管理器失败", logger.F("path", absPath), logger.F("error", err)) return err } log.Info("已打开用户数据目录", logger.F("path", absPath)) return nil } // OpenCorePath 在资源管理器中打开内核路径 func (a *App) OpenCorePath(corePath string) error { log := logger.New("Browser") corePath = strings.TrimSpace(corePath) if corePath == "" { return fmt.Errorf("内核路径不能为空") } var fullPath string if filepath.IsAbs(corePath) { fullPath = corePath } else { fullPath = a.resolveAppPath(corePath) } if _, err := os.Stat(fullPath); os.IsNotExist(err) { return fmt.Errorf("路径不存在: %s", fullPath) } absPath, err := filepath.Abs(fullPath) if err != nil { log.Error("获取绝对路径失败", logger.F("path", fullPath), logger.F("error", err)) return err } if err := openPathInFileManager(absPath); err != nil { log.Error("打开资源管理器失败", logger.F("path", absPath), logger.F("error", err)) return err } log.Info("已打开内核路径", logger.F("path", absPath)) return nil } // OpenProjectRoot 在资源管理器中打开项目根目录 func (a *App) OpenProjectRoot() error { log := logger.New("Browser") rootPath := strings.TrimSpace(a.appRootAbs()) if rootPath == "" { return fmt.Errorf("项目根目录不能为空") } if _, err := os.Stat(rootPath); os.IsNotExist(err) { return fmt.Errorf("项目根目录不存在: %s", rootPath) } absPath, err := filepath.Abs(rootPath) if err != nil { log.Error("获取项目根目录绝对路径失败", logger.F("path", rootPath), logger.F("error", err)) return err } if err := openPathInFileManager(absPath); err != nil { log.Error("打开项目根目录失败", logger.F("path", absPath), logger.F("error", err)) return err } log.Info("已打开项目根目录", logger.F("path", absPath)) return nil } // openPathInFileManager 调用系统文件管理器打开路径。 // Windows 下不能复用 hideWindow,否则可能导致资源管理器窗口被隐藏。 func openPathInFileManager(absPath string) error { info, err := os.Stat(absPath) if err != nil { return err } switch goruntime.GOOS { case "windows": if info.IsDir() { return exec.Command("explorer.exe", absPath).Start() } return exec.Command("explorer.exe", "/select,", absPath).Start() case "darwin": if info.IsDir() { return exec.Command("open", absPath).Start() } return exec.Command("open", "-R", absPath).Start() default: target := absPath if !info.IsDir() { target = filepath.Dir(absPath) } return exec.Command("xdg-open", target).Start() } }