软件工程第二次结对作业
软件工程第二次结对作业:校园失物招领系统的设计与实现
| 项目 | 内容 |
|---|---|
| 这个作业属于哪个课程 | 202601软件工程 |
| 这个作业要求在哪里 | 2026秋软件工程结对作业(第二次之程序实现) |
| GitHub 项目地址 | 102401434-102401436 |
| 在线演示地址 | 校园失物招领系统 |
| 项目成员 | 102401434 包学丰、102401436 冯玄 |
一、项目背景与目标
校园里的失物招领信息经常分散在不同群聊中,新消息容易覆盖旧消息,同学需要反复翻找才能找到相关内容。物品已经找回或归还后,如果原信息没有及时更新,也容易产生重复询问。
第一次结对作业中,我们完成了需求分析和交互原型。本次作业在已有设计的基础上,实现一个可以实际操作的 Web 应用,围绕以下流程组织功能:
发布信息 → 浏览或搜索 → 查看详情 → 通过联系方式联系发布者 → 发布者更新状态。
本项目使用 HTML、CSS 和原生 JavaScript 实现页面与交互,使用 localStorage 保存本地数据。当前版本面向课程演示,不依赖后台服务器;不同浏览器、不同设备之间的数据不会自动同步。
二、具体分工
| 成员 | 主要工作 |
|---|---|
| 包学丰 | 建立项目骨架,实现首页浏览、详情查看及本地存储;整理 README、PSP、测试报告与项目截图;增加交互动画;管理主仓库并合并 PR |
| 冯玄 | 实现关键词搜索、类型与分类筛选、寻物和招领发布、“我的发布”及状态修改;完善页面样式和测试用例;通过 Fork 和 PR 提交代码 |
协作时,我们先确定模块职责、数据字段和存储键,再分别实现功能。冯玄通过 Fork 仓库提交修改,我在主仓库检查并合并。对于代码合并后出现的兼容问题,再结合测试结果处理。
三、PSP 表格
以下记录与仓库中的 docs/psp.md 保持一致,时间单位为分钟。
| PSP2.1 阶段 | 具体任务 | 预估耗时 | 实际耗时 |
|---|---|---|---|
| Planning | 制定项目计划和成员分工 | 20 | 15 |
| Estimate | 估计项目各阶段耗时 | 15 | 10 |
| Analysis | 分析需求并学习相关技术 | 45 | 35 |
| Design Spec | 设计页面、数据结构和项目目录 | 45 | 35 |
| Design Review | 检查页面设计和数据结构 | 25 | 15 |
| Coding Standard | 制定代码命名和格式规范 | 20 | 15 |
| Design | 完成功能流程和具体实现设计 | 70 | 50 |
| Coding | 编写 HTML、CSS 和 JavaScript 代码 | 360 | 290 |
| Code Review | 检查代码和 Pull Request | 50 | 45 |
| Test | 功能测试、单元测试和问题修复 | 110 | 80 |
| Test Report | 整理测试用例和测试结果 | 40 | 35 |
| Size Measurement | 统计项目文件和测试数量 | 15 | 10 |
| Reporting | 完善 README 和作业文档 | 60 | 45 |
| Postmortem | 总结问题与改进方向 | 25 | 20 |
| 合计 | 900 | 700 |
预估总耗时为 15 小时,实际总耗时为 11 小时 40 分钟,比预估减少 200 分钟。
第一次作业已经完成需求分析和交互原型,因此本次可以直接依据已有设计实现核心功能。明确模块分工也减少了重复开发。不过,旧数据兼容、存储失败处理、测试路径和文档合并仍产生了额外工作,说明编码之外的检查和整理同样需要预留时间。
四、解题思路与设计实现
4.1 从原型到功能实现
我们把原型中的操作整理为浏览、搜索、详情、发布、发布成功和“我的发布”等视图,并通过 JavaScript 控制视图切换。
实现时优先保证基本流程可用:
- 用户可以发布寻物或招领信息。
- 首页能够展示已有信息。
- 用户可以通过关键词及筛选条件查找物品。
- 详情页展示物品特征和联系方式。
- 发布者在“我的发布”中结束信息状态。
联系方式用于用户自行通过 QQ、微信或电话等方式联系对方,应用本身不提供即时聊天。
4.2 模块划分
| 模块 | 职责 |
|---|---|
data.js |
示例数据、分类和状态等公共常量 |
storage.js |
本地数据读取、保存与旧格式兼容 |
logic.js |
搜索、筛选、校验、信息组装和状态转换 |
render.js |
卡片、详情、列表和错误提示渲染 |
app.js |
页面初始化、导航、事件绑定和操作流程 |
业务判断集中在 logic.js,尽量通过纯函数实现,使搜索和校验等功能能够脱离真实浏览器进行测试。页面展示与事件处理分别放在其他模块,降低修改样式时影响业务规则的概率。
4.3 数据结构
每条信息主要包含以下字段:
| 字段 | 含义 |
|---|---|
id |
信息编号 |
type |
寻物或招领 |
name |
物品名称 |
category |
物品分类 |
location |
丢失或拾取地点 |
date |
丢失或拾取日期 |
status |
当前状态 |
description |
物品特征 |
contact |
联系方式 |
image |
图片 Data URL,可为空 |
isMine |
本地演示中是否属于本人发布 |
createdAt |
信息创建时间 |
isMine 用于当前浏览器中的“我的发布”展示和状态修改判断。当前没有账户系统,该字段属于本地演示规则,不是服务器验证的身份权限。
4.4 系统流程图

