# 2026秋软件工程结对作业(第二次之程序实现)——失物有迹

项目 内容
课程 H202601 软件工程与软件工程实践
作业要求 2026秋软件工程结对作业(第二次之程序实现)
学生 102401216 吴欣键
组队情况 独立完成
原型链接 https://www.cnblogs.com/PIG1/p/23001643
GitHub 仓库 baomihua1234/102401216

一、项目简介

“失物有迹”是一个可离线运行的校园失物招领 Web 应用。我基于第一次作业原型,实现了“发布信息 → 浏览或搜索 → 查看详情并联系 → 发布者更新状态”的完整闭环。

项目只使用原生 HTML、CSS、JavaScript 和浏览器 LocalStorage;下载全部文件后,用 Chrome 直接打开 index.html 即可运行。

二、个人工作说明

本项目以一人组形式完成。我负责需求回顾、页面结构与样式、业务逻辑、交互实现、核心逻辑测试、README、GitHub 提交和博客整理。双人 Fork、Pull Request、队友评价等要求不适用于本次一人组,未作虚构填写。

工作项 具体完成内容
需求与设计 回顾原型,确定发布、搜索、详情、联系与状态更新的主流程及数据字段。
前端实现 独立编写 HTML、CSS 与 JavaScript,完成响应式界面、表单和弹窗交互。
核心逻辑 将校验、筛选、状态更新抽取为 core.js 纯函数。
测试与交付 编写 12 个单元测试用例,整理 README、GitHub 提交记录与博客材料。

三、PSP

“预估”可直接使用;“实际”请根据自己的真实记录填写,不能把预估时间当作实际时间提交。

PSP2.1 阶段 预估(分钟) 实际(分钟)
Planning 计划与任务拆分 20 25
Estimate 估计任务时间 15 15
Analysis 需求回顾、技术学习 45 70
Design Spec 页面、数据字段与流程设计 50 60
Design Review 核对原型与功能边界 30 35
Coding Standard 制定命名与文件组织规则 15 20
Design 具体交互和数据结构设计 60 80
Coding HTML、CSS、JavaScript 编码 210 270
Code Review 检查表单、搜索与状态逻辑 40 45
Test 单元测试、Chrome 走查与修复 100 120
Test Report 截图与测试说明整理 45 45
Size Measurement 整理目录和提交记录 20 20
Postmortem 总结、README 与博客 70 35
合计 720(12 小时) 840(14 小时)

实际耗时比预估多 2 小时,主要是低估了表单异常分支、组合筛选、状态更新走查及 GitHub 上传整理的时间。下次会在计划阶段为浏览器兼容检查和提交材料预留更独立的时间。

四、解题思路与设计实现

4.1 数据与模块划分

每条信息包含 id、type、title、category、location、date、contact、description、status。type 区分寻物与招领,status 表示待处理或已解决。

  • index.html:页面结构,包括失物广场、发布表单和我的发布。
  • css/style.css:颜色、卡片、表单、弹窗与窄屏适配。
  • js/core.js:输入校验、筛选、状态更新等纯函数。
  • js/app.js:DOM 渲染、表单提交、详情弹窗和 LocalStorage 持久化。

4.2 核心流程与数据流

填写发布表单 → 完整性校验 → 保存到 LocalStorage → 广场/我的发布展示
                                                   ↓
浏览或关键词搜索 → 查看详情 → 复制联系方式 → 双方线下核验
                                                   ↓
发布者在“我的发布”标记为已解决 → 页面同步显示已解决

数据流由表单输入开始:FormData 被转换为普通对象后先调用 validateListing;校验成功的数据写入 LocalStorage。页面每次渲染都从完整数据源读取,再将关键词、类型、类别和状态交给 filterListings 组合筛选。发布者确认物品已处理后,transitionStatus 只允许“待处理 → 已解决”的单向变更,并将结果重新保存和渲染。

4.3 关键实现

输入校验逐项检查类型、名称、类别、地点、日期、联系方式和描述;筛选函数同时匹配关键词、类型、类别和状态;状态更新只允许“待处理 → 已解决”,避免重复修改。

