第1题-达人数据看板

小红书9月13日机考题目与解析

第一题 - 项目需求概览:达人数据看板

题目

项目名称:达人数据看板

本项目面向运营团队,目标是构建一个前后端分离的「达人数据分析看板」Web 应用,帮助运营人员从多维度了解平台达人的成长趋势、内容表现与粉丝画像。系统需预置不少于 500 条达人初始数据,并支持数据持久化与 API 通信。

核心功能包括:

  1. 数据概览:展示平台达人总数、本周新增达人、平均互动率、平均粉丝数等关键指标卡片,并显示环比升降百分比。
  2. 达人排行:支持按粉丝数、互动率、近 7 天涨粉数、笔记数排序,支持昵称搜索与达人等级筛选。
  3. 趋势分析:以折线图展示日活跃达人数、日均互动率、日新增笔记数,支持近 7 天 / 近 30 天切换与悬停交互。
  4. 粉丝画像:展示地域、年龄、兴趣标签等分布,支持切换不同达人查看。
  5. 内容分析:对比美妆、穿搭、美食、旅行、健身等品类的平均互动率、点赞数、收藏数。
  6. 数据导出:将当前筛选达人列表导出为 CSV,字段包括昵称、等级、粉丝数、互动率、涨粉数、笔记数。
  7. 实时更新:支持每 30 秒或自定义间隔自动刷新,图表平滑过渡,页面顶部显示最后更新时间。
  8. 图表下钻:点击品类或地域图表可逐级下钻,保留面包屑导航并支持返回上级。
  9. 达人对比:选择 2–5 个达人,用雷达图或多维柱状图对比粉丝数、互动率、涨粉数、笔记数。
  10. 自定义布局:支持拖拽调整图表卡片位置、显示/隐藏模块,布局配置自动保存。
  11. 高级筛选:支持多条件组合筛选,筛选方案可命名、保存、切换、增删改。
  12. 数据缓存:实现前端缓存策略,相同条件不重复请求,支持 5 分钟自动失效与手动强制刷新。
  13. 异常检测:自动标记互动率突增/突降超过 50% 的异常数据,红色高亮并在悬停时展示原因分析。

技术约束: 前后端分离、API 通信、使用图表库、数据持久化、首屏加载不超过 3 秒、筛选响应不超过 500ms、缓存命中率不低于 70%、提供一条命令启动与 README 说明。

第1题-达人数据看板

1000ms尝试: 0已通过: 0难度: 5所属公司 :小红书

https://codefun2000.com/aicoder-gym/problems

项目说明 赤帖内容运营组需要一块达人经营台,用来盯创作者体量变化、笔记互动、粉丝结构和品类对比。本题要求做成可预览的经营台 Web 应用,把多维展示、筛选和下钻接到同一套接口。

考试说明

  • 允许借助 AI 辅助编码
  • 目标:实现完整的达人经营台,支持可视化呈现与多维分析

一、功能要求

1.1 数据概览

  • 页面顶部四张指标卡,选择器与字段如下:
