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

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

项目 内容
课程 202601 软件工程
作业要求 第二次结对作业:程序实现
作业目标 基于上次原型,实现发布、浏览、搜索、详情、联系、本人编辑与状态更新的完整流程
结对成员 102400412 龚巍斌 / 102401111 郑瀚
结对同学博客 https://www.cnblogs.com/Gwbin/p/23243043
GitHub 仓库 https://github.com/illnessemc/102400412-102401111

上次作业中,我们用墨刀设计了寻物、招领、搜索、详情和"我的发布"等页面。本次选择 Web 实现,将原型中的点击路径变成真正可保存、可查询、可更新的数据流程。项目以仓库根目录的 index.html 为正式入口;html/ 保存的是上次作业的原型页面。


一、具体分工

  • 队友(102400412 龚巍斌):负责基础框架搭建(路由守卫、首页渲染、搜索、详情页基础展示、演示数据初始化、32个基础单元测试编写)。
  • 本人(102401111 郑瀚):负责发布模块(表单校验、防连点)、我的发布模块(统计/筛选/返回路径)、状态机管理(标记已找到/已归还/删除、ownerId权限校验)、演示数据与真实数据合并隔离、修复重复弹窗/路由拦截等bug、补充白盒测试用例及博客撰写。

二、PSP 表格

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 30 40
Estimate 估计这个任务需要多少时间 30 40
Development 开发 300 380
Analysis 需求分析(包括学习新技术) 40 50
Design Spec 生成设计文档 30 30
Design Review 设计复审 20 20
Coding Standard 代码规范 10 10
Design 具体设计 40 50
Coding 具体编码 120 160
Code Review 代码复审 20 30
Test 测试(自我测试,修改代码,提交修改) 20 30
Reporting 报告 60 80
Test Report 测试报告 30 40
Size Measurement 计算工作量 10 10
Postmortem & Process Improvement Plan 事后总结,并提出过程改进计划 20 30
合计 390 500

三、解题思路描述与设计实现说明

1. 代码实现思路(文字描述)

项目采用纯前端 Web 实现(HTML+CSS+原生JS),无后端依赖。数据层使用 localStorage 模拟持久化存储。

核心流程:用户进入根目录 index.html → 路由分发(哈希路由) → 首页集中浏览/搜索 → 点击详情查看联系方式 → 发布者可在"我的发布"中标记状态或删除。

状态机设计:记录存在"进行中"、"已找到/已归还"(已结束)状态,已结束记录不可再更新状态,非所有者(无 ownerId 或匹配失败)不可删除/修改。

2. 关键实现的流程图或数据流图

image

3. 重要代码片段及解释

javascript
// 防连点锁与表单提交核心逻辑(publish.js)
let isSubmitting = false;
function handleSubmit(e) {
e.preventDefault();
if (isSubmitting) return; // 防连点
const data = getFormData();
if (!validate(data)) return showToast('请填写必填项');
isSubmitting = true;
savePost(data);
showToast('发布成功');
setTimeout(() => { location.hash = '#success'; isSubmitting = false; }, 800);
}
解释:通过 isSubmitting 标志位阻断快速连续点击;校验通过后写入本地存储,并延迟跳转防止重复提交。
javascript
// 演示数据与真实数据合并隔离(posts.js)
function loadPosts() {
const real = JSON.parse(localStorage.getItem('posts') || '[]');
const demo = DEMO_DATA.map(p => ({...p, _demo: true}));
return [...demo, ...real];
}
解释:演示数据打上 _demo 标记无 ownerId,真实发布数据带 ownerId,合并渲染且互不影响,防止覆盖。

四、附加特点设计与展示

1. 创意独到之处及意义

  • 防连点与局部DOM更新:解决快速连点产生脏数据及 innerHTML 重绘导致的事件丢失/重复弹窗问题,提升稳定性。
  • 状态机与权限校验:前端模拟严谨的状态流转(已结束不可改)和越权拦截(非所有者不可删),贴近真实业务。
  • 演示数据隔离:保证测试人员刷新/发布新数据后,初始展示依然完整。

2. 实现思路

详情页返回路径动态计算(backRoute 参数),从"我的发布"进详情则返回"我的发布";路由守卫增加白名单放行新页面。

3. 重要代码片段

