fix: 优化 Windows 启动性能与聊天图片缓存

- 增加聊天图片磁盘持久化缓存,重启后直接复用
- 将 DAT 图片解密移至 Worker,避免阻塞主进程
- 增加图片加载优先级和并发控制
- 优化会话目录与图片文件的异步查找
- 使用本地媒体协议加载缓存图片,减少 Base64 IPC 开销
- 优化启动缓存与数据库初始化流程,降低窗口未响应时间

(cherry picked from commit 82bcc8d32ca674de38c745cc9925ed2309887dc7)
This commit is contained in:
电摇小子
2026-08-03 10:03:19 +08:00
committed by Wxw-Gu
parent 8a6d443acc
commit a3955d691d
10 changed files with 1615 additions and 362 deletions
+29 -7
View File
@@ -10,6 +10,7 @@ type VideoAsset = {
export class VideoAssetService {
private readonly urlTokens = new Map<string, string>()
private readonly fileTokens = new Map<string, string>()
private index: Map<string, VideoAsset> | null = null
constructor(private readonly client: Wcdb4Client) {}
@@ -48,8 +49,8 @@ export class VideoAssetService {
if (!asset) continue
return {
success: true,
url: this.createUrl(asset.filePath),
poster: asset.posterPath ? this.createUrl(asset.posterPath) : undefined
url: this.createLocalMediaUrl(asset.filePath),
poster: asset.posterPath ? this.createLocalMediaUrl(asset.posterPath) : undefined
}
}
return { success: false, error: '本地未找到该视频文件' }
@@ -61,12 +62,33 @@ export class VideoAssetService {
return filePath
}
private createUrl(filePath: string): string {
pathForUrl(url: string): string | undefined {
try {
const parsed = new URL(url)
if (parsed.protocol !== 'wxe-media:' || parsed.hostname !== 'local') return undefined
return this.pathForToken(parsed.pathname.replace(/^\/+/, ''))
} catch {
return undefined
}
}
createLocalMediaUrl(filePath: string): string {
const normalizedPath = path.resolve(filePath)
const existingToken = this.fileTokens.get(normalizedPath)
if (existingToken && this.urlTokens.get(existingToken) === normalizedPath) {
return `wxe-media://local/${existingToken}`
}
const token = crypto.randomBytes(18).toString('hex')
this.urlTokens.set(token, filePath)
if (this.urlTokens.size > 500) {
const first = this.urlTokens.keys().next().value
if (first) this.urlTokens.delete(first)
this.urlTokens.set(token, normalizedPath)
this.fileTokens.set(normalizedPath, token)
if (this.urlTokens.size > 2048) {
const oldestToken = this.urlTokens.keys().next().value
if (oldestToken) {
const oldestPath = this.urlTokens.get(oldestToken)
this.urlTokens.delete(oldestToken)
if (oldestPath) this.fileTokens.delete(oldestPath)
}
}
return `wxe-media://local/${token}`
}