fix: 排序作用于组内事件+时间线限高滚动+UTM别名归一消冲突误报

- attribution.py:新增 _canon 归一(小写/去协议与域名后缀/别名表 fb→facebook、百度→baidu 等/仅留字母数字汉字),
  冲突判定改为两路各自归一后比较——同源升级 combined 并在 detail 记 utm_source 原文,仍不同才 conflict
- detail.vue:orderedDays 组内会话/事件同步翻转(desc=组与组内都最新在前,asc=都最早在前);
  .tl-body 限高 calc(100vh - 380px) 卡内滚动,日期组头随内容滚动
- test_attribution.py:+4 用例(fb↔facebook、chatgpt.com↔ChatGPT、google↔facebook 仍冲突、百度↔baidu)

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
浅念
2026-09-16 18:39:02 +08:00
parent 50faa73cf9
commit 7f2a746f66
3 changed files with 70 additions and 6 deletions
+15 -5
View File
@@ -90,7 +90,7 @@
<ElRadioButton :value="30">近 30 天</ElRadioButton>
<ElRadioButton :value="90">近 90 天</ElRadioButton>
</ElRadioGroup>
<!-- 正序/倒序真实切换:倒序=日期组最新在前;正序=整体按时间正序 -->
<!-- 正序/倒序真实切换:倒序=日期组与组内事件都最新在前;正序=都最早在前 -->
<div class="vd-order-toggle" role="group" aria-label="时间线排序">
<button
type="button"
@@ -640,7 +640,7 @@
// ---------- 跨天时间线 ----------
const activeTab = ref<'sessions' | 'raw'>('sessions')
const days = ref(30)
/** 排序:desc=日期组最新在前(现行为);asc=整体按时间正序(最早日期组在前) */
/** 排序:desc=日期组最新在前+组内事件最新在前;asc=都最早在前 */
const order = ref<'desc' | 'asc'>('desc')
const timeline = ref<TimelineResp | null>(null)
const timelineLoading = ref(false)
@@ -662,10 +662,17 @@
}
}
/** 展示用日期组:倒序原样(后端倒序),正序整体翻转 */
/** 展示用日期组:后端=日期组倒序+组内正序,前端按口径组装(浅拷贝,不动原数据)。
* desc=日期组最新在前+组内(会话/事件)最新在前;asc=日期组最早在前+组内最早在前 */
const orderedDays = computed<TimelineDay[]>(() => {
const list = timeline.value?.days ?? []
return order.value === 'desc' ? list : [...list].reverse()
if (order.value === 'asc') return [...list].reverse()
return list.map((day) => ({
...day,
sessions: [...day.sessions]
.reverse()
.map((s) => ({ ...s, events: [...s.events].reverse() }))
}))
})
/** ISO 日期(YYYY-MM-DD)→ 「09月16日」 */
@@ -1113,8 +1120,11 @@
padding-bottom: 12px;
}
// 时间线滚动容器:长轨迹卡内滚动(日期组头随内容滚动,不做 sticky)
.tl-body {
min-height: 200px;
max-height: calc(100vh - 380px);
min-height: 320px;
overflow-y: auto;
padding: 4px 20px 8px;
}