BIZ-102 v1.1: 记录-比对 中奖金额展示 PRD 与 UI 原型
v1.0: 3 字段增量扩展(prize_amount/total_prize/prize_summary)+ 前端 3 处扩展 v1.1: 落实架构评审 3 点意见 - 金额字段统一'(单位:元)'与量级安全说明 - prize_summary key 改英文枚举(first_prize..sixth_prize),新增 prize_level 中文名 - floating 标记落 results[i] 与 prize_summary[key] 两粒度 - 兼容性条款:每次实时计算,不依赖持久化 Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
@@ -0,0 +1,187 @@
|
||||
# 产品需求文档(PRD):记录-比对 中奖金额展示
|
||||
|
||||
> **编号**:BIZ-102(BIZ-101 子任务1)
|
||||
> **负责人**:沈路明(productmanager)
|
||||
> **版本**:v1.1
|
||||
> **状态**:架构评审通过(条件式已落实),待设计与开发评审
|
||||
> **父任务**:BIZ-101「webui 记录-比对 中奖金额展示」(CO 已批准)
|
||||
> **关联系统**:双色球 WebUI(后端 Flask `app.py` + 前端 `index.html`)
|
||||
|
||||
---
|
||||
|
||||
## 1. 背景与目标
|
||||
|
||||
### 1.1 业务背景
|
||||
当前 `POST/GET /api/records/<id>/compare` 已完成「是否中奖 + 几等奖」的比对,前端弹窗展示每注的奖项徽标与红球/蓝球命中情况,但**不展示中奖金额**。运营人员与刘总在查看比对结果时,只能看到「x 注中奖」,无法直观获知本次生成号码的**总中奖金额**与**各奖级分布金额**,不利于快速评估生成策略的价值与复盘。
|
||||
|
||||
### 1.2 解决的问题
|
||||
- 运营/管理层查看比对结果时,缺少「中奖金额」这一核心经营指标。
|
||||
- 现有比对只给出奖项枚举,无法按奖级聚合金额,复盘成本结构困难。
|
||||
|
||||
### 1.3 成功指标(可量化)
|
||||
- [ ] 比对弹窗统计区新增「总中奖金额」与「各奖级金额分布」两项,覆盖率 100%。
|
||||
- [ ] 每条中奖注在奖项徽标旁展示该注中奖金额,覆盖率 100%。
|
||||
- [ ] 后端响应新增字段后,旧版前端(不消费新字段)功能不受影响,回归通过率 100%。
|
||||
- [ ] 中奖金额计算口径在 UI 中对浮动奖显式标注「以官方公布为准」,避免误导。
|
||||
|
||||
---
|
||||
|
||||
## 2. 用户故事
|
||||
|
||||
- **作为运营人员**,我希望在比对弹窗中一眼看到「本次生成共中奖多少元、各奖级各多少元」,以便快速汇报生成效果,无需人工逐注累加。
|
||||
- **作为刘总**,我希望查看每注的中奖金额与总额,以便评估号码生成策略的投入产出,并在浮动奖场景下明确知晓金额口径来源。
|
||||
- **作为开发(徐聪)**,我希望后端以结构化字段(`prize_amount` / `total_prize` / `prize_summary`)一次性返回金额,前端直接消费,避免前端重复实现中奖金额计算逻辑。
|
||||
|
||||
---
|
||||
|
||||
## 3. 功能需求
|
||||
|
||||
### 3.1 后端 API 扩展(`app.py` `/api/records/<id>/compare`)
|
||||
|
||||
现有响应 `data` 已包含:`status, gen_time, compare_type, compare_rule, draw{...}, results[], total, win_count, win_tickets[]`。
|
||||
每条 `results[i]` 已包含:`index, reds, blue, red_matches, blue_match, prize_level, prize_desc, is_win`。
|
||||
|
||||
本需求在**不改动既有字段**前提下做增量扩展:
|
||||
|
||||
| 功能点 | 位置 | 字段 | 类型 | 描述 | 优先级 | 验收标准 |
|
||||
|--------|------|------|------|------|--------|----------|
|
||||
| F-1 每注中奖金额 | `results[i]` | `prize_amount` | int(单位:元) | 该注中奖金额(元),未中奖为 `0` | P0 | 中奖注 `prize_amount` = 该奖级单注金额;未中奖注恒为 `0` |
|
||||
| F-2 总中奖金额 | `data` 顶层 | `total_prize` | int(单位:元) | 所有中奖注金额合计(元) | P0 | `total_prize` = Σ `results[i].prize_amount`,与前端展示一致 |
|
||||
| F-3 按奖级汇总 | `data` 顶层 | `prize_summary` | dict | 按奖项分组汇总,仅含实际出现的奖项 | P0 | key 为英文枚举(见 3.3),每项含 `{count, amount, prize_level, floating}`;未出现奖级不出现 |
|
||||
| F-3.1 单注浮动标记 | `results[i]` | `floating` | bool | 该注是否属浮动奖(一/二/三等奖);固定奖或未中奖为 `false` | P1 | 浮动奖注 `floating = true`,固定奖注 `floating = false` |
|
||||
|
||||
**字段类型与单位**(v1.1 落实架构评审 #1):
|
||||
- 所有金额字段(`prize_amount` / `total_prize` / `prize_summary[].amount`)均为 **整数**,**单位:元(非分)**。
|
||||
- 量级说明:双色球一等奖历史最高单注超 1500 万元,Python int 无溢出(任意精度);前端 JS `Number` 在 `2^53 ≈ 9007 万亿` 以下安全,本场景安全。
|
||||
|
||||
**边界**:
|
||||
- `status === 'waiting'`(等待开奖)的响应**不新增**上述字段(无开奖数据,无法计算)。
|
||||
- 浮动奖(一/二/三等奖)单注金额来源见第 4 节;若取不到动态金额,使用占位值并通过 F-3.1 的 `floating: true` 提示前端「金额以官方公布为准」。
|
||||
|
||||
### 3.2 前端展示扩展(`index.html` `compareRecord()` 比对弹窗)
|
||||
|
||||
现有弹窗结构(`.compare-summary` 含 4 项:生成时间 / 比对开奖期 / 总注数 / 中奖注数)保持不变,做增量插入:
|
||||
|
||||
| 功能点 | 位置 | 描述 | 优先级 | 验收标准 |
|
||||
|--------|------|------|--------|----------|
|
||||
| F-4 统计区-总额 | `.compare-summary` 内 | 新增「总中奖金额 `<total_prize>` 元」 | P0 | 使用 `data.total_prize`;`0` 时显示「0 元」 |
|
||||
| F-5 统计区-分布 | `.compare-summary` 下方 | 遍历 `prize_summary`,逐行展示「`<count>` 注 `<奖级>` 共 `<amount>` 元」 | P0 | 仅展示 `count > 0` 的奖级;每行一条 |
|
||||
| F-6 每注金额 | 每注 `.compare-ticket` | 在 `prize-badge`(几等奖)旁额外显示该注金额,如「`五等奖 10元`」 | P0 | 使用 `r.prize_amount`;未中奖注不显示金额 |
|
||||
|
||||
**展示文案规范**:
|
||||
- 统计区总额:`总中奖金额 25 元`
|
||||
- 分布行:`1 注 五等奖 共 10 元` / `3 注 六等奖 共 15 元`
|
||||
- 每注:`五等奖 10元`(浮动奖额外追加 `· 浮动以官方为准` 角标,角标数据源为 `r.floating === true`,见第 4 节)
|
||||
|
||||
**前端字段消费映射**:
|
||||
- 统计区总额 ← `data.total_prize`
|
||||
- 分布行每条 ← `Object.entries(data.prize_summary)` 遍历,每项含 `count` / `amount` / `prize_level`(中文显示名)/ `floating`
|
||||
- 每注金额 ← `r.prize_amount`,浮动角标 ← `r.floating`
|
||||
|
||||
---
|
||||
|
||||
## 3.3 `prize_summary` 字段结构与 key 命名规范(v1.1 落实架构评审 #2)
|
||||
|
||||
采用**方案 A(推荐)**:`prize_summary` 的 key 使用**英文枚举**,每项内显式带中文 `prize_level` 字段供前端展示。
|
||||
|
||||
**理由**:
|
||||
- **[常识]** JSON key 使用中文在日志检索、grep、跨语言消费、后期 i18n 时易踩坑;英文枚举是更稳定的契约。
|
||||
- 前端用映射表把英文 key 翻译成中文显示名,仅多写一处常量映射,零成本。
|
||||
|
||||
`prize_summary` 结构示例:
|
||||
```json
|
||||
{
|
||||
"fifth_prize": {"count": 1, "amount": 10, "prize_level": "五等奖", "floating": false},
|
||||
"sixth_prize": {"count": 3, "amount": 15, "prize_level": "六等奖", "floating": false}
|
||||
}
|
||||
```
|
||||
|
||||
| key | prize_level | 类型 | 中奖条件 |
|
||||
|------|------|------|----------|
|
||||
| `first_prize` | 一等奖 | 浮动 | 6红+1蓝 |
|
||||
| `second_prize` | 二等奖 | 浮动 | 6红+0蓝 |
|
||||
| `third_prize` | 三等奖 | 浮动 | 5红+1蓝 |
|
||||
| `fourth_prize` | 四等奖 | 固定 | 5红+0蓝 或 4红+1蓝 |
|
||||
| `fifth_prize` | 五等奖 | 固定 | 4红+0蓝 或 3红+1蓝 |
|
||||
| `sixth_prize` | 六等奖 | 固定 | 2红+1蓝 或 1红+1蓝 或 0红+1蓝 |
|
||||
|
||||
字段含义:
|
||||
- `prize_summary[key].count` = 该奖级中奖注数
|
||||
- `prize_summary[key].amount` = `count × 该奖级单注金额`(元,整数)
|
||||
- `prize_summary[key].prize_level` = 中文显示名(前端直接展示)
|
||||
- `prize_summary[key].floating` = 是否浮动奖(前端决定是否展示「以官方公布为准」角标)
|
||||
- 仅当 `count > 0` 的奖级出现在 `prize_summary` 中(未中奖注不计入)
|
||||
|
||||
## 4. 中奖金额口径与浮动奖说明
|
||||
|
||||
### 4.1 单注奖级金额表
|
||||
|
||||
| 奖项 | 单注金额(元) | 类型 | 中奖条件 | 声明 |
|
||||
|------|---------------|------|----------|------|
|
||||
| 一等奖 | 浮动(官方公布) | 浮动 | 6红+1蓝 | [已知] 双色球一等奖为浮动奖池 |
|
||||
| 二等奖 | 浮动(官方公布) | 浮动 | 6红+0蓝 | [已知] 二等奖为浮动奖池 |
|
||||
| 三等奖 | 浮动(官方公布) | 浮动 | 5红+1蓝 | [已知] 三等奖为浮动奖池 |
|
||||
| 四等奖 | 200 | 固定 | 5红+0蓝 或 4红+1蓝 | [已知] 中彩中心固定奖级 |
|
||||
| 五等奖 | 10 | 固定 | 4红+0蓝 或 3红+1蓝 | [已知] 中彩中心固定奖级 |
|
||||
| 六等奖 | 5 | 固定 | 2红+1蓝 或 1红+1蓝 或 0红+1蓝 | [已知] 中彩中心固定奖级 |
|
||||
|
||||
> 固定奖级(四/五/六等奖)金额由中彩中心规则固定,可直接硬编码;浮动奖(一/二/三等奖)实际金额随奖池浮动。
|
||||
|
||||
### 4.2 浮动奖处理规则(关键决策点)
|
||||
[推论] 本迭代先采用**单注固定/占位金额**驱动展示,浮动奖金额本期以「占位值 + UI 显式标注」呈现,待数据源(开奖数据接口)能提供每期实际奖金后再切换为动态读取。
|
||||
|
||||
- **数据源可读取实际奖金时**:`prize_amount` 取接口返回的实际单注金额;`prize_summary` 的 `amount` 按实际金额计算。
|
||||
- **数据源不可读取时(本期默认)**:浮动奖使用占位值(建议一等奖 5,000,000 / 二等奖 200,000 / 三等奖 3,000 作占位,**[猜测]** 具体占位值待刘总确认),并在 UI 该奖级旁追加角标「`浮动·以官方公布为准`」。
|
||||
- **Fallback 策略**:优先实际金额 → 缺失时占位值 + 标注。
|
||||
|
||||
### 4.3 计算边界
|
||||
- `prize_amount` 一律为非负整数(元),未中奖 = `0`。
|
||||
- `total_prize` = Σ `results[i].prize_amount`,由后端聚合,前端不做二次计算。
|
||||
- `prize_summary[key].amount` = `count × 该奖级单注金额`,由后端聚合。
|
||||
- 每次比对请求都**重新计算**上述字段,**不持久化到数据库**(v1.1 落实架构评审兼容性补充:避免老记录因历史缺字段导致新版本回放异常)。
|
||||
|
||||
---
|
||||
|
||||
## 5. 兼容性(不影响现有比对流程)
|
||||
|
||||
- [ ] 新增字段为**纯增量**,旧版前端未消费新字段时比对弹窗功能不变。
|
||||
- [ ] 旧版后端(无新字段)对新版前端:前端需做字段存在性判断(`data.total_prize ?? 0`),避免 `undefined` 渲染异常。
|
||||
- [ ] `status === 'waiting'` 响应结构不变,不新增字段。
|
||||
- [ ] 比对核心逻辑(奖项判定、命中统计)零改动,仅追加金额计算分支。
|
||||
|
||||
---
|
||||
|
||||
## 6. 验收标准
|
||||
|
||||
### 后端
|
||||
1. 中奖记录比对响应中,`results[i]` 含 `prize_amount`(int,单位:元),且中奖注 = 对应奖级单注金额、未中奖注 = `0`。
|
||||
2. `data.total_prize`(int,单位:元)= 所有中奖注 `prize_amount` 之和。
|
||||
3. `data.prize_summary` 仅含 `count > 0` 的奖级;key 为英文枚举(`first_prize` ... `sixth_prize`);每项含 `{count, amount, prize_level, floating}`,且 `amount = count × 单注金额`。
|
||||
4. `results[i].floating` 在浮动奖(一/二/三等奖)注上为 `true`,固定奖与未中奖注为 `false`。
|
||||
5. `waiting` 状态下不返回上述字段。
|
||||
6. 字段每次实时计算,不依赖持久化(老记录重新比对也能正确返回新字段)。
|
||||
|
||||
### 前端
|
||||
7. 比对弹窗统计区显示「总中奖金额 <total_prize> 元」。
|
||||
8. 弹窗展示各奖级分布行「x 注 y 等奖 共 z 元」,仅 `count > 0` 奖级;显示名取 `prize_summary[key].prize_level`。
|
||||
9. 每条中奖注在奖项徽标旁显示该注金额;未中奖注不显示金额。
|
||||
10. `floating: true` 的注/奖级在 UI 显式标注「以官方公布为准」。
|
||||
|
||||
### 回归
|
||||
9. 不消费新字段的旧逻辑(命中统计、奖项徽标)行为不变。
|
||||
10. 字段缺失时前端不报错(存在性兜底)。
|
||||
|
||||
---
|
||||
|
||||
## 7. 范围与边界(与 BIZ-101 的关系)
|
||||
- **本卡(BIZ-102)**:仅产出 PRD + UI 原型,不写后端/前端代码,不做部署。
|
||||
- **后续链路**:本卡 `in_review` → 产研交叉评审(@梁思筑 @徐聪 @苏锦绘)→ 通过后进入 BIZ-101 子任务2(开发落地)。
|
||||
- 中奖金额的**具体数值**(尤其浮动奖占位值)由本 PRD 决策,落地细节在子任务2 实现。
|
||||
|
||||
---
|
||||
|
||||
## 版本历史
|
||||
| 版本 | 日期 | 作者 | 说明 |
|
||||
|------|------|------|------|
|
||||
| v1.0 | 2026-08-30 11:57 | 沈路明 | 首版 PRD,基于现有 `app.py` compare 与 `index.html` compareRecord 结构增量设计 |
|
||||
| v1.1 | 2026-08-30 14:35 | 沈路明 | 落实架构评审(梁思筑)3 点意见:① 金额字段追加 `(单位:元)` 标注与量级安全说明;② `prize_summary` key 改用英文枚举(方案 A),新增 `prize_level` 中文显示名字段;③ 浮动标记 `floating` 落到 `results[i]` 与 `prize_summary[key]` 两处粒度;④ 验收标准补充兼容性「每次实时计算」条款 |
|
||||
@@ -0,0 +1,252 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>BIZ-102 比对弹窗原型 · 中奖金额展示</title>
|
||||
<style>
|
||||
:root {
|
||||
--text-light: #888;
|
||||
--border: #e8e8e8;
|
||||
}
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
|
||||
background: #f5f6f8;
|
||||
margin: 0;
|
||||
padding: 24px;
|
||||
color: #333;
|
||||
}
|
||||
.modal-wrap {
|
||||
max-width: 520px;
|
||||
margin: 0 auto;
|
||||
background: #fff;
|
||||
border-radius: 14px;
|
||||
box-shadow: 0 8px 30px rgba(0,0,0,0.12);
|
||||
overflow: hidden;
|
||||
}
|
||||
.modal-header {
|
||||
padding: 16px 20px;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
border-bottom: 1px solid var(--border);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
.modal-body { padding: 18px 20px; }
|
||||
|
||||
/* 统计区(.compare-summary) */
|
||||
.compare-summary {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 10px;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
.compare-summary .item {
|
||||
background: #f8f9fa;
|
||||
border-radius: 8px;
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
.compare-summary .item .label { font-size: 12px; color: var(--text-light); margin-bottom: 4px; }
|
||||
.compare-summary .item .value { font-size: 16px; font-weight: 700; }
|
||||
/* 新增:总额与分布区 */
|
||||
.prize-total {
|
||||
grid-column: 1 / -1;
|
||||
background: #eafaf0;
|
||||
border: 1px solid #bdebcd;
|
||||
color: #1e8e4a;
|
||||
border-radius: 8px;
|
||||
padding: 12px;
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
font-weight: 800;
|
||||
}
|
||||
.prize-breakdown {
|
||||
grid-column: 1 / -1;
|
||||
background: #fcfcfd;
|
||||
border: 1px dashed #d8dde3;
|
||||
border-radius: 8px;
|
||||
padding: 10px 12px;
|
||||
font-size: 13px;
|
||||
line-height: 1.9;
|
||||
}
|
||||
.prize-breakdown .row { display: flex; justify-content: space-between; }
|
||||
.prize-breakdown .row .lv { font-weight: 600; }
|
||||
.prize-breakdown .row .amt { color: #1e8e4a; font-weight: 700; }
|
||||
.prize-breakdown .floating-note {
|
||||
margin-top: 6px;
|
||||
font-size: 11px;
|
||||
color: #c0392b;
|
||||
}
|
||||
|
||||
/* 开奖号码 */
|
||||
.draw-line {
|
||||
background: #f0f0f0;
|
||||
padding: 10px;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 10px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
/* 每注 */
|
||||
.compare-ticket {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 8px 10px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
font-size: 13px;
|
||||
}
|
||||
.compare-ticket.win { background: #f4fcf7; }
|
||||
.compare-ticket .idx { color: var(--text-light); min-width: 30px; font-size: 12px; }
|
||||
.ball {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 24px; height: 24px;
|
||||
border-radius: 50%;
|
||||
font-size: 12px;
|
||||
color: #fff;
|
||||
font-weight: 700;
|
||||
}
|
||||
.ball-red { background: #e74c3c; }
|
||||
.ball-blue { background: #3498db; }
|
||||
.prize-badge {
|
||||
padding: 2px 8px;
|
||||
border-radius: 10px;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
}
|
||||
.prize-badge.win { background: #27ae60; color: #fff; }
|
||||
.prize-badge.lose { background: #eee; color: var(--text-light); }
|
||||
/* 新增:每注金额 */
|
||||
.ticket-amount {
|
||||
margin-left: 2px;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
color: #1e8e4a;
|
||||
}
|
||||
.ticket-amount.floating::after {
|
||||
content: " · 浮动以官方为准";
|
||||
font-size: 10px;
|
||||
color: #c0392b;
|
||||
font-weight: 400;
|
||||
}
|
||||
.compare-ticket-info { margin-left: auto; color: var(--text-light); font-size: 12px; }
|
||||
|
||||
.footer-msg {
|
||||
text-align: center;
|
||||
padding: 14px;
|
||||
font-size: 14px;
|
||||
color: #27ae60;
|
||||
font-weight: 700;
|
||||
}
|
||||
.legend { max-width: 520px; margin: 14px auto 0; font-size: 12px; color: var(--text-light); line-height: 1.8; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- ===== 比对弹窗(仅弹窗部分,便于设计师评审) ===== -->
|
||||
<div class="modal-wrap">
|
||||
<div class="modal-header">🎯 中奖比对</div>
|
||||
<div class="modal-body">
|
||||
|
||||
<!-- 统计区:保留原有 4 项,新增总额 + 分布 -->
|
||||
<div class="compare-summary">
|
||||
<div class="item"><div class="label">生成时间</div><div class="value" style="font-size:14px;">2026-08-30 11:00:00</div></div>
|
||||
<div class="item"><div class="label">比对开奖期</div><div class="value" style="font-size:14px;">2026098 · 2026-08-25</div></div>
|
||||
<div class="item"><div class="label">总注数</div><div class="value">5</div></div>
|
||||
<div class="item"><div class="label">中奖注数</div><div class="value" style="color:#27ae60;">4</div></div>
|
||||
|
||||
<!-- 新增 F-4:总中奖金额 -->
|
||||
<div class="prize-total">总中奖金额 25 元</div>
|
||||
|
||||
<!-- 新增 F-5:各奖级分布(数据源 prize_summary,key 为英文枚举) -->
|
||||
<div class="prize-breakdown">
|
||||
<!-- 示例对应 prize_summary.fifth_prize -->
|
||||
<div class="row"><span class="lv">1 注 五等奖</span><span class="amt">共 10 元</span></div>
|
||||
<!-- 示例对应 prize_summary.sixth_prize -->
|
||||
<div class="row"><span class="lv">3 注 六等奖</span><span class="amt">共 15 元</span></div>
|
||||
<!-- 示例对应 prize_summary.first_prize(floating: true) -->
|
||||
<div class="row"><span class="lv">1 注 一等奖 · 浮动</span><span class="amt">共 5,000,000 元*</span></div>
|
||||
<div class="floating-note">* 浮动奖金额为占位/官方公布值,以官方公布为准(数据源:prize_summary[key].floating)</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 开奖号码 -->
|
||||
<div class="draw-line">
|
||||
<strong>开奖号码:</strong>
|
||||
<span class="ball ball-red">03</span><span class="ball ball-red">08</span><span class="ball ball-red">14</span><span class="ball ball-red">19</span><span class="ball ball-red">22</span><span class="ball ball-red">27</span>
|
||||
<span class="ball ball-blue">11</span>
|
||||
</div>
|
||||
|
||||
<!-- 每注:F-6 在奖项徽标旁显示该注金额 -->
|
||||
<div class="compare-ticket win">
|
||||
<span class="idx">001</span>
|
||||
<span class="ball ball-red">03</span><span class="ball ball-red">08</span><span class="ball ball-red">14</span><span class="ball ball-red">19</span><span class="ball ball-red">22</span><span class="ball ball-red">27</span>
|
||||
<span class="ball ball-blue">11</span>
|
||||
<span class="prize-badge win">一等奖</span>
|
||||
<span class="ticket-amount floating">5,000,000元</span>
|
||||
<span class="compare-ticket-info">红6 蓝✓</span>
|
||||
</div>
|
||||
<div class="compare-ticket win">
|
||||
<span class="idx">002</span>
|
||||
<span class="ball ball-red">03</span><span class="ball ball-red">08</span><span class="ball ball-red">14</span><span class="ball ball-red">19</span>
|
||||
<span class="ball ball-blue">11</span>
|
||||
<span class="prize-badge win">五等奖</span>
|
||||
<span class="ticket-amount">10元</span>
|
||||
<span class="compare-ticket-info">红4 蓝✓</span>
|
||||
</div>
|
||||
<div class="compare-ticket win">
|
||||
<span class="idx">003</span>
|
||||
<span class="ball ball-red">03</span><span class="ball ball-red">08</span>
|
||||
<span class="ball ball-blue">11</span>
|
||||
<span class="prize-badge win">六等奖</span>
|
||||
<span class="ticket-amount">5元</span>
|
||||
<span class="compare-ticket-info">红2 蓝✓</span>
|
||||
</div>
|
||||
<div class="compare-ticket win">
|
||||
<span class="idx">004</span>
|
||||
<span class="ball ball-red">08</span>
|
||||
<span class="ball ball-blue">11</span>
|
||||
<span class="prize-badge win">六等奖</span>
|
||||
<span class="ticket-amount">5元</span>
|
||||
<span class="compare-ticket-info">红1 蓝✓</span>
|
||||
</div>
|
||||
<div class="compare-ticket">
|
||||
<span class="idx">005</span>
|
||||
<span class="ball ball-red">01</span><span class="ball ball-red">02</span><span class="ball ball-red">03</span>
|
||||
<span class="ball ball-blue">09</span>
|
||||
<span class="prize-badge lose">未中奖</span>
|
||||
<span class="compare-ticket-info">红0 蓝✗</span>
|
||||
</div>
|
||||
|
||||
<div class="footer-msg">🎉 共 4 注中奖!</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="legend">
|
||||
原型说明(BIZ-102 / PRD v1.1):<br>
|
||||
· 绿色总额条 = 新增 F-4(<code>data.total_prize</code>);虚线框 = 新增 F-5(遍历 <code>data.prize_summary</code>,key 为英文枚举 <code>first_prize</code>...<code>sixth_prize</code>,展示名取 <code>prize_level</code>);<br>
|
||||
· 每注徽标后的绿色金额 = 新增 F-6(<code>results[i].prize_amount</code>);<br>
|
||||
· 浮动奖(一/二/三等奖)金额旁红色「浮动以官方为准」角标,数据源 <code>results[i].floating === true</code> 与 <code>prize_summary[key].floating === true</code>(PRD 第 3.1 / 3.3 节);<br>
|
||||
· 未中奖注不显示金额。原型数据为演示用占位值。<br>
|
||||
· mock JSON 示例:
|
||||
<pre style="background:#f8f9fa;padding:8px;border-radius:6px;font-size:11px;line-height:1.6;margin:6px 0 0;">
|
||||
{
|
||||
"total_prize": 25,
|
||||
"prize_summary": {
|
||||
"fifth_prize": {"count": 1, "amount": 10, "prize_level": "五等奖", "floating": false},
|
||||
"sixth_prize": {"count": 3, "amount": 15, "prize_level": "六等奖", "floating": false}
|
||||
},
|
||||
"results": [
|
||||
{"index": 1, "prize_level": "五等奖", "prize_amount": 10, "floating": false, "is_win": true},
|
||||
{"index": 2, "prize_level": "六等奖", "prize_amount": 5, "floating": false, "is_win": true}
|
||||
]
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user