状态更新由发布者从“我的发布”入口操作:
- 寻物信息:
寻找中 → 已找回。 - 招领信息:
待认领 → 已归还。
已结束的信息不能重复修改。保存成功后,首页、搜索结果和“我的发布”同步刷新,使后续浏览者能看到最新状态。
项目中的“已找回”对应题目要求的“已找到”,表达相同的结束状态。
4.5 数据流图

页面初始化时读取 localStorage,得到信息数组,再交给业务逻辑和渲染模块。
用户发布新信息或修改状态后,程序先保存数据,再刷新展示。保存失败时终止成功流程,避免出现“页面提示成功,但数据实际没有保存”的情况。
五、关键代码及解释
5.1 多条件搜索与筛选
以下代码来自 js/logic.js:
function filterItems(list, filters) {
const options = filters || {};
const type = options.type || ALL_TYPE;
const category = options.category || ALL_CATEGORY;
const keyword = options.keyword || "";
const matched = (list || []).filter(function (item) {
if (!item) {
return false;
}
if (type !== ALL_TYPE && item.type !== type) {
return false;
}
if (category !== ALL_CATEGORY && item.category !== category) {
return false;
}
return matchKeyword(item, keyword);
});
return sortItems(matched);
}
关键词、类型和分类采用“同时满足”的关系。例如,搜索“校园卡”并选择“招领”,结果必须同时符合名称或描述匹配和类型匹配。
matchKeyword 对输入进行去除首尾空格和转小写处理,并检查物品名称与描述。空关键词表示不限制关键词;无匹配结果则返回空数组,由页面显示空状态提示。
5.2 本地保存及失败反馈
以下代码来自 js/storage.js:
function saveItems(list) {
try {
localStorage.setItem(STORAGE_KEY, JSON.stringify(list));
return true;
} catch (error) {
console.warn("物品数据保存失败:", error);
return false;
}
}
程序把信息数组序列化为 JSON,保存在 campus-lost-found-items 键中。
保存函数返回布尔值,让调用方能够区分成功和失败。如果浏览器存储空间不足,程序返回 false,而不是继续展示成功提示。
5.3 状态更新失败时恢复原状态
以下代码来自 js/app.js:
function resolveItem(itemId) {
const result = itemLogic.changeStatus(items, itemId, null);
if (!result.ok) {
itemRender.showToast(result.reason);
return;
}
if (!persist()) {
result.item.status = result.from;
refreshAll();
return;
}
refreshAll();
itemRender.showToast(
"已标记为「" + result.to + "」,首页与搜索结果会同步显示"
);
}
业务层先判断信息是否存在、是否属于本人发布、是否已经结束,再修改状态。
如果保存失败,就使用 result.from 恢复原状态;只有保存成功,才提示状态更新完成。这样能减少页面状态与本地保存结果不一致的问题。
六、附加特点与成果展示
6.1 分类与组合筛选
除了关键词搜索,用户还可以按物品类型和分类缩小范围。例如,选择“电子产品”和“招领”,可以减少无关结果。
实现上复用前面的 filterItems,避免首页与搜索页分别编写一套筛选规则。