javascript
// 动态返回路径与状态修改校验(detail.js / my.js)
function canModify(post) {
return post.ownerId === CURRENT_USER && post.status === '进行中';
}
解释:严格校验身份与状态,保障数据安全。

4. 实现成果展示

image
image

五、目录说明和使用说明

1. 目录组织

├── .github/workflows/ # CI 自动化测试配置
├── README.md # 项目说明与最终指南
├── 测试说明.md # 测试相关说明文档
├── index.html # 正式入口页面
├── css/ # 样式文件
│ └── style.css
├── js/ # 核心逻辑
│ ├── app.js # 路由
│ ├── posts.js # 数据层
│ ├── publish.js # 发布
│ ├── my.js # 我的发布
│ └── detail.js # 详情
├── html/ # 上次原型页面
│ └── (原型资产)
├── resource/ # 素材与截图
├── tests/ # 单元测试
│ └── (测试文件)
├── posts.js # 数据核心文件(根目录)
├── server.cjs # 本地服务/测试入口
└── .gitignore # Git 忽略配置

2. 测试人员运行说明

  1. 克隆/下载仓库到本地。
  2. 确保文件结构完整。
  3. 使用谷歌浏览器(Chrome)直接双击打开根目录 index.html 即可运行。
  4. 无需配置环境,数据自动存于浏览器 localStorage。
  5. 运行单元测试:终端执行 node --test tests/posts.test.cjs(需 Node.js 24+)。

六、单元测试

1. 测试工具与简易教程

使用 Node.js 内置 node:test 和 node:assert/strict。学习途径:查阅 Node 官方文档及廖雪峰 JS 测试教程。

简易教程:编写测试文件 xxx.test.cjs,引入 test 和 assert,运行 node --test 即可输出结果。

2. 构造测试数据思路

  • 正常数据:合法字段与正常状态流转。
  • 边界数据:空表单、超长文本、特殊字符。
  • 异常数据:损坏JSON、存储满、非所有者ID。
  • 刁难场景:快速连点、刷新持久化、越权修改已结束记录。

3. 测试用例表(≥10个)

用例 测试内容 预期结果
发布缺参校验 提交空表单 返回错误,不写入
状态机非法流转 已结束记录再标记 拒绝
非所有者越权 不同ownerId删除 拒绝
防连点锁 快速连续点击提交 只产生一条
存储失败回退 模拟存储满 保存失败不跳页
演示数据隔离 验证 _demo 标记 无ownerId不被误删
路由白名单 访问 #my 不回退首页
返回路径参数 从my进详情 返回my
统计数正确 多条进行中/已结束 统计匹配
筛选联动 删除后筛选 状态重置正确

七、GitHub 代码签入记录

image
image

八、遇到的代码模块异常/结对困难及解决方法

问题描述 尝试过的方法 是否解决 收获
路由强制回退#home 加入白名单 publish/success/my 是 理解路由守卫机制
发布按钮无响应 移除默认disabled,改JS控制 是 排查DOM属性影响
演示数据被覆盖 合并逻辑+_demo标记 是 数据层隔离策略
删除后重复弹窗 局部DOM更新+防连点锁 是 局部更新优于重绘
协作流程不熟 网页端ZIP/Upload 是 掌握基础Git协作

九、心得体会

本次结对编程让我从"产品经理视角"真正切换到"程序员视角"。上次作业画原型时觉得流程很简单,真正写代码才发现,一个"标记已找到"的按钮背后涉及状态机校验、权限判断、DOM局部刷新、事件绑定防丢失等一系列问题。尤其是修复重复弹窗的bug,最初用 innerHTML 整体重绘导致事件丢失,后来改为局部更新才彻底解决,这个教训让我深刻理解了前端渲染机制。

另外,在队友已有代码基础上做增量开发,比从零开始更难——你需要先读懂别人的路由逻辑、数据结构和命名习惯,才能在不破坏原有功能的前提下接入新模块。这锻炼了我的代码阅读能力和协作意识。

PSP 记录也让我意识到,实际编码时间比预估短,但调试和修复bug(尤其是路由拦截、存储隔离这类隐性问题)占了大量时间。下次应该给"排查异常"预留更多buffer。

总的来说,这次作业让我对前端工程化、状态管理、单元测试设计有了更实际的理解,也体会到好的代码规范和清晰的交接文档对团队协作有多重要。

posted @ 2026-10-10 00:00  Kerical  阅读(5)  评论(0)    收藏  举报