Merge pull request #96 from ILoveBingLu/wdev

fix: 修复 issue #92 中的 4 个 bug
This commit is contained in:
BingLu
2026-03-21 03:55:13 +08:00
committed by GitHub
3 changed files with 54 additions and 9 deletions
+35 -5
View File
@@ -301,13 +301,24 @@ class ExportService {
const tables = db.prepare(
"SELECT name FROM sqlite_master WHERE type='table' AND name LIKE 'Msg_%'"
).all() as any[]
const hash = this.getTableNameHash(sessionId)
const hash = this.getTableNameHash(sessionId).toLowerCase()
// 1. 精确哈希提取匹配(大小写无关):从表名中提取 32 位 hex 片段后比对
for (const table of tables) {
if ((table.name as string).includes(hash)) {
return table.name
const name = table.name as string
const hexMatch = name.match(/[0-9a-fA-F]{32}/)
if (hexMatch && hexMatch[0].toLowerCase() === hash) {
return name
}
}
// 2. 包含匹配(大小写无关)
for (const table of tables) {
const name = table.name as string
if (name.toLowerCase().includes(hash)) {
return name
}
}
} catch { }
// 匹配失败时返回 null,不回退到第一个表(避免数据串)
return null
}
@@ -1137,6 +1148,9 @@ class ExportService {
const fileext = this.extractXmlValue(body, 'fileext')
const datasize = parseInt(this.extractXmlValue(body, 'datasize') || '0')
// 过滤红包(2001)和群收款(2002)消息,不在导出中显示
if (datatype === 2001 || datatype === 2002) continue
items.push({
datatype,
sourcename,
@@ -1168,6 +1182,15 @@ class ExportService {
.replace(/"/g, '"')
.replace(/'/g, "'")
.replace(/'/g, "'")
// 常见十六进制数字实体
.replace(/ /gi, ' ')
.replace(/
/gi, '\n')
.replace(/	/gi, '\t')
.replace(/
/gi, '\r')
// 通用十六进制实体 &#xHH;
.replace(/&#x([0-9a-fA-F]+);/g, (_, hex) => String.fromCodePoint(parseInt(hex, 16)))
// 通用十进制实体 &#NN;
.replace(/&#(\d+);/g, (_, dec) => String.fromCodePoint(parseInt(dec, 10)))
}
/**
@@ -1230,11 +1253,18 @@ class ExportService {
content = record.datadesc || record.datatitle || '[消息]'
}
// 对关键字段进行 HTML 实体解码,防止导出时出现   等转义字符
content = this.decodeHtmlEntities(content)
const senderDisplayName = this.decodeHtmlEntities(record.sourcename || 'unknown')
const formattedTime = this.decodeHtmlEntities(
timestamp > 0 ? this.formatTimestamp(timestamp) : (record.sourcetime || '')
)
const chatRecord: any = {
sender: record.sourcename || 'unknown',
senderDisplayName: record.sourcename || 'unknown',
senderDisplayName,
timestamp,
formattedTime: timestamp > 0 ? this.formatTimestamp(timestamp) : record.sourcetime,
formattedTime,
type: typeName,
datatype: record.datatype,
content
+10 -1
View File
@@ -878,10 +878,19 @@ body {
return 'c' + (Math.abs(hash) % 8);
}
// HTML 实体解码(防止导出数据中残留   等转义字符)
function decodeEntities(text) {
if (!text) return '';
const d = document.createElement('textarea');
d.innerHTML = text;
return d.value;
}
// HTML 转义
function esc(text) {
const decoded = decodeEntities(String(text || ''));
const d = document.createElement('div');
d.textContent = text;
d.textContent = decoded;
return d.innerHTML;
}
+9 -3
View File
@@ -747,6 +747,12 @@ function MomentsWindow() {
const [isLoading, setIsLoading] = useState(true)
const [loadingNewer, setLoadingNewer] = useState(false)
const [posts, setPosts] = useState<SnsPost[]>([])
const postsRef = useRef<SnsPost[]>([])
// 同步 postsRef 与 posts state
useEffect(() => {
postsRef.current = posts
}, [posts])
const [deletedPostIds, setDeletedPostIds] = useState<Set<string>>(new Set())
const [error, setError] = useState<string | null>(null)
@@ -877,7 +883,7 @@ function MomentsWindow() {
}
currentOffset = 0
} else if (direction === 'newer') {
const topPost = posts[0]
const topPost = postsRef.current[0]
if (topPost) {
startTs = topPost.createTime + 1
}
@@ -885,7 +891,7 @@ function MomentsWindow() {
endTs = undefined // Ensure endTs is cleared for newer posts check
} else {
// Load older
currentOffset = posts.length
currentOffset = postsRef.current.length
// Maintain jumpTargetDate filter if active
if (jumpTargetDate) {
@@ -946,7 +952,7 @@ function MomentsWindow() {
setLoadingNewer(false)
loadingRef.current = false
}
}, [posts, selectedUsernames, searchKeyword, jumpTargetDate])
}, [selectedUsernames, searchKeyword, jumpTargetDate])
// 监听筛选条件变化,自动重置加载
useEffect(() => {