Appearance
第十四章 异常与边界处理
14.1 空状态处理
当列表数据为空时,根据不同场景显示不同的空状态界面:
| 场景 | 显示内容 | 操作建议 |
|---|---|---|
| 筛选结果为空 | 插图 +「没有符合条件的赛事」 | 显示「清除筛选条件」按钮 |
| 今日无赛事 | 插图 +「今日暂无赛事安排」 | 提示切换日期查看 |
| 无待上架赛事 | 插图 +「没有待上架的赛事」 | 无 |
| 搜索无结果 | 插图 +「未找到匹配的赛事」 | 提示修改搜索关键词 |
14.2 加载状态处理
| 场景 | 显示内容 |
|---|---|
| 首次加载 | 表格区域显示骨架屏(10 行灰色占位符) |
| 刷新中 | 刷新按钮显示旋转图标 |
| 筛选中 | 表格内容半透明遮罩 + 居中旋转图标 |
| 操作执行中 | 操作按钮显示加载状态,禁止重复点击 |
加载超时处理
| 超时时间 | 处理方式 |
|---|---|
| 5 秒 | 显示「加载时间较长,请耐心等待」 |
| 15 秒 | 显示「加载超时」+「重试」按钮 |
| 30 秒 | 自动取消请求,显示错误状态 |
14.3 错误状态处理
| 错误类型 | 处理方式 |
|---|---|
| 数据加载失败 | 显示错误提示 +「重试」按钮 |
| 操作执行失败 | Toast 通知提示错误原因 |
| 权限不足 | 对话框提示「权限不足」 |
| 网络超时 | 显示网络异常横幅 |
| 服务器错误 | 显示「服务暂时不可用,请稍后重试」 |
错误码与提示映射
| 错误码 | 用户提示 | 处理建议 |
|---|---|---|
| 400 | 请求参数错误 | 检查输入内容 |
| 401 | 登录已过期 | 跳转登录页 |
| 403 | 权限不足 | 联系管理员 |
| 404 | 数据不存在 | 刷新页面 |
| 429 | 操作过于频繁 | 稍后重试 |
| 500 | 服务器错误 | 稍后重试 |
| 502/503 | 服务暂时不可用 | 稍后重试 |
| 504 | 请求超时 | 检查网络后重试 |
14.4 并发冲突处理
当多个用户同时操作同一赛事时,采用乐观锁机制处理冲突:
| 场景 | 处理方式 |
|---|---|
| 用户 A 上架,用户 B 也点上架 | 用户 B 收到提示「该赛事已被他人上架」 |
| 用户 A 下架,用户 B 正在操盘 | 用户 B 收到提示「该赛事已被下架」 |
| 用户 A 分配操盘手,用户 B 也在分配 | 后提交的覆盖先提交的(分配操作允许覆盖) |
冲突检测机制
| 机制 | 说明 |
|---|---|
| 版本号校验 | 每次操作提交时携带数据版本号 |
| 实时状态推送 | 状态变更实时推送给所有在线用户 |
| 行级锁 | 同一赛事的状态变更操作采用数据库行级锁,先到先得 |
冲突提示对话框
| 元素 | 内容 |
|---|---|
| 标题 | 操作冲突 |
| 描述 | 该赛事状态已被其他用户修改,请刷新后重试 |
| 按钮 | 「刷新」「取消」 |
14.5 跨天比赛处理
比赛日以每日 06:00(北京时间)为分界线:
| 开赛时间 | 所属比赛日 |
|---|---|
| 1月19日 23:30 | 1月19日 |
| 1月20日 01:30 | 1月19日 |
| 1月20日 05:59 | 1月19日 |
| 1月20日 06:00 | 1月20日 |
跨天比赛的筛选规则
| 筛选条件 | 筛选结果 |
|---|---|
| 日期 = 1月19日 | 包含 1月19日 06:00 至 1月20日 05:59 开赛的比赛 |
| 日期 = 今日 | 包含今日 06:00 至明日 05:59 开赛的比赛 |
跨天比赛的显示规则
| 场景 | 显示方式 |
|---|---|
| 开赛时间 | 显示实际开赛时间(如 01:30) |
| 日期标签 | 显示所属比赛日(如 1月19日) |
| 列表排序 | 按实际开赛时间排序 |
14.6 大数据量处理
分页策略
| 参数 | 值 | 说明 |
|---|---|---|
| 每页条数选项 | 50 / 100 / 200 条 | 用户可选 |
| 默认每页条数 | 50 条 | 平衡性能与信息密度 |
| 最大总数据量 | 10000 条 | 超出时提示缩小筛选范围 |
14.7 告警阈值配置
各类告警阈值的默认值、允许范围及调整方式,按配置归属分别参阅:
- 风控管理配置:单边超限、大额投注阈值
- 联赛管理配置:延期超时、即将开赛告警等阈值
操盘列表中涉及告警阈值判断的功能(如告警标签、置顶规则等)均读取对应配置模块中的阈值设定,本文档不重复定义具体数值。
14.8 操作时序边界场景
当操盘手发起操作到提交之间,赛事状态会发生变化。以下定义各类时序边界场景的处理规则。
14.8.1 上架操作时序边界
| 场景 | 触发条件 | 系统行为 | 操盘手感知 |
|---|---|---|---|
| 上架时赛事进入滚球 | 点击上架时赛前,提交时已滚球 | 弹出二次确认弹窗 | 提示「该赛事已进入滚球,是否继续上架?」 |
| 上架时赛事已取消 | 点击上架时正常,提交时已取消 | 阻止上架,关闭弹窗 | Toast「赛事已取消,无法上架」 |
| 上架时赛事已结束 | 点击上架时滚球,提交时已完场 | 阻止上架,关闭弹窗 | Toast「赛事已结束」 |
| 上架时赛事已延期 | 点击上架时正常,提交时已延期 | 阻止上架 | Toast「赛事延期中,无法上架」 |
| 跟随数据源但 IM 暂停 | 上架选择跟随,数据源当前暂停 | 上架成功,盘口状态=开盘(C端显示暂停投注) | 弹窗提示当前数据源状态 |
| 跟随数据源但 IM 关盘 | 上架选择跟随,数据源已关盘 | 阻止上架 | Toast「数据源已关盘,无法上架」 |
14.8.2 批量上架时序边界
| 场景 | 触发条件 | 系统行为 | 操盘手感知 |
|---|---|---|---|
| 批量含已取消赛事 | 批量选中 5 场,其中 1 场已取消 | 部分成功:4 场上架成功,1 场跳过 | 结果弹窗显示「成功 4 场,失败 1 场」,点击查看详情 |
| 批量含延期赛事 | 批量选中含延期赛事 | 延期赛事跳过,其他正常上架 | 结果弹窗显示失败原因「赛事延期中」 |
| 批量含已结束赛事 | 批量选中含已结束赛事 | 已结束赛事跳过,其他正常上架 | 结果弹窗显示失败原因「赛事已结束」 |
14.8.3 下架操作时序边界
| 场景 | 触发条件 | 系统行为 | 操盘手感知 |
|---|---|---|---|
| 下架时赛事已结束 | 点击下架,提交时赛事完场 | 阻止下架 | 提示「赛事已流转到结算管理」 |
| 下架滚球赛事 | 对滚球中的赛事执行下架 | 弹窗增加红色警告,显示当前投注额 | 需二次确认,下架后盘口状态=隐藏(客户端不可见) |
| 下架时赛事已取消 | 点击下架,提交时赛事取消 | 阻止下架 | 提示「赛事已流转到结算管理」 |
14.8.4 锁盘解锁时序边界
操作位置说明:根据D1设计决策,锁盘/解锁操作统一在「赛事操盘详情页」进行,列表页不提供这些操作按钮。
| 场景 | 触发条件 | 系统行为 | 操盘手感知 |
|---|---|---|---|
| 锁盘时数据源推送关盘 | 人工锁盘中,数据源推送关盘 | 数据源关盘优先级最高,盘口变为关盘 | Toast「数据源已推送关盘,盘口最终状态为关盘」 |
| 解锁时数据源暂停(跟随=是) | 人工解锁,数据源暂停 | 解锁成功,本地恢复开盘,C端显示暂停投注 | Toast「解锁成功,数据源暂停中」 |
| 解锁时数据源暂停(跟随=否) | 人工解锁,数据源暂停 | 解锁成功,本地恢复开盘,告警列显示「数据源暂停」 | Toast「解锁成功」 |
| 解锁时数据源维护 | 人工解锁,数据源维护中 | 解锁成功,盘口强制隐藏 | Toast「解锁成功,数据源维护中,盘口状态为隐藏」 |
| 解锁时数据源已关盘 | 人工解锁,数据源已关盘 | 阻止解锁 | Toast「数据源已关盘,无法解锁」 |
解锁后状态与跟随配置的关系
| 数据源状态 | 跟随配置 | 解锁后盘口状态 |
|---|---|---|
| 开盘 | 是/否 | 开盘 |
| 暂停 | 是 | 开盘(C端暂停投注) |
| 暂停 | 否 | 开盘(告警列显示「数据源暂停」) |
| 维护 | 是/否 | 隐藏(强制) |
| 关盘 | 是/否 | 阻止解锁 |
14.8.5 延期相关时序边界
字段说明:赛事状态(延期、取消等)由SettlementId标识,与EventStatusId(盘口状态)是不同字段。详见第9章/第10章数据字段定义。
| 场景 | 触发条件 | 系统行为 | 操盘手感知 |
|---|---|---|---|
| 滚球时收到延期 | 赛事滚球中,收到 SettlementId=5 | 赛事状态变为延期,盘口自动隐藏 | 行变为橙色背景,告警列显示「延期」 |
| 滚球时收到取消 | 赛事滚球中,收到 SettlementId=6 | 关盘盘口,流转到结算管理 | 赛事从操盘列表消失 |
| 延期→恢复→再次延期 | 延期赛事恢复后再次收到延期状态 | 允许状态循环,记录完整状态变更链 | 日志记录完整流转历史 |
| 延期期间尝试上架 | 对延期赛事点击上架 | 阻止上架 | 按钮禁用,hover 显示「赛事延期中」 |
| 延期期间尝试取消隐藏盘口 | 对延期赛事的隐藏盘口点击取消隐藏 | 阻止取消隐藏 | 按钮禁用,提示「赛事延期中,盘口无法取消隐藏」 |
14.8.6 并发操作竞争处理
操作位置说明:隐藏/取消隐藏/锁定/解锁操作在详情页进行,以下并发场景指不同用户在各自页面同时操作同一赛事。
| 场景 | 触发条件 | 系统行为 | 操盘手感知 |
|---|---|---|---|
| A 上架,B 也上架 | 两个操盘手同时对同一赛事上架 | 先提交者成功,后提交者收到「赛事已被上架」 | 后操作者弹窗关盘,列表刷新 |
| A 下架,B 锁盘 | A 下架,B 同时锁盘同一赛事 | 先提交者成功,后提交者收到冲突提示 | 后操作者需刷新查看最新状态 |
| A 解锁,B 下架 | A 解锁,B 同时下架同一赛事 | 下架优先级高于解锁,以下架为准 | A 操作失败,收到「赛事已被下架」 |
| A 隐藏,B 锁盘 | A 隐藏,B 同时锁盘同一赛事 | 锁盘优先级高于隐藏,以锁盘为准 | A 操作被覆盖,B 操作成功 |
并发操作竞争优先级
同一赛事的状态变更操作采用数据库行级锁,先到先得。当两个操作在极短时间内到达时,按以下优先级决定最终状态:
| 优先级 | 操作类型 | 说明 |
|---|---|---|
| 1(最高) | 下架 | 涉及客户端可见性,影响最大 |
| 2 | 锁盘 | 主动风控行为,优先保障 |
| 3 | 解锁 | 需确认数据源状态后执行 |
| 4(最低) | 隐藏/取消隐藏 | 临时状态变更 |
概念区分:
- 状态覆盖优先级(第16章16.3.11节):决定盘口最终状态由哪个触发源(数据源/人工/风控/联赛)决定
- 操作竞争优先级(本节):决定同时到达的多个人工操作请求哪个先执行
两者是不同层面的优先级规则,状态覆盖优先级用于计算最终状态,操作竞争优先级用于解决并发冲突。
14.9 批量操作失败详情
当批量操作存在部分失败时,点击「查看详情」弹出失败详情弹窗。
弹窗结构
| 元素 | 内容 |
|---|---|
| 标题 | 批量操作结果 |
| 汇总信息 | 成功 X 场,失败 Y 场 |
| 失败列表 | 表格形式展示失败详情(赛事编号、赛事名称、联赛、失败原因) |
| 按钮 | 「关盘」 |
失败原因与建议操作映射
| 失败原因 | 建议操作 |
|---|---|
| 赛事已取消 | 无需处理,自动流转到结算管理 |
| 赛事已结束 | 无需处理,自动流转到结算管理 |
| 赛事延期中 | 等待数据源推送恢复或取消状态 |
| 数据源已关盘 | 等待数据源恢复 |
| 已被其他用户操作 | 刷新列表查看最新状态 |
| 权限不足 | 联系主管处理 |
14.10 延期超时处理
当赛事延期时间超过配置阈值时,系统触发延期超时告警。阈值定义请参考联赛管理配置。
延期超时告警规则
| 条件 | 系统行为 |
|---|---|
| 延期时长达到阈值的 80% | 告警列显示「延期较长」标签(橙色) |
| 延期时长达到阈值的 100% | 告警列显示「延期超时」标签(红色) |
| 延期时长超过阈值的 150% | 自动置顶该赛事,建议下架 |
延期超时后的操作建议
| 建议 | 说明 |
|---|---|
| 下架处理 | 如确认赛事不会恢复,执行下架 |
| 继续等待 | 如有消息表明赛事将恢复,可继续等待 |
| 联系数据源 | 确认赛事最新状态 |
说明:延期超时告警为建议性提示,系统不会自动执行下架操作,最终决策权归操盘手。
14.11 投注时序边界
当盘口状态变更(关盘、隐藏、锁定)时,服务端状态变更与客户端收到通知之间存在延迟窗口。本节定义该窗口期内投注请求的处理规则。
14.11.1 时序窗口定义
| 时间点 | 定义 |
|---|---|
| T0 | 服务端盘口状态变更时间 |
| T1 | 客户端收到状态推送时间(T1 > T0,延迟约 100-500ms) |
| Tx | 用户投注请求到达服务端时间 |
14.11.2 窗口期投注处理规则
| 场景 | Tx 位置 | 处理方式 | 用户提示 |
|---|---|---|---|
| 盘口关盘 | T0 < Tx < T1 | 拒绝投注 | 该盘口已关盘 |
| 盘口隐藏 | T0 < Tx < T1 | 拒绝投注 | 盘口隐藏中,请稍后 |
| 盘口锁定 | T0 < Tx < T1 | 拒绝投注 | 盘口已锁定 |
| 赛事流转 | T0 < Tx < T1 | 拒绝投注 | 该赛事已结束 |
关键原则:以服务端状态为准,客户端延迟不影响判断。
14.11.3 服务端校验流程
投注请求处理时,服务端按以下顺序校验:
| 步骤 | 校验内容 | 失败错误码 |
|---|---|---|
| 1 | 赛事是否存在且已上架 | EVENT_NOT_AVAILABLE |
| 2 | 盘口状态是否为开盘 | MARKET_NOT_OPEN |
| 3 | 赔率版本是否匹配 | ODDS_CHANGED |
| 4 | 投注额度是否在限额内 | AMOUNT_EXCEED_LIMIT |
| 5 | 用户是否有投注权限 | USER_RESTRICTED |
修订记录
| 版本 | 日期 | 修订内容 |
|---|---|---|
| v1.0 | 2026-01-15 | 初稿 |
| v1.1 | 2026-01-21 | 【10/D1对齐】1) 14.8.5节EventStatusId改为SettlementId;2) 14.8.4/14.8.6节增加操作位置说明(详情页);3) 14.4节移除列表页不存在的锁盘场景 |
| v1.2 | 2026-01-29 | 【宪法v1.6术语对齐】本地状态术语统一:14.8.5/14.8.6节"暂停/恢复"→"隐藏/取消隐藏";14.11节"盘口暂停"→"盘口隐藏" |
| v1.3 | 2026-02-11 | 【A1架构修正】IM暂停不再改变本地状态,仅影响C端展示:1)14.8.4节解锁场景修正:暂停改为本地恢复开盘,C端显示差异说明;2)14.8.4下方解锁后状态表:暂停项从"隐藏"改为"开盘(C端暂停投注)" |
| v1.4 | 2026-02-11 | 【全量交叉验证】14.8.1节上架时IM暂停场景:盘口状态从"隐藏"改为"开盘(C端显示暂停投注)";14.7节"可配置范围"改为"允许范围" |