软件工程第二次结对作业

软件工程第二次结对作业:校园失物招领系统的设计与实现

项目 内容
这个作业属于哪个课程 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 控制视图切换。

实现时优先保证基本流程可用:

  1. 用户可以发布寻物或招领信息。
  2. 首页能够展示已有信息。
  3. 用户可以通过关键词及筛选条件查找物品。
  4. 详情页展示物品特征和联系方式。
  5. 发布者在“我的发布”中结束信息状态。

联系方式用于用户自行通过 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 系统流程图

image

状态更新由发布者从“我的发布”入口操作:

  • 寻物信息:寻找中 → 已找回。
  • 招领信息:待认领 → 已归还。

已结束的信息不能重复修改。保存成功后,首页、搜索结果和“我的发布”同步刷新,使后续浏览者能看到最新状态。

项目中的“已找回”对应题目要求的“已找到”,表达相同的结束状态。

4.5 数据流图

image

页面初始化时读取 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,避免首页与搜索页分别编写一套筛选规则。

image

6.2 一键复制联系方式

详情页提供“复制联系方式”按钮,减少用户手动输入号码的操作。

程序优先调用浏览器剪贴板接口,并提供兼容方式。如果复制失败,显示手动记录提示。该功能的实际效果受浏览器权限影响,需要在真实浏览器中检查。

image

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,后续用于预览并随信息保存。当前图片保存在浏览器本地,不上传至服务器;较大的图片也会占用更多本地存储空间。

image

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。动画用于帮助用户感知页面变化,同时提供减少动态效果的系统偏好适配。

image

6.5 其他成果展示

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

image

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

image

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

image

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

image

七、目录组织与运行说明

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 基本使用步骤

  1. 首页浏览寻物和招领信息。
  2. 切换类型或选择物品分类。
  3. 进入搜索页,输入关键词并组合筛选条件。
  4. 点击卡片查看物品特征和联系方式。
  5. 通过联系方式自行联系发布者。
  6. 从底部“发布”入口填写寻物或招领信息。
  7. 发布成功后进入“我的发布”。
  8. 找回或归还物品后,标记为“已找回”或“已归还”。
  9. 刷新页面,检查信息和状态是否保留。

数据保存在当前浏览器中。清除浏览器数据会影响已保存的信息,本地文件页面与在线页面的数据也不应视为自动共享。

八、单元测试工具、教程与测试设计

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 提交记录与结对协作

我们按功能划分提交内容,使首页、详情、本地存储、搜索发布、文档和动画等修改可以追溯。

image

主要 PR 记录如下:

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

image

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

image

十、遇到的问题、尝试与解决方法

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.找同学试用:看筛选、状态入口是否好懂,无结果提示是否清楚。

posted on 2026-10-07 06:12  Unitur  阅读(1)  评论(0)    收藏  举报

导航