ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

原生HTML+CSS+JS构建宠物店猫咖管理系统前端完整解析

原生HTML+CSS+JS构建宠物店猫咖管理系统前端完整解析 简介面向宠物店与猫咖管理场景的HTMLCSSJavaScript前端设计源码包聚焦门店日常管理的信息化展示与基础交互适合前端初学者拆解练习也可作为实际管理系统界面的参照和二次开发底子。压缩包共24个文件大小约2.35MB包含6个HTML页面、4个JavaScript脚本和1个CSS样式表另有图片与字体文件辅助视觉呈现HTML负责搭建页面结构和信息层级CSS统一整体视觉风格JavaScript承担登录校验、信息列表渲染、消息管理等动态交互图片与字体让界面更友好直观。源码目录按js、css等文件夹清晰归类页面覆盖首页入口、登录页面、用户信息、宠物信息和消息管理等多个模块开发者可以顺着页面跳转关系快速理解每一块功能对应的代码实现也方便在此基础上扩展或改造。目前已有120人浏览学习适合需要从零看完整前端项目组织方式、或想为宠物店猫咖快速搭建管理界面原型的人群参考。1. 基于 HTML 的宠物店猫咖先别急着上框架在猫咖门口放一台点单屏店员要同时处理“空位是否够用、猫咪是否在休息、套餐里绑定哪只猫”三件事。如果第一反应是上 Vue 或 React得先装 Node、配构建器门店机器稍微旧一点启动时间就够客人多等一分钟。我要讲的基于 HTML 的宠物店猫咖管理系统前端设计源码是用原生 HTML CSS JavaScript 组织的一整套页面代码入口就一个 index.html样式单独放 css业务逻辑单独放 js浏览器打开就能跑刷新后状态还能留住。它既适合前端学习者当课程设计也能用来给正式系统做高保真原型核心是把数据层和视图层拆清楚将来接后端不用推翻重来。下面按业务建模、列表渲染、交互反馈、本地持久化四条线展开。2. 从预约结账到商品库存猫咖管理系统源码里的业务建模2.1 两条主链路客人与猫咪都要有状态流转猫咖管理系统的核心不只是一个宠物图库。店员一天里重复最多的事情是客人进店安排座位把某只猫从“休息中”切成“可互动”客人离店结算时长、卖出去几袋冻干、会员积分累计。这些动作如果只做猫咪展示不叫管理系统叫宣传页。常见做法是把业务拉成两条链路一条是“客人-预约-结账”另一条是“猫咪-商品-库存”最后都汇入订单列表。前端源码不碰后端也能先模拟因为订单对象可以挂在内存里等后端就绪了再替换接口。2.2 数据模型用 JSON 对象定义猫咪、会员、订单这套源码的起点是一个 db.js 文件里面不调用接口只维护三个数组。每个字段都要能直接对应业务输入框否则后面做表单要来回改。下面是最小可运行的数据结构const db { cats: [ { id: 1, name: 豆花, breed: 美短, age: 2, status: available, // available 可互动 / resting 休息 / feeding 进食 pricePerHour: 48, tags: [亲人, 抱抱] } ], members: [ { id: 101, phone: 13800001111, points: 220, level: 银卡 } ], orders: [ { id: A001, catId: 1, phone: 13800001111, startTime: 14:00, endTime: 16:00, total: 96, status: paid } ] };参数说明status用英文字符串而不是中文是因为后续筛选和样式类名都会直接用这个值tags用数组而不是逗号分隔字符串渲染成标签时不用再 split。orders里不冗余存猫咪名字只存catId页面展示时去cats里反查这样改一只猫的名字不会导致历史订单要批量更新。我一般还会写一个工厂函数createCat(name, breed)来生成默认对象避免每次录入都要手填available和空 tags。因为这是纯前端源码上面的 db 对象默认值通过const声明实际运行时替换数据对象方法参考第 5 章。2.3 页面骨架index.html 只放容器不放业务代码整个系统只有一个页面但内容不要写死在 HTML 里。结构上分成顶栏、侧栏、内容区三块点击导航时通过>body header idapp-header宠物店猫咖管理系统/header aside idapp-nav button>function renderCats(cats) { return cats.map(cat div classcat-card ${cat.status}>const filter { keyword: , status: all, breed: all }; function updateView() { const result db.cats.filter(cat { const okStatus filter.status all || cat.status filter.status; const okBreed filter.breed all || cat.breed filter.breed; const okKeyword !filter.keyword || cat.name.includes(filter.keyword) || cat.tags.join(,).includes(filter.keyword); return okStatus okBreed okKeyword; }); document.getElementById(cat-list).innerHTML renderCats(result); } document.getElementById(search-input).addEventListener(input, function (e) { clearTimeout(window.searchTimer); window.searchTimer setTimeout(() { filter.keyword e.target.value.trim(); updateView(); }, 300); });防抖时间 300ms 是常用的窗口值店员连续输入“加菲猫”三个字页面只会在停顿之后过滤一次不会每敲一个字符就把整张列表重建一遍。filter的三字段之间是“与”的关系也就是说选“可互动”再搜“布偶”只会显示同时满足两个条件的猫。如果以后要支持“等同于任一条件”需要单独写一个条件分支源码阶段不用考虑。筛选方式与 DOM 元素对应关系filter 字段表单元素示例值keyword#search-input布偶、豆花、粘人status#status-selectavailable / resting / feedingbreed#breed-select美短、英短、布偶表格里#breed-select的选项建议在初始化时从 db.cats 里动态生成这样以后新增品种不用改 HTML。搜索输入框加上autocompleteoff否则浏览器的历史下拉框会把门店的平板界面挡住。3.3 事件委托动态列表上的按钮只绑定一次每张猫咪卡片上都有“切换状态”按钮如果每次渲染后都重新绑定内存里会留下一堆旧监听器。更干净的做法是在列表容器上只绑定一次 click然后用closest找到目标按钮document.getElementById(cat-list).addEventListener(click, function (e) { const actionBtn e.target.closest([data-actionswitch-status]); if (!actionBtn) return; const card actionBtn.closest(.cat-card); const id Number(card.dataset.id); const cat db.cats.find(item item.id id); cat.status cat.status available ? resting : available; updateView(); });closest会向上查找直到匹配选择器所以即使点击的是按钮里的文字节点也能找到按钮。Number(card.dataset.id)必须转数字DOM 的 dataset 属性一律是字符串不转的话find会一直找不到。这块逻辑就是前端面试题里高频的“事件委托 dataset”用法代码量不大但能把动态渲染的交互问题一次解决。4. 管理系统交互层宠物店风格的模态框、表单校验与状态反馈4.1 表单校验不能用 required 解决全部问题门店录入猫咪信息时最容易出错的是价格和库存。HTML 自带的required只在提交按钮触发表单事件时生效而这段源码里的“新增/编辑”弹窗用的是 div 自定义 button所以校验必须写在 save 函数里。下面是一个通用的校验函数function validateForm(data) { const errors []; if (!data.name.trim()) errors.push(请输入猫咪昵称); if (!/^1[3-9]\d{9}$/.test(data.phone || ) data.phone) errors.push(手机号格式不正确); const price Number(data.price); if (data.price ! (isNaN(price) || price 0 || price 999)) { errors.push(价格必须是 0 到 999 之间的数字); } return errors; }参数说明data.name.trim()去掉首尾空格避免只输入空格通过校验手机正则^1[3-9]\d{9}$是前端原型里常用的简化校验覆盖 13 到 19 开头的号段。price先转成数字再判断范围同时把空字符串排除掉因为空值可能表示“价格待定”。返回的errors是数组页面展示时用errors.join()拼成一行比逐条 alert 更友好。如果字段增多单独写 if 会越来越长。我一般把规则配成数组循环执行const rules [ { field: name, test: v v.trim().length 0, msg: 请输入猫咪昵称 }, { field: price, test: v Number(v) 0 Number(v) 1000, msg: 价格范围不对 } ];这个不算复杂但至少能让你在加字段时只加一条规则而不是复制一段代码。规则数组还可以接入 input 的 blur 事件实现“离开输入框就即时校验”比点保存再一次性报错更贴近门店使用习惯。4.2 新增与编辑共用一个模态框的 state 管理同一份表单打开时可能是新增也可能是编辑。源码里用currentEditId区分打开时根据 id 预填数据let currentEditId null; function openModal(catId) { currentEditId catId || null; const cat catId ? db.cats.find(item item.id catId) : { name: , pricePerHour: 48 }; document.getElementById(modal-title).textContent catId ? 编辑猫咪 : 新增猫咪; document.getElementById(cat-name).value cat.name || ; document.getElementById(cat-price).value cat.pricePerHour || ; document.getElementById(cat-modal).classList.add(show); }保存时判断currentEditId是否存在决定走更新还是新增。容易踩的坑是关闭弹窗后忘记把currentEditId重置为 null于是连续新增两条时第二条被当成编辑覆盖了第一条。解决办法是在closeModal里统一重置表单和 id。模态框常见字段校验规则可以列成一张配置表方便后端同学看懂字段控件校验规则错误提示猫咪昵称input text必填按 trim 后长度判断请输入猫咪昵称参考价格input number0 price 999价格范围不合法联系电话input tel11 位手机号可空手机号格式不正确表格里的“可空”很重要不是所有字段都必填校验时要考虑门店实际录入节奏。比如流浪猫救助信息里联系电话可能缺失这时空值应该被允许。4.3 用颜色和 toast 给店员明确反馈猫咪状态切换如果只是文字从“休息”变成“可互动”桌面端可能注意不到。这里给cat-card加三个状态类利用边框颜色做区分.cat-card.available { border-left: 4px solid #34a853; } .cat-card.resting { border-left: 4px solid #f59e0b; } .cat-card.feeding { border-left: 4px solid #ea4335; } .status-tag { padding: 2px 8px; border-radius: 10px; font-size: 12px; background: #f3f4f6; }左边界用 4px 色条不会破坏整张卡片绿、黄、红分别对应可互动、休息、进食符合店员对状态灯的既有认知。切换状态后再调用一个简单的showToast(cat.name 已切换为休息)反馈就完整了。toast 的实现不要依赖组件库用下面这个极简函数即可function showToast(message) { const toast document.getElementById(toast); toast.textContent message; toast.classList.add(show); clearTimeout(window.toastTimer); window.toastTimer setTimeout(() toast.classList.remove(show), 2000); }这里最好也加一层保护如果当前状态是feeding切走前先用confirm问一句因为进食中的猫强行打断可能会有应激反应。这个设计不是前端技术问题但管理系统源码里业务状态越真实演示给店长看时说服力越强。5. 源码收尾技巧用 localStorage 模拟持久化顺便准备好接后端5.1 封装 Store避免每个模块直接读写 localStorage纯 HTML 原型最大问题是刷新后所有新增数据消失。这里在storage.js里封装两层方法让页面看起来有持久化能力const Store { load(key, fallback) { try { const saved JSON.parse(localStorage.getItem(key)); return saved ?? fallback; } catch { return fallback; } }, save(key, data) { try { localStorage.setItem(key, JSON.stringify(data)); } catch (e) { console.warn(本地存储失败, e); } } };调用方式初始化时db.cats Store.load(cats, db.cats)每次updateView前把当前db对应字段传回给Store.save。try/catch必须加浏览器隐私模式或禁用 cookie 时 localStorage 会直接抛异常不加的话页面会白屏。??空值合并运算符只在有 fallback 时兜底避免把 null 写回数据源。5.2 验证“前端管理系统”是否可交接的三个检查点打开页面先走一遍“新增猫咪-刷新-再看列表”确认数据没丢接着打开 DevTools 的 Application 面板看 Local Storage 下对应 key 的数据是否能手动编辑这一步能发现字段命名混乱的问题最后在 Network 面板把请求禁用再点击列表筛选页面应该不报错因为纯前端源码本来就不发请求所有异常只可能来自数据层。这套源码的边界很清楚它是单机原型不是多端同步系统。后端就绪后的替换点集中在 Store 的load和save上把load换成fetch(/api/cats)的返回值转换把save换成POST请求渲染函数renderCats、筛选逻辑updateView、事件委托都不需要动。这样源码交接时后端同事看到的数据字段和页面结构完全对得上不需要再来问“orders 里的 catName 为什么没存”。本文还有配套的精品资源点击获取
返回列表