function transitionStatus(item, nextStatus) {
  if (!item || item.status !== 'active') {
    return { ok: false, message: '该信息已是已解决状态' };
  }
  if (nextStatus !== 'resolved') {
    return { ok: false, message: '不支持的状态变更' };
  }
  return { ok: true, item: { ...item, status: 'resolved' } };
}

该逻辑使“联系之后如何结束信息”有清晰答案:发布者在“我的发布”操作,状态立即更新,其他用户也能看到已解决标识。

五、附加特点与成果展示

5.1 多条件组合筛选

设计意义: 除关键词搜索外,系统支持按信息类型、物品类别和处理状态组合筛选。校园失物信息较多时,用户能够更快缩小范围,减少无关信息干扰。

实现思路: 每次筛选均从完整信息列表开始,先将关键词统一转换为小写,再同时判断关键词、类型、类别和状态,避免先后筛选导致隐藏状态累积。

function filterListings(listings, filters) {
  const query = normalized(filters.keyword);
  return listings.filter(item => {
    const haystack = [item.title, item.location, item.description, item.category]
      .map(normalized).join(' ');
    return (!query || haystack.includes(query)) &&
      (!filters.type || item.type === filters.type) &&
      (!filters.category || item.category === filters.category) &&
      (!filters.status || item.status === filters.status);
  });
}

【图 1:首页与失物广场截图】

图1:首页与失物广场

【图 2:输入“校园卡”后仅显示一条匹配信息的截图】

图2:校园卡关键词搜索结果

5.2 一键复制联系方式与隐私提示

设计意义: 联系方式只在详情弹窗中展示,减少首页直接暴露个人信息;用户确认物品特征后可一键复制联系方式,避免手动抄写出错,也能加快线下核验。

实现思路: 详情页仅对待处理信息渲染“复制联系方式”按钮;点击后调用浏览器 Clipboard API。若浏览器不允许剪贴板写入,则提示用户手动复制,保证功能可理解、可降级。

async function copyContact(text) {
  try {
    await navigator.clipboard.writeText(text);
    showToast('联系方式已复制');
  } catch (_) {
    showToast('请手动复制:' + text);
  }
}

5.3 表单异常反馈与状态更新闭环

发布时缺少必填项会显示具体提示;页面提醒避免公开身份证号等敏感信息。发布成功后,信息出现在“我的发布”中;发布者可将它从待处理更新为已解决,更新后按钮不可重复操作。

设计意义: 表单即时反馈能够减少无效信息;状态更新让已找回或已归还的信息不再持续干扰其他用户,形成完整闭环。

【图 3:未填写物品名称时显示“请填写物品名称”的截图】

图3:表单异常提示

【图 4:黑色保温杯处于待处理、可标记为已解决的截图】

图4:待处理状态

【图 5:黑色保温杯更新为已解决的截图】

图5:已解决状态

六、目录与运行说明

102401216/
├─ index.html              # 网页入口
├─ css/style.css           # 样式与响应式布局
├─ js/core.js              # 校验、筛选、状态更新等核心逻辑
├─ js/app.js               # 页面交互与本地数据存储
├─ tests/core.test.html    # 可在浏览器运行的 12 个自动化测试
├─ README.md               # 运行说明
└─ 作业博客稿.md            # 博客 Markdown 初稿

打开 GitHub 仓库,点击绿色 Code,选择 Download ZIP;解压后保留目录结构,用 Google Chrome 打开根目录 index.html。不要只下载单个 HTML 文件,否则 CSS 和 JavaScript 无法加载。

七、单元测试

7.1 测试工具与学习方式

本项目没有额外引入测试框架,而是在 tests/core.test.html 中使用原生 JavaScript 编写断言式测试,并调用 js/core.js 的纯函数。选择这种方式的原因是项目无需 Node.js 或安装依赖,测试人员下载项目后,用 Chrome 直接打开测试页即可复现。

我的简易测试流程如下:

  1. 将不依赖 DOM 的业务规则提取到 core.js。
  2. 在测试页引入 core.js,为每个规则准备输入数据与预期结果。
  3. 执行函数并判断布尔结果,将“通过/失败”逐条显示在页面上。
  4. 用 Chrome 打开 tests/core.test.html,核对汇总结果是否为 12/12 通过。