选择器 JSON 字段 口径
#kpi-total totalCreators 当前达人条数
#kpi-week-new weekNew createdAt2026-09-07(含)的人数
#kpi-avg-rate avgInteractionRate 全量 interactionRate 算术平均,四舍五入到 4 位小数
#kpi-avg-followers avgFollowers 全量 followers 算术平均,四舍五入到整数
  • 每张卡旁展示环比:#kpi-total-wow / #kpi-week-new-wow / #kpi-avg-rate-wow / #kpi-avg-followers-wow
  • GET /api/overview 返回上述四项,以及
{
  "wow": {
    "totalCreators": { "value": 2.1, "direction": "up" },
    "weekNew": { "value": 0.0, "direction": "flat" },
    "avgInteractionRate": { "value": -1.4, "direction": "down" },
    "avgFollowers": { "value": 3.0, "direction": "up" }
  },
  "lastUpdated": "2026-09-13T10:00:00+08:00"
}
  • 环比公式:value = round1((current - previous) / previous * 100)previous 为 0 时 value0.0directionup / down / flatvalue 分别为正、负、零)
  • 启动后上期快照固定为:totalCreators=490weekNew=12avgInteractionRate=0.0310avgFollowers=72000
  • 百分数展示一位小数,并带 %(例如 2.1%

1.2 达人排行

  • GET /api/creators 查询参数:
参数 含义
sort followers / interactionRate / followerGrowth7d / posts,缺省 followers;其它值 → 400 invalid sort
q 按昵称包含匹配,大小写不敏感;缺省或空串不过滤
level 初级 / 中级 / 高级 / 头部;缺省不过滤
category 品类精确匹配
city 城市精确匹配
schemeId 使用已保存筛选方案;缺省则用「当前已应用方案」(若有)
  • 排序一律降序;主键能相等时按 nickname Unicode 码点升序。rank 从 1 连续编号(过滤之后)
  • 响应:{ "items": [ ... ], "total": <过滤后条数> }。单条含 rank,id,nickname,avatar,level,category,followers,interactionRate,followerGrowth7d,posts,city,createdAt,anomaly,anomalyReason
  • interactionRate 输出 4 位小数。anomaly 为布尔;非异常时 anomalyReasonnull
  • 表体 #ranking-table tbody 中每一行:[data-testid="creator-row"],带 data-id;异常行再带 data-anomaly="true"
  • 搜索框 #search-input,等级 #level-filter,排序 #sort-select(option 的 valuesort 参数相同)

1.3 趋势分析

  • GET /api/trends?range=7range=30。其它值 → 400 invalid range
  • 点按 date 升序;最后一天固定 2026-09-13range=7 共 7 个点(2026-09-072026-09-13),range=30 共 30 个点
  • 每个点:date, activeCreators, avgInteractionRate, newNotes
  • 页面 #trend-range7 / 30),折线容器 #trend-chart;悬停点用 title 写出该日三个数值

1.4 粉丝画像

  • GET /api/portraits/:id{ "creatorId", "region", "age", "interests" },三个对象的取值均为比例且各自求和为 1(允许 1e-9 误差)
  • 未知 id → 404 creator not found
  • #portrait-select 切换达人;#portrait-region#portrait-age 用柱或扇区展示,扇区/柱带 data-key

1.5 内容分析

  • GET /api/categories{ "items": [ { "category", "avgInteractionRate", "avgLikes", "avgCollections", "creatorCount" } ] }
  • 品类顺序固定:美妆穿搭美食旅行健身
  • 三个均值只统计该品类下达人,分别对 interactionRate / likes / collections 做算术平均;比率 4 位小数,点赞与收藏四舍五入到整数
  • #category-chart 内每个品类:[data-testid="category-bar"][data-category="美妆"]

1.6 数据导出

  • GET /api/creators/export 使用与列表相同的过滤参数(含已应用方案)
  • Content-Typetext/csv;UTF-8;LF 换行;无 BOM
  • 表头恰好一行且顺序为:nickname,level,followers,interactionRate,followerGrowth7d,posts
  • interactionRate 写成 4 位小数;行顺序与当前列表一致
  • #export-btn 触发下载

1.7 实时数据更新

  • 页面顶部 #last-updated 展示 overview.lastUpdated(ISO-8601)
  • #refresh-btn 调用 POST /api/refresh:先把当前四项概览写入上期快照,再对每条达人执行 followers += max(1, followerGrowth7d // 7),然后将虚拟时钟推进 1 秒,把 lastUpdated 设为推进后的时刻,并清空列表缓存
  • 不要求浏览器定时器;刷新后卡片与图表按新数据重绘即可

1.8 图表下钻功能

  • 点击品类柱:列表改为该 category,面包屑为 概览 / <品类>
  • 点击地域柱:列表改为该 city,面包屑为 概览 / <城市>
  • 再点击一名达人:面包屑为 概览 / <上一层名称> / <昵称>,画像切到该达人
  • #breadcrumb 内节点 [data-level="0"](概览)、[data-level="1"][data-level="2"];点击上级应回到对应层级
  • 下钻列表与 GET /api/creators?category= / ?city= 结果一致

1.9 达人对比分析

  • POST /api/compare{ "ids": ["fix-mei", "fix-cmp-a"] }
  • 先按出现顺序去重;去重后数量不在 25400 compare size;任一 id 不存在 → 404 creator not found
  • 成功:{ "items": [ { "id", "nickname", "followers", "interactionRate", "followerGrowth7d", "posts" } ] },顺序与去重后的 ids 一致
  • #compare-panel 展示结果;行 [data-testid="compare-row"][data-id];可用多维柱(每个度量一个 [data-metric]
  • 面板内可加减达人,但提交前必须仍满足 2~5 人

1.10 自定义看板布局

  • 不做拖拽。GET /api/layout{ "modules": { "overview": true, "ranking": true, "trend": true, "portrait": true, "category": true, "compare": true } }
  • PUT /api/layout 体可只带部分键,与现网状态合并;未知模块名或非布尔 → 400 invalid layout
  • 对应区块 [data-module="<name>"] 必须带 data-visible="true""false"
  • 勾选框 #layout-toggle-<name>(例如 #layout-toggle-ranking)切换显隐;配置保存在服务端内存,刷新页面后应再拉接口恢复

1.11 高级筛选

  • 方案体:{ "name": "高粉美妆", "rules": [ { "field": "level", "op": "eq", "value": "高级" }, { "field": "category", "op": "eq", "value": "美妆" }, { "field": "followers", "op": "gt", "value": 100000 } ] }
  • fieldnickname / level / category / followers / interactionRate / followerGrowth7d / posts / city
  • opeq / ne / gt / gte / lt / lte / containscontains 仅对字符串字段,大小写不敏感)
  • 多条规则之间是 AND
  • POST /api/filters 创建,id 形如 flt-1 起递增;GET /api/filters{ "items": [...] }
  • PUT /api/filters/:id 整单替换 namerulesDELETE /api/filters/:id
  • POST /api/filters/:id/apply 设为当前方案;POST /api/filters/clear 清空当前方案
  • 列表在方案结果之上再叠加 qlevelcategorycitysort
  • name 空 → 400 invalid filter;未知 field/op400 invalid filter;创建时 name 与已有方案重复 → 400 duplicate filter;更新时与其它方案重名同样 duplicate filter;未知 id → 404 filter not found
  • #filter-name#filter-save#filter-schemes(每项 [data-testid="filter-item"][data-id])、#filter-clear

