怎么用 这是格式与深度的参考,不是让你照抄的模板。数字全部是示例,直接抄进简历一问就穿——必须换成你自己的真实数据,而且要能说清是怎么测出来的。下面每个模块都有「数字是怎么测的」和「面试追问」两段,写不出那两段的模块就不要往简历上写

面试题库(电商 / 短视频 / 社区 / 本地生活 / 旅游 / 企业服务 多业务场景)

项目背景设定 短视频平台的创作者后台,Vue 3 单页应用,跑在创作者的电脑浏览器上。使用者是个人创作者与 MCN 机构运营,不是平台内部运营。核心场景是发布视频看数据管评论
为什么选这三个模块 创作者后台和内部运营后台的差异很具体:要在浏览器里上传几个 G 的视频(这是纯前端难题,分片、断点续传、秒传、并发控制都要自己做);数据看板的用户会拿数字质问你(「为什么我的播放量掉了」「为什么两个页面的数字不一样」,所以指标口径和数据延迟必须可解释);一条爆款视频有几万条评论(批量处理和自动屏蔽是刚需,不是加分项)。

模块一:视频发布与大文件上传

  1. 视频发布与大文件上传(分片断点续传 + 秒传 + 发布前预检)★★★
    简历这样写 浏览器端大文件上传与发布流程(Vue 3 + File 分片 + Web Worker 计算哈希 + IndexedDB 记录进度 + 并发受控队列 + 直传对象存储):视频走分片直传对象存储,分片哈希在 Web Worker 中计算避免卡住主线程,进度与已完成分片写 IndexedDB 实现刷新页面与跨会话续传;相同文件命中秒传;发布前做封面尺寸、时长、码率等预检并给出可执行的修改建议,支持定时发布与草稿。4GB 视频在限速 2MB/s 条件下可完整上传,中途刷新页面后从已完成分片继续,哈希计算期间页面保持可交互
    展开完整拆解
    为什么要这么设计

    「在浏览器里上传一个几 G 的视频」是这个后台最硬的前端问题,而且它有一批只在浏览器环境下才出现的约束。

    第一版用了一个 input file 加一次性 POST,问题全面爆发。

    一是大文件一次性上传几乎必然失败。4GB 的文件传半小时,中间任何一次网络抖动、代理超时、浏览器标签被系统回收,整个上传从零开始。创作者传三次都失败之后就不传了。

    二是计算文件哈希把页面卡死。为了做秒传要算文件哈希,在主线程里读 4GB 文件算 MD5,页面卡住几十秒完全无响应,创作者以为浏览器崩了。

    三是刷新页面进度全丢。进度只存在内存里,创作者手滑刷新或者关了标签,重开要从头传。

    四是发布后才发现不合规。封面尺寸不对、时长超限、码率过高,上传完等了半小时转码,最后审核驳回。创作者的反馈是「你们不能早点告诉我吗」。

    所以四个设计:分片上传加断点续传哈希计算放 Web Worker进度持久化到 IndexedDB发布前预检并给出可执行建议

    整体链路
    选择文件后的完整流程 │ ├─ 1 本地快速预检(在算哈希之前,成本最低的先做) │ 文件类型 / 大小上限 / 用 video 元素读时长与分辨率 │ 不合规直接拦下并给出可执行建议 │ 「时长 18 分钟超过 15 分钟上限,请剪辑后重试」 │ ├─ 2 计算文件指纹(在 Web Worker 里做,不阻塞主线程) │ 全量哈希对 4GB 文件太慢 │ → 采样哈希:首尾各若干分片 + 中间等距抽样 + 文件大小 │ 速度快很多,碰撞概率对业务足够低 │ Worker 里用 FileReader 分块读,边读边算,内存可控 │ ├─ 3 秒传判定:拿指纹问服务端「这个文件传过吗」 │ 命中 → 直接创建视频记录,跳过上传(秒完成) │ 未命中 → 进入分片上传 │ ├─ 4 查询已上传分片(断点续传的关键) │ 带指纹问服务端「这个文件已经传了哪些分片」 │ 本地 IndexedDB 里也存了一份,两者取并集校验 │ → 服务端为准,本地记录只用于快速恢复界面 │ ├─ 5 分片上传(并发受控) │ 分片大小按文件大小与网速动态定(几 MB 到几十 MB) │ 并发数 3 到 4(太高抢带宽反而慢,浏览器也有连接上限) │ 每片独立重试(退避),单片失败不影响其他片 │ 每片成功 → 更新 IndexedDB 与界面进度 │ ├─ 6 通知服务端合并分片 → 服务端校验完整性 → 触发转码 │ └─ 7 填写信息并发布(此时视频还在转码,可以并行填) 标题 / 简介 / 话题 / 封面(可从视频抽帧选,也可自定义上传) 定时发布 / 存草稿 / 立即发布 进度持久化(刷新页面也能续传) │ ├─ IndexedDB 存:文件指纹 / 文件名大小 / 已完成分片序号 / 创建时间 │ 不存文件内容本身(存不下,也没必要) │ ├─ 重新进入页面 → 读出未完成的上传任务并展示 │ 提示「有一个未完成的上传,请重新选择该文件继续」 │ → 浏览器安全限制:不能自动读取上次的文件,必须用户重选 │ ├─ 用户重选文件 → 算指纹比对 → 一致则从断点继续 │ └─ 过期清理:超过保留期的记录自动删除 因为服务端的分片也有保留期,过期后续传会失败 发布前预检(把驳回提前到上传前) ├─ 硬性限制:时长、大小、格式、分辨率下限 ├─ 软性建议:码率过高(转码慢)、封面模糊、标题过短 ├─ 每条问题都要给「怎么改」而不只是「不合规」 └─ 封面单独预检:尺寸、比例、是否有明显文字遮挡
    分步拆解
    1. 预检要放在算哈希之前,因为它最便宜。video 元素读时长和分辨率是毫秒级的,如果时长超限就没必要花几十秒算哈希。顺序按「成本从低到高」排。
    2. 哈希必须在 Web Worker 里算,这是不卡页面的唯一办法。主线程读 4GB 文件算哈希会卡几十秒,创作者以为浏览器崩了。Worker 里用 FileReader 分块读、边读边算,内存占用可控且主线程保持响应。
    3. 用采样哈希而不是全量哈希。全量哈希 4GB 文件即使在 Worker 里也要很久。取首尾各若干分片加中间等距抽样,再拼上文件大小,速度快一个数量级,而碰撞概率对「判断是否同一文件」这个用途足够低。要说明这是有意的取舍——如果业务要求严格去重(比如版权判定),就得用全量哈希或者服务端二次校验。
    4. 秒传要先问服务端,别自己判断。拿指纹问「这个文件传过吗」,命中就直接创建记录跳过上传。秒传对创作者的体验提升极大(重复发布、多平台分发时经常传同一个文件)。
    5. 断点续传要以服务端的已传分片为准。本地 IndexedDB 的记录只用于快速恢复界面,实际续传前必须问服务端「已经有哪些分片」——本地记录可能和服务端不一致(分片上传成功但本地记录失败)。
    6. 分片大小要动态定。小文件用小分片(减少最后一片的浪费),大文件用大分片(减少请求数和合并开销)。还要考虑网速——慢网下大分片失败重传的代价很高。
    7. 并发数控制在 3 到 4,不是越多越好。浏览器对同域并发连接有上限,而且并发太高会互相抢带宽导致每片都慢、更容易超时。这个数字要实测
    8. 每片独立重试,单片失败不影响其他片。退避重试,重试到上限才标记整体失败。这是「分片」相比「整体上传」最大的价值——失败的粒度从整个文件降到一个分片。
    9. 浏览器不能自动读取上次的文件,这个限制必须正面处理。刷新后我们知道「有个未完成的上传」,但拿不到文件句柄(安全限制)。做法是提示用户重新选择该文件,选完算指纹比对,一致就从断点继续。不能假装能自动恢复。
    10. IndexedDB 记录要有过期清理。服务端的分片也有保留期,过期后续传必然失败。本地记录的保留期要短于服务端,避免让用户看到一个注定失败的续传任务。
    11. 预检的每条问题都要给「怎么改」。「封面不合规」没用,要说「封面建议 16:9,当前是 4:3,请重新裁剪」。创作者不是技术人员,只说不合规他不知道怎么办。
    12. 信息填写要能和转码并行。视频上传完就开始转码(几分钟),这段时间让创作者填标题简介,不要让他干等
    关键决策与取舍

    采样哈希牺牲了严格性换速度,这个取舍要说清适用边界。它足以判断「是不是同一个文件」(用于秒传和续传),但不能用于版权判定或严格去重——那些需要全量哈希甚至内容指纹。我们的做法是采样哈希用于前端秒传判定,服务端在合并分片后再做一次完整校验,两层配合。

    分片直传对象存储,而不是经过我们的服务器。直传的好处是不占用应用服务器带宽、上传速度更快(对象存储的边缘节点更近)。代价是要签发上传凭证并严格限制(路径前缀、大小上限、有效期),以及不能信任客户端说的「传完了」——服务端必须去对象存储核实分片存在且大小正确。

    踩过的坑:Worker 里一次性读整个文件导致内存爆掉。第一版在 Worker 里用 FileReader.readAsArrayBuffer 读整个 4GB 文件,浏览器直接崩溃(标签页崩溃提示)。修法是File.slice 分块读,读一块算一块,读完就释放教训是:处理大文件时任何「一次性读进内存」的操作都是隐患,无论在主线程还是 Worker 里——Worker 只解决了「不卡主线程」,没解决内存。

    踩过的坑二:本地记录说已传 80 片,服务端只有 60 片,续传后合并失败。某些分片上传请求实际失败了但客户端记成功(响应解析问题),本地记录比服务端多,续传时跳过了那些分片,最后合并时服务端发现缺片,整个上传失败,而创作者已经等了半小时。修法是续传前必须以服务端返回的已传分片列表为准,本地记录只用于快速恢复界面显示。教训是:客户端记录的状态永远不能作为「事实」,必须以服务端为准。

    没做的部分:没做上传的后台化(关闭标签页后继续上传)。浏览器里做不到真正的后台上传(Service Worker 也无法在标签关闭后持续大文件上传)。只能做到「刷新页面可续传」,并明确告知创作者不要关闭标签页——这个能力边界要如实说明,不能承诺做不到的事。

    数字是怎么测的

    4GB 在 2MB/s 下可完整上传:用浏览器开发者工具限速到 2MB/s,传一个 4GB 的真实视频文件,验证能完整走完(约半小时)。过程中要制造干扰:断网几十秒再恢复、刷新页面、切到其他标签,验证每种情况下都能继续。这类能力靠演练而不是数字说明,要能说出演练了哪些干扰场景。

    哈希计算期间页面可交互:用 Performance 面板录制哈希计算全程,检查主线程有没有长任务(超过 50ms 的任务块)。放到 Worker 之后主线程应该基本空闲。要报出哈希计算的耗时(采样哈希对 4GB 文件大约几秒),以及对比全量哈希的耗时,说明采样的收益。

    秒传命中:同一文件重复上传,验证第二次直接完成。可以报秒传的命中次数——如果有埋点,这个数字证明功能被真实使用(创作者多平台分发时经常传同一个文件)。

    并发分片数的选择依据:压测不同并发数(1、2、4、8)下的整体上传耗时,报出「为什么选 3 到 4」——通常会发现超过某个数之后耗时不再下降甚至上升(抢带宽、超时增多)。能给出这条曲线比直接说「我用了 4 个并发」有说服力。

    不要报「上传成功率 99%」。上传失败的主要原因是创作者的网络,我们改不了。可以报的是「因客户端逻辑导致的上传失败」(比如那个「本地记录与服务端不一致导致合并失败」的 bug 修复前后的对比),这个是我们能控制的。

    面试追问
    Q:浏览器里怎么上传一个 4GB 的视频? A:核心是分片直传加断点续传,配合 Worker 算哈希。完整顺序是:先做便宜的预检(用 video 元素读时长分辨率,毫秒级,超限就不用往下走了);然后在 Web Worker 里算文件指纹(主线程算会卡几十秒,创作者以为浏览器崩了);拿指纹问服务端秒传(传过就直接完成);没命中则问服务端「已传了哪些分片」做断点续传;分片并发上传(并发 3 到 4,每片独立重试);通知服务端合并并校验完整性两个关键细节:分片直传对象存储而不经过应用服务器(省带宽、边缘节点更近),但要签发受限的上传凭证且服务端必须核实分片真实存在用采样哈希而不是全量哈希(首尾分片加中间等距抽样再拼文件大小),全量算 4GB 即使在 Worker 里也太慢,采样对「判断是否同一文件」这个用途足够,但不能用于版权判定,那需要服务端二次完整校验。
    Q:算哈希会卡页面,放到 Web Worker 就好了吗? A:不够,Worker 只解决了「不卡主线程」,没解决内存。我们踩过这个坑:在 Worker 里用 FileReader.readAsArrayBuffer 读整个 4GB 文件,浏览器直接崩溃(标签页崩溃提示)——因为 4GB 数据要一次性进内存。修法是File.slice 分块读,读一块算一块,读完立刻释放引用,这样内存占用只有一个分块的大小。教训是处理大文件时任何「一次性读进内存」的操作都是隐患,无论在哪个线程。另外还有个优化:采样哈希——不需要读完整个文件,只读首尾各若干分片加中间等距抽样,再拼上文件大小作为指纹,速度快一个数量级。验证方式是用 Performance 面板录制全程,检查主线程有没有超过 50ms 的长任务,放到 Worker 后主线程应该基本空闲。
    Q:创作者刷新了页面,上传进度还在吗? A:进度在,但文件拿不回来,这个限制必须正面处理。我们把「文件指纹、文件名大小、已完成分片序号」存在 IndexedDB 里(不存文件内容,存不下也没必要),刷新后能读出「有一个未完成的上传」。但浏览器的安全限制是拿不到上次的文件句柄,所以只能提示用户重新选择该文件,选完算指纹比对,一致就从断点继续。不能假装能自动恢复。更重要的一个坑:续传前必须以服务端返回的已传分片列表为准,不能信本地记录。我们踩过——某些分片上传实际失败但客户端记成功了,本地记录比服务端多,续传时跳过了那些分片,最后合并时服务端发现缺片,整个上传失败,而创作者已经等了半小时客户端记录的状态永远不能作为「事实」。另外本地记录要有过期清理,且保留期要短于服务端分片的保留期,避免让用户看到一个注定失败的续传任务。
    Q:分片并发数设多少合适? A:3 到 4,而且不是越多越好,这个数字要实测得出。三个约束:浏览器对同域并发连接有上限(通常六个),超出的请求会排队,看起来并发实际串行;并发太高会互相抢带宽,每片都变慢、更容易触发超时,整体反而更慢;还要给其他请求留余量(页面上还有轮询、心跳、其他接口)。验证方式是压测不同并发数(1、2、4、8)下的整体上传耗时,画出曲线——通常会发现超过某个数之后耗时不再下降甚至上升。能给出这条曲线比直接说「我用了 4 个并发」有说服力得多。进阶做法是按实测网速动态调整:好网络多开几个,弱网降到 1 到 2 个(弱网下并发只会加剧超时)。分片大小也要动态定:小文件用小分片,大文件用大分片减少请求数,但慢网下大分片失败重传的代价很高,要平衡。

