项目地址:https://atomgit.com/Hhuhkt/campus-second-hand 技术栈:HTML5 CSS3 JavaScript(原生三件套,零框架、零构建工具)一、项目背景与动机每逢毕业季,宿舍楼下总会堆满被遗弃的宝贝:九成新的台灯、只翻过几页的考研教材、吃灰一年的吉他;而开学季,新生们又在四处打听哪里能买到便宜的二手教材和电器。供给和需求明明就在同一栋楼里,却缺少一个把它们连接起来的地方。这就是「校淘 CampusSecond」的出发点——一个专为大学生设计的二手货物交易平台。它不像闲鱼那样面向全社会,而是聚焦校园场景:同校面交、当天拿货、当面验货,信任成本天然更低。作为一个课程实践项目,我选择用最朴素的前端三件套来实现它:不依赖 React、不依赖 Vue、不用任何打包器,一个浏览器、三个文件,双击 index.html 就能完整运行。我希望用这个项目证明:原生 Web 技术同样能做出体验现代、功能完整的页面。二、功能总览模块 功能点 导航栏 毛玻璃吸顶导航、全局关键词搜索 Hero 首屏 渐变主视觉 平台口号,一键直达商品区️ 商品分类 8 大类目,每类独立图标与专属配色,点击即筛选️ 在售好物 分类筛选 关键词搜索 商品卡片(价格/成色/浏览量) 价格分析 各类目均价柱状图 各成色占比饼图(纯 CSS 实现) AI 购物顾问 对接大模型流式接口,实时逐字回答二手购物问题 响应式 适配手机、平板、桌面三种屏幕宽度三、页面结构与设计思路整个页面按「先逛、再买、后决策」的用户路径纵向展开:导航栏 → Hero → 商品分类 → 在售好物 → 价格分析 → AI 顾问 → 页脚3.1 视觉设计主色调:科技蓝 #4f6ef7 作为主色,传递平台托管、值得信赖的感觉;暖橙 #ff7e5f 作为强调色,专门用于价格数字——价格是二手交易里最抓眼球的元素,必须让它跳出来。配色系统:所有颜色收敛到 CSS 变量里,一处修改全站生效::root {–primary: #4f6ef7;–accent: #ff7e5f;–radius: 14px;–shadow: 0 6px 20px rgba(79, 110, 247, .12);}卡片化语言:分类、商品、图表全部使用白底圆角卡片 悬浮上浮动效(translateY(-4px) 阴影加深),风格统一、层次清晰。毛玻璃导航:backdrop-filter: blur(10px) 让吸顶导航呈现半透明磨砂质感,滚动时内容从导航下穿过的细节很有质感。3.2 图标系统:用不同图标代表不同分类分类图标是这个项目里我最花心思的部分。每种类目都绑定了一个 Font Awesome 图标 一种专属颜色,用户扫一眼颜色就能定位类目:分类 图标 专属色 设计理由教材教辅 fa-book 科技蓝 知识、学术的经典联想电子产品 fa-laptop 青绿 科技感、数码感生活用品 fa-mug-hot 琥珀黄 宿舍生活的烟火气服饰鞋包 fa-shirt 珊瑚橙 活力、年轻运动器材 fa-basketball 正红 运动的能量感乐器 fa-guitar 紫色 艺术与个性美妆护肤 fa-spray-can-sparkles 玫粉 美妆品类天然联想其他 fa-box-open 中性灰 兜底类目,不抢视觉这些图标不只在分类区出现——商品卡片的封面色块复用同一套图标和颜色,同品类商品在页面任何位置都保持一致的视觉身份,形成色彩即类目的条件反射。四、核心功能实现细节4.1 数据驱动的渲染所有数据集中定义为 JS 数组,渲染函数从数据出发生成 DOM,改数据即改页面:const CATEGORIES [{ name: “教材教辅”, icon: “fa-solid fa-book”, color: “#4f6ef7” },// …];const GOODS [{ title: “联想小新 Pro14 笔记本”, cat: “电子产品”, price: 2899, cond: “轻微使用”, views: 512 },// …];筛选逻辑只有一行判断,分类筛选和搜索共用同一个渲染入口:function renderGoods(keyword “”) {const list GOODS.filter(g (activeCat “全部” || g.cat activeCat) (!keyword || g.title.includes(keyword) || g.cat.includes(keyword)));// …生成卡片 HTML}点击分类卡片、点击筛选 chip、点搜索按钮,走的都是 filterCat() → renderGoods() 这条单一路径,状态永远只有一份(activeCat),不会出现筛选不同步的 bug。4.2 价格分析:不借助任何图表库的两张图这是项目的技术亮点。为了保持零依赖,两张图全部用 CSS 原生能力手写:① 各类目平均价格——柱状图先对数据做 filter reduce 求出每个类目的均价,再按最大值归一化,用宽度百分比驱动 div 填充:const avg items.reduce((s, g) s g.price, 0) / items.length;// 填充条宽度 avg / max * 100%div classbar-fill stylewidth:${(s.avg / max * 100).toFixed(1)}%/div配合 transition: width .8s ease,页面加载时柱条有一个平滑生长的动画,数据活了起来。② 各成色占比——饼图用 CSS conic-gradient 直接在圆形 div 上绘制扇区:segs.push(${color} ${start}% ${start pct}%);// background: conic-gradient(蓝 0% 40%, 黄 40% 65%, 红 65% 100%)一段渐变就是一个饼图,再配一个纯 HTML 图例列出每档成色的件数和百分比。相比引入 ECharts 的上百 KB 体积,这套方案轻到可以忽略。4.3 AI 购物顾问:浏览器端消费流式接口项目接入了 GitCode AI 开放接口(示例指定模型 deepseek-ai/DeepSeek-V4-Flash),用浏览器原生的 fetch ReadableStream 消费 SSE 流式响应,实现打字机效果:const reader resp.body.getReader();const decoder new TextDecoder();let buffer “”;while (true) {const { done, value } await reader.read();if (done) break;buffer decoder.decode(value, { stream: true });const lines buffer.split(“\n”);buffer lines.pop(); // ⚠️ 关键:最后一段可能被 TCP 切断,留到下一轮拼接for (const line of lines) {if (!line.startsWith(“data:”)) continue;const payload line.slice(5).trim();if (payload “[DONE]”) continue;const json JSON.parse(payload);answer json.choices?.[0]?.delta?.content || “”;loading.textContent answer; // 实时追加,逐字显示}}三个值得记录的细节:半包处理:buffer lines.pop() 是流式解析的命门。网络分包不按行对齐,如果不把不完整的尾行留到下一轮拼接,JSON.parse 会随机报错。多轮上下文:每轮问答都推入 chatHistory,随请求携带,顾问能记住之前聊过什么。优雅降级:请求前显示AI 正在思考…,失败时原地把提示替换为错误原因,不会白屏或卡死。4.4 响应式适配通过 grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)) 实现商品网格的自动换列;另设 media (max-width: 760px) 断点,手机上收起导航链接、压缩 Hero 字号、图表区变单列。没有写大量媒体查询,大部分自适应是 Grid 自动完成的。五、踩坑记录流式解析的随机报错:最初没有做半行缓存,页面时不时弹出 JSON.parse 异常。加上 lines.pop() 尾部缓存后彻底解决——SSE 按行解析必须假设任意两个字节之间都可能被切断。中文字体渲染:饼图和柱状图的数字混用中英文,统一指定 “PingFang SC”, “Microsoft YaHei” 字体栈,保证 Windows / macOS 表现一致。Enter 键全局误触:最初回车发送监听绑在整个 document 上,在搜索框回车也会触发 AI 提问。改为判断 document.activeElement.id “aiInput” 后修复。六、文件结构与运行方式campus-second-hand/├── index.html # 页面骨架(约 80 行,语义化标签)├── style.css # 全部样式(约 180 行,含 CSS 变量与响应式)├── app.js # 数据 渲染 图表 AI 流式调用(约 210 行)└── README.md # 项目说明运行方式:浏览器直接打开 index.html 即可(图标依赖 Font Awesome CDN,需要联网)。七、后续规划商品详情页与发布闲置表单(localStorage 持久化)模拟站内 IM 聊天窗口把示例数据替换为真实后端 APIAI 顾问接入商品数据,实现基于在售商品的价格点评用 Canvas 重写图表,支持悬停查看数值八、写在最后这个项目让我重新审视了原生三件套的能力边界:CSS 变量 Grid 能撑起整套设计系统,conic-gradient 能画饼图,fetch ReadableStream 能消费大模型流式接口——框架解决的是工程规模问题,而不是能力问题。对课程作业或前端入门者来说,这样的项目难度适中、亮点足够;未来若接入真实后端与支付托管,校淘完全有从演示走向真实的潜力。如果这个项目对你有帮助,欢迎到 仓库 点个 Star ⭐