需求规格说明书 - xych5q/online-shop GitHub Wiki

需求规格说明书(迭代 1 版)

第 1 组 · 在线购物系统 | 版本:v1.4(2026-10-13) | 编写:董嘉润、陈星宇 编写分工:董嘉润提出需求问题、组织需求澄清并确认答复依据;陈星宇负责需求分析、条目化编写与版本维护——需求澄清与说明书编写两项工作由两人共同完成。 依据:老师口述需求 + 课程 Wiki《需求澄清记录》全站问答 + 本组提问(见需求问题库) 本版为迭代 1(基线 MVP)的范围;后续迭代需求随老师逐轮发布追加。 v1.1 变更:回填需求方 2026-10-07 的 8 条答复(需求问题库 第三节)。要点:队首进入交易为系统自动(Q1);交易中买家仍可撤销(修正 FR-B5);失败意向由卖家后台逐单处置、重排无上限(FR-S7);手动下架不受排队意向限制(FR-S8)。 v1.2 变更:新增 1.4 需求矛盾识别(显式记录口径冲突与裁决依据);非功能需求补关键操作时间戳、后台可检索、线下交易免责声明。 v1.3 变更(2026-10-07):统一术语表述,去除内部实现口径的痕迹;明确编写分工。 v1.4 变更(2026-10-13,第 1 次评审后整改): ① FR-B5「交易中可撤销」已回改代码与需求对齐(原实现为交易中拒绝撤销,见 4.2); ② 4.1 增补「进入交易」的触发机制说明(触发者、触发条件、代码位置),如实记录该实现与需求方第 8 条答复之间的口径差异,并由本组裁定(Q6); ③ Q4(口令码字符集)补充现实现取值与依据; ④ Q4、Q6、Q7 三项开放点由本组裁定取值并在 需求问题库 第四节登记 #10~#12,不再向需求方追问。


1. 引言

1.1 目的

定义"单卖家在线购物系统"基线版本的功能边界与业务规则,作为设计、开发、测试与验收的统一依据。

1.2 范围

做:单卖家商品发布与管理、买家免注册排队购买意向、口令码自助服务、交易冻结与结果标记、历史档案。 不做(需求方明确排除):注册/登录(买家侧)、线上支付、物流、购物车、搜索分类、评价、库存、买家订单历史、App/小程序。

1.3 术语

术语 含义
口令码 买家提交意向后获得的唯一凭证,8 位大写字母数字,仅提交成功时显示一次
冻结 商品因进入交易或卖家手动操作而暂停接收新意向的状态
递补 交易失败后,队列下一位自动进入交易
重新排队 失败买家再次入队,排到队尾、提交时间刷新、口令码不变

1.4 需求矛盾识别与裁决(口径冲突记录)

原始需求为带噪声的口述口径,编写时识别出以下表面矛盾,均经澄清后裁决并回写正文:

# 表面矛盾 裁决结论 依据
C1 需求方称"无注册",同时要求"卖家可修改密码"——没有注册哪来密码? 买家完全无账号;卖家账号由系统指定(初始化生成用户名与随机初始密码,首次启动打印),故"无注册"与"改密码"不冲突 需求问题库 澄清记录
C2 "先到先得排队"与"卖家处理交易"并存,易误解为卖家可挑选买家 卖家不可挑人,队首自动进入交易、系统自动冻结;卖家仅有"标记结果"与"冻结/解冻"两项手动操作 需求问题库 #8 答复
C3 "线下交易"与"系统内标记结果"的边界 系统只做意向排队与状态记录,资金与货品交割完全在线下,平台不参与担保(见第 6 节免责声明) 老师口述需求
C4 "无通知功能"与"买家需要知道结果"的张力 系统明确无任何通知机制(无邮件/短信/站内信),买家凭口令码自助查询感知状态变化——这是有意取舍,非遗漏 需求问题库 #2 答复

2. 角色与权限

角色 说明 入口
卖家 唯一,系统指定账号(无注册),登录后台管理商品与交易 /admin
买家 免注册,凭口令码自助操作 /
系统 自动执行:与队首进入交易、冻结、失败递补、口令码失效 —

3. 功能需求