7.2 测试代码与被测函数

下列测试直接调用 transitionStatus,验证待处理信息能更新为已解决,同时验证已解决信息不能重复更新:

['09 待处理信息可更新为已解决', () =>
  C.transitionStatus({ id: '1', status: 'active' }, 'resolved')
    .item.status === 'resolved'
],
['10 已解决信息不能重复更新', () =>
  !C.transitionStatus({ id: '1', status: 'resolved' }, 'resolved').ok
]

同一测试页还覆盖了 validateListing 的必填项、非法类型和标题边界,以及 filterListings 的大小写无关搜索、地点搜索和多条件组合筛选。

7.3 测试数据构造思路

12 个用例覆盖正常路径、异常路径、边界条件和组合条件。正常路径验证合法信息可发布、待处理信息可更新;异常路径验证缺失名称、缺失联系方式、非法类型和非法状态更新;边界条件使用 31 个字符的标题检验长度限制;组合条件验证类型与状态同时满足才返回结果。对于测试人员可能的“刁难”,还考虑了空关键词、英文大小写不同、已解决信息重复更新等情况。

单元测试主要覆盖业务规则;DOM 点击、浏览器存储和剪贴板权限另通过 Chrome 人工走查验证。

【图 6:core.test.html 显示 12/12 通过的截图】

图6:12个单元测试全部通过

八、GitHub 签入记录

仓库地址:https://github.com/baomihua1234/102401216

提交按可验证的功能拆分:

  1. docs: 添加项目入口与使用说明
  2. feat: 添加响应式页面样式
  3. feat: 实现发布搜索详情和状态更新
  4. test: 增加核心业务逻辑自动化测试

【图 7:GitHub 提交历史截图】

图7:GitHub提交历史

九、问题与解决办法

9.1 状态闭环不完整

  • 问题: 原型中有“已找到/已归还”的概念,但未明确谁修改、在哪里修改。
  • 尝试: 先考虑在详情页直接修改,随后发现任何访问者都可能误操作;最终增加“我的发布”入口,仅在发布者自己的列表中提供状态按钮。
  • 结果: 已解决。状态更新后会保存并同步渲染,按钮不可重复操作。
  • 收获: 业务状态不仅要有显示,还要明确操作主体、入口与允许的状态迁移。

9.2 页面逻辑不便测试

  • 问题: 若将校验和筛选全部写在 DOM 事件中,浏览器界面测试难以覆盖异常分支。
  • 尝试: 将校验、筛选和状态更新拆为 core.js 中的纯函数,再在独立测试页引入这些函数。
  • 结果: 已解决。测试页可直接复用核心逻辑,12 个用例均可在 Chrome 中运行。
  • 收获: 将业务规则与页面渲染分离,既提高可测试性,也降低后续修改风险。

9.3 筛选条件容易相互干扰

  • 问题: 若在已筛选结果上继续筛选,清空某个条件后可能无法恢复完整结果。
  • 尝试: 每次筛选都从完整数据源开始,同时应用关键词、类型、类别和状态条件。
  • 结果: 已解决。用户调整任意条件后都能得到一致结果。
  • 收获: 多条件筛选应保持无状态计算,避免把中间结果当作新的数据源。

9.4 联系方式与隐私风险

  • 问题: 联系方式若在卡片列表中直接展示,可能造成不必要的公开暴露。
  • 尝试: 不实现即时聊天或复杂认证;改为仅在详情弹窗展示联系方式,同时加入敏感证件信息提示。
  • 结果: 已解决。用户需先查看详情再复制联系方式,信息展示范围更小。
  • 收获: 即使是课程项目,也应在便利性与个人信息保护之间做明确取舍。

十、总结与改进

本次作业把第一次的原型转化为可以运行、可以测试、可以复现的网页。后续可增加信息编辑、图片上传和数据导入导出;但应优先保证当前发布、搜索、详情、联系与状态更新主流程稳定可用。

posted @ 2026-10-07 18:29  PIG—  阅读(21)  评论(0)    收藏  举报