1.12 数据缓存机制

  • GET /api/creators 缓存。键为影响结果的查询串(sort,q,level,category,city,schemeId)以及当前已应用方案
  • 首次或失效后响应头 X-Cache: MISS;虚拟时钟 TTL 内的相同键 X-Cache: HIT,正文与首次字节级一致
  • TTL 为 300 虚拟秒
  • POST /api/cache/flushPOST /api/refreshPOST /api/reset 均清空缓存
  • POST /api/clock{ "seconds": 301 } 只推进虚拟时钟(不改达人数据);GET /api/clock{ "now": "<ISO-8601>" }

1.13 异常数据检测

  • 对每条达人:change = (interactionRate - prevInteractionRate) / prevInteractionRate(分母为 0 则不标记)
  • 严格大于 0.5 的绝对值才算异常;等于 0.5 不算
  • anomalyReason 必须含 突增突降,以及一位小数的百分数
  • 异常行加红(class is-anomaly),悬停 title 等于 anomalyReason

二、技术约束

  • 前后端分离:页面只请求 /api/*;预览栈会把 /api 反代到后端
  • 图表用 SVG 或 DOM 绘制,工作区不能再装依赖
  • 状态放在进程内存。POST /api/reset 恢复启动态(达人、快照、时钟 2026-09-13T10:00:00+08:00、布局全显、方案清空、缓存清空),成功 { "ok": true }
  • 失败体统一 { "error": "<关键字>" },关键字只能是:not implemented / invalid sort / invalid range / creator not found / compare size / invalid layout / invalid filter / duplicate filter / filter not found
  • 启动读环境变量 PORT,绑定 0.0.0.0:$PORT,未设置时为 8000
  • 不要求登录、数据库、第三方开放平台

三、非功能要求

  1. 数据量:启动即有 500 条达人(预置生成,含下方固定样例行)
  2. 页面在 1280px 宽屏下各模块可同时看见,无需横向滚动才能读到四张指标卡
  3. 筛选、排序切换后列表与导出应对齐同一结果
  4. 统计口径按上文公式,四舍五入采用「一半远离 0」(与 Python decimal.ROUND_HALF_UP 相同)
  5. 一条命令可启动后端;预览由平台拉起 backend/main.pyfrontend/index.html
  6. 虚拟时钟与缓存失效必须可复现,不依赖机器墙钟

四、数据描述

初始数据 应用启动时需预置以下数据(用生成逻辑即可,固定样例行的 id 不得改):

达人(共 500 条,字段如下):

{
  "id": "fix-mei",
  "nickname": "赤帖小美",
  "avatar": "https://placeholder.local/100",
  "level": "头部",
  "category": "美妆",
  "followers": 980000,
  "following": 210,
  "posts": 186,
  "likes": 4200000,
  "collections": 980000,
  "interactionRate": 0.082,
  "prevInteractionRate": 0.080,
  "followerGrowth7d": 12600,
  "createdAt": "2024-03-01",
  "city": "上海",
  "ageGroup": "18-24"
}

等级只能是 初级 / 中级 / 高级 / 头部。品类只能是 美妆 / 穿搭 / 美食 / 旅行 / 健身。城市只能是 上海 / 北京 / 广东 / 浙江 / 其他

固定样例行(必须原样存在,其余 487 条由生成器补齐):

id nickname level category followers 备注
fix-mei 赤帖小美 头部 美妆 980000 高粉
fix-drop 穿搭阿北 高级 穿搭 88000 互动率相对昨日下跌超过 50%
fix-surge 寻味阿广 中级 美食 56000 互动率相对昨日上涨超过 50%
fix-edge 旅行边沿 旅行 42000 相对昨日上涨 51%
fix-exact 恰好五成 40000 相对昨日恰好 50%,不算异常
fix-safe 健身稳当 初级 健身 9800 未过异常线
fix-new 本周新人甲 美妆 860 createdAt=2026-09-11
fix-case LimeLook 高级 穿搭 64000 用于大小写搜索
fix-tie-a 并列阿西 77777 fix-tie-b 粉丝相同
fix-tie-b 并列阿东 昵称码点大于阿西
fix-cmp-a 对照阿一 头部 健身 410000 对比用
fix-cmp-b 对照阿二 高级 旅行 210000
fix-cmp-c 对照阿三 中级 美食 91000

fix-dropinteractionRate=0.0120prevInteractionRate=0.0400fix-surge0.0900 / 0.0300fix-edge0.1510 / 0.1000fix-exact0.1500 / 0.1000fix-safe0.0450 / 0.0400

趋势(近 30 天,含当天):

{
  "date": "2026-08-15",
  "activeCreators": 8000,
  "avgInteractionRate": 0.0300,
  "newNotes": 20000
}

粉丝画像(每个达人一条):region / age / interests 为比例对象。本城在 region 中为 0.40,其余四城各 0.15age 固定 18-24:0.35, 25-30:0.30, 31-35:0.20, 36+:0.15interests 固定 美妆:0.30, 穿搭:0.25, 美食:0.20, 旅行:0.15, 其他:0.10

品类接口的均值必须从达人列表现场汇总,启动示例里的品类数字只表示字段形状:

[
  {"category": "美妆", "avgInteractionRate": 0.042, "avgLikes": 5600, "avgCollections": 2300}
]

五、作答要求

  1. 代码提交:在工作区内改后端与页面,保持预览可打开
  2. README:以本文为规格;技术栈为 Python(Flask 已在镜像)+ 静态页
  3. 数据初始化:首次启动即有 500 条达人与 30 天趋势
  4. 代码规范:命名清楚,分区注释说明各块职责即可

六、启动方式

请从工作区根目录启动后端:

# 启动服务
PORT=8000 python3 backend/main.py

未设置 PORT 时监听 8000。平台预览会注入 PORT 并托管 frontend/index.html。公开自测入口为 sample_testcase/run_sample_testcases.js(由平台拉起页面与接口,不计成绩)。

七、验证策略

提交结果将从以下维度进行验证:

  1. 功能完整性:概览、排行、趋势、画像、品类、导出、刷新、下钻、对比、布局显隐、筛选方案、缓存头、异常标记是否按契约工作
  2. 数据可视化:图表容器有可交互节点,下钻与对比区域可用
  3. 数据准确性:汇总、环比、品类均值、异常判定与题面公式一致
  4. 筛选功能:搜索、排序、等级、多规则 AND、方案切换与导出范围一致
  5. 实时性:刷新后 lastUpdated 与环比快照更新,缓存按 TTL 与手动失效
  6. 代码质量:结构可维护
  7. 视觉呈现:1280px 下模块齐全,隐藏模块不再占主视区

第1题-达人数据看板
https://mingsm17518.github.io/2026/09/19/刷题笔记/小红书/2026年9月13日/第1题-达人数据看板/
作者
Ming
发布于
2026年9月19日
更新于
2026年9月20日
许可协议