refactor(useTalkRecord): 简化消息比较逻辑,改为全量检查

根据用户建议,只比较msg_id和is_revoke字段,并改为全量检查所有消息。因为消息ID是唯一的,且一次只有30条消息,全量检查不会带来太大性能负担。
This commit is contained in:
Phoenix 2025-07-03 14:13:09 +08:00
parent 0b8de6f5c2
commit c3abd733ad

View File

@ -224,91 +224,38 @@ export const useTalkRecord = (uid: number) => {
// 如果首尾消息ID存在于服务器数据中进行详细比较 // 如果首尾消息ID存在于服务器数据中进行详细比较
if (firstServerIdx !== undefined && lastServerIdx !== undefined) { if (firstServerIdx !== undefined && lastServerIdx !== undefined) {
const criticalFields = ['is_revoke', 'is_read', 'is_mark'] // 根据用户建议只比较msg_id和is_revoke字段
// 因为消息ID是唯一的内容变化主要是由撤回操作引起的
// 比较首尾消息的关键字段
const compareMessage = (localMsg, serverMsg) => { const compareMessage = (localMsg, serverMsg) => {
// 比较基本字段 // 消息ID已在外部比较过这里只需检查is_revoke状态
for (const field of criticalFields) { return localMsg.is_revoke === serverMsg.is_revoke
if (localMsg[field] !== serverMsg[field]) {
return false
}
}
// 特殊处理content字段它在extra对象中
const localContent = localMsg.extra?.content
const serverContent = serverMsg.extra?.content
if (localContent !== serverContent) {
return false
}
return true
} }
const firstMatch = compareMessage(firstLocalMsg, items[firstServerIdx]) const firstMatch = compareMessage(firstLocalMsg, items[firstServerIdx])
const lastMatch = compareMessage(lastLocalMsg, items[lastServerIdx]) const lastMatch = compareMessage(lastLocalMsg, items[lastServerIdx])
// 如果首尾消息匹配,使用抽样检查中间消息 // 如果首尾消息匹配,进行全量检查所有消息
if (firstMatch && lastMatch) { if (firstMatch && lastMatch) {
// 智能抽样检查策略 // 全量检查策略:检查所有消息
// 1. 检查首尾消息(已完成) // 由于一次只有30条消息全量检查不会带来太大的性能负担
// 2. 检查中间点消息
// 3. 检查最近修改的消息(通常是最新的几条)
// 4. 随机抽样检查
let allMatch = true let allMatch = true
// 中间点检查 // 遍历所有本地消息,与服务器消息进行比较
const midIndex = Math.floor(localMessages.length / 2) for (let i = 0; i < localMessages.length; i++) {
const midMsg = localMessages[midIndex] const localMsg = localMessages[i]
const midServerIdx = serverMsgMap.get(midMsg.msg_id) const serverIdx = serverMsgMap.get(localMsg.msg_id)
if (midServerIdx === undefined || !compareMessage(midMsg, items[midServerIdx])) { // 如果消息ID不存在于服务器数据中或者消息内容不匹配
if (serverIdx === undefined || !compareMessage(localMsg, items[serverIdx])) {
allMatch = false allMatch = false
} console.log(`消息不匹配,索引: ${i}, 消息ID: ${localMsg.msg_id}`)
break // 一旦发现不匹配,立即退出循环
// 最近消息检查检查最新的3条消息通常是最可能被修改的
if (allMatch && localMessages.length >= 4) {
for (let i = 1; i <= 3; i++) {
const recentMsg = localMessages[localMessages.length - i]
const recentServerIdx = serverMsgMap.get(recentMsg.msg_id)
if (recentServerIdx === undefined || !compareMessage(recentMsg, items[recentServerIdx])) {
allMatch = false
break
}
}
}
// 随机抽样检查(如果前面的检查都通过)
if (allMatch && localMessages.length > 10) {
// 随机选择5%的消息或至少2条进行检查
const sampleSize = Math.max(2, Math.floor(localMessages.length * 0.05))
const usedIndices = new Set([0, midIndex, localMessages.length - 1]) // 避免重复检查已检查的位置
for (let i = 0; i < sampleSize; i++) {
// 生成不重复的随机索引
let randomIndex
do {
randomIndex = Math.floor(Math.random() * localMessages.length)
} while (usedIndices.has(randomIndex))
usedIndices.add(randomIndex)
const randomMsg = localMessages[randomIndex]
const randomServerIdx = serverMsgMap.get(randomMsg.msg_id)
if (randomServerIdx === undefined || !compareMessage(randomMsg, items[randomServerIdx])) {
allMatch = false
break
}
} }
} }
if (allMatch) { if (allMatch) {
const compareEndTime = performance.now() const compareEndTime = performance.now()
console.log(`本地数据与服务器数据一致(抽样检查无需更新UI比较耗时: ${(compareEndTime - compareStartTime).toFixed(2)}ms`) console.log(`本地数据与服务器数据一致全量检查无需更新UI比较耗时: ${(compareEndTime - compareStartTime).toFixed(2)}ms`)
return return
} }
} }