模块二:数据看板与口径可解释

  1. 数据看板与口径可解释(多维下钻 + 延迟标注 + 指标口径说明)★★★
    简历这样写 创作者数据看板(Vue 3 + 图表降采样 + 多维下钻 + 口径说明与延迟标注 + 请求竞态控制):核心指标支持按时间、内容、来源、人群多维下钻,长时间跨度的曲线做降采样后再渲染;每个指标都有可点开的口径说明(统计范围、去重规则、更新频率),页面上显式标注数据延迟与统计截止时间;维度切换时用请求序号丢弃过期响应避免图表与筛选条件不一致。90 天 × 多指标曲线渲染约 200ms(降采样后),维度切换的图表错配改造后未再出现,「为什么两个页面的数字不一样」类咨询由口径说明消化。
    展开完整拆解
    为什么要这么设计

    创作者数据看板和内部运营报表最大的差异是:它的用户会拿数字来质问你。创作者的收入和这些数字直接相关,他会逐个核对、会截图对比、会在社群里和其他创作者比。

    第一版是标准的图表页,问题不在技术而在「说不清」。

    一是同一个指标在不同页面数字不一样,创作者认为我们造假。首页的「总播放量」和视频详情页的播放量加起来不相等。原因其实很正常——一个是去重后的、一个是不去重的,一个含站外播放、一个不含,但页面上完全没说明。创作者的结论是「你们的数据不准」。

    二是数据延迟没有标注,创作者以为是实时的。他刚发的视频看播放量是 0,以为没人看,实际是统计还没跑到。他会在这个错误认知下做决策(比如立刻删了重发)。

    三是长时间跨度的图表卡死。90 天 × 多个指标 × 分小时粒度,几万个数据点全丢给图表库,渲染卡住好几秒,缩放拖动完全不流畅

    四是切换维度时图表和筛选条件对不上。快速切了几次维度,慢的那个请求最后返回覆盖了界面,图表显示的是上一个维度的数据,而筛选器显示的是当前维度。创作者截图来问「这是什么数据」。

    所以四个设计:每个指标都有可点开的口径说明显式标注数据延迟与截止时间长跨度曲线降采样请求竞态用序号控制前两条是这个模块最重要的部分——它们不是技术问题,但决定了创作者是否信任这个产品。

    整体链路
    指标的口径必须可解释(这是信任的基础) │ ├─ 每个指标旁边一个说明入口,点开展示 │ 统计范围 含哪些来源(站内推荐 / 搜索 / 主页 / 站外分享) │ 去重规则 同一用户多次播放算几次、多久算一次 │ 计入条件 播放多少秒才算一次有效播放 │ 更新频率 每小时 / 每天几点更新 │ 不含什么 比如不含创作者自己的播放、不含刷量被过滤的 │ ├─ 相关指标之间的关系也要说明 │ 「首页总播放 ≠ 各视频播放之和」的原因写清楚 │ → 这一条直接消化了最高频的一类咨询 │ └─ 口径变更要公告并在历史数据上标注 口径改了之后,历史曲线会出现台阶 不标注的话创作者会以为是自己的数据掉了 数据延迟与截止时间(显式标注,不要让人猜) │ ├─ 页面顶部固定展示「数据统计截止:今天 14:00」 │ ├─ 不同指标的延迟不同 → 各自标注 │ 播放量 小时级更新 │ 收入 日级更新(要等结算) │ 粉丝画像 日级更新(要跑离线任务) │ ├─ 今日数据标注为「实时估算,与最终数据可能有差异」 │ └─ 新发布的视频给明确提示 「数据将在发布后约 1 小时内开始更新」 → 避免创作者看到 0 就以为没人看而删掉重发 长跨度曲线的降采样(几万个点不能直接丢给图表) │ ├─ 服务端按请求的时间跨度返回合适粒度 │ 7 天以内 按小时 │ 30 天以内 按天 │ 90 天以上 按天但做聚合,或按周 │ → 返回的点数控制在几百个以内 │ ├─ 前端仍要做一次保护性降采样 │ 万一服务端返回了大量点,按容器像素宽度抽样 │ 屏幕上只有 800 像素,画 5000 个点没有意义 │ ├─ 降采样要保留极值(最高点最低点不能被抽掉) │ 纯等距抽样会让尖峰消失,曲线形状失真 │ └─ 缩放交互:缩放到小范围时按新范围重新请求细粒度数据 而不是在本地已有的粗粒度数据上放大 多维下钻与竞态控制 │ ├─ 维度:时间粒度 / 内容(单个或全部视频)/ 流量来源 / 人群 │ ├─ 切换维度 → 发起新请求 │ 每次请求前 seq++,请求带上当前 seq │ 响应回来比对 seq,小于当前值直接丢弃 │ → 避免慢的旧请求覆盖新结果 │ ├─ 切换期间用骨架占位,不清空旧数据(避免闪白) │ 但要标注「加载中」,防止用户误读旧数据 │ └─ 空数据要区分「没有数据」和「加载失败」 没有数据 → 说明为什么(比如该时段没有发布内容) 加载失败 → 给重试按钮
    分步拆解
    1. 每个指标都要有口径说明,这是最该先做的一件事。不是文档,是页面上点一下就能看到的说明:统计范围、去重规则、计入条件、更新频率、不含什么。创作者的信任建立在「数字能被解释」上,而不是「数字好看」。
    2. 相关指标之间的差异必须主动说明。「首页总播放 ≠ 各视频播放之和」这类问题如果不主动解释,创作者的第一反应就是「数据造假」。把原因写在口径说明里,直接消化了最高频的一类咨询。
    3. 口径变更要公告并在历史曲线上标注。口径改了之后曲线会出现台阶,不标注创作者会以为是自己的数据掉了,进而怀疑平台限流。
    4. 数据延迟必须显式标注,而且不同指标分别标注。播放量小时级、收入日级、画像日级,混在一个页面里如果不分别标注,创作者会用最快的那个的预期去看最慢的那个。
    5. 新发布视频要给「数据何时开始更新」的提示。这一条防的是很具体的行为:创作者看到 0 播放以为没人看,直接删了重发——而删除重发会损失已有的推荐权重,是实际损失。
    6. 降采样要在服务端做,前端再做一层保护。服务端按时间跨度返回合适粒度(点数控制在几百个),前端按容器像素宽度再抽一次——屏幕只有 800 像素,画 5000 个点毫无意义。
    7. 降采样必须保留极值。纯等距抽样会让尖峰消失、曲线形状失真,而创作者最关心的往往就是那个爆发日。做法是在每个采样区间内保留最大最小值。
    8. 缩放到小范围时要重新请求细粒度数据,不要在粗粒度数据上放大。否则放大后还是那几个点,看不到细节。「按当前视图范围请求对应粒度」是图表交互的正确做法。
    9. 维度切换必须做请求竞态控制。用自增序号,响应回来比对,过期的直接丢弃。否则会出现「图表是旧维度的数据、筛选器是新维度」的错配,创作者会截图来问。
    10. 切换期间不清空旧数据但要标注加载中。清空会闪白很难看,但不标注会让用户误读旧数据。骨架或半透明遮罩加「加载中」是平衡。
    11. 空数据要区分「确实没有」和「加载失败」。前者要说明原因(该时段没发布内容),后者要给重试按钮。都显示成空白图表会让人以为数据丢了。
    关键决策与取舍

    把「口径说明」当成核心功能而不是文档补充,这是这个模块最重要的判断。技术上它只是几个弹窗,但它解决的是整个产品的信任问题。创作者不信任数据的后果很严重——他会认为平台限流、会去社群里传播、会流失。我在这个项目里的体会是:面向外部用户的数据产品,「可解释性」的优先级高于「功能丰富度」。

    显式标注延迟看起来是「暴露缺点」,实际是减少投诉。产品最初担心「写了延迟创作者会觉得我们的数据不及时」。但实际情况是不写延迟的投诉远多于写了延迟的抱怨——因为前者是「你们数据不准」(信任问题),后者只是「希望更快」(需求问题)。这个判断在很多产品决策里通用:如实告知局限比隐藏局限的总成本低。

    降采样在服务端做,代价是灵活性下降。服务端决定粒度,前端想要不同粒度就要重新请求。但把降采样放前端意味着要传几万个点,网络和解析开销都大。折中是服务端按跨度给合适粒度,前端支持「按视图范围重新请求」,这样既控制了传输量又保留了看细节的能力。

    踩过的坑:降采样用等距抽样,创作者的爆发日在曲线上消失了。90 天曲线按等距抽样降到 200 个点,某个单日播放量暴涨的尖峰正好落在被抽掉的位置,曲线上完全看不到。创作者说「我那天明明爆了,你们图上没有」。修法是每个采样区间内保留最大值和最小值,保证极值不丢失。教训是:降采样的目标是「保持曲线的视觉形状」而不是「均匀取点」,极值点是形状的关键。

    踩过的坑二:维度切换的竞态导致图表与筛选器错配。创作者快速切了几次流量来源维度,最慢的那个请求最后返回覆盖了界面,图表显示的是「搜索来源」的数据,而筛选器显示的是「推荐来源」。他截图来问「这是什么数据」,我们查了很久才发现是竞态。修法是请求序号比对丢弃过期响应。这和旅游客户端切换日期的坑是同一类问题——任何「用户输入驱动的异步查询」都必须处理竞态,搜索联想、筛选、分页、维度切换都是。

    没做的部分:没做数据的自定义看板(让创作者自己拖拽组合想看的指标)。MCN 机构提过,但需要一套配置化的图表编排,工作量不小,而且大部分个人创作者用不上,当时排在后面。

    数字是怎么测的

    90 天多指标曲线渲染耗时:量「数据到手」到「图表绘制完成」,降采样后约 200ms。必须同时说明降采样后的实际点数——「90 天多指标」听起来是几万个点,实际渲染的只有几百个,这才是 200ms 的原因。报「原始点数」和「渲染点数」两个数字才能说明设计。

    降采样保留极值的验证:造一组含明显尖峰的数据,降采样后检查尖峰是否仍在曲线上、位置是否正确。这是个可精确验证的点,也正是我们踩过坑的地方。

    竞态控制的验证:用工具让第一个请求延迟数秒返回,然后快速连续切换三次维度,验证最终图表对应的是最后一次选择、且筛选器与图表一致。改造前每次都能复现错配。

    「口径咨询被消化」怎么量化:「为什么两个页面数字不一样」这类咨询工单的数量变化,以及口径说明的点开次数。两个一起看才有意义——如果说明没人点但咨询也降了,可能是别的原因。点开次数还能反映哪些指标最容易引起疑惑,指导后续优化。

    不要报「数据准确率」。数据准不准是数仓和埋点的事,前端只负责如实呈现。也不要报「创作者满意度提升」——没有可靠测量方式。可以报的是可核查的事实:覆盖了多少个指标的口径说明、延迟标注覆盖了哪些指标、竞态错配的修复验证。

    面试追问
    Q:创作者说「首页显示总播放 10 万,但我几个视频加起来只有 8 万,你们数据有问题」,怎么办? A:这通常不是数据错,是口径不同,而问题在于我们没说明。常见原因:首页的总播放可能含站外分享带来的播放而视频详情页只统计站内;或者一个是去重后的(同一用户一天内多次播放算一次)另一个不去重;或者首页含已删除视频的历史播放解法不是去改数据,而是把口径写清楚并放在页面上——每个指标旁边一个可点开的说明:统计范围(含哪些来源)、去重规则、计入条件(播放多少秒算一次)、更新频率、以及不含什么特别要主动说明「首页总播放 ≠ 各视频之和」的原因,这一条直接消化了最高频的一类咨询。我的体会是:面向外部用户的数据产品,「可解释性」的优先级高于「功能丰富度」——创作者不信任数据的后果是认为平台限流、去社群传播、流失,比少一个图表严重得多。
    Q:90 天的分小时数据有几万个点,图表怎么不卡? A:降采样,而且要在服务端做为主、前端做一层保护。服务端按请求的时间跨度返回合适粒度(7 天内按小时、30 天内按天、90 天以上按天聚合或按周),把返回点数控制在几百个以内;前端再按容器像素宽度抽一次——屏幕只有 800 像素,画 5000 个点毫无意义。但降采样有个必须注意的坑:我们第一版用等距抽样,某个单日播放暴涨的尖峰正好落在被抽掉的位置,曲线上完全看不到,创作者说「我那天明明爆了,你们图上没有」。修法是每个采样区间内保留最大值和最小值教训是降采样的目标是「保持曲线的视觉形状」而不是「均匀取点」,极值点是形状的关键。另外缩放交互要按新视图范围重新请求细粒度数据,而不是在已有的粗粒度数据上放大——否则放大后还是那几个点,看不到细节。
    Q:创作者刚发的视频显示 0 播放,他以为没人看,怎么处理? A:必须显式告知数据延迟,这个提示防的是很具体的损失行为。创作者看到 0 播放的第一反应往往是「限流了」或「没人看」,然后删掉重发——而删除重发会损失已积累的推荐权重,是实际损失。所以要做三件事:页面顶部固定展示「数据统计截止:今天 14:00」不同指标分别标注延迟(播放量小时级、收入日级、画像日级,混在一起不分别标注的话创作者会用最快那个的预期去看最慢的);新发布视频给明确提示「数据将在发布后约 1 小时内开始更新」产品最初担心「写了延迟显得我们数据不及时」,但实际是不写延迟的投诉远多于写了延迟的抱怨——前者是「你们数据不准」(信任问题),后者只是「希望更快」(需求问题)。如实告知局限比隐藏局限的总成本低,这个判断在很多产品决策里通用。
    Q:创作者快速切换筛选维度,图表显示的数据和筛选器不一致,为什么? A:请求竞态——快速切了几次维度,发了几个并发请求,最慢的那个最后返回覆盖了界面,图表是「搜索来源」的数据而筛选器显示「推荐来源」。创作者截图来问「这是什么数据」,我们查了很久才定位。修法是请求序号比对:每次发请求前序号加一,请求带上当前序号,响应回来比对——小于当前值说明是过期响应,直接丢弃。为什么不用「取消上一个请求」:取消的支持在各环境不一致,而且响应可能已在路上;序号比对是纯逻辑,行为完全确定。这和旅游客户端切换日期的坑是完全同一类问题——任何「用户输入驱动的异步查询」都必须处理竞态,搜索联想、筛选、分页、维度切换都是。配套还要注意:切换期间不清空旧数据(避免闪白)但必须标注「加载中」,否则用户会误读旧数据。

