| 304 | * @returns 在当前路径上有效的 TopicGroup 列表 |
| 305 | */ |
| 306 | export function computeTopicGroups(topics: Topic[], currentPath: ChatMessage[]): TopicGroup[] { |
| 307 | if (currentPath.length === 0 || topics.length === 0) return [] |
| 308 | |
| 309 | // 构建消息 ID 到索引的映射 |
| 310 | const messageIndexMap = new Map<string, number>() |
| 311 | for (let i = 0; i < currentPath.length; i++) { |
| 312 | messageIndexMap.set(currentPath[i].id, i) |
| 313 | } |
| 314 | |
| 315 | // 筛选出 startMessageId 在当前路径上的 Topics,并按路径顺序排序 |
| 316 | const validTopics = topics |
| 317 | .filter((t) => messageIndexMap.has(t.startMessageId)) |
| 318 | .map((t) => ({ |
| 319 | topic: t, |
| 320 | startIndex: messageIndexMap.get(t.startMessageId)! |
| 321 | })) |
| 322 | .sort((a, b) => a.startIndex - b.startIndex) |
| 323 | |
| 324 | if (validTopics.length === 0) return [] |
| 325 | |
| 326 | const groups: TopicGroup[] = [] |
| 327 | |
| 328 | for (let i = 0; i < validTopics.length; i++) { |
| 329 | const { topic, startIndex } = validTopics[i] |
| 330 | let endIndex: number |
| 331 | |
| 332 | if (topic.endMessageId && messageIndexMap.has(topic.endMessageId)) { |
| 333 | // 有明确的 endMessageId 且在路径上 |
| 334 | endIndex = messageIndexMap.get(topic.endMessageId)! |
| 335 | } else { |
| 336 | // 找下一个 Topic 作为结束边界 |
| 337 | if (i + 1 < validTopics.length) { |
| 338 | endIndex = validTopics[i + 1].startIndex - 1 |
| 339 | } else { |
| 340 | endIndex = currentPath.length - 1 // 默认到末尾 |
| 341 | } |
| 342 | } |
| 343 | |
| 344 | // 确保 endIndex >= startIndex |
| 345 | endIndex = Math.max(startIndex, endIndex) |
| 346 | |
| 347 | // 收集消息 ID |
| 348 | const messageIds: string[] = [] |
| 349 | for (let k = startIndex; k <= endIndex; k++) { |
| 350 | messageIds.push(currentPath[k].id) |
| 351 | } |
| 352 | |
| 353 | groups.push({ |
| 354 | topicId: topic.id, |
| 355 | startMessageId: topic.startMessageId, |
| 356 | endMessageId: currentPath[endIndex].id, |
| 357 | name: topic.name, |
| 358 | messageIds, |
| 359 | collapsed: topic.collapsed |
| 360 | }) |
| 361 | } |
| 362 | |
| 363 | return groups |