mirror of
https://github.com/hicccc77/WeFlow.git
synced 2026-03-25 15:25:50 +00:00
@@ -899,42 +899,71 @@ export class ImageDecryptService {
|
||||
}
|
||||
|
||||
private findCachedOutput(cacheKey: string, preferHd: boolean = false, sessionId?: string): string | null {
|
||||
const root = this.getCacheRoot()
|
||||
const allRoots = this.getAllCacheRoots()
|
||||
const normalizedKey = this.normalizeDatBase(cacheKey.toLowerCase())
|
||||
const extensions = ['.jpg', '.jpeg', '.png', '.gif', '.webp']
|
||||
|
||||
if (sessionId) {
|
||||
const sessionDir = join(root, this.sanitizeDirName(sessionId))
|
||||
if (existsSync(sessionDir)) {
|
||||
try {
|
||||
const sessionEntries = readdirSync(sessionDir)
|
||||
for (const entry of sessionEntries) {
|
||||
const timeDir = join(sessionDir, entry)
|
||||
if (!this.isDirectory(timeDir)) continue
|
||||
const hit = this.findCachedOutputInDir(timeDir, normalizedKey, extensions, preferHd)
|
||||
if (hit) return hit
|
||||
}
|
||||
} catch {
|
||||
// ignore
|
||||
// 遍历所有可能的缓存根路径
|
||||
for (const root of allRoots) {
|
||||
// 策略1: 新目录结构 Images/{sessionId}/{YYYY-MM}/{file}_hd.jpg
|
||||
if (sessionId) {
|
||||
const sessionDir = join(root, this.sanitizeDirName(sessionId))
|
||||
if (existsSync(sessionDir)) {
|
||||
try {
|
||||
const dateDirs = readdirSync(sessionDir, { withFileTypes: true })
|
||||
.filter(d => d.isDirectory() && /^\d{4}-\d{2}$/.test(d.name))
|
||||
.map(d => d.name)
|
||||
.sort()
|
||||
.reverse() // 最新的日期优先
|
||||
|
||||
for (const dateDir of dateDirs) {
|
||||
const imageDir = join(sessionDir, dateDir)
|
||||
const hit = this.findCachedOutputInDir(imageDir, normalizedKey, extensions, preferHd)
|
||||
if (hit) return hit
|
||||
}
|
||||
} catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 新目录结构: Images/{normalizedKey}/{normalizedKey}_thumb.jpg 或 _hd.jpg
|
||||
const imageDir = join(root, normalizedKey)
|
||||
if (existsSync(imageDir)) {
|
||||
const hit = this.findCachedOutputInDir(imageDir, normalizedKey, extensions, preferHd)
|
||||
if (hit) return hit
|
||||
}
|
||||
// 策略2: 遍历所有 sessionId 目录查找(如果没有指定 sessionId)
|
||||
try {
|
||||
const sessionDirs = readdirSync(root, { withFileTypes: true })
|
||||
.filter(d => d.isDirectory())
|
||||
.map(d => d.name)
|
||||
|
||||
// 兼容旧的平铺结构
|
||||
for (const ext of extensions) {
|
||||
const candidate = join(root, `${cacheKey}${ext}`)
|
||||
if (existsSync(candidate)) return candidate
|
||||
}
|
||||
for (const ext of extensions) {
|
||||
const candidate = join(root, `${cacheKey}_t${ext}`)
|
||||
if (existsSync(candidate)) return candidate
|
||||
for (const session of sessionDirs) {
|
||||
const sessionDir = join(root, session)
|
||||
// 检查是否是日期目录结构
|
||||
try {
|
||||
const subDirs = readdirSync(sessionDir, { withFileTypes: true })
|
||||
.filter(d => d.isDirectory() && /^\d{4}-\d{2}$/.test(d.name))
|
||||
.map(d => d.name)
|
||||
|
||||
for (const dateDir of subDirs) {
|
||||
const imageDir = join(sessionDir, dateDir)
|
||||
const hit = this.findCachedOutputInDir(imageDir, normalizedKey, extensions, preferHd)
|
||||
if (hit) return hit
|
||||
}
|
||||
} catch { }
|
||||
}
|
||||
} catch { }
|
||||
|
||||
// 策略3: 旧目录结构 Images/{normalizedKey}/{normalizedKey}_thumb.jpg
|
||||
const oldImageDir = join(root, normalizedKey)
|
||||
if (existsSync(oldImageDir)) {
|
||||
const hit = this.findCachedOutputInDir(oldImageDir, normalizedKey, extensions, preferHd)
|
||||
if (hit) return hit
|
||||
}
|
||||
|
||||
// 策略4: 最旧的平铺结构 Images/{file}.jpg
|
||||
for (const ext of extensions) {
|
||||
const candidate = join(root, `${cacheKey}${ext}`)
|
||||
if (existsSync(candidate)) return candidate
|
||||
}
|
||||
for (const ext of extensions) {
|
||||
const candidate = join(root, `${cacheKey}_t${ext}`)
|
||||
if (existsSync(candidate)) return candidate
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
@@ -1104,15 +1133,19 @@ export class ImageDecryptService {
|
||||
if (this.cacheIndexed) return
|
||||
if (this.cacheIndexing) return this.cacheIndexing
|
||||
this.cacheIndexing = new Promise((resolve) => {
|
||||
const root = this.getCacheRoot()
|
||||
try {
|
||||
this.indexCacheDir(root, 2, 0)
|
||||
} catch {
|
||||
this.cacheIndexed = true
|
||||
this.cacheIndexing = null
|
||||
resolve()
|
||||
return
|
||||
// 扫描所有可能的缓存根目录
|
||||
const allRoots = this.getAllCacheRoots()
|
||||
this.logInfo('开始索引缓存', { roots: allRoots.length })
|
||||
|
||||
for (const root of allRoots) {
|
||||
try {
|
||||
this.indexCacheDir(root, 3, 0) // 增加深度到3,支持 sessionId/YYYY-MM 结构
|
||||
} catch (e) {
|
||||
this.logError('索引目录失败', e, { root })
|
||||
}
|
||||
}
|
||||
|
||||
this.logInfo('缓存索引完成', { entries: this.resolvedCache.size })
|
||||
this.cacheIndexed = true
|
||||
this.cacheIndexing = null
|
||||
resolve()
|
||||
@@ -1120,6 +1153,39 @@ export class ImageDecryptService {
|
||||
return this.cacheIndexing
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有可能的缓存根路径(用于查找已缓存的图片)
|
||||
* 包含当前路径、配置路径、旧版本路径
|
||||
*/
|
||||
private getAllCacheRoots(): string[] {
|
||||
const roots: string[] = []
|
||||
const configured = this.configService.get('cachePath')
|
||||
const documentsPath = app.getPath('documents')
|
||||
|
||||
// 主要路径(当前使用的)
|
||||
const mainRoot = this.getCacheRoot()
|
||||
roots.push(mainRoot)
|
||||
|
||||
// 如果配置了自定义路径,也检查其下的 Images
|
||||
if (configured) {
|
||||
roots.push(join(configured, 'Images'))
|
||||
roots.push(join(configured, 'images'))
|
||||
}
|
||||
|
||||
// 默认路径
|
||||
roots.push(join(documentsPath, 'WeFlow', 'Images'))
|
||||
roots.push(join(documentsPath, 'WeFlow', 'images'))
|
||||
|
||||
// 兼容旧路径(如果有的话)
|
||||
roots.push(join(documentsPath, 'WeFlowData', 'Images'))
|
||||
|
||||
// 去重并过滤存在的路径
|
||||
const uniqueRoots = Array.from(new Set(roots))
|
||||
const existingRoots = uniqueRoots.filter(r => existsSync(r))
|
||||
|
||||
return existingRoots
|
||||
}
|
||||
|
||||
private indexCacheDir(root: string, maxDepth: number, depth: number): void {
|
||||
let entries: string[]
|
||||
try {
|
||||
|
||||
@@ -247,10 +247,33 @@ export class WcdbCore {
|
||||
// InitProtection (Added for security)
|
||||
try {
|
||||
this.wcdbInitProtection = this.lib.func('bool InitProtection(const char* resourcePath)')
|
||||
const protectionOk = this.wcdbInitProtection(dllDir)
|
||||
|
||||
// 尝试多个可能的资源路径
|
||||
const resourcePaths = [
|
||||
dllDir, // DLL 所在目录
|
||||
dirname(dllDir), // 上级目录
|
||||
this.resourcesPath, // 配置的资源路径
|
||||
join(process.cwd(), 'resources') // 开发环境
|
||||
].filter(Boolean)
|
||||
|
||||
let protectionOk = false
|
||||
for (const resPath of resourcePaths) {
|
||||
try {
|
||||
console.log(`[WCDB] 尝试 InitProtection: ${resPath}`)
|
||||
protectionOk = this.wcdbInitProtection(resPath)
|
||||
if (protectionOk) {
|
||||
console.log(`[WCDB] InitProtection 成功: ${resPath}`)
|
||||
break
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn(`[WCDB] InitProtection 失败 (${resPath}):`, e)
|
||||
}
|
||||
}
|
||||
|
||||
if (!protectionOk) {
|
||||
console.error('Core security check failed')
|
||||
return false
|
||||
console.warn('[WCDB] Core security check failed - 继续运行但可能不稳定')
|
||||
this.writeLog('InitProtection 失败,继续运行')
|
||||
// 不返回 false,允许继续运行
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('InitProtection symbol not found:', e)
|
||||
|
||||
2
package-lock.json
generated
2
package-lock.json
generated
@@ -6,7 +6,7 @@
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "weflow",
|
||||
"version": "1.4.0",
|
||||
"version": "1.4.1",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"better-sqlite3": "^12.5.0",
|
||||
|
||||
Reference in New Issue
Block a user