Private
Public Access
1
0
Files
u-desk/internal/filesystem/zip_helper.go
绝尘 f7d648ea52 新增:文件系统导航面包屑
功能:
- 新增 PathBreadcrumb 组件,支持路径快速跳转
- 新增 DropdownItem 通用下拉菜单组件

优化:
- 版本升级流程优化(Pinia 状态管理、进度节流、完整下载验证)
- 模块延迟初始化(数据库、文件系统按需启动)
- API 数据格式统一(蛇形转驼峰)
- CodeMirror 语言包按需动态加载
- Markdown 渲染增强(支持锚点跳转)

重构:
- 迁移到 Pinia 状态管理(stores/config.ts、stores/theme.ts、stores/update.ts)
- 简化 UpdatePanel、UpdateNotification、ThemeToggle 逻辑
- 优化表结构加载逻辑

清理:
- 删除测试组件 index-simple.vue
- 删除旧的 useTheme.ts
2026-02-05 00:17:32 +08:00

122 lines
3.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package filesystem
import (
"archive/zip"
"fmt"
"io"
"path/filepath"
)
// ZipOperation ZIP操作回调函数类型
// 用于 withZipReader 通用包装器
type ZipOperation func(*zip.ReadCloser) (interface{}, error)
// withZipReader 通用的ZIP文件操作包装器
// 消除重复的打开/关闭逻辑,统一错误处理
// 参数:
// - zipPath: ZIP文件路径
// - operation: 操作回调函数,接收 *zip.ReadCloser返回任意结果
//
// 返回:
// - interface{}: 操作结果
// - error: 错误信息
func withZipReader(zipPath string, operation ZipOperation) (interface{}, error) {
// 1. 统一验证路径
if err := validateZipPath(zipPath); err != nil {
return nil, err
}
// 2. 打开 ZIP 文件
reader, err := zip.OpenReader(zipPath)
if err != nil {
return nil, fmt.Errorf("打开 zip 文件失败: %v", err)
}
defer reader.Close()
// 3. 执行操作
result, err := operation(reader)
if err != nil {
return nil, err
}
return result, nil
}
// withZipFile 在ZIP文件中查找特定文件并执行操作
// 进一步封装,用于处理单个文件的操作
type ZipFileOperation func(*zip.File) (interface{}, error)
// withZipFile 在ZIP中查找文件并执行操作
func withZipFile(zipPath, filePath string, operation ZipFileOperation) (interface{}, error) {
return withZipReader(zipPath, func(reader *zip.ReadCloser) (interface{}, error) {
// 查找目标文件
for _, file := range reader.File {
if isMatchFile(file, filePath) {
return operation(file)
}
}
return nil, fmt.Errorf("文件在 zip 中不存在: %s", filePath)
})
}
// isMatchFile 检查文件是否匹配目标路径
func isMatchFile(file *zip.File, targetPath string) bool {
return file.Name == targetPath ||
filepath.Clean(file.Name) == filepath.Clean(targetPath)
}
// openZipFileInReader 在ZIP reader中打开指定文件
// 用于读取文件内容的辅助函数
func openZipFileInReader(reader *zip.ReadCloser, filePath string) (io.ReadCloser, *zip.File, error) {
for _, file := range reader.File {
if isMatchFile(file, filePath) {
if file.Mode().IsDir() {
return nil, nil, fmt.Errorf("不能读取目录")
}
rc, err := file.Open()
if err != nil {
return nil, nil, fmt.Errorf("打开 zip 中的文件失败: %v", err)
}
return rc, file, nil
}
}
return nil, nil, fmt.Errorf("文件在 zip 中不存在: %s", filePath)
}
// readAllFromFile 从文件读取所有内容
// 辅助函数,避免重复的 io.ReadAll 调用
func readAllFromFile(rc io.ReadCloser) ([]byte, error) {
defer rc.Close()
return io.ReadAll(rc)
}
// getCompressionMethodString 获取压缩方法字符串描述
func getCompressionMethodString(method uint16) string {
if method == 8 {
return "Deflate"
}
return "Store"
}
// createFileInfoMap 创建文件信息map通用格式
func createFileInfoMap(file *zip.File, includeExtra ...bool) map[string]interface{} {
info := map[string]interface{}{
"name": filepath.Base(file.Name),
"path": file.Name, // zip 中的路径(已使用 /
"is_dir": file.Mode().IsDir(),
"size": file.UncompressedSize64,
"compressed": file.CompressedSize64,
"mod_time": file.Modified.Format("2006-01-02 15:04:05"),
"method": getCompressionMethodString(file.Method),
}
// 可选:额外信息
if len(includeExtra) > 0 && includeExtra[0] {
info["mode"] = file.Mode().String()
info["comment"] = file.Comment
}
return info
}