3.1 卖家端(FR-S)

  • FR-S1 卖家登录:用户名 + 密码;错误提示"用户名或密码错误";无注册、无退出登录。
  • FR-S2 修改密码:验证原密码;新密码 ≥ 8 位;成功后旧密码立即失效。
  • FR-S3 发布商品:名称必填 ≤100 字、描述选填 ≤2000 字、价格必填 >0(人民币两位小数)、图片选填 JPG/PNG ≤5MB;已有在售/交易中商品时禁止发布;发布后即"在售",不可修改。
  • FR-S4 手动冻结/解冻:仅"在售"可手动冻结;仅手动冻结的商品可手动解冻;交易中的商品必须先标记交易结果。
  • FR-S5 意向购买人管理:查看排队列表(姓名、电话、提交时间、位次);卖家不可挑人,按先到先得与队首交易;后台全程不显示、不记录口令码。
  • FR-S6 标记交易结果:仅"成功/失败"两档;成功后不可撤销;成功 → 商品下架进历史、队列剩余全部转失败、全部口令码失效;失败 → 队列有人自动递补、队列空自动恢复在售。
  • FR-S7 失败意向处置:交易失败后,该单意向是"作废"还是"重新排队"由卖家在后台逐单确认(非系统自动入队);重新排队排队尾、原口令码继续有效;重排次数无上限。
  • FR-S8 手动下架:不因有排队意向而禁止(2026-10-07 拍板);进入历史;队列剩余意向转失败、口令码全部失效(查不到、改不了、撤不了);系统无通知功能,买家仅凭口令码自查发现。
  • FR-S9 历史商品:只读档案,按成交时间倒序、每页 10 条;每条记录包含商品自身字段(名称、描述、图片、价格、发布时间、最终交易结果(成功成交 / 手动下架)、交易完成时间)与意向流水(姓名、电话、提交时间、终态三档:成功/撤销/失败);不记录口令码;支持翻页检索。

3.2 买家端(FR-B)

  • FR-B1 浏览商品:在售商品的名称/描述/图片/价格;无图显示占位图(已定);描述为空则留空,不加"卖家没有填写描述"等默认文案(2026-10-07 拍板);无商品显示"暂无商品在售";交易中显示"商品交易中"。
  • FR-B2 提交意向:姓名 + 电话必填(不校验格式;需求方明确坚持完全不校验,不做"11 位数字"等格式检查,填错责任在买家);成功即入队并获口令码(仅显示一次,提供复制与"请截图保存"提示);同一人重复提交不去重。
  • FR-B3 凭码查询:位次、提交时间、是否已进入交易。
  • FR-B4 凭码修改:改姓名/电话,不改变位次;修改后卖家后台与历史记录均只显示最新的姓名电话,不保留改动前的旧记录。
  • FR-B5 凭码撤销:撤销后意向进入"已撤销"终态(历史留痕)、口令码失效;交易中买家仍可撤销(2026-10-07 拍板,口令码在交易结束前始终有效)——若队首撤销:交易终止、撤销者口令码失效;队列仍有排队意向则下一位自动递补进入交易、商品保持冻结,队列为空则商品自动恢复在售;撤销按钮无需隐藏。

4. 业务规则(状态机)

4.1 商品状态机