6.2 一键复制联系方式
详情页提供“复制联系方式”按钮,减少用户手动输入号码的操作。
程序优先调用浏览器剪贴板接口,并提供兼容方式。如果复制失败,显示手动记录提示。该功能的实际效果受浏览器权限影响,需要在真实浏览器中检查。

6.3 图片选择与预览
发布时可以选择物品图片,检查图片类型和 2MB 大小限制,并在提交前预览,帮助用户更清楚地描述物品。
以下代码来自 js/app.js:
function readImageFile(file, done) {
const reader = new FileReader();
reader.onload = function () {
done(typeof reader.result === "string" ? reader.result : "");
};
reader.onerror = function () {
done("");
};
reader.readAsDataURL(file);
}
FileReader 把图片读取为 Data URL,后续用于预览并随信息保存。当前图片保存在浏览器本地,不上传至服务器;较大的图片也会占用更多本地存储空间。

6.4 页面动画与操作反馈
我们为页面切换、卡片出现、按钮点击和成功提示加入轻量动画。例如,页面进入时淡入并轻微上移:
.view:not([hidden]) {
animation: view-enter 0.22s ease-out;
}
@keyframes view-enter {
from {
opacity: 0;
transform: translateY(8px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
这段代码来自 css/style.css。动画用于帮助用户感知页面变化,同时提供减少动态效果的系统偏好适配。

6.5 其他成果展示
首页以信息卡片展示物品,配合底部导航和移动端布局,方便浏览和进入其他功能。

发布完成后显示成功页面,提供明确反馈。

“我的发布”集中展示当前浏览器中属于本人发布的信息。

物品找回或归还后,发布者可以更新状态,列表中显示对应的结束状态。

七、目录组织与运行说明
7.1 项目目录
102401434-102401436/
├─ assets/
│ └─ screenshots/ # 功能截图、测试截图、流程图和 GIF
├─ css/
│ └─ style.css # 布局、样式和动画
├─ js/
│ ├─ data.js # 示例数据和公共常量
│ ├─ storage.js # 本地存储
│ ├─ logic.js # 业务逻辑
│ ├─ render.js # 页面渲染
│ └─ app.js # 导航与事件处理
├─ docs/
│ ├─ psp.md # PSP 预估与实际耗时
│ ├─ psp-复盘.md # PSP 总结
│ ├─ test-report.md # 测试报告
│ ├─ 设计核对清单.md
│ └─ 上传时间表.md
├─ tests/
│ ├─ cases.js # 基础测试用例
│ ├─ index.html # 浏览器测试入口
│ └─ run-tests.js # Node.js 基础测试入口
├─ unit-tests/
│ ├─ tests/ # Jest 测试文件
│ ├─ api.js # 独立模拟提交模块,未接入网页
│ ├─ package.json
│ ├─ package-lock.json
│ └─ README.md
├─ .gitignore
├─ index.html # 网页入口
└─ README.md # 项目介绍及使用说明
HTML、CSS、JavaScript 和展示素材分目录保存,测试与文档也分别组织。这样测试人员可以先阅读 README,再定位入口和相关模块。
7.2 本地运行
网页功能不需要构建,也不需要安装 Node.js。请统一使用 Google Chrome 打开。
有 Git 的测试人员可以在 PowerShell 中执行:
git clone https://github.com/tw1l1ghtcc/102401434-102401436.git
Set-Location '.\102401434-102401436'
随后打开 Google Chrome,按 Ctrl+O,选择仓库根目录的 index.html。
没有 Git 时,也可以在 GitHub 点击 Code → Download ZIP,解压后使用相同方式打开。
7.3 基本使用步骤
- 首页浏览寻物和招领信息。
- 切换类型或选择物品分类。
- 进入搜索页,输入关键词并组合筛选条件。
- 点击卡片查看物品特征和联系方式。
- 通过联系方式自行联系发布者。
- 从底部“发布”入口填写寻物或招领信息。
- 发布成功后进入“我的发布”。
- 找回或归还物品后,标记为“已找回”或“已归还”。
- 刷新页面,检查信息和状态是否保留。
数据保存在当前浏览器中。清除浏览器数据会影响已保存的信息,本地文件页面与在线页面的数据也不应视为自动共享。
八、单元测试工具、教程与测试设计
8.1 工具选择和学习路径
本项目使用 Node.js 运行测试,使用 Jest 组织测试用例、断言及模拟函数,使用 jsdom 模拟页面环境。
测试直接读取正式项目源码,不另外复制一份应用代码,避免测试副本通过但正式代码仍有问题。
学习和复现时,可以依次阅读 Jest 入门文档、Jest 断言说明 和 jsdom 项目说明。先理解输入与预期结果,再尝试正常用例,最后补充边界、异常和页面交互用例。
8.2 简易运行教程
首先安装 Node.js,然后在项目根目录运行基础测试:
node .\tests\run-tests.js
运行 Jest 测试:
Set-Location .\unit-tests
npm.cmd install
npm.cmd test -- --runInBand
安装依赖后,后续只需在 unit-tests 目录执行:
npm.cmd test -- --runInBand
Windows PowerShell 中使用 npm.cmd,避免 npm.ps1 被执行策略阻止。--runInBand 用于串行执行测试。
阅读测试代码时,可以把一个用例理解为三个部分:准备输入、调用函数、检查结果。test 定义用例,expect 配合匹配器检查结果;例如 toBe 检查值,toMatchObject 检查对象中的指定字段。Jest 断言说明
8.3 项目测试代码示例
以下片段来自 unit-tests/tests/logic.test.js,依赖该文件中已有的 makeList 测试数据和 L 业务模块:
test("寻物:寻找中 → 已找回", () => {
const list = makeList();
const r = L.changeStatus(list, 1, "已找回");
expect(r).toMatchObject({
ok: true,
from: "寻找中",
to: "已找回"
});
expect(list[0].status).toBe("已找回");
expect(L.isResolved(list[0].status)).toBe(true);
});
这个用例检查 changeStatus 的返回结果,也检查列表中的实际状态,避免函数报告成功却没有更新数据。
以下用例检查非法目标状态:
test("目标状态不合法时拒绝,且不污染数据", () => {
const list = makeList();
expect(L.changeStatus(list, 1, "已归还").ok).toBe(false);
expect(list[0].status).toBe("寻找中");
});
寻物信息不能直接变成招领的“已归还”,拒绝操作后原状态也应保持不变。
8.4 白盒测试与测试数据构造
我们根据业务函数内部的条件判断构造用例,覆盖成功、拒绝和异常分支,同时结合等价类与边界条件设计数据。
| 场景 | 测试数据或操作 | 预期 |
|---|---|---|
| 名称搜索 | 输入名称中的关键词 | 返回匹配信息 |
| 描述搜索 | 输入特征描述中的关键词 | 返回匹配信息 |
| 空关键词 | 输入空字符串 | 不限制关键词 |
| 无匹配结果 | 输入无关内容 | 返回空数组 |
| 空列表 | 使用空数组搜索 | 不报错 |
| 组合筛选 | 同时限定关键词、类型、分类 | 条件同时生效 |
| 必填项缺失 | 使用空表单 | 返回字段错误 |
| 名称长度 | 少于 2 字或超过 30 字 | 拒绝发布 |
| 描述长度 | 少于 5 字或超过 200 字 | 拒绝发布 |
| 日期异常 | 不存在的日期或未来日期 | 拒绝发布 |
| 图片异常 | 非图片或超过 2MB | 返回校验错误 |
| 正常状态修改 | 本人未结束信息 | 修改成功 |
| 他人信息 | isMine 为 false |
拒绝修改 |
| 重复修改 | 已找回或已归还的信息 | 拒绝再次修改 |
| 非法目标状态 | 给寻物设置“已归还” | 拒绝且保持原状态 |
| 信息不存在 | 使用不存在的 ID | 返回失败,不崩溃 |
| 非法存储数据 | 非法 JSON 或非数组 | 回退为示例数据 |
| 保存失败 | 模拟存储写入异常 | 返回失败并提供反馈 |
面对测试人员可能构造的特殊字符、空白输入、缺失字段和损坏数据,我们优先检查程序是否崩溃、是否误报成功、是否错误修改原数据,而不仅检查正常路线。
8.5 测试结果与评价
本次重新运行的自动化测试结果为:
| 测试方式 | 结果 |
|---|---|
| Node.js 基础测试 | 35 项全部通过,结构契约检查通过 |
| Jest 单元测试 | 4 个测试文件、67 项全部通过 |
【插图位置:assets/screenshots/08-basic-tests.png,基础测试结果】
【插图位置:assets/screenshots/09-jest-tests.png,Jest 测试结果】
67 项 Jest 测试中,58 项针对正式应用,9 项针对尚未接入网页的独立模拟提交模块 api.js。模拟接口测试用于检查请求组装和异常处理,不代表网页已经具备后台服务。
当前用例覆盖主要业务判断、边界输入、部分页面交互和存储异常,满足至少 10 个测试用例的要求。但测试通过不等于没有缺陷,也不等于已经实现全部分支覆盖。
动画、实际剪贴板权限和图片交互仍需要真实浏览器验收。Jest 运行结束后还出现异步操作未及时结束的提示,这是测试环境需要继续清理的问题,与全部用例通过的结果分别记录。
仓库原测试报告记录了 12 项手动验收通过。本次补充确认了 Chrome 可以正常打开本地首页;其余操作的 Chrome 复核应逐项记录,不能仅以自动化测试替代。
九、GitHub 提交记录与结对协作
我们按功能划分提交内容,使首页、详情、本地存储、搜索发布、文档和动画等修改可以追溯。

主要 PR 记录如下:
| PR | 内容 |
|---|---|
| #1 | 首页基础布局和示例信息展示 |
| #2 | 物品详情查看 |
| #3 | 浏览器本地数据存储 |
| #4 | 合并队友的搜索、筛选、发布、状态修改及测试功能 |
| #5 | 完善目录结构与使用说明 |
| #6 | 补充测试报告 |
| #7 | 补充 PSP 实际耗时与总结 |
| #8 | 增加交互动画 |
| #9 | 补充截图、测试结果、流程图和 GIF |
| #10 | 完善 README 展示与使用说明 |
| #11 | 修正文档并明确测试范围 |
| #12 | 统一 PSP 复盘与主表的耗时口径 |

仓库主页集中展示项目介绍、功能效果、目录和运行方法,方便其他同学下载与测试。

十、遇到的问题、尝试与解决方法
10.1 运行环境差异:命令入口、内联脚本与统计口径
问题: 在 Windows PowerShell 下做同一个操作,命令入口和结果统计都容易出偏差:把多行脚本直接塞进 node -e "..." 时,引号会被 PowerShell 吞掉,脚本报语法错误;用 Get-Content | Measure-Object -Line 统计行数比真实值少 15%~20%(曾因此把 1682 行的 JS 写成 1429 行)。
尝试: 先用最小命令复现(只打印一行 → 确认是命令入口被改写,而不是被测代码的问题),再用两种方式统计同一个文件互相校验。
解决: 需要多行的脚本一律落盘成 .js 再执行(node scripts/xxx.js),不依赖 shell 传参;行数与规模一律以 git log --stat / node 统计为准,并重算了文档里的数字(JS 1682 行、CSS 695 行、HTML 207 行、tests 750 行、端到端脚本 619 行;仓库合计 3943 行 · 17 个文件)。README 里与命令有关的说明同时标注 Windows 写法(npm.cmd install、npm.cmd test)。
收获: 环境问题要先定位到"是命令入口、被测代码,还是统计工具"这一层;运行说明也要考虑别人使用的系统与 shell。
10.2 旧版本地数据与新版字段不一致
问题: 浏览器里已有的旧数据缺少 image、isMine、createdAt 字段,读取后可能让"我的发布"为空、状态修改入口不出现。
尝试: 对比新旧字段,沿着 loadItems 的读取路径逐段检查,确认问题出在"有旧数据就直接用",而不是页面渲染。
解决: 在存储模块增加 needsMigration() 识别旧格式:检测到缺字段时回退新版示例数据;同时保留"数据被改坏(非数组/非法 JSON)"的回退处理。
收获: 调整数据结构时必须同时考虑已有数据。当前的兼容逻辑只适用于"早期只有示例数据"的场景;将来要保留真实历史记录时,需要逐条补字段迁移,而不是整表回退示例数据。
10.3 保存失败却显示操作成功
问题: 如果本地存储写入失败后仍进入"发布成功"页、或提示状态修改成功,用户会误以为数据已保存(首屏测试里一度出现"提交被拦下、但成功面板可见"的现象)。
尝试: 检查保存函数与成功提示的调用顺序,并尝试在 jsdom 里制造"写入失败"(先试给 Storage.prototype.setItem 打桩,未生效;最后改为直接替换应用内部的 itemStorage.saveItems 返回值),把失败路径变成一条可断言的用例。
解决: persist() 返回保存结果;发布失败时 items.pop() 撤销刚加入的信息并停留在发布页;状态修改失败时用 result.item.status = result.from 回滚。成功提示只在真正保存成功后出现。
收获: 成功提示必须依据真实的持久化结果,而不能只依据"按钮被点了""内存里的对象被改了"。
10.4 测试源码与正式源码不一致
问题: 测试目录里曾保留一份项目源码副本(unit-tests/js/),修改正式代码后副本可能没同步,测试通过也不能说明交付代码正确;同时 submit.test.js 的源码基准路径写错,导致该套件"跑不起来"。
尝试: 检查每个测试文件读取源码的位置与目录关系,逐条核对。
解决: 让测试直接读取项目根的正式源码(../js/ 与根目录 index.html),删除源码副本与"复制源码后测试"的旧说明,并修正 submit.test.js 的 ROOT 指向。
收获: 测试对象必须与交付对象一致,否则测试结果的参考价值会大幅下降。
10.5 测试运行环境:新版 jsdom 与 Jest 不兼容
问题: 安装最新版 jsdom 后,Jest 报 SyntaxError: Unexpected token 'export'——它依赖的 @exodus/bytes 是 ESM 模块,而 Jest 默认不转换 node_modules,整个渲染层套件无法解析。
尝试: 从 Jest 的报错栈定位到具体模块与文件,确认不是自己的测试代码写错;随后按版本逐个试。
解决: 把 jsdom 固定为 jsdom@22(CJS 友好),并在 unit-tests/README.md 里写明版本要求。
收获: 依赖升级后要立刻跑一遍测试;把版本钉在"能跑通"的组合上,比追最新版更可靠。
10.6 文档与过程记录不一致
问题: README 合并时被重写,丢掉了两名成员、第一次作业仓库和 Figma 链接;后期核对还发现"无结果提示会带上关键词"这类说明与实际不符、测试范围(正式应用测试与 Mock API 测试)表述含糊、PSP 复盘口径与 PSP 主表不一致。
尝试: 对照实际代码、测试文件与 PSP 主表逐项核查,把"文档说了但代码没做"的地方标出来。
解决: README 以原有项目信息为底稿、再追加实现说明;修正与实际不符的一句话;明确 unit-tests/ 的覆盖范围;PSP 复盘与主表统一到同一套时间轴口径。
收获: 文档也是交付物的一部分。代码变更后要同步检查 README、测试报告与博客,避免同一件事在不同地方说法不同。
10.7 提交历史与主库没有共同祖先
问题: 为满足"删掉原有 main 的文件与提交"的要求重新生成历史后,本地历史与主库 main 没有共同祖先,PR 会显示成"整仓删除 + 新增一大堆",实际上无法合并。
尝试: 先在网页上比对差异,确认问题是历史基线而不是文件内容;再核对主库分支。
解决: 改为从主库 main 拉出 feature/partner-work 分支,把成果作为普通提交叠加上去;此后 PR 变成可快进合并(远端 SHA 与本地一致)。
收获: 交付分支必须以主库为基线;"清理历史"不能以牺牲可合并性为代价。
十一、队友评价
队友负责建立项目骨架,实现首页浏览、详情查看及本地存储,并整理 README、PSP、测试报告与项目截图,还为页面补充了交互动画;同时管理主仓库、负责合并 PR。
他先定下页面外壳、命名与存储键(campus-lost-found-items)以及数据字段,我这边做搜索、筛选、发布和状态修改时可以直接沿用同一套模型与组件命名,几乎没有因为字段或结构不一致而返工——"先搭骨架、后填功能"的顺序,是这次合作能顺利衔接的基础。
他在代码评审时的细致最值得我学习:PR #4 上他逐条指出"旧版本地数据缺 image、isMine、createdAt,更新后『我的发布』可能为空""README 被重写后丢掉了两名成员、第一次作业仓库和 Figma 链接""测试目录又复制了一套项目代码,容易与正式代码不一致"。这三条都不是格式问题,而是真实的可靠性或交付问题,我据此补上了旧数据兼容、恢复了文档原有内容、并把测试改为直接读取正式源码。
需要改进的地方是:功能和数据结构调整时,可以更早同步接口约定与文档说明,减少合并后集中处理兼容问题;交互动画和测试范围的说明也可以随功能一起写进 README,避免事后再补。
对我而言,这次合作提醒我:管理主仓库不只是合并代码,还需要检查不同模块连接后的行为,以及文档是否准确反映最终成果。
十二、项目收获与后续改进
这次作业完整做了:需求分析、交互原型、结对实现、测试、交付。做完发现,项目好不好用,关键看三件事。
1.队友先定好页面结构、数据字段、存储键和命名规则,后面搜索、筛选、发布、改状态都沿用同一套,没有返工。先搭骨架,再填功能,两个人才能同时推进。
2.能跑只是及格。 搜索、发布能演示成功还不够,空结果、非法日期、重复修改、保存失败、旧数据缺字段,才真正影响可靠性。比如保存失败却提示成功,用户会以为发布成功了。后来补了回退、撤销和状态回滚,并用单元测试固定。
3.交付的是一整套。 代码、测试、文档、提交历史要能对上。README 被改乱会丢成员和原型链接;测试目录复制源码会让测试结果没参考价值;提交历史和主库不一致会导致 PR 合不了。文档和提交记录也要评审。
后续改进:
1.js/api.js 已预留提交逻辑,接上真实接口,并补账户和身份校验。
2.旧数据逐条迁移:现在只兼容早期示例数据,以后要按字段逐条补齐。
3.做真实浏览器回归:jsdom 测试不够,关键交互还要在 Chrome 里过一遍,最好做端到端测试。
4.加 CI:每次提交自动跑测试,测试不绿不能合并。
5.找同学试用:看筛选、状态入口是否好懂,无结果提示是否清楚。
浙公网安备 33010602011771号