AIGC标识 第四次结对作业

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

项目 内容
结对同学博客 https://www.cnblogs.com/chizhi
本次作业博客 https://i.cnblogs.com/posts/edit
GitHub 项目 https://github.com/Feion-Chen/102402118-102402117
作业要求 https://edu.cnblogs.com/campus/fzu/202601SofwareEngineering/homework/16744
小组成员 陈飞扬 102402118、蔡以恒 102402117

一、分工与完成情况

陈飞扬负责前端页面、LostFoundStore 数据逻辑、搜索和状态转换、单元测试与 README。蔡以恒负责根据第一次原型检查页面流程、补充物品分类和地点筛选需求,并核验发布、搜索、详情、状态更新等测试场景。两人共同完成页面检查、边界情况讨论和最终验证。

程序选择 WEB 形式,使用原生 HTML、CSS 和 JavaScript,不使用第三方框架。用户可以在 Chrome 或 Edge 中直接打开 index.html。

二、需求与实现范围

本次程序实现围绕以下闭环:

发布信息 → 浏览或搜索 → 查看详情 → 联系发布者 → 更新状态

已实现功能:

  1. 浏览校园失物和招领信息。
  2. 发布寻物信息或招领信息。
  3. 按物品名称、地点或描述搜索。
  4. 按类型、分类、地点筛选。
  5. 查看物品详情和联系方式。
  6. 一键复制联系方式。
  7. 在“我的发布”中修改状态。
  8. 表单校验、空结果提示、图片预览和响应式布局。

没有加入实名认证、即时聊天和地图定位,保持流程简单。

应用界面

三、解题思路与代码设计

项目分为界面层、逻辑层和数据层。index.html 提供页面结构,src/app.js 处理 DOM、事件和 localStorage,src/store.js 负责校验、搜索和状态规则,tests/store.test.js 独立测试数据逻辑。逻辑层不依赖 DOM,因此可以在 Node.js 中直接运行测试。

应用结构与数据流

核心业务流程

搜索实现会把物品名称、分类、地点和描述合并为搜索文本,支持多个关键词跨字段匹配。核心代码:

const query = normalizeText(filters.query);
if (query) {
  const haystack = normalizeText([
    item.title,
    item.category,
    item.location,
    item.description,
  ].join(' '));
  const tokens = String(filters.query).trim().toLowerCase().split(/\s+/);
  if (!tokens.every((token) => haystack.includes(normalizeText(token)))) {
    return false;
  }
}

状态转换不直接在界面中任意修改,而是由配置约束。寻物信息只能在“寻找中”和“已找到”之间切换,招领信息只能在“待认领”和“已归还”之间切换:

const STATUS_OPTIONS = {
  lost: ['searching', 'found'],
  found: ['holding', 'returned'],
};

updateStatus(id, status) {
  const item = this.getById(id);
  if (!STATUS_OPTIONS[item.type].includes(status)) {
    throw new Error('该状态不适合当前信息类型');
  }
  item.status = status;
  item.updatedAt = new Date().toISOString();
  return item;
}

数据使用 localStorage 保存,刷新或重新打开页面后仍能保留。图片通过 FileReader 转为 Data URL 后随信息一起保存在本机,不需要上传服务器。

四、附加特点

  1. 分类与地点双重筛选,方便缩小搜索范围。
  2. 一键复制联系方式,减少手工抄写。
  3. 发布成功直接打开详情页,方便核对内容。
  4. 图片大小限制为 2 MB,并支持移除预览。
  5. 空结果状态提供“清除筛选”按钮。
  6. 逻辑层与界面层分离,后续可以在不修改页面的情况下替换数据存储方式。

发布信息页面

五、目录说明与使用说明

102402118-102402117/
├── index.html
├── package.json
├── src/
│   ├── app.js
│   ├── store.js
│   └── styles.css
├── tests/
│   └── store.test.js
├── docs/
│   ├── architecture.svg
│   ├── user-flow.svg
│   ├── images/
│   ├── PSP.md
│   ├── 测试报告.md
│   └── 博客园提交稿.md
└── README.md

运行方法一:下载仓库后,用 Chrome 或 Edge 双击 index.html。

运行方法二:在项目根目录执行 python -m http.server 8080,然后访问 http://localhost:8080。

六、单元测试

测试使用 Node.js 自带的 node:test,不需要额外安装测试框架。运行命令:

node --test tests/store.test.js

共设计 14 个白盒测试用例,覆盖文本规范化、必填字段校验、非法类型、默认状态、名称搜索、跨字段搜索、组合筛选、新增信息、状态合法转换、非法状态、排序和统计。

test('T10 寻物信息不能设置为已归还', () => {
  const store = new LostFoundStore([createItem(baseInput, { id: '1' })]);
  assert.throws(
    () => store.updateStatus('1', ITEM_STATUS.RETURNED),
    /状态/
  );
});

构造测试数据时不只测试正常流程,还考虑缺少字段、非法筛选、非法状态和不存在的 id。这样以后增加新的分类或状态时,可以先补测试再修改实现,减少回归问题。

Git 提交记录

七、遇到的问题与解决

问题一:最初使用 ES Module 时,直接双击 HTML 可能被 Chrome 的本地文件策略拦截。解决方法是改用普通脚本并通过全局对象连接 store.js 和 app.js,保证无需服务器也能运行。

问题二:文件直接打开时,部分浏览器不允许访问 localStorage。代码对此做了容错处理,读取失败时使用示例数据,保存失败时提示但仍保留当前页面数据。

问题三:寻物和招领的状态含义不同。解决方法是使用状态配置表限制可选状态,并在“我的发布”中只显示合法的下一步操作。

八、队友评价

评价组员蔡以恒:能够从测试者角度检查页面流程,指出筛选条件和空结果反馈的重要性,提出的分类和地点筛选提高了查找效率。后续协作中可以在开始编码前更早确定接口字段和测试用例,减少返工。

九、PSP

阶段 预估耗时(分钟) 实际耗时(分钟)
计划与估计 25 20
需求分析 30 20
设计与设计复审 75 60
具体编码 120 95
代码复审 20 15
测试与测试报告 60 45
报告、总结与改进 70 50
合计 400 305

完整 PSP 见仓库中的 docs/PSP.md。

posted @ 2026-10-09 21:00  Feion  阅读(8)  评论(0)    收藏  举报