Робопрактика 前端测试任务:用 React 构建员工社交网络用时统计表格)
教程【免费下载链接】ru-test-assignmentsТестовые задания для самостоятельного выполнения от разных it компаний项目地址https://gitcode.com/gh_mirrors/ru/ru-test-assignments点击查看免费下载导读本指南以 frontend/red-mad-robot/frontend-robopractice.md 这份真实测试任务文档为核心讲解如何完成 Red Mad Robot「Робопрактика」实习前端任务用 React 从后端接口取回员工在工作电脑上使用社交网络的时长数据渲染成一张支持排序、搜索、分页、固定首末列与列宽拖拽的月度统计表格。读完本文你将掌握该任务从需求拆解、技术选型到每个进阶功能的具体实现思路可直接作为动手编码的完整清单。一、任务背景与核心目标公司记录了员工在工作电脑上访问社交网络所花费的时间任务要求做一个 Web 应用让使用者能够方便地查看这些数据。文档明确要求应用必须提供三种查看能力每天的时间展示用户在某月每一天1 日、2 日、3 日……在社交网络上花费的时间月度总时间展示每个用户整月的累计时长按姓名搜索能够按员工姓名快速定位。整个任务在仓库中的定位是 red_mad_robot 公司的前端标注(JS)测试题仓库 README.md 的 Frontend 索引中将其登记为「Тестовое задание Робопрактики」。需要说明的是该仓库是 Hexlet 社区维护的约 400 个真实测试任务目录刻意不提供任何解决方案README 明确写道「Решений здесь нет намеренно」因此本文提供的是任务拆解与实现思路而不是参考答案这正是该仓库「用实践练手」的设计初衷。二、技术选型约束与自由度原文档对技术栈给出了明确的强制项与可选项维度要求说明框架React必须这是唯一强制技术栈语言TypeScript / JavaScript 任选按团队习惯与个人偏好决定组件库MUI React、Ant Design 或其他允许直接使用现成组件库加速开发构建工具create-react-app或自建webpack、rollup、parcel、vite、esbuild 等CRA 开箱即用vite 更适合追求速度的新项目从源码结构推断任务留出的自由度很大语言、组件库、构建工具都不限制唯独 React 是硬性要求。这意味着考察重点是用 React 正确组织组件状态、数据流与交互逻辑的能力而非工具熟练度。选型建议如果追求最快交付可直接使用create-react-app Ant Design 的Table组件其内置排序、固定列、分页能力如果想展示更深的技术功底可选用vite TypeScript 自行实现全部交互更能体现对受控组件与性能优化的理解。三、数据获取启动本地服务并拉取用户数据原文档给出了数据获取的明确步骤运行命令npm run server启动本地数据服务服务提供GET /api/users接口返回表格所需的全部数据。这是一个典型的「前端 本地 mock 服务」开发模式。可以推断后端返回的是一个用户数组每个用户对象至少包含姓名字段对应任务中搜索依据的Fullname按日期组织的时长数据用于填充 1、2、3…N 号列月度总时长或可由前端累加得出。实现要点在 React 中获取数据应放在useEffect中并用loading/error/data三段式状态管理const [users, setUsers] useStateUser[]([]); const [loading, setLoading] useState(true); useEffect(() { fetch(/api/users) .then((res) res.json()) .then((data) { setUsers(data); setLoading(false); }) .catch((err) console.error(err)); }, []);建议将server与前端 dev server 配置为可同时启动如concurrently或 Vite proxy避免跨域与端口不一致问题。四、表格结构、数据填充与渲染规则应用主体是一张用户统计表列结构为| User | 1 | 2 | 3 | ... | Monthly |其中User是员工姓名中间数字列对应月份中的每一天Monthly是用户当月总时长。原文档对渲染规则有两条硬性要求必须精确实现逐日填充每一行中若该用户在某个日期有数据则显示对应时长若当天没有数据必须显示 0而不是留空或显示-月度合计Monthly total列显示该用户整月的总时间。实现思路先确定表格的日期列集合从所有用户数据中取当月天数例如 31 天再为每个用户按日期索引取值function buildRows(users: User[], daysInMonth: number) { return users.map((user) { const daily new Array(daysInMonth).fill(0); user.dailyStats?.forEach((d) { daily[d.day - 1] d.minutes; }); return { fullname: user.fullname, daily, monthly: daily.reduce((sum, v) sum v, 0), }; }); }这样无数据显示 0与月度合计两条规则在同一份数据结构中天然成立后续排序、搜索也只需基于这份扁平化后的行数据操作。五、五个进阶功能完整实现思路原文档在「Дополнительно」部分列出五项加分功能它们是本任务真正的考察重点1. 每列升序 / 降序排序要求对每一列User、每一天、Monthly都支持升序与降序切换。实现思路维护一个排序状态{ key: string; order: asc | desc }点击表头时切换方向用useMemo缓存排序结果避免每次渲染都重新计算const sortedRows useMemo(() { const sorted [...rows]; if (sort.key) { sorted.sort((a, b) { const av a[sort.key], bv b[sort.key]; return sort.order asc ? av - bv : bv - av; // 数值列 }); } return sorted; }, [rows, sort]);注意 User 是字符串列应使用localeCompare做文本比较数值列每日、Monthly直接用数字差。表头点击处应给出当前排序方向的可视化指示如箭头图标。2. 按姓名Fullname 字段搜索搜索框输入关键字时实时过滤出 Fullname 匹配的用户。实现思路受控输入框 useMemo过滤建议用toLowerCase().includes()做不区分大小写的子串匹配数据量大时可加防抖debounce或直接用useDeferredValue降低输入卡顿const [query, setQuery] useState(); const filtered useMemo( () sortedRows.filter((r) r.fullname.toLowerCase().includes(query.trim().toLowerCase())), [sortedRows, query] );注意过滤、排序、分页三个环节的顺序先过滤 → 再排序 → 最后分页才能保证结果正确一致。3. 前端分页前端切分页面明确要求后端返回全量列表分页在前端完成。这与常见的「后端分页」模式相反数据量不大时是合理做法。实现思路维护page与pageSize状态对过滤排序后的结果做切片const pagedRows useMemo( () filtered.slice((page - 1) * pageSize, page * pageSize), [filtered, page, pageSize] );同时展示第 X / Y 页、总条数并处理过滤后页数收缩导致页码越界的场景例如page totalPages时回退到最后一页。4. 首列与末列在横向滚动时固定User首列与Monthly total末列在表格出现横向滚动条时必须吸附sticky在自己的侧边不能被滚动隐藏。这是长表格可用性的经典需求。实现思路给首列position: sticky; left: 0末列position: sticky; right: 0并设置对应的z-index表头区再高一档与背景色避免滚动时内容穿透重叠th:first-child, td:first-child { position: sticky; left: 0; z-index: 1; background: #fff; } th:last-child, td:last-child { position: sticky; right: 0; z-index: 1; background: #fff; } th { position: sticky; top: 0; z-index: 2; }若使用 Ant Design 的Table可通过fixed: left/fixed: right直接声明固定列MUI 的DataGrid也原生支持该能力。5. 列宽可拖拽调整resizeable所有列都应支持用鼠标拖拽表头边缘改变宽度。实现思路为每个表头维护宽度状态在表头右侧放置拖拽手柄监听mousedown→mousemove计算增量→mouseup结束事件更新宽度注意拖拽结束后移除监听、防止文本选中user-select: none。也可直接引入react-resizable、react-table配合useResizeColumns等成熟库降低实现成本。六、建议的组件拆分与验收清单从实现角度建议将应用拆分为四个职责单一的组件App数据获取与顶层状态SearchBar受控搜索输入StatsTable表格主体接收过滤/排序/分页后的行数据Pagination分页控件或复用组件库内置分页。建议的验收顺序对照原文档逐条勾选npm run server能启动GET /api/users能返回数据前端成功渲染表格列完整User 当月每一天 Monthly无数据的日期单元格显示 0Monthly 合计正确点击任意表头可升序/降序切换搜索框按 Fullname 过滤即时生效分页在前端生效翻页、总数显示正确横向滚动时首列与末列固定不动拖拽表头可改变列宽。七、仓库上下文与延伸阅读本任务文档位于仓库的 frontend/red-mad-robot/frontend-robopractice.md仓库根 README.md 按公司字母序索引了全部任务该条目为「red_mad_robot — Тестовое задание Робопрактики(JS)」。与本题同类型的 React 表格/列表任务还可见 frontend/kode/trainee-test-frontend.md、frontend/quantify-the-world/react-test.md可一并作为练习素材。仓库由 scripts/download-assignments.py 与 scripts/check-relative-links.py 等脚本维护保证各任务文档与索引链接一致。最后提醒完成本任务时不要忘记仓库的约定——练习时应像真实面试一样自带 git、写清 README、尽可能补测试如用 Vitest 覆盖排序与合计逻辑这既是 README 中「Как пользоваться」的建议也是此类任务在真实面试中的加分项。赞分享教程【免费下载链接】ru-test-assignmentsТестовые задания для самостоятельного выполнения от разных it компаний项目地址https://gitcode.com/gh_mirrors/ru/ru-test-assignments点击查看免费下载相关推荐KODE 前端实习生测试任务实战指南React TypeScript 实现员工目录应用KODE 前端实习生测试任务实战指南React TypeScript 实现员工目录应用 导读 本文以开源仓库 ru test assignments ht教程Aviasales 前端测试任务实战指南用 React 从零构建机票列表与筛选页面Aviasales 前端测试任务实战指南用 React 从零构建机票列表与筛选页面 导读 本文以 frontend/kosyanmedia/deprecate教程AppBooster 前端 GraphQL 测试任务实战用 React GitHub GraphQL API 构建 Issue 管理器AppBooster 前端 GraphQL 测试任务实战用 React GitHub GraphQL API 构建 Issue 管理器 导读 本文围绕开源教程上一篇VideoSrt多语言支持中英日韩法德西意泰等多国语言字幕生成终极指南下一篇GarlandView Android动画原理详解从源码到实现创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考