fix: 修复静态资源哈希 key 与模板 URL 路径不匹配导致版本号全为 0

- 重构 walkStaticDir 统一处理三个 static 目录
- URL key 基于文件相对于 static 目录的路径,不含主题目录名
This commit is contained in:
2026-05-31 02:16:54 +08:00
parent eabceecaae
commit 09a9394c30

View File

@ -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 {