软件工程第二次结对作业
校园失物招领——第二次结对作业(程序实现)
| 项目 | 内容 |
|---|---|
| 课程 | 202601 软件工程(福州大学) |
| 作业要求 | 2026秋软件工程结对作业(第二次之程序实现) |
| 成员 | 102401504 马晨曦;102401505 林金晶 |
| 结对同学博客 | https://www.cnblogs.com/machenxi/p/23242757 |
| 本作业博客 | https://www.cnblogs.com/StarrLin/p/23230589 |
| GitHub 项目 | StarrLin7/102401505-102401504 |
一、项目说明
本项目将第一次结对作业的原型落实为纯前端网页:信息发布后可浏览、按关键词/类别/地点筛选、查看详情与联系方式,并可在“我的发布”中更新物品状态。项目无需安装依赖,使用 Google Chrome 直接打开 index.html 即可运行;完整目录与操作说明见 README。
二、结对分工与 PSP 预估
| 成员 | 主要工作 |
|---|---|
| 102401505 林金晶 | 需求梳理、首页与发布页实现、详情交互、页面样式、博客排版与联调。 |
| 102401504 马晨曦 | 数据存储与筛选逻辑、我的发布与状态更新、单元测试、README 操作说明。 |
| PSP2.1 | 任务 | 预估(分钟) | 实际(分钟) |
|---|---|---|---|
| Planning | 计划 | 25 | 25 |
| Estimate | 估计任务时间 | 15 | 15 |
| Development | 开发 | 540 | 600 |
| Analysis | 需求分析 | 50 | 55 |
| Design Spec | 生成设计文档 | 30 | 25 |
| Design Review | 设计复审 | 30 | 40 |
| Coding Standard | 代码规范 | 15 | 20 |
| Design | 具体设计 | 45 | 55 |
| Coding | 具体编码 | 260 | 300 |
| Code Review | 代码复审 | 40 | 45 |
| Test | 测试与修复 | 70 | 60 |
| Reporting | 报告 | 70 | 75 |
| Test Report | 测试报告 | 40 | 45 |
| Size Measurement | 工作量统计 | 10 | 10 |
| 合计 | 650 | 715 |
偏差分析: 实际开发和设计复审时间略高于预估,主要花在筛选逻辑、页面交互的边界验证以及普通脚本加载方式的兼容性排查;测试时间因提前编写可重复执行的用例而得到控制。
三、功能实现与核心流程
3.1 功能闭环
- 发布信息: 在发布页填写物品名称、类别、地点、时间、描述和联系方式;必填项缺失会提示,提交成功后立即回到首页。
- 浏览和搜索: 首页以卡片展示寻物/招领信息,支持关键词、类别、地点和状态的组合筛选。
- 详情和联系: 点击卡片进入详情页,按需展示联系人及联系方式,避免在列表页直接暴露全部个人信息。
- 状态更新: “我的发布”只展示本人信息,可将状态更新为“已找到”或“已归还”,并同步回写列表。
3.2 主流程图
下图以“数据读取—发布—状态更新”为主线呈现页面跳转及关键数据流;蓝色节点表示页面流程,菱形节点表示筛选或状态判断。
3.3 核心代码说明(以图片呈现)
表单校验与数据写入: 数据层统一负责校验、读取、写入、筛选和状态更新;页面层只调用公共接口,便于测试和维护。
筛选与状态更新: 首页通过 store.list(filters) 完成组合筛选;状态修改后再渲染卡片,保证视图与数据一致。
四、功能界面展示
4.1 多条件筛选
首页提供关键词、类别、地点和状态四类筛选入口,适合从较多失物信息中快速定位目标。点击卡片可进入详情页。
4.2 一键复制联系方式
详情页的“一键复制”采用 navigator.clipboard.writeText;在不支持 Clipboard API 的环境下回退到传统复制方式。复制结果会有明确反馈,减少手动输入联系方式的错误。
4.3 发布信息和状态更新
发布页明确标注必填信息;“我的发布”支持将已解决条目改为“已找到/已归还”,避免过期信息持续干扰搜索结果。
五、附加特点的设计与展示
除作业要求中的发布、浏览、详情和状态更新外,我们实现了以下两个面向实际使用的附加特点:
- 多条件组合筛选(附加特点一): 可同时按类别、地点、关键词和状态缩小范围。筛选逻辑在数据层集中处理,空条件返回全部,组合条件返回交集,减少用户反复翻页的时间。
- 一键复制联系方式(附加特点二): 用户在确认需要联系后可复制号码/社交账号;页面展示“复制成功”提示,并兼容 Clipboard API 不可用的浏览器环境。
两个特点分别提升了“找得快”和“联系快”的体验,且均提供了实际运行界面与代码证据,不将作业基础功能重复计作附加功能。
附加功能界面截图:
- 多条件筛选:搜索框支持关键词输入,顶部可在“全部 / 寻物 / 招领”之间切换;下图展示切换到“寻物”后的真实筛选结果。
- 便捷联系:详情页在完整呈现拾取地点、物品描述和状态后提供“联系发布者”入口;点击后展示联系方式,并可继续一键复制。
六、目录组织(可视化表格)
| 层级 / 路径 | 文件或目录 | 作用 | 评分者是否需要直接打开 |
|---|---|---|---|
| 根目录 | index.html | 程序唯一入口,Chrome 直接打开 | 是 |
| src/css | style.css | 统一的配色、布局、响应式样式与状态样式 | 否 |
| src/js | store.js | 数据读写、校验、筛选、状态更新;内部使用 IIFE 隔离,只暴露 window.LostFoundStore | 否 |
| src/js | app.js | 页面渲染、路由、交互事件与用户操作反馈 | 否 |
| tests | store.test.html | 浏览器内运行的 12 条存储层单元测试 | 建议 |
| docs | blog-draft.md | 本报告 Markdown 源稿与图片说明 | 否 |
| 根目录 | README.md | 环境、启动、操作、测试、数据重置说明 | 是 |
七、运行说明、测试与质量保证
7.1 运行步骤
- 从 GitHub 下载或克隆项目,保持目录结构不变。
- 使用 Google Chrome 直接打开 index.html;不需要 Node.js、框架或服务器。
- 首页可浏览和筛选;点击卡片查看详情;点击“发布信息”填写表单;在“我的发布”修改本人条目状态。
- 刷新页面后数据保存在浏览器 localStorage 中;需要恢复演示数据时,按 README 的说明清除本站点 localStorage 后刷新。
- 直接用 Chrome 打开 tests/store.test.html,查看 12 条测试结果。
7.2 单元测试
我们优先测试独立的数据层函数,覆盖新增、必填校验、列表筛选、状态更新、异常 id 处理和持久化读写。测试页使用隔离的 MemoryStorage 替代真实 localStorage,确保每条用例不互相影响。
实际运行结果: 使用 Google Chrome 直接打开 tests/store.test.html,12 条用例全部通过(结果:12/12 通过);随后回归验证了首页浏览、组合筛选、发布信息、详情联系方式展示和本人信息状态更新。
八、GitHub 签入记录
| 提交 | 说明 |
|---|---|
| chore: initialize campus lost and found project | 初始化目录、入口页面和规范文件。 |
| feat: add post storage and validation | 实现数据存储、校验、筛选和状态更新。 |
| feat: add responsive lost and found interface | 实现首页、发布、详情与移动端样式。 |
| feat: implement publish search detail and status workflow | 完成核心闭环及交互。 |
| test: add browser coverage for store logic | 增加 12 条可直接打开运行的浏览器测试。 |
| docs: improve evaluator run guide | 补强 README 的运行环境、复现步骤、数据重置和测试预期。 |
| fix: isolate browser data layer | 用 IIFE 隔离 store.js 顶层声明,修复普通脚本同名声明冲突。 |
仓库真实提交记录截图: 下图直接截自 GitHub 提交历史页,可核对功能实现、浏览器测试、文档完善与数据层隔离修复等提交。
九、困难、解决过程与收获
问题 1:普通脚本加载时出现同名声明冲突
- 问题描述: 为满足“下载后直接用 Chrome 打开”的要求,项目使用普通脚本顺序加载。数据层导出的 createStore 等名称,与页面和测试页中解构得到的同名常量处在同一顶层作用域,浏览器报 SyntaxError,表现为页面空白、测试无结果。
- 做过哪些尝试: 先分别检查首页和测试页的控制台,再从两处重复出现的名称定位到 store.js 顶层声明;在本地副本中对比“页面改用命名空间”和“数据层使用 IIFE 隔离”两种方案。
- 是否解决: 已解决。最终用 IIFE 包裹 store.js 内部声明,只通过 window.LostFoundStore 暴露统一入口;回归结果为页面正常渲染、12/12 测试通过。
- 有何收获: 普通脚本能加载不等于可以随意复用顶层名称。即使没有构建工具,也应明确模块边界和唯一公共接口。
问题 2:筛选、发布与状态更新后需要保持页面一致
- 问题描述: 页面需要按关键词、类别、地点、状态筛选,同时新增和改状态后应立即反映在当前列表;若各页面自行读写数据,容易出现字段不一致或遗漏刷新。
- 做过哪些尝试: 在编码前列出 kind、name、category、location、place、happenedAt、description、contact 等统一字段;将数据读写和筛选逻辑集中到 store.js,并为新增、筛选、状态更新分别编写测试。
- 是否解决: 已解决。校验、发布、筛选和详情复用同一字段集合,更新后重渲染首页和“我的发布”,测试覆盖关键边界。
- 有何收获: 小型项目同样需要先确定数据模型与单一数据源;功能拆小、可单测后,定位问题和联调效率会明显提高。
十、对队友的评价
马晨曦同学在本次结对中认真完成了数据存储、筛选逻辑、状态更新和单元测试等任务。她在联调阶段能够主动复现问题、补充 README 中的操作说明,并针对异常场景完善测试。沟通中能及时同步进度,对功能细节提出可执行建议。后续若能进一步把边界用例整理成更清晰的检查清单,协作效率会更高。总体而言,本次结对分工明确、配合顺畅,按计划完成了程序实现与测试。
浙公网安备 33010602011771号