在售 →(手动冻结)→ 已冻结[manual] →(解冻)→ 在售 在售 →(队首**自动**进入交易,同时自动冻结)→ 已冻结[auto] →(标记成功)→ 已下架 已冻结[auto] →(标记失败且队列空)→ 在售 在售 / 已冻结[manual] →(手动下架)→ 已下架

  • 同一时间最多一件商品处于在售/冻结
  • 队首进入交易与冻结均由系统自动完成,卖家后台无"进入交易"操作(2026-10-07 拍板;后台手动仅"标记交易结果"与"冻结/解冻"两项)
  • 手动下架不因有排队意向而禁止;下架后排队意向口令码全部失效
  • 冻结期间不接收新意向;无超时自动解冻
  • 买家端对手动冻结与交易冻结不区分文案
  • 「进入交易」的触发机制(2026-10-13 增补,回应第 1 次评审技术意见 #1「自动要写清什么条件触发」):
    • 触发者:系统(TradeService.enterDeal),取队列首位,卖家不可挑人;
    • 触发条件:商品处于在售状态,且该商品存在「排队中」的意向;
    • 触发动作:队首意向置「交易中」,商品置「已冻结」、frozenBy='auto'、frozenAt=当前时间——冻结由系统自动完成,卖家无需另行操作;
    • 自动递补:交易失败后若队列仍有排队意向,下一位由系统自动递补进入交易、商品保持冻结,卖家无需再次操作;
    • 口径裁定(Q6,见 需求问题库 #10;2026-10-13 本组决定不再向需求方追问):需求方第 8 条答复要求「买家提交意向后队首自动进入交易」。若照字面实现(提交即冻结),因 FR-B1 / FR-B2 规定「商品交易中不接收新意向」,第二位及之后的买家将无法提交,排队队列无法形成——这与"排队本身是本项目核心功能"相冲突。处理方式:保留队首由系统进入交易的机制(TradeService.enterDeal),买家可正常排队,队首进入交易时才冻结商品;由此产生的差异作为本组既定口径记录在此。若需求方后续主动提出调整,再按其答复对齐代码与文档。

4.2 意向状态机

排队中 →(进入交易)→ 交易中 →(标记结果)→ 成功 / 失败 排队中 / 交易中 →(买家撤销)→ 已撤销(交易中撤销:交易终止、后续队列递补;队列空则商品自动恢复在售) 终态三档:成功 / 撤销 / 失败;口令码随终态失效(重新排队除外,见 4.3)。

2026-10-13 代码对齐记录(FR-B5):原实现为「交易中拒绝撤销」(IntentService.cancel 抛「你已进入交易,无法自行撤销」),与 FR-B5 拍板口径矛盾。现已改为:交易中撤销 → TradeService.abortDealByBuyer 置该意向为已撤销并终止交易 → 队列有人则下一位自动递补(商品保持冻结)、队列无人则商品恢复在售;口令码随终态失效。补测试用例 17(交易中撤销且递补)、18(交易中撤销且队列空恢复在售),mvn test 18 组全通过。

4.3 排队与口令码规则

  • 排队按提交时间先到先得;冻结发生在进入交易时
  • 口令码全局唯一、仅显示一次、不可找回
  • 失效条件:交易结束(成功/失败)、意向撤销、商品下架
  • 重新排队不换码;重排以新提交时间计位次

5. 待需求方确认事项(编写时的开放点)

# 事项 现实现取值 状态
Q1 进入交易由卖家手动发起还是系统自动 卖家手动点(已废弃) 已答复(2026-10-07):系统自动,早期版本中手动触发须移除(需求问题库 #8)
Q2 重新排队由卖家处置还是买家自助 卖家处置 已答复(间接):卖家在后台处置(需求问题库 #9,经 #6 答复确认;建议再正式追问一次)
Q3 手动下架时队列意向的处置 全部转失败 已答复(2026-10-07):不禁止下架,队列意向终结、口令码全部失效(需求问题库 #2)
Q4 口令码格式是否可限定 8 位无易混字符 已限定为 8 位、大写字母+数字、剔除易混字符 I / O / 0 / 1(可用字符 32 个:ABCDEFGHJKLMNPQRSTUVWXYZ23456789,组合数 32⁸ ≈ 1.1×10¹²) 本组裁定(2026-10-13,不再追问,见 需求问题库 #11):2026-10-07 的 8 条答复未涉及本条,由本组自行取值;代码实现见 IntentService.CODE_ALPHABET / CODE_LENGTH = 8。剔除理由:买家需手抄/口头转述口令码,I/1、O/0 易误认。如需改为纯数字或其他长度,仅需改这两个常量,无需改库表结构
Q5 名称/描述长度、历史分页大小 100/2000 字、每页 10 需求方未规定,自行取值
Q6 「买家提交即自动进入交易」与「交易中不接收新意向」冲突时如何处理 保留队首由系统进入交易的机制(TradeService.enterDeal);队列可正常形成,队首进入交易时才冻结商品 本组裁定(2026-10-13,不再追问,见 需求问题库 #10):见 4.1。若改为提交即冻结,第二位及之后买家无法提交,排队与位次功能失效,与"排队是核心功能"冲突,故采用现口径
Q7 「进入交易」的触发时间点 队首提交后不立即冻结;交易结束(成功/失败/队首撤销)后由系统自动推进下一位 本组裁定(2026-10-13,不再追问,见 需求问题库 #12):见 4.1。采用"交易结束后自动推进下一位",与第 8 条「自动」的诉求一致且不影响排队

6. 非功能需求

  • 终端:仅 Web(桌面浏览器)
  • 密码存储:BCrypt 加盐哈希;卖家密码长度 ≥ 8 位(FR-S2)
  • 数据持久化:关系数据库(H2/MySQL),核心数据(商品/意向/账户)重启不丢失
  • 关键操作审计:冻结/解冻、修改密码、标记交易结果、手动下架等后台关键操作均记录操作时间戳,可在后台追溯
  • 卖家后台易用性:后台入口唯一(/admin)、布局清晰;操作流程简洁(核心动作不超过两步);历史商品支持按成交时间倒序浏览与翻页检索
  • 空态提示:无在售商品显示"暂无商品在售";交易中显示"商品交易中";无效口令码给出明确错误提示
  • 图片:服务端本地存储,URL 访问
  • 线下交易免责声明:本系统仅提供意向排队与状态管理;交易的资金结算与货品交割由买卖双方线下自行完成,平台不担保交易真实性、不参与纠纷仲裁,买家应审慎核实后再线下交易

7. 追踪

需求 用户故事 接口 测试
卖家端 FR-S1~S10 [用户故事与产品订单]] US-01~07 ](/xych5q/online-shop/wiki/[[接口设计) 卖家 12 个 用例表 TC 系列
买家端 FR-B1~B5 US-08~11 接口设计 买家 5 个 同上
图片 US-12 /uploads/** 同上