diff --git a/kernel/cache/asset.go b/kernel/cache/asset.go index fc20c0891..fce48acdb 100644 --- a/kernel/cache/asset.go +++ b/kernel/cache/asset.go @@ -104,17 +104,53 @@ var ( assetsLock = sync.Mutex{} ) +// GetAssets 返回所有资源的副本 func GetAssets() (ret map[string]*Asset) { assetsLock.Lock() defer assetsLock.Unlock() - ret = map[string]*Asset{} + // 指定长度避免分配新内存时扩容和迁移 + ret = make(map[string]*Asset, len(assetsCache)) for k, v := range assetsCache { ret[k] = v } return } +// IterateAssets 遍历所有资源,适合只读场景 +func IterateAssets(fn func(path string, asset *Asset) bool) { + assetsLock.Lock() + defer assetsLock.Unlock() + + for path, asset := range assetsCache { + if !fn(path, asset) { + break + } + } +} + +// FilterAssets 根据过滤函数返回符合条件的资源 +func FilterAssets(filter func(path string, asset *Asset) bool) (ret map[string]*Asset) { + assetsLock.Lock() + defer assetsLock.Unlock() + + ret = make(map[string]*Asset) + for path, asset := range assetsCache { + if filter(path, asset) { + ret[path] = asset + } + } + return +} + +// GetAssetByPath 根据路径获取资源 +func GetAssetByPath(path string) *Asset { + assetsLock.Lock() + defer assetsLock.Unlock() + + return assetsCache[path] +} + func RemoveAsset(path string) { assetsLock.Lock() defer assetsLock.Unlock() diff --git a/kernel/model/assets.go b/kernel/model/assets.go index b17bf1374..deb07eb2b 100644 --- a/kernel/model/assets.go +++ b/kernel/model/assets.go @@ -448,7 +448,9 @@ func SearchAssetsByName(keyword string, exts []string) (ret []*cache.Asset) { } pathHitCount := map[string]int{} filterByExt := 0 < len(exts) - for _, asset := range cache.GetAssets() { + matchedAssets := cache.FilterAssets(func(path string, asset *cache.Asset) bool { + + // 扩展名过滤 if filterByExt { ext := filepath.Ext(asset.HName) includeExt := false @@ -459,10 +461,11 @@ func SearchAssetsByName(keyword string, exts []string) (ret []*cache.Asset) { } } if !includeExt { - continue + return false } } + // 关键字匹配 lowerHName := strings.ToLower(asset.HName) lowerPath := strings.ToLower(asset.Path) var hitNameCount, hitPathCount int @@ -485,13 +488,21 @@ func SearchAssetsByName(keyword string, exts []string) (ret []*cache.Asset) { } } + // 只返回有匹配的资源 if 1 > hitNameCount+hitPathCount { - continue + return false } - pathHitCount[asset.Path] += hitNameCount + hitPathCount + // 记录命中次数用于排序 + pathHitCount[asset.Path] = hitNameCount + hitPathCount + return true + }) + + // 添加高亮 + for _, asset := range matchedAssets { + hitCount := pathHitCount[asset.Path] hName := asset.HName - if 0 < hitNameCount { + if hitCount > 0 { _, hName = search.MarkText(asset.HName, strings.Join(keywords, search.TermSep), 64, Conf.Search.CaseSensitive) } ret = append(ret, &cache.Asset{ diff --git a/kernel/model/history.go b/kernel/model/history.go index b908101b7..fd5c68ace 100644 --- a/kernel/model/history.go +++ b/kernel/model/history.go @@ -770,15 +770,21 @@ func (box *Box) recentModifiedDocs() (ret []string) { var assetsLatestHistoryTime = time.Now().Unix() func recentModifiedAssets() (ret []string) { - assets := cache.GetAssets() - for _, asset := range assets { - if asset.Updated > assetsLatestHistoryTime { - absPath := filepath.Join(util.DataDir, asset.Path) - if filelock.IsHidden(absPath) { - continue - } - ret = append(ret, absPath) + // 只获取最近修改的资源 + recentAssets := cache.FilterAssets(func(path string, asset *cache.Asset) bool { + if asset.Updated <= assetsLatestHistoryTime { + return false } + absPath := filepath.Join(util.DataDir, asset.Path) + if filelock.IsHidden(absPath) { + return false + } + return true + }) + + for _, asset := range recentAssets { + absPath := filepath.Join(util.DataDir, asset.Path) + ret = append(ret, absPath) } assetsLatestHistoryTime = time.Now().Unix() return diff --git a/kernel/model/ocr.go b/kernel/model/ocr.go index 638c5ca6b..96c2e3f26 100644 --- a/kernel/model/ocr.go +++ b/kernel/model/ocr.go @@ -55,21 +55,18 @@ func autoOCRAssets() { } func getUnOCRAssetsAbsPaths() (ret []string) { - var assetsPaths []string - assets := cache.GetAssets() - for _, asset := range assets { - if !util.IsTesseractExtractable(asset.Path) { - continue - } - assetsPaths = append(assetsPaths, asset.Path) - } + // 只获取需要 OCR 的资源 + ocrAssets := cache.FilterAssets(func(path string, asset *cache.Asset) bool { + return util.IsTesseractExtractable(asset.Path) + }) assetsPath := util.GetDataAssetsAbsPath() - for _, assetPath := range assetsPaths { - if util.ExistsAssetText(assetPath) { + for _, asset := range ocrAssets { + // 跳过已经存在 OCR 文本的资源 + if util.ExistsAssetText(asset.Path) { continue } - absPath := filepath.Join(assetsPath, strings.TrimPrefix(assetPath, "assets")) + absPath := filepath.Join(assetsPath, strings.TrimPrefix(asset.Path, "assets")) ret = append(ret, absPath) } return