模块三:海量评论管理

  1. 海量评论管理(批量处理 + 自动屏蔽规则 + 危险操作保护)★★★
    简历这样写 创作者侧评论管理(Vue 3 + 虚拟列表 + 批量选择与部分成功处理 + 关键词规则即时生效 + 撤销窗口):一条爆款视频的数万条评论走虚拟列表加游标分页,支持跨页批量选择与按条件筛选(含关键词、低赞、新粉丝等)后批量删除或屏蔽,批量结果逐条返回并区分成功与失败;创作者可配置关键词自动屏蔽规则并即时生效,规则命中的评论进独立的待确认列表而非直接删除;删除类操作提供短时撤销窗口。数万条评论列表滚动流畅,批量处理数百条一次完成并可仅重试失败项,误删由撤销窗口兜住。
    展开完整拆解
    为什么要这么设计

    评论管理在创作者后台里是使用频率最高的功能之一,而且它的数据量级是前面几个模块里最大的——一条爆款视频几万条评论,其中相当比例是需要处理的(广告、引流、攻击性言论)

    第一版是标准的分页列表加单条操作,几乎不可用。

    一是逐条处理完全跟不上。几万条评论里有几百条广告,创作者要一条条点删除,每次点完等刷新。他的实际做法是干脆关闭评论区——这对平台是损失(评论是重要的互动数据)。

    二是分页处理时页码会错乱。删掉几条之后,后面的评论往前移,翻到第二页会跳过一些评论(因为用的是 offset 分页)。创作者以为处理完了,实际漏了一批。

    三是同样的垃圾评论反复出现。某个引流广告的固定话术,创作者今天删了明天又来。他需要的是「以后这类评论自动屏蔽」而不是每天手动删。

    四是误删无法恢复。批量选中时手滑多选了正常评论,删了就没了。粉丝的评论被误删会引发不满,而创作者根本不知道自己删了什么。

    所以四个设计:虚拟列表加游标分页支撑数万条跨页批量选择与条件筛选关键词自动屏蔽规则删除操作给撤销窗口

    整体链路
    列表承载(数万条评论) │ ├─ 游标分页(不用 offset,避免删除后翻页错乱) │ 游标编码「上一页最后一条的排序值 + 评论 ID」 │ 删除评论不影响后续翻页的连续性 │ ├─ 虚拟列表:只渲染可视区 + 缓冲 │ 评论卡片高度不定(内容长短不一) │ → 用预估高度 + 实测后修正的方案 │ 或者强制折叠长评论为固定高度(更简单,我们选这个) │ └─ 滚动到底自动加载下一页 筛选与批量选择(这是能不能用的关键) │ ├─ 筛选条件(帮创作者快速找到要处理的那批) │ 含指定关键词 / 疑似广告(平台标记)/ 零点赞 │ 新注册用户发的 / 非粉丝发的 / 含外链或联系方式 │ 时间范围 / 已屏蔽 / 待确认 │ ├─ 跨页批量选择 │ 「全选当前页」「全选筛选结果」两种 │ 全选筛选结果时不是选中具体 ID 列表(可能几千条) │ 而是记录「筛选条件 + 排除的 ID」 │ → 提交时传条件让服务端处理,避免传超大 ID 列表 │ ├─ 选中数量与影响范围要明确展示 │ 「已选中 1247 条,其中 89 条来自你的粉丝」 │ → 粉丝评论要单独提示,避免误伤真实互动 │ └─ 批量操作:删除 / 屏蔽(仅作者可见)/ 标记为垃圾 批量结果处理(部分成功是常态) │ ├─ 服务端逐条处理,返回逐条结果 │ 不返回一个整体的成功或失败 │ ├─ 界面展示:成功的移出列表,失败的保留并标出原因 │ 失败原因:评论已被删除 / 无权限 / 已被平台处理 │ ├─ 顶部汇总「1198 条成功,49 条失败」+「仅重试失败项」 │ └─ 大批量走异步任务 超过阈值(比如 500 条)转为后台任务 返回任务 ID,界面展示进度,完成后通知 → 避免一个请求处理几千条导致超时 关键词自动屏蔽规则(治本,不是每天手动删) │ ├─ 创作者配置关键词或短语(支持精确与包含) │ 不开放正则(创作者不会写,而且有性能风险) │ ├─ 规则即时生效:新评论命中则自动屏蔽 │ ├─ 关键设计:命中的评论进「待确认」列表而不是直接删除 │ 创作者可以复查有没有误伤 │ 确认无误可以批量清理,发现误伤可以恢复并调整规则 │ → 避免规则配得太宽把正常评论也屏蔽了却不知道 │ ├─ 规则可以对历史评论「回溯执行一次」 │ 配了新规则后,问「要不要处理已有的评论」 │ 回溯是一次性的批量任务,同样进待确认 │ └─ 规则命中统计:每条规则命中了多少条 长期零命中的规则提示删除(减少无效规则) 误操作保护 ├─ 删除类操作给短时撤销窗口(几秒内可撤销) ├─ 批量删除超过阈值时要求二次确认并显示影响范围 ├─ 已删除的评论进「最近删除」保留一段时间可恢复 └─ 所有操作留痕(谁在什么时候删了什么,规则触发的也记)
    分步拆解
    1. 分页必须用游标,不能用 offset。删掉几条之后后面的评论往前移,offset 分页翻到下一页会跳过一批,创作者以为处理完了实际漏了。游标编码「上一页最后一条的排序值加评论 ID」,删除不影响后续翻页的连续性。
    2. 评论卡片的不定高问题,选「强制折叠长评论」而不是「实测高度修正」。不定高虚拟列表要维护高度累积表并支持反查,复杂度高一个量级。长评论折叠为固定行数、点击展开,从源头消除不定高——这和之前几个长列表的判断一致:用设计约束换实现简单。
    3. 筛选条件要贴合创作者的真实诉求。「含指定关键词」「疑似广告」「零点赞」「新注册用户发的」「含外链或联系方式」——这些是从创作者实际要处理的评论类型倒推出来的,不是凭想象设计的筛选器。
    4. 「全选筛选结果」不能选中具体 ID 列表。筛选结果可能几千条,传一个几千个 ID 的数组既大又容易超限。做法是记录「筛选条件 + 用户手动排除的 ID」,提交时传条件让服务端处理。
    5. 选中数量和影响范围要明确展示,尤其要单独提示粉丝评论。「已选中 1247 条,其中 89 条来自你的粉丝」——粉丝评论是真实互动,误删的代价比误删广告大得多,必须让创作者注意到。
    6. 批量结果必须逐条返回,把「部分成功」当常态。有些评论可能已被平台处理或已被删除。返回整体成功或失败会让创作者不知道该重试哪些,配合「仅重试失败项」按钮。
    7. 大批量走异步任务。超过阈值(几百条)转后台任务,返回任务 ID,界面展示进度。一个请求处理几千条必然超时。
    8. 关键词规则是「治本」的手段,比每天手动删有价值得多。创作者的真实痛点是同样的引流话术每天都来。规则即时生效,新评论命中自动屏蔽。
    9. 规则命中的评论必须进「待确认」而不是直接删除,这是这个模块最重要的设计。创作者配的规则很可能过宽(比如把某个常用词加进去了),直接删除会静默误伤大量正常评论而他完全不知道。进待确认列表让他能复查、能恢复、能调整规则。
    10. 不开放正则给创作者。他们不会写,而且写错的正则可能有灾难性回溯导致性能问题。提供「精确匹配」和「包含」两种就够覆盖绝大多数场景。
    11. 规则要支持对历史评论回溯执行一次。配了新规则后问「要不要处理已有评论」,回溯是一次性批量任务,同样进待确认,不直接删除。
    12. 删除类操作给短时撤销窗口,并保留「最近删除」。批量选中时手滑多选是常见的,几秒的撤销窗口加上一段时间的「最近删除」可恢复,是成本极低的保护。
    关键决策与取舍

    「规则命中进待确认而不是直接删除」是有代价的——创作者要多一步操作。他会问「为什么不能自动删掉」。理由是规则的准确性完全由他自己保证,而他配的规则大概率过宽:把一个常用词加进关键词,可能屏蔽掉几百条正常评论而他毫不知情,等发现时粉丝已经在抱怨「我的评论怎么没了」。待确认列表让误伤是可见可恢复的。折中做法是:对明确的高危模式(含手机号、微信号、外链)允许直接删除,普通关键词进待确认——按规则的确定性分级。

    「全选筛选结果」传条件而不是传 ID,代价是前后端的语义要严格一致。创作者点全选时看到的是「1247 条」,服务端按条件处理时可能因为期间有新评论进来而变成 1250 条。做法是全选时把「筛选条件 + 时间上界」一起传,服务端只处理这个时间点之前的评论,保证数量与创作者看到的一致。这个细节不处理会出现「我选了 1247 条,结果处理了 1250 条」的困惑。

    踩过的坑:批量删除用 offset 分页导致漏处理。创作者删了第一页的 50 条,翻到第二页时后面的评论已经前移,第二页实际显示的是原来第 100 到 150 条,中间第 50 到 100 条被跳过了。他以为处理完了,实际漏了一批广告,粉丝还在举报。修法是游标分页。教训是:任何「边遍历边删除」的场景都不能用 offset 分页——这和之前评论后端、Feed 分页的判断一致。

    踩过的坑二:创作者配了一个过宽的关键词,静默屏蔽了大量正常评论。他把一个常见词加进屏蔽规则(本意是屏蔽某类广告),结果几百条正常评论被自动屏蔽,粉丝在其他地方抱怨「评论被删」,创作者自己完全不知道,还以为是平台在删。修法就是「规则命中进待确认」,并且给每条规则展示命中数量——命中数异常高的规则会很显眼,创作者自己就会去检查。教训是:把规则配置权交给非技术用户时,必须让规则的效果可见,否则错误会静默累积。

    没做的部分:没做评论的情感分析与自动分类(自动识别攻击性言论、正向互动)。这需要模型支持,而且误判的代价(把正常评论判成攻击性)不好承担,当时只用平台已有的「疑似广告」标记。

    数字是怎么测的

    数万条评论列表的滚动流畅度:造一条有 5 万条评论的测试视频,用 Performance 面板录制持续滚动过程,检查有无长任务和掉帧要报出虚拟列表实际渲染的节点数(可视区加缓冲大约几十个)——这才是流畅的原因。同时要报测试机型。

    批量处理的规模与耗时:报「一次批量可处理多少条」以及超过阈值转异步任务的阈值是多少、怎么定的(压测出的单请求超时边界)。异步任务的完成时长也要报,否则会被问「你只是把慢转移到了后台」。

    「漏处理」的验证:构造场景——列表有 200 条评论,删除前 50 条后翻页,验证第二页显示的是第 51 到 100 条而不是第 100 到 150 条。这是个可精确验证的点,也正是我们踩过的坑。

    规则的效果与误伤:「每条规则的命中数量」以及「待确认列表中被创作者恢复的比例」。后者直接反映规则误伤情况——如果某条规则命中的评论大量被恢复,说明规则配得太宽。这个数据比「规则拦下多少广告」更有价值,因为它暴露问题而不只是展示成绩。

    不要报「垃圾评论清理率」。需要「垃圾评论总量」作为分母,而那个数字不可知。也不要报「评论管理效率提升 N 倍」——没有可比基线。可以报的是可核查的事实:单次批量的处理量、筛选条件覆盖了哪些场景、撤销窗口拦下过多少次误删。

    面试追问
    Q:一条爆款视频有几万条评论,创作者要删掉其中几百条广告,怎么支持? A:三件事配合。一是筛选——提供贴合真实诉求的条件(含指定关键词、疑似广告、零点赞、新注册用户发的、含外链或联系方式),先把要处理的那批筛出来。二是跨页批量选择——支持「全选筛选结果」,但不能选中具体 ID 列表(几千个 ID 的数组既大又容易超限),做法是记录「筛选条件 + 手动排除的 ID + 时间上界」,提交时传条件让服务端处理;时间上界很关键,保证服务端处理的数量和创作者看到的一致(否则期间有新评论进来会出现「我选了 1247 条结果处理了 1250 条」)。三是批量结果逐条返回,把「部分成功」当常态,界面区分成功与失败并提供「仅重试失败项」。还有个必须做的提示:选中数量旁边单独标出「其中 89 条来自你的粉丝」——粉丝评论是真实互动,误删的代价比误删广告大得多。
    Q:创作者边删边翻页,为什么会漏掉一批评论? A:因为用了 offset 分页。删掉第一页的 50 条之后,后面的评论整体前移,翻到第二页时 offset 还是 50,实际显示的是原来第 100 到 150 条,中间第 50 到 100 条被跳过了。创作者以为处理完了,实际漏了一批广告,粉丝还在举报。修法是游标分页:游标编码「上一页最后一条的排序值 + 评论 ID」,下一页查「排序值更小,或相等但 ID 更小」的,删除不影响后续翻页的连续性。排序值相同时必须有 ID 作为 tie-breaker,否则同时间的评论顺序不稳定,还是会乱。通用教训是:任何「边遍历边删除(或边修改排序字段)」的场景都不能用 offset 分页——这和评论后端的分页、Feed 流分页、房态网格的分页是完全同一个问题。
    Q:让创作者自己配关键词自动屏蔽,会不会把正常评论也屏蔽了? A:会,而且他自己不会知道——这是我们踩过的坑。某个创作者把一个常见词加进屏蔽规则(本意是屏蔽某类广告),结果几百条正常评论被自动屏蔽,粉丝在其他地方抱怨「评论被删」,而创作者完全不知情,还以为是平台在删修法是规则命中的评论进「待确认」列表而不是直接删除:创作者可以复查、可以恢复、可以据此调整规则。配套还要给每条规则展示命中数量——命中数异常高的规则会很显眼,他自己就会去检查;以及「待确认中被恢复的比例」,这个指标直接反映规则误伤情况。取舍上他会问「为什么不能自动删」,我的回答是按规则确定性分级:明确的高危模式(含手机号、微信号、外链)允许直接删除,普通关键词进待确认核心原则是:把规则配置权交给非技术用户时,必须让规则的效果可见,否则错误会静默累积。
    Q:创作者批量选中时手滑多选了,删了怎么恢复? A:三层保护,成本都很低。一是操作前的影响范围提示——显示选中数量以及「其中多少条来自粉丝」,批量删除超过阈值时要求二次确认;二是短时撤销窗口,删除后几秒内界面上有「撤销」按钮,这是成本最低也最有效的保护(大部分误操作会在几秒内被发现);三是「最近删除」保留一段时间可恢复,作为过了撤销窗口后的兜底。另外所有操作要留痕(谁在什么时候删了什么,规则自动触发的也要记),因为粉丝可能来问「我的评论为什么没了」,创作者需要能查。这套「提示 + 撤销 + 回收站 + 留痕」的组合是所有批量删除类功能的标准配置——我在房态后台的批量改价那里也用了同一套思路(预览 + 变更批次 + 回滚),本质是同一个判断:任何能一次性影响大量数据的操作,必须让误操作可发现、可恢复。

没有匹配的内容,换个关键词试试。

项目拆解 · 创作者后台(Vue)· 共 3 个模块 · 数字均为示例,需替换成自己项目的真实数据