Anmedio 前端测试题全解析:用 React 实现送水服务分步下单与按星期切换的配送时段
教程【免费下载链接】ru-test-assignmentsТестовые задания для самостоятельного выполнения от разных it компаний项目地址https://gitcode.com/gh_mirrors/ru/ru-test-assignments点击查看免费下载导读本文以仓库中的 Anmedio 前端测试题 为主体完整拆解这份「送水服务在线下单」实战题的业务规则、任务分级与评估标准并给出基于 React 的分步表单、配送时段切换与表单校验的参考实现方案。读完本文你将掌握如何把一个带明确业务约束工作日/周末配送时段不同的前端需求落地为可运行、可测试、可提交评审的完整工程并理解面试官在「布局质量、自适应、语义化、JS 与 React 功底」四个维度上如何考察候选人。任务背景为什么一家送水公司要做在线下单题目设定了一个非常具体的业务场景一家抽象的送水公司доставка воды在 2020 年认为通过电话接单已经不够先进因此希望给客户在网站上直接下单的能力。这份任务的核心挑战在于它不是一个纯 UI 展示题而是一个带明确业务规则的交互题页面必须能够根据客户选择的日期星期几动态决定可选的配送时段。这类设定在真实的前端招聘测试中很典型——用最简单的业务外壳下单表单考察候选人对状态管理、条件渲染、表单校验和工程化习惯的综合掌握。在仓库的 README 中也可以看到本仓库收录了约 400 份来自近 200 家 IT 公司的真实测试题且有意不收录任何解决方案本任务同样遵循这一原则——仓库 frontend/anmedio 目录下只有题目描述本身没有现成答案因此下面所有实现方案均为基于题面要求的参考设计。核心业务规则工作日与周末的配送时段差异题目对配送时段给出了精确且唯一的业务约束见 原题 Особенности 一节日期类型可用配送时段工作日周一至周五10:00–11:00、12:00–13:00、15:00–16:003 个时段周末周六、周日12:00–13:00、15:00–16:002 个时段注意其中的业务细节周末不仅时段数量更少而且不提供上午 10:00–11:00 的时段只保留中午与下午两个时段。这意味着实现时不能简单地周末多一个或少一个时段而必须用两套独立的时段数组来表达才能保证规则的准确性。把规则形式化后可以设计为一份纯数据驱动的配置将业务逻辑与渲染逻辑解耦// deliverySlots.js export const DELIVERY_INTERVALS { weekday: [10:00–11:00, 12:00–13:00, 15:00–16:00], weekend: [12:00–13:00, 15:00–16:00], }; export function isWeekend(date new Date()) { const day date.getDay(); // 0 Sunday, 6 Saturday return day 0 || day 6; } export function getAvailableIntervals(date new Date()) { return isWeekend(date) ? DELIVERY_INTERVALS.weekend : DELIVERY_INTERVALS.weekday; }这里的关键是Date.prototype.getDay()的返回约定0 代表周日6 代表周六因此周末判断条件是day 0 || day 6其余 1–5 均为工作日。这一判断逻辑是整个功能的核心建议单独抽成纯函数并重点测试。任务分级拆解最低要求 / 最高要求 / 加分项原题将任务划分为三个层级这本身就透露出面试官的考察节奏——先看能不能交付再看有没有工程素养最低要求必做完成布局заверстать макеты按照提供的 Figma 设计稿还原页面包括整体结构、间距、字体与控件样式实现步骤切换逻辑логика переключения шагов下单流程由多个步骤组成候选人是纯 JS / jQuery 方案即可接受。最高要求进阶完成完成布局使用 React 实现这是题目对技术栈的明确期待实现不同日期星期几对应不同配送时段的逻辑——即上文的核心业务规则对用户输入添加校验例如姓名、电话、地址、配送时段等字段的非空、格式与合理性校验。加分项工程素养使用 Storybook 做组件开发与文档化统一的代码风格并使用 ESLint按开发过程提交有意义的 git commits使用构建/预处理工具链gulp、webpack 或同类工具用 jest或同类框架覆盖测试。从层级划分可以明确看到题目想要的最低交付是能跑的页面 能切换的步骤而区分度来自 React 实现、业务规则正确性、校验完整性和工程化程度。做这道题时建议按最低 → 最高 → 加分项的顺序推进先把核心流程跑通再逐层加固。分步下单表单的架构设计虽然题目没有明确规定下单流程包含哪些步骤需要以 Figma 设计稿为准但从送水服务的业务常识和分步表单的通用模式推断典型流程通常包括选择商品/数量 → 填写配送地址 → 选择配送日期与时段 → 确认订单。具体步骤以设计稿为准但步骤的状态管理思路是通用的。推荐用一个stepIndex状态驱动步骤切换配合「下一步 / 上一步」按钮与步骤校验守卫// OrderWizard.jsx import { useState } from react; const STEPS [product, address, delivery, confirm]; function OrderWizard() { const [stepIndex, setStepIndex] useState(0); const [order, setOrder] useState({}); const currentStep STEPS[stepIndex]; const goNext () { setStepIndex((index) Math.min(index 1, STEPS.length - 1)); }; const goBack () { setStepIndex((index) Math.max(index - 1, 0)); }; return ( div classNameorder-wizard headerШаг {stepIndex 1} из {STEPS.length}/header {/* 根据 currentStep 渲染对应步骤表单 */} footer button onClick{goBack} disabled{stepIndex 0}Назад/button button onClick{goNext} disabled{stepIndex STEPS.length - 1}Далее/button /footer /div ); }进阶版本可以把每一步的是否可继续抽象为isStepValid(step, order)纯函数由各步骤的校验结果驱动按钮的disabled状态避免在组件内部堆叠大量 if/else。这样既满足步骤切换逻辑的最低要求又为输入校验的最高要求预留了清晰的结构。配送时段动态切换的落地实现「按星期几展示不同配送时段」是本题区分度最高的功能点实现上需要解决两个问题数据源把工作日/周末两套时段配置化见上文DELIVERY_INTERVALS交互时机客户选择配送日期后页面立即按该日期计算可用时段并重新渲染时段选择器。典型做法是在步骤表单中维护deliveryDate状态选中日期后调用getAvailableIntervals(deliveryDate)得到当前可选项// DeliveryStep.jsx import { useState } from react; import { getAvailableIntervals } from ./deliverySlots; function DeliveryStep({ onChange }) { const [date, setDate] useState(); const [intervals, setIntervals] useState([]); const handleDateChange (event) { const value event.target.value; // 2020-01-06周一 setDate(value); setIntervals(getAvailableIntervals(new Date(value))); onChange({ deliveryDate: value, deliveryInterval: null }); // 重置时段选择 }; return ( fieldset legendДата и время доставки/legend input typedate value{date} onChange{handleDateChange} / {intervals.length 0 ( ul classNameslots {intervals.map((slot) ( li key{slot} label input typeradio namedeliveryInterval value{slot} / {slot} /label /li ))} /ul )} /fieldset ); }需要特别注意的边界情况日期未选择时不应展示时段列表避免空数据下的报错切换日期后必须清空已选的配送时段防止客户选了一个周五的 10:00–11:00再改成周六后仍保留该选项如果设计稿允许今天参与选择还要处理当天时段是否已过期的判断属于可选增强题目未强制。这一段的正确性可以用 jest 直接对纯函数做单元测试与 UI 解耦// deliverySlots.test.js import { getAvailableIntervals, isWeekend } from ./deliverySlots; describe(getAvailableIntervals, () { it(returns 3 weekday slots on Monday, () { // 2020-01-06 是周一 expect(getAvailableIntervals(new Date(2020, 0, 6))) .toEqual([10:00–11:00, 12:00–13:00, 15:00–16:00]); }); it(returns 2 weekend slots on Saturday, () { // 2020-01-04 是周六 expect(getAvailableIntervals(new Date(2020, 0, 4))) .toEqual([12:00–13:00, 15:00–16:00]); }); it(recognizes Sunday as weekend, () { // 2020-01-05 是周日 expect(isWeekend(new Date(2020, 0, 5))).toBe(true); }); });测试用例应覆盖周一至周五中的某一天、周六、周日三类情况确保getDay()的 0/6 边界没有被写错——这正是业务规则类题目最值得用测试锁定的部分。表单校验设计原题在最高要求中明确要求对用户输入做校验。结合下单场景建议覆盖以下字段与规则具体字段以设计稿为准字段校验规则失败提示示例姓名非空、去除首尾空格后长度 ≥ 2«Укажите имя»电话非空、匹配电话号码格式«Введите корректный номер телефона»配送地址非空、最小长度如 ≥ 5«Укажите адрес доставки»配送日期必选«Выберите дату доставки»配送时段必选且必须是当前日期可用时段«Выберите время доставки»推荐把校验写成返回错误信息的纯函数与 UI 解耦// validation.js export function validateAddress(value) { const trimmed value.trim(); if (!trimmed) return Укажите адрес доставки; if (trimmed.length 5) return Адрес слишком короткий; return null; } export function validatePhone(value) { const trimmed value.trim(); if (!trimmed) return Укажите номер телефона; if (!/^\?\d[\d\s()-]{9,}$/.test(trimmed)) return Введите корректный номер телефона; return null; }交互上有两种常见策略提交时统一校验错误全部展示或失焦后即时校验逐字段提示。更完善的方案是二者结合——首次失焦即校验再次输入时实时清除错误最后在下一步时做整体把关。此外配送时段必须属于当前日期的可用列表这条规则建议与getAvailableIntervals复用同一数据源避免校验逻辑和展示逻辑各自维护一份时段列表而导致不一致。工程化加分项把交付从能跑提升到可维护原题明确列出五项加分项这五项共同指向同一个信号面试官想看候选人是否具备交付生产级前端代码的习惯。逐项落地建议如下Storybook组件驱动的开发与文档化把表单拆成可独立展示的组件输入框、单选时段组、步骤指示器、按钮并为每个组件编写 Story。好处是开发时无需启动整个下单流程即可单独调试每个 UI 状态如校验失败态、空态同时 Story 本身也是给面试官展示组件设计能力的说明书。ESLint 统一代码风格配置 ESLint推荐eslint-plugin-react与eslint-plugin-react-hooks并把npm run lint纳入提交前检查。统一风格的价值在多人协作中体现但即使单人来写一份可运行的 lint 配置也是工程化的直观证据。有意义的 git commits按完成布局 → 步骤切换 → 配送时段逻辑 → 校验 → 测试 → 工程化配置的顺序切分提交每个 commit 只做一件事、信息清晰可读。提交历史本身就是面试官评估候选人工作组织方式的素材。构建与预处理工具链题目点名了 gulp、webpack 等工具。现代实践是使用 Vite 或 Create React App 这类开箱即用的构建工具配以 Sass/PostCSS 做样式预处理。核心诉求是证明候选人理解构建、打包与开发服务器的工作方式而不必纠结于具体框架选型。jest 测试覆盖至少覆盖两类测试对getAvailableIntervals、isWeekend、校验函数等纯逻辑的单元测试以及用 React Testing Library 对选择周六后只出现两个时段这类交互行为的组件测试。测试不追求覆盖率数字而是精准锁住业务规则。评估标准解读面试官在看什么原题在提交说明中给出了明确的评估维度见 原题 Как делать тестовое? 一节布局质量качество верстки像素级还原设计稿的程度间距、字号、颜色是否一致自适应адаптивность在手机、平板、桌面不同视口下布局是否正常重点考察表单与时段列表的响应式处理语义化семантичность是否正确使用header、main、fieldset、legend、label、button等语义标签能否做到无鼠标操作下的键盘可达性JS 功底对异步、事件、日期处理等基础能力的掌握React 经验组件拆分、状态管理、Hooks 使用是否自然是否存在反模式。由此可以反推一份自我检查清单设计稿上的每个元素是否都对齐在 375px 宽度下时段单选是否仍然可点所有表单控件是否有对应的label切换日期后旧时段是否被正确清空React 组件是否按职责拆分而非一个巨型组件这些细节往往比功能本身更能拉开候选人差距。提交方式与实战建议原题推荐的提交方式为fork 该仓库 → 在分支上完成实现 → 提交 pull request并以Иванов Иван Иванович式的个人文件夹命名示例同时也明确表示这只是建议候选人可以按自己习惯的方式交付评估以实际能力为准参见 原题提交说明。联系人和联系方式在原题中均有提供正式应聘时可直接按题目中的邮箱与 Telegram 联系。实战推进建议按以下顺序先看设计稿梳理页面结构、步骤数量与每个字段把 UI 拆成组件清单先做纯静态布局完成最低要求保证设计稿还原度接入步骤切换用stepIndex状态驱动让流程先跑通实现配送时段逻辑把业务规则抽成纯函数并配单测补全校验字段级 步骤级双重把关最后做工程化Storybook、ESLint、构建工具、测试与规范的 git 提交历史。延伸这道题在仓库中的练习价值在仓库的 frontend 目录 下还有大量同类真实测试题如 avito-tech、aviasales、tutu-ru 等公司的前端题目它们与本任务共享同一考察内核用真实业务约束考察组件设计、状态管理与工程习惯。由于本仓库 README 明确说明有意不收录解决方案其缺失恰恰让练习成为练习因此把本任务当作一次全真模拟——按真实面试节奏从零交付一个可运行、有测试、有清晰提交历史的工程——就是最高效的练习方式。赞分享教程【免费下载链接】ru-test-assignmentsТестовые задания для самостоятельного выполнения от разных it компаний项目地址https://gitcode.com/gh_mirrors/ru/ru-test-assignments点击查看免费下载相关推荐CloudExplorer Lite API接口详解如何快速集成到现有企业系统CloudExplorer Lite API接口详解如何快速集成到现有企业系统 CloudExplorer Lite作为一款开源的轻量级云管平台提供了强大的掌握macOS菜单栏管理Ice让你的工作空间清爽高效掌握macOS菜单栏管理Ice让你的工作空间清爽高效 macOS菜单栏整理神器Ice是一款专为效率追求者设计的强大工具它能帮你一键告别杂乱界面打造清爽有序桌面应用推荐项目Pushdeer - 实时消息推送服务的简单实现推荐项目Pushdeer 实时消息推送服务的简单实现 是一个轻量级的开源项目旨在为开发者提供一种快速、简单的实时消息推送服务。该项目由易晨easychen后端消息路由移动开发物联网上一篇vJoy虚拟摇杆终极配置指南从Windows驱动到游戏开发的完整解决方案下一篇游戏性能革命DLSS版本智能管理全攻略创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考