2026秋软件工程第二次结对作业——校园失物招领
| 项目 | 内容 |
|---|---|
| 这个作业属于哪个课程 | 软件工程 |
| 这个作业要求在哪里 | 软工第四次作业 |
| 这个这作业的目标 | 程序实现“校园失物招领小程序” |
| GitHub项目地址 | https://github.com/lickchime/102402147-102402146 |
| 成员一 | 102402147郑宇嘉 |
| 成员二 | 102402146郑仕廷 |
一、具体分工
- 102402147郑宇嘉:负责GitHub仓库的创建。负责首页信息列表、搜索页面、详情页的 UI 设计与前端逻辑;编写单元测试;README 文档撰写。
- 102402146郑仕廷:负责fork郑宇嘉的仓库。负责发布信息页面(寻物/招领)、状态修改逻辑;数据持久化(localStorage)封装;APK 打包与真机测试。
二、PSP 表格
| PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|---|
| Planning | 计划 | 20 | 30 |
| Estimate | 估计这个任务需要多少时间 | 10 | 15 |
| Development | 开发 | 210 | 300 |
| Analysis | 需求分析 (包括学习新技术) | 30 | 45 |
| Design Spec | 生成设计文档 | 20 | 30 |
| Design Review | 设计复审 | 15 | 20 |
| Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 10 | 15 |
| Design | 具体设计 | 30 | 45 |
| Coding | 具体编码 | 120 | 180 |
| Code Review | 代码复审 | 20 | 30 |
| Test | 测试 (自我测试, 修改代码, 提交修改) | 40 | 65 |
| Reporting | 报告 | 50 | 75 |
| Test Report | 测试报告 | 20 | 25 |
| Size Measurement | 计算工作量 | 10 | 10 |
| Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 30 | 45 |
| 合计 | 400 | 540 |
三、解题思路描述与设计实现说明
1. 代码实现思路
本次作业采用 移动端 Web APP(H5) 方案,使用 HTML5 + CSS3 + 原生 JavaScript 开发,通过 localStorage 实现数据持久化,最终使用 HBuilderX 打包成 APK 提交。功能严格控制在“发布—浏览/搜索—详情—联系—更新状态”这一闭环内,坚决不添加地图定位、即时聊天、实名认证等复杂模块。
关键设计:
- 数据模型:
{ id, type, name, place, contact, desc, status },其中type为寻物/招领,status为进行中/已完成。 - 数据流:所有页面共享一套数据层,通过
localStorage读写。页面切换通过 JS 控制显示隐藏,详情页通过传入id获取指定数据。 - 异常与空状态处理:发布时校验必填项;搜索无结果时展示“没有找到相关物品”提示,而不是白屏。
2. 关键实现的流程图
3.关键代码片段
- 搜索功能的实现(支持物品名称模糊搜索):
function goSearch() {
const kw = document.getElementById('search-input').value.trim().toLowerCase();
const results = items.filter(i => i.name.toLowerCase().includes(kw));
document.getElementById('search-results').innerHTML = results.length ?
results.map(item => `<div class="card" onclick="openDetail(${item.id})"><h4>${item.name}</h4><p> ${item.place}</p ></div>`).join('') :
'<p style="text-align:center;color:#999;">没有找到相关物品</p >';
showPage('page-search');
}
- 状态更新逻辑(只有发布者可以修改,并同步到列表):
function updateStatus() {
const item = items.find(i => i.id === currentDetailId);
item.status = 'done';
saveData();
alert('状态已更新为已完成!');
openDetail(currentDetailId); // 刷新详情页
}
四、附加特点设计与展示
1. 设计的创意独到之处及意义
特点一:一键复制联系方式
在详情页,如果用户想要联系发布者,通常需要手动记录微信号或手机号。我们设计了一个“复制联系方式”按钮,点击后直接将信息放入剪贴板,用户无需长按选中,可以直接去微信或QQ粘贴,极大地提升了便捷性。
特点二:空状态与搜索无结果友好提示
针对老师上次反馈的“不能只按一条顺利成功的路线设计产品”的问题,我们在搜索无结果、发布信息不完整的情况下均设置了友好的提示,避免用户面对白屏不知所措。这一改动虽然不大,但体现了对真实使用场景的思考。
2. 实现思路与关键代码
一键复制功能:利用现代浏览器的 Clipboard API。
function copyContact() {
const item = items.find(i => i.id === currentDetailId);
navigator.clipboard.writeText(item.contact).then(() => alert('联系方式已复制!'));
}
空状态处理:在渲染搜索结果时先判断数组长度。
const results = items.filter(i => i.name.toLowerCase().includes(kw));
document.getElementById('search-results').innerHTML = results.length ?
results.map(...).join('') :
'<p style="text-align:center;color:#999;">没有找到相关物品</p >';
3.实现成果展示
- 首页
![8a020116e700c2a26df6f5283d86f16b]()
- 发布页
![04bf237f486fb95fb8d08bd7436305c6]()
- 详情页
![5b64b05d26a544bb4ba44f5ab8ce2ed7]()
*搜索无结果
![140bcd057206657368ae457c8442e9b8]()
五、目录说明和使用说明
1. 目录结构说明
本项目采用 H5 目录结构,方便后续使用 HBuilderX 打包为 Android APP。项目目录组织如下:
index.html:主页面(包含首页、发布、搜索、详情四个视图)test.html:单元测试页面manifest.json:HBuilderX 打包配置文件css/style.css:全局样式表js/script.js:核心逻辑(数据层、页面切换、搜索、发布、状态更新)README.md:项目说明文档
HTML 采用单页面多视图方式,切换时通过 JavaScript 控制显示隐藏;CSS 统一管理样式,实现移动端界面的清爽布局;JS 封装了 localStorage 数据层、搜索逻辑、发布逻辑和状态更新逻辑,职责分明。
2. 如何使用
(1)网页测试
- 下载整个项目文件夹到本地
- 双击打开
index.html - 使用谷歌浏览器(Chrome)打开,按
F12切换到手机模式即可预览效果
(2)APP 测试
- 直接下载安装我们提供的
.apk文件 - 在安卓手机上打开,即可看到“校园失物招领”应用
- 推荐安卓 8.0 及以上系统
(3)操作流程
- 首页浏览信息,点击卡片查看详情
- 在详情页点击“复制联系方式”一键获取发布者联系方式
- 点击右下角“+ 发布”,选择寻物或招领并填写信息
- 在详情页点击“标记为已找到/已归还”,更新状态
六、单元测试
1. 选用的测试工具与学习教程
测试工具:我们选用了原生 JavaScript 断言,配合简易的 HTML 页面进行测试。因为项目没有复杂的第三方依赖,直接写一个 test.html 就能运行,学习成本极低,非常适合两人快速协作。
简易教程:
- 新建一个
test.html文件,在<script>中引入核心逻辑 - 用条件判断或
console.assert编写测试断言 - 在浏览器打开
test.html,查看页面上的 ✅ 和 ❌ 结果
2. 部分单元测试代码
results.push(["测试1: 搜索存在的物品 '校园卡'", searchItems('校园卡').length === 1 ? "✅ 通过" : "❌ 失败"]);
results.push(["测试2: 搜索不存在的物品 '钥匙'", searchItems('钥匙').length === 0 ? "✅ 通过" : "❌ 失败"]);
results.push(["测试3: 按类型筛选 '寻物'", items.filter(i => i.type === 'lost').length === 1 ? "✅ 通过" : "❌ 失败"]);
results.push(["测试4: 发布信息缺少必填项", addItem('雨伞', '') === false ? "✅ 通过" : "❌ 失败"]);
results.push(["测试5: 修改物品状态为已归还", updateStatus(1) && items[0].status === 'done' ? "✅ 通过" : "❌ 失败"]);
七、GitHub 签入记录截图
-
队友提交
![image]()
-
我修改提交
![image]()
八、遇到的代码模块异常或结对困难及解决方法
问题描述 1:页面样式失效与按钮无反应
做过哪些尝试:检查了 HTML 中的引入路径,发现 CSS 和 JS 文件被放在了子文件夹中(css/ 和 js/),但代码中直接写的是 style.css 和 script.js,导致文件 404 加载失败。
是否解决:已解决。将路径改为 css/style.css 和 js/script.js 后恢复正常,页面样式和按钮交互都能跑通。
有何收获:界面画出来和用户能够用起来是两回事。结对编程中,同学B在真机上测试时发现了这个问题,而我在电脑模拟器上一直没发现。这提醒我们要重视真机走查。
问题描述 2:云打包被通讯录权限拦截
做过哪些尝试:使用 HBuilderX 云打包时,提示“本次打包选择了通讯录权限,请登录开发者中心完成实名认证”。检查了 manifest.json 的权限配置,发现默认勾选了通讯录权限。因为是校园失物招领 APP,完全不需要读取通讯录。
是否解决:已解决。在 manifest.json 中取消了通讯录权限,并清空额外添加的权限,重新打包成功。
有何收获:打包不仅是技术操作,更需要对项目所需的权限有清晰的认知,遵循最小权限原则。同时,遇到报错要学会查官方文档,而不是盲目试错。
九、评价你的队友
郑宇嘉负责 GitHub 仓库搭建、首页 / 搜索 / 详情页面 UI 与前端逻辑、单元测试和项目文档撰写。他设计的移动端页面布局清爽,并且考虑了空状态等异常场景,同时编写单元测试验证核心功能,文档整理完整。开发过程中沟通积极,能够及时同步进度,配合我完成前后页面的数据联调,认真完成分配的全部任务,是很好的结对队友。







浙公网安备 33010602011771号