Files
fangke/docs/superpowers/plans/2026-09-18-visitor-detail-tabs.md
2026-09-18 16:25:53 +08:00

7.3 KiB
Raw Permalink Blame History

访客详情页三栏 Tab 化 — 实现计划

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: 访客详情页重组为三栏布局——左栏 ElTabs(访问时间线默认/会话/原始数据),中栏 2×2 统计卡+来源证据,右栏访问环境;含三级响应式降级。

Architecture: 单文件(admin/src/views/tracker/visitor/detail.vue,1479 行)纯模板+样式重组,逻辑/API/抽屉零改动。

Tech Stack: Vue3 + Element Plus(ElTabs/ElTabPane)+ SCSS。

Spec: docs/superpowers/specs/2026-09-18-visitor-detail-tabs-design.md

现状锚点(实现者必读,行号已对照实测):

  • 模板:62-75 行 4 统计卡横排(div.vd-stats);77-228 行 div.vd-main 双栏(78-227 左=时间线卡 vd-timeline-card;167-227 右=div.vd-side 含来源证据+访问环境);231-329 行 div.vd-bottom-card(ElTabs:235-272 sessions pane;276-326 raw pane;底卡闭合 328-329);332-369 行是原始数据抽屉 ElDrawer——绝对不动;330 行 </template> 闭合 v-else 边界,重组不得越界
  • 状态:695 行 const activeTab = ref<'sessions' | 'raw'>('sessions');811 行附近 watch(activeTab, ...) 只匹配 'raw'(懒加载 rawBatches,无需改动);858-874 ensureLoad 无条件加载时间线,默认 timeline tab 无需额外加载逻辑
  • 样式:1093-1099 .vd-main(minmax(0,1fr) 340px);1101-1106 .vd-side;1409-1412 .vd-bottom-card;1463-1478 旧媒体查询(1200px 单栏 + 900px stats 两列)
  • 统计卡数据:statTiles computed(模板 v-for),不改动

Task 1: 模板重组 + activeTab 扩展

Files:

  • Modify: admin/src/views/tracker/visitor/detail.vue(模板 62-329 区段 + 695 行状态)

  • Step 1: activeTab 扩展(695 行):

const activeTab = ref<'timeline' | 'sessions' | 'raw'>('timeline')

(TS 会强制模板 v-model 类型吻合;watch(activeTab) 只匹配 'raw' 不动。)

  • Step 2: 模板重组(62-329 行区段重排;330 行 </template> 与 332+ 抽屉严禁触碰):
删除:div.vd-stats(62-75 全宽横排区)——statTiles v-for 块移入中栏
删除:div.vd-bottom-card 外壳(231 与 328-329 的开闭标签)——两个 ElTabPane 内容保留

新的主体结构(替换现 77-329):
<div class="vd-main">
  <!-- 左栏:三 tab -->
  <div class="vd-card vd-tabs-card">
    <ElTabs v-model="activeTab" class="detail-tabs">
      <ElTabPane label="访问时间线" name="timeline">
        <!-- 时间线工具行(原 vd-card-tools 整块迁入,含 RadioGroup+正倒序) -->
        <!-- truncated ElAlert(原 115-122) -->
        <!-- tl-body 时间线主体(原 124-226,原样) -->
      </ElTabPane>
      <ElTabPane :label="`会话(${detail?.sessions.length ?? 0})`" name="sessions">
        <!-- 原底部 sessions pane 内容原样迁入(235-272) -->
      </ElTabPane>
      <ElTabPane label="原始数据" name="raw">
        <!-- 原底部 raw pane 内容原样迁入(276-326) -->
      </ElTabPane>
    </ElTabs>
  </div>

  <!-- 中栏:统计卡(2×2)+ 来源证据 -->
  <div class="vd-side">
    <div class="vd-stats">  <!-- statTiles v-for 原样,容器改由样式控制 2×2 -->
      ...原 64-74 卡片模板块...
    </div>
    ...来源证据卡(原 168-204 原样)...
  </div>

  <!-- 右栏:访问环境(原 205-227 卡,提出 vd-side 成独立栏) -->
  <div class="vd-side">
    ...访问环境卡原样...
  </div>
