File size: 4,546 Bytes
9e40388
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
// 音乐图片URL缓存管理器
class UrlCacheManager {
  constructor() {
    this.cache = new Map()
    this.maxCacheSize = 1000 // 上限1000个
    this.storageKey = 'music-url-cache-v1'
    this.cacheExpiry = 7 * 24 * 60 * 60 * 1000 // 7天过期
    this.loadFromStorage()
  }

  /**
   * 生成缓存键
   * @param {string} source - 音乐源 
   * @param {string} id - 歌曲或图片ID
   * @param {string} br - 比特率或尺寸
   * @returns {string} 缓存键
   */
  getCacheKey(source, id, br) {
    return `${source}+${id}+${br}`
  }

  /**
   * 获取缓存的URL
   * @param {string} source - 音乐源
   * @param {string} id - 歌曲或图片ID  
   * @param {string} br - 比特率或尺寸
   * @returns {string|null} 缓存的URL,如果不存在返回null
   */
  getCachedUrl(source, id, br) {
    if (!source || !id) return null
    
    const key = this.getCacheKey(source, id, br)
    const cached = this.cache.get(key)
    
    if (cached) {
      // 检查是否过期
      if (Date.now() - cached.timestamp < this.cacheExpiry) {
        return cached.url
      } else {
        // 过期删除
        this.cache.delete(key)
        this.saveToStorage()
      }
    }
    
    return null
  }

  /**
   * 设置缓存URL
   * @param {string} source - 音乐源
   * @param {string} id - 歌曲或图片ID
   * @param {string} br - 比特率或尺寸  
   * @param {string} url - 要缓存的URL
   */
  setCachedUrl(source, id, br, url) {
    if (!source || !id || !url) return
    
    const key = this.getCacheKey(source, id, br)
    
    // 如果缓存已满,删除最旧的条目
    if (this.cache.size >= this.maxCacheSize) {
      this.evictOldest()
    }
    
    this.cache.set(key, {
      url,
      timestamp: Date.now()
    })
    
    this.saveToStorage()
  }

  /**
   * 删除最旧的缓存条目
   */
  evictOldest() {
    let oldestKey = null
    let oldestTime = Date.now()
    
    for (const [key, value] of this.cache.entries()) {
      if (value.timestamp < oldestTime) {
        oldestTime = value.timestamp
        oldestKey = key
      }
    }
    
    if (oldestKey) {
      this.cache.delete(oldestKey)
    }
  }

  /**
   * 清理过期的缓存条目
   */
  cleanExpired() {
    const now = Date.now()
    const expiredKeys = []
    
    for (const [key, value] of this.cache.entries()) {
      if (now - value.timestamp > this.cacheExpiry) {
        expiredKeys.push(key)
      }
    }
    
    expiredKeys.forEach(key => this.cache.delete(key))
    
    if (expiredKeys.length > 0) {
      this.saveToStorage()
    }
  }

  /**
   * 从localStorage加载缓存
   */
  loadFromStorage() {
    try {
      const saved = localStorage.getItem(this.storageKey)
      if (saved) {
        const data = JSON.parse(saved)
        if (data && Array.isArray(data.entries)) {
          // 恢复Map数据,同时清理过期条目
          const now = Date.now()
          data.entries.forEach(([key, value]) => {
            if (now - value.timestamp < this.cacheExpiry) {
              this.cache.set(key, value)
            }
          })
        }
      }
    } catch (error) {
      console.error('加载URL缓存失败:', error)
      this.cache.clear()
    }
  }

  /**
   * 保存缓存到localStorage
   */
  saveToStorage() {
    try {
      const data = {
        entries: Array.from(this.cache.entries()),
        timestamp: Date.now()
      }
      localStorage.setItem(this.storageKey, JSON.stringify(data))
    } catch (error) {
      console.error('保存URL缓存失败:', error)
      // 如果保存失败(可能是空间不足),清理一些旧缓存
      this.evictOldest()
      try {
        const data = {
          entries: Array.from(this.cache.entries()),
          timestamp: Date.now()
        }
        localStorage.setItem(this.storageKey, JSON.stringify(data))
      } catch (e) {
        console.warn('URL缓存保存最终失败:', e)
      }
    }
  }

  /**
   * 清空所有缓存
   */
  clear() {
    this.cache.clear()
    localStorage.removeItem(this.storageKey)
  }

  /**
   * 获取缓存统计信息
   */
  getStats() {
    return {
      size: this.cache.size,
      maxSize: this.maxCacheSize,
      utilization: (this.cache.size / this.maxCacheSize * 100).toFixed(1) + '%'
    }
  }
}

// 创建全局实例
export const urlCacheManager = new UrlCacheManager()

// 启动定期清理过期缓存(每小时清理一次)
setInterval(() => {
  urlCacheManager.cleanExpired()
}, 60 * 60 * 1000)

export default urlCacheManager