需求规格说明书 - 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 test18 组全通过。
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/** |
同上 |