AIGC标识 软件工程第二次结对作业

2026秋软件工程第二次结对作业:校园寻物站程序实现

项目 内容
这个作业属于哪个课程 202601 软件工程
这个作业要求在哪里 2026秋软件工程第二次结对作业之程序实现(在线作业地址待补,内容依据老师原文)
这个作业的目标 基于第一次原型,实现发布、浏览与搜索、详情与联系、发布者更新状态的完整流程
结对成员(学号、姓名) 102401421丁政伟;102401435 乔震宇
结对同学的博客链接 https://www.cnblogs.com/102401435q/p/23239144
GitHub项目地址 102401421-102401435

一、分工与PSP

成员 模块与任务 验收重点
丁政伟 发布表单、输入校验、本机保存与草稿;阅读 domain.js 和 storage.js 对应逻辑 空白必填、日期、保存失败、刷新恢复
乔震宇 首页、搜索与组合筛选、详情、我的发布及状态确认;阅读 app.js 对应逻辑 搜索结果、联系方式、本人权限、完成状态一致性
共同 核对第一次原型、审查接口、复测、整理 README 与博客、进行真实 fork/PR 协作 两种发布类型均走通,说明与程序一致
PSP2.1 阶段 建议预估 用时 用时
Planning 计划(小计) 15 17.8 16.4
Estimate 估计任务时间 15 17.8 16.4
Development 开发(小计) 395 468.7 463.0
Analysis 需求分析与技术学习 35 41.6 38.7
Design Spec 设计文档 30 33.2 28.9
Design Review 设计复审 15 18.4 19.6
Coding Standard 代码规范 10 12.3 9.7
Design 具体设计 40 46.7 51.3
Coding 编码 170 198.6 187.4
Code Review 代码复审 25 29.5 32.8
Test 测试与修改 70 88.4 94.6
Reporting 报告(小计) 60 65.7 67.6
Test Report 测试报告 25 28.7 31.2
Size Measurement 工作量统计 10 9.4 10.6
Postmortem & Process Improvement Plan 总结与改进 25 27.6 25.8
合计 明细之和 470 552.2 547.0

二、实现思路

校园失物信息容易被群聊消息覆盖,因此程序把寻物和招领放在统一列表中。首页卡片显示名称、地点、日期和状态,用户可以先筛选或搜索,再进入详情查看特征与联系方式。

实现采用原生 HTML、CSS、JavaScript,业务规则、保存逻辑和页面交互分开组织:domain.js 负责校验、搜索、筛选和状态规则;storage.js 负责保存信息与草稿;app.js 负责呈现页面、处理点击及表单提交。页面通过哈希地址切换,浏览器返回键可返回上一视图。

image

发布流程是“填写表单 → 校验 → 保存 → 发布成功”。必填项缺失、日期无效或晚于今天、文本超长时,表单提示原因;只有保存成功才进入成功页。

image
image

查看流程是“浏览或搜索 → 详情 → 联系发布者”。物品交还后,发布者从“我的发布”进入本人详情,确认并更新状态。寻物完成显示“已找到”,招领完成显示“已归还”;首页的状态筛选可以查看已完成记录。

image

状态更新的核心代码如下:

function finishItem(items, id, ownerId, now = new Date().toISOString()) {
  const item = items.find(entry => entry.id === id);
  if (!item) throw new Error('这条信息不存在');
  if (item.ownerId !== ownerId || item.isDemo)
    throw new Error('只能修改自己发布的信息');
  if (item.status === 'done') return items;
  return items.map(entry => entry.id === id
    ? { ...entry, status: 'done', updatedAt: now } : entry);
}

函数先检查信息是否存在和发布者是否匹配,再更新目标记录。重复完成操作返回原数据,避免覆盖完成时间;其他物品保持原样。

image
image

三、附加特点

1. 类别与地点组合筛选

用户可能只记得物品类别或遗失区域。按类别、地点和状态筛选,可以缩小查找范围;筛选条件与关键词同时生效,并提供一键重置。

if (filters.category && filters.category !== 'all'
    && item.category !== filters.category) return false;
if (filters.place && filters.place !== 'all'
    && item.place !== filters.place) return false;

这是 selectItems 中的部分逻辑。条件取交集,剩余代码处理类型、状态和关键词,结果按发布时间排序。关键词支持匹配名称、地点或特征,并统一外围空格、英文大小写与全角字符。

image

2. 复制联系方式

详情页提供复制按钮,减少手工抄写错误。浏览器不允许自动复制时,选中联系文字并提示手动复制。

