diff --git a/internal/common/helper.go b/internal/common/helper.go index 35d55ee..8be8312 100644 --- a/internal/common/helper.go +++ b/internal/common/helper.go @@ -11,7 +11,6 @@ import ( "path/filepath" "regexp" "strconv" - "sync" "metazone.cc/metalab/internal/model" @@ -19,81 +18,44 @@ import ( ) // assetHashes 静态资源文件哈希表(URL 路径 → 短哈希,文件不变哈希不变) -var ( - assetHashes map[string]string - assetOnce sync.Once -) +var assetHashes map[string]string -// ComputeAssetHashes 遍历 static 目录,计算每个文件的 CRC32作为版本号 +// ComputeAssetHashes 遍历 static 目录,计算每个文件的 CRC32 作为版本号 func ComputeAssetHashes(templateDir string) { assetHashes = make(map[string]string) - staticDir := filepath.Join(templateDir, "static") - filepath.WalkDir(staticDir, func(path string, d fs.DirEntry, err error) error { - if err != nil || d.IsDir() { - return nil - } - // 只处理 .js 和 .css - ext := filepath.Ext(path) - if ext != ".js" && ext != ".css" { - return nil - } - data, err := os.ReadFile(path) - if err != nil { - return nil - } - h := crc32.ChecksumIEEE(data) - shortHash := strconv.FormatUint(uint64(h), 16) - // 生成 URL 路径:/static/... - rel, _ := filepath.Rel(filepath.Dir(templateDir), path) - urlPath := "/" + filepath.ToSlash(rel) - assetHashes[urlPath] = shortHash - return nil - }) - // 也处理 shared/static 目录 - sharedDir := filepath.Join(filepath.Dir(templateDir), "shared", "static") - filepath.WalkDir(sharedDir, func(path string, d fs.DirEntry, err error) error { - if err != nil || d.IsDir() { - return nil - } - ext := filepath.Ext(path) - if ext != ".js" && ext != ".css" { - return nil - } - data, err := os.ReadFile(path) - if err != nil { - return nil - } - h := crc32.ChecksumIEEE(data) - shortHash := strconv.FormatUint(uint64(h), 16) - rel, _ := filepath.Rel(filepath.Dir(templateDir), path) - urlPath := "/" + filepath.ToSlash(rel) - assetHashes[urlPath] = shortHash - return nil - }) - // 也处理 admin/static 目录 - adminDir := filepath.Join(filepath.Dir(templateDir), "admin", "static") - filepath.WalkDir(adminDir, func(path string, d fs.DirEntry, err error) error { - if err != nil || d.IsDir() { - return nil - } - ext := filepath.Ext(path) - if ext != ".js" && ext != ".css" { - return nil - } - data, err := os.ReadFile(path) - if err != nil { - return nil - } - h := crc32.ChecksumIEEE(data) - shortHash := strconv.FormatUint(uint64(h), 16) - rel, _ := filepath.Rel(filepath.Dir(templateDir), path) - urlPath := "/" + filepath.ToSlash(rel) - assetHashes[urlPath] = shortHash - return nil - }) + // 前端主题:templates/MetaLab-2026/static → URL /static/ + walkStaticDir(filepath.Join(templateDir, "static"), "/static") + // 共享资源:templates/shared/static → URL /shared/static/ + walkStaticDir(filepath.Join(filepath.Dir(templateDir), "shared", "static"), "/shared/static") + // 管理后台:templates/admin/static → URL /admin/static/ + walkStaticDir(filepath.Join(filepath.Dir(templateDir), "admin", "static"), "/admin/static") log.Printf("[AssetHashes] computed %d file hashes", len(assetHashes)) } +// walkStaticDir 遍历目录,计算每个 .js/.css 的 CRC32,存入 assetHashes +func walkStaticDir(dir, urlPrefix string) { + filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error { + if err != nil || d.IsDir() { + return nil + } + ext := filepath.Ext(path) + if ext != ".js" && ext != ".css" { + return nil + } + data, err := os.ReadFile(path) + if err != nil { + return nil + } + h := crc32.ChecksumIEEE(data) + shortHash := strconv.FormatUint(uint64(h), 16) + // 生成 URL 路径:urlPrefix + 相对于 dir 的子路径 + rel, _ := filepath.Rel(dir, path) + urlPath := urlPrefix + "/" + filepath.ToSlash(rel) + assetHashes[urlPath] = shortHash + return nil + }) +} + // AssetV 返回指定静态资源的哈希版本号(模板函数) func AssetV(path string) string { if h, ok := assetHashes[path]; ok {