package handlers import ( "context" "encoding/base64" "fmt" "github.com/wailsapp/wails/v2/pkg/runtime" "io" "os" "path/filepath" "strings" ) // ProcessResult 处理结果结构体 type ProcessResult struct { Success bool `json:"success"` Message string `json:"message"` Progress int `json:"progress"` } // ProcessCallback 处理过程回调函数类型 type ProcessCallback func(result ProcessResult) type DirectoryHandler struct { ctx context.Context } func NewDirectoryHandler(ctx context.Context) *DirectoryHandler { return &DirectoryHandler{ctx: ctx} } // HandlerDirectory 处理目录复制的主要方法 func (dh *DirectoryHandler) HandlerDirectory(sourceDir, targetDir string) error { // 检查源目录是否存在 if _, err := os.Stat(sourceDir); os.IsNotExist(err) { return fmt.Errorf("源目录不存在: %s", sourceDir) } // 检查目标目录,如果不存在则创建 if _, err := os.Stat(targetDir); os.IsNotExist(err) { // 源目录不存在时不需要创建目录,但目标目录可以创建 err := os.MkdirAll(targetDir, os.ModePerm) if err != nil { return fmt.Errorf("创建目标目录失败: %v", err) } } // 执行具体的处理逻辑 return dh.processDirectories(sourceDir, targetDir) } // processDirectories 实际处理目录的逻辑 func (dh *DirectoryHandler) processDirectories(sourceDir, targetDir string) error { // 发送初始进度 dh.sendProgress(ProcessResult{ Success: true, Message: "开始处理目录...", Progress: 0, }) // 遍历和处理逻辑 err := filepath.Walk(sourceDir, func(path string, info os.FileInfo, err error) error { if err != nil { dh.sendProgress(ProcessResult{ Success: false, Message: fmt.Sprintf("访问路径出错: %v", err), Progress: 0, }) return err } fmt.Printf("正在处理: %s\n", path) // 处理 800x800 目录的逻辑 if info.IsDir() && strings.Contains(info.Name(), "800x800") { fmt.Printf("👍👍👍符合条件: %s\n", path) // 获取上级目录名称 parentDirName := filepath.Base(filepath.Dir(path)) // 在目标目录中创建以父目录命名的子目录 newTargetDir := filepath.Join(targetDir, parentDirName) // 检查目标目录,如果不存在则创建 if _, err := os.Stat(newTargetDir); os.IsNotExist(err) { // 源目录不存在时不需要创建目录,但目标目录可以创建 err := os.MkdirAll(newTargetDir, os.ModePerm) if err != nil { return fmt.Errorf("创建目标目录失败: %v", err) } } dh.sendProgress(ProcessResult{ Success: true, Message: fmt.Sprintf("找到目录: %s,将在目标目录创建子目录: %s", info.Name(), parentDirName), Progress: 50, }) // 执行复制操作到新创建的子目录 err := dh.copyFilesFromDir(path, newTargetDir) if err != nil { dh.sendProgress(ProcessResult{ Success: false, Message: fmt.Sprintf("复制文件到:%v 失败: %v", newTargetDir, err), Progress: 50, }) return err } } return nil }) // 发送完成进度 if err != nil { dh.sendProgress(ProcessResult{ Success: false, Message: fmt.Sprintf("处理失败: %v", err), Progress: 100, }) } else { dh.sendProgress(ProcessResult{ Success: true, Message: "处理完成", Progress: 100, }) } return err } // copyFilesFromDir 从指定目录复制所有文件到目标目录 func (dh *DirectoryHandler) copyFilesFromDir(sourceDir, targetDir string) error { entries, err := os.ReadDir(sourceDir) if err != nil { return fmt.Errorf("读取目录失败 %s: %v", sourceDir, err) } for _, entry := range entries { // 只处理文件,跳过子目录 if entry.IsDir() { continue // 忽略目录 } // 检查是否为有效的图片文件 if !dh.isValidImageFile(entry.Name()) { continue // 跳过非图片文件 } sourcePath := filepath.Join(sourceDir, entry.Name()) targetPath := filepath.Join(targetDir, entry.Name()) err := dh.copyFile(sourcePath, targetPath) if err != nil { return fmt.Errorf("复制文件失败 %s 到 %s: %v", sourcePath, targetPath, err) } } return nil } // copyFile 复制单个文件 func (dh *DirectoryHandler) copyFile(src, dst string) error { sourceFile, err := os.Open(src) if err != nil { return err } defer sourceFile.Close() // 创建目标文件 destFile, err := os.Create(dst) if err != nil { return err } defer destFile.Close() // 复制文件内容 _, err = io.Copy(destFile, sourceFile) if err != nil { return err } // 同步文件内容到磁盘 return destFile.Sync() } // isValidImageFile 检查文件是否为有效的图片文件 func (dh *DirectoryHandler) isValidImageFile(filename string) bool { validExtensions := []string{".avif", ".bmp", ".png", ".jpg", ".jpeg"} ext := strings.ToLower(filepath.Ext(filename)) for _, validExt := range validExtensions { if ext == validExt { return true } } return false } type ImageResult struct { GoodsArtNo string `json:"goods_art_no"` ImagePath string `json:"image_path"` Category string `json:"category"` Description string `json:"description"` Price string `json:"price"` ImageBase64 string `json:"image_base64"` } // sendProgress 发送进度更新 func (dh *DirectoryHandler) sendProgress(result ProcessResult) { runtime.EventsEmit(dh.ctx, "copy800-progress", result) } // HandlerOutPutDirectory 处理输出目录的主要方法 func (dh *DirectoryHandler) HandlerOutPutDirectory(sourceDir string) ([]ImageResult, error) { // 检查源目录是否存在 if _, err := os.Stat(sourceDir); os.IsNotExist(err) { return nil, fmt.Errorf("源目录不存在: %s", sourceDir) } var Results []ImageResult // 执行具体的处理逻辑 // 遍历和处理逻辑 err := filepath.Walk(sourceDir, func(path string, info os.FileInfo, err error) error { if err != nil { return err } fmt.Printf("正在处理: %s\n", path) // 处理 800x800 目录的逻辑 if info.IsDir() && strings.Contains(info.Name(), "800x800") { fmt.Printf("👍👍👍符合条件: %s\n", path) // 获取父目录名作为 goods_art_no parentDirName := filepath.Base(filepath.Dir(path)) goodsArtNo := parentDirName // 查找该目录下的第一张有效图片 imagePath, err := dh.findFirstImageInDir(path) if err == nil { toBase64, err := dh.ImageToBase64(imagePath) if err != nil { toBase64 = "" } // 添加到结果数组 Results = append(Results, ImageResult{ GoodsArtNo: goodsArtNo, ImagePath: imagePath, Description: "", Category: "", Price: "0", ImageBase64: toBase64, }) } } return nil }) if err != nil { return nil, err } return Results, nil } // findFirstImageInDir 查找目录下的第一张有效图片 func (dh *DirectoryHandler) findFirstImageInDir(dirPath string) (string, error) { entries, err := os.ReadDir(dirPath) if err != nil { return "", fmt.Errorf("读取目录失败: %v", err) } for _, entry := range entries { if entry.IsDir() { continue } if dh.isValidImageFile(entry.Name()) { return filepath.Join(dirPath, entry.Name()), nil } } return "", fmt.Errorf("未找到有效图片文件") } // ImageToBase64 将图片文件转换为Base64编码 func (dh *DirectoryHandler) ImageToBase64(imagePath string) (string, error) { // 读取图片文件 fileData, err := os.ReadFile(imagePath) if err != nil { return "", fmt.Errorf("读取图片文件失败: %v", err) } // 获取文件的MIME类型 mimeType := getMimeType(imagePath) // 将文件数据编码为Base64 encoded := base64.StdEncoding.EncodeToString(fileData) // 返回带有数据URI方案的Base64字符串 return fmt.Sprintf("data:%s;base64,%s", mimeType, encoded), nil } // getMimeType 根据文件扩展名获取MIME类型 func getMimeType(filePath string) string { ext := strings.ToLower(filePath[strings.LastIndex(filePath, "."):]) mimeTypes := map[string]string{ ".png": "image/png", ".jpg": "image/jpeg", ".jpeg": "image/jpeg", ".gif": "image/gif", ".bmp": "image/bmp", ".webp": "image/webp", } if mime, exists := mimeTypes[ext]; exists { return mime } return "application/octet-stream" } // GetCurrentWorkingDirectory 获取当前工作目录 func (dh *DirectoryHandler) GetCurrentWorkingDirectory() (string, error) { return os.Getwd() } // GetApplicationDirectory 获取应用程序所在目录 func (dh *DirectoryHandler) GetApplicationDirectory() (string, error) { execPath, err := os.Executable() if err != nil { return "", err } return filepath.Dir(execPath), nil }