try {
  await navigator.clipboard.writeText(value);
  toast('联系方式已复制');
} catch {
  const node = document.getElementById('contact-value');
  const range = document.createRange();
  range.selectNodeContents(node);
  const selection = window.getSelection();
  selection.removeAllRanges();
  selection.addRange(range);
  toast('已选中联系方式,请按 Ctrl+C 或长按复制');
}

3. 草稿恢复与手机布局

表单修改后自动保存草稿,刷新后恢复,发布成功后清除。桌面采用多列卡片,手机改为紧凑列表;本次检查的手机首页和发布表单没有横向溢出。

image

四、目录及运行说明

仓库根目录/
  index.html                    网页入口
  README.md                     使用说明
  package.json                  统一测试入口
  .gitignore                    Git忽略规则
  .github/
    workflows/test.yml          GitHub自动测试配置
  assets/
    css/app.css                 页面样式与手机布局
    js/domain.js                输入校验、搜索、筛选和状态规则
    js/storage.js               信息保存与草稿
    js/app.js                   页面交互
    images/logo.svg             本地图标
  tests/
    domain.test.cjs              业务规则测试
    storage.test.cjs             保存逻辑测试

下载完整程序目录,用 Google Chrome 打开 index.html,保留旁边的 assets。网页运行无需安装依赖,也不需要联网加载字体或前端框架。

首页选择“发布信息”,填写物品和联系方式后提交;通过搜索或卡片进入详情;交还完成后,在“我的发布”中更新状态。首页默认显示未完成信息,选择“全部状态”或“已完成”可查看历史记录。

五、单元测试及简易教程

测试使用Node自带的node:test和node:assert/strict,无需下载测试框架。测试文件采用CommonJS格式,业务规则可通过require导入,这样不用打开网页也能检查输入校验、搜索和状态转换。

学习单元测试时,我们先理解“准备输入—调用函数—断言结果”的基本结构,明确测试需要比较程序的实际结果与预期结果。随后结合项目中的输入校验和状态更新函数,了解如何使用断言检查返回值和异常。测试数据从正常输入扩展到空白字段、无效日期、长度边界和修改他人信息等情况,逐步理解白盒测试中分支覆盖与边界检查的作用。

一个最小测试包含三步:准备输入,调用函数,断言结果。例如合法数据应返回成功,未来日期应返回日期错误,修改他人信息应抛出异常。assert.equal比较值,assert.deepEqual比较数组或对象,assert.throws检查预期异常。

安装Node.js 24或兼容版本,在仓库根目录,即index.html所在目录打开终端:

node --test tests/domain.test.cjs tests/storage.test.cjs

运行后查看每个用例是否通过以及末尾的汇总。如果出现失败,先阅读断言给出的实际值与预期值,检查相应规则,再修复程序或错误的测试输入;不要仅为让测试通过而删除失败用例。修复后重新运行整套测试,确认没有影响其他功能。

下面的测试验证“更新他人信息”被拒绝:

const test = require('node:test');
const assert = require('node:assert/strict');
const D = require('../assets/js/domain.js');

test('不能修改他人信息', () => {
  const entries = [{id:'x',ownerId:'a',isDemo:false,status:'active'}];
  assert.throws(() => D.finishItem(entries,'x','b'), /自己/);
});

本段是简化教程示例;项目实际权限用例同时覆盖他人、示例及不存在的信息。

测试数据采用白盒分支与边界设计:空白必填、错误枚举、闰年与未来日期、文本恰好上限和多一个字、大小写与全角搜索、无结果及组合筛选;还考虑重复更新、HTML字符、保存空间不足、损坏JSON和草稿异常。存储测试使用内存替身,不修改网页里的个人记录。

2026-10-05,在Node.js 24.15.0下运行28个测试,全部通过。业务规则17个、存储11个,满足附录至少10个的要求。

六、异常与解决

对程序本身的异常,设计了“保存成功才进入成功页”和“损坏数据不自动覆盖”。测试用模拟写入失败确认旧记录保留;模拟损坏JSON确认返回只读提示。这提醒我们,按钮跳转正确和数据真正保存是两件需要分别检查的事。

手机检查时发现发布导航的读屏名称会重复“+”,现补充明确的无障碍名称“发布信息”。同时把完成提示改为本机列表与详情同步,避免让演示界面暗示已经实现跨设备共享。

代码签入记录截图:
image

七、队友评价

值得我学习的是从用户操作的角度考虑问题,关注搜索无结果时的提示、页面之间的跳转,以及物品交还后的状态变化。这让我认识到,界面设计不仅要清楚,也要让用户能够顺利完成操作。后续可以改进的是更早整理需要调整的内容,按优先顺序处理,减少反复修改。

posted @ 2026-10-05 17:09  SiJiu0801  阅读(27)  评论(0)    收藏  举报