</div>

注意:时间线卡的 vd-card-head(81-113)取消卡头形态——标题职能由 tab label 承担,工具行(vd-card-tools 内容)改为 pane 内顶部一行工具条(保留现有类名与功能,外层可套 div.vd-tl-tools flex 容器,样式 Task 2 补)。

  • Step 3: 编译验证

Run: cd admin && npx vue-tsc --noEmit 2>&1 | head -5 Expected: 无与 detail.vue 相关错误

  • Step 4: Commit
git add admin/src/views/tracker/visitor/detail.vue
git commit -m "feat(admin): 访客详情模板重组三栏Tabs——时间线/会话/原始数据合并左栏

Co-Authored-By: Claude Code <noreply@anthropic.com>"

Task 2: 样式区更新(三栏 grid/统计卡 2×2/断点替换)

Files:

  • Modify: admin/src/views/tracker/visitor/detail.vue(样式区 1092-1478)

  • Step 1: .vd-main 三栏(1093-1099 替换):

.vd-main {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 1fr) minmax(0, 1fr);
  align-items: start;
  gap: 20px;
  margin-bottom: 16px;
}
  • Step 2: .vd-stats 2×2 窄卡形态(找到现有 .vd-stats 样式块改写):grid-template-columns: repeat(2, minmax(0, 1fr))、gap 12px;卡片内缩(padding 减、.vd-stat-value 字号从现值降 2px 档)——保持客迹 V1 色板,具体值实现时按 460px 栏宽目测微调,方向:更紧凑。

  • Step 3: tabs 卡与工具条样式:

  • .vd-tabs-card:padding 收窄(tabs 自带间距,padding: 0 20px 16px 起)

  • .vd-tl-tools:display:flex; align-items:center; flex-wrap:wrap; justify-content:flex-end; gap:8px 12px; padding:12px 0 4px;

  • 原 .vd-timeline-card 专属样式保留复用(tl-body/tl-day 等不动)

  • 删除 .vd-bottom-card 样式块(1409-1412);.detail-tabs 若有样式微调确保 tab 头部对齐卡 padding

  • Step 4: 断点替换(1463-1478 整块替换):

// 响应式:两栏(访问环境整行下沉)→ 单栏
@media (max-width: 1400px) {
  .vd-main {
    grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
  }
  // 第三栏(访问环境)flow 到下方占满整行(与 spec"来源证据下方"等价实现:整行下沉,1100 档截图确认观感)
  .vd-main > :last-child {
    grid-column: 1 / -1;
  }
}
@media (max-width: 1000px) {
  .vd-main {
    grid-template-columns: minmax(0, 1fr);
  }
}

(900px 的 .vd-hstat-divider { display:none } 规则保留——属头部卡不动区,单独留下。)

  • Step 5: build 验证

Run: cd admin && pnpm build 2>&1 | tail -3 Expected: ✓ built

  • Step 6: Commit
git add admin/src/views/tracker/visitor/detail.vue
git commit -m "feat(admin): 访客详情三栏样式——2fr/1fr/1fr、统计卡2×2、断点1400/1000替换旧规则

Co-Authored-By: Claude Code <noreply@anthropic.com>"

Task 3: 四档视口验证 + 部署

  • Step 1: dev server + Playwright 四档截图(1920/1365/1100/900),需登录进访客详情(选一个有数据的访客):

  • 1920:三栏 + tabs 默认时间线

  • 1365:三栏(>1400 临界下)观察

  • 1100:两栏(访问环境下沉)

  • 900:单栏堆叠(顺序 tabs→统计→证据→环境)

  • 冒烟:tab 切换三页、会话抽屉打开、原始抽屉打开、时间线 7/30/90 切换与正倒序

  • 发现布局问题回 Task 1/2 修正

  • Step 2: 部署(标准流程):pnpm build → tar dist → scp 经跳板 → 解压 /opt/cms-cj → cp -rf dist/ admin/dist/*(真实 nginx 挂载点,勿只解压到 dist/)→ curl 验证新哈希

  • Step 3: 线上验证:Playwright 登录 → 访客详情页截图核对三栏 tabs 生效;汇报版本哈希