菜单消费分类模式需求文档

1. 文档信息

字段 内容
Use Case ID UC-MENU-001
Use Case 名称 管理员配置菜单消费分类模式
云效任务编号 VWCG-1327
所属项目 CusumptionMachine
所属模块 基础设置、菜单消费
优先级 P0
版本 v1.6
状态 Ready
DoR READY:云效任务编号已确认;关联任务、代码提交等流程不在本需求文档范围内
需求日期 2026-09-07
事实来源 用户需求、当前 Android 代码、POST /p/api/getMeal 实际接口回读

2. 背景与目标

当前菜单消费页面使用客户端固定分类展示菜品,分类固定为“全部、主食、素菜、荤菜、蛋奶坚果、水果、汤饮”。服务端现已在原有 POST /p/api/getMeal 接口上增加 custom_category_v1 响应模式,可以返回餐厅配置的自定义分类和菜品所属分类。

本需求目标是在基础设置中增加“菜单消费模式”,让管理员可以在固定分类和自定义分类之间切换。菜单消费页面根据设置选择对应的请求和响应契约,同时保持现有购物车、营养筛选、排序和支付流程不变。

3. 范围

3.1 In Scope

3.2 Out of Scope

4. 参与者与系统边界

角色或系统 目标或职责 权限或数据范围 交互入口
设备管理员 选择菜单消费分类模式 当前消费机本地设置 基础设置页面
消费用户 按分类浏览和选择菜品 当前设备对应餐厅的菜单 菜单消费页面
Android 客户端 保存模式、请求菜单、解析协议、展示分类和菜品 当前设备编号对应的数据 SharedPreferences、HTTP
菜单服务 根据 group_mode 返回固定或自定义分类菜单 当前设备所属餐厅 POST /p/api/getMeal

5. 触发、前置条件与后置条件

5.1 触发事件

5.2 前置条件

ID 条件 不满足时处理 验证方式
PRE-01 设备已完成基础配置并取得设备编号 沿用现有基础配置校验,不进入菜单请求 读取本地配置
PRE-02 接口地址已配置 沿用现有基础配置提示 读取本地配置
PRE-03 菜单消费入口对当前设备可用 沿用当前入口显示规则 页面检查

5.3 成功后置条件

5.4 失败后置条件

6. 页面与交互要求

6.1 基础设置页面

新增设置项:

菜单消费模式    [固定分类] [自定义分类]

交互要求:

建议持久化值:

显示文本 持久化值
固定分类 fixed_category
自定义分类 custom_category_v1

6.2 菜单消费页面

固定分类模式:

自定义分类模式:

7. API 契约

7.1 后端接口

固定分类和自定义分类复用同一个后端接口:

POST /p/api/getMeal

本需求不新增后端 URL。

7.2 固定分类请求

category=false
keyword=
code=<当前设备编号>

固定分类请求不提交 group_mode

7.3 自定义分类请求

category=false
keyword=
code=<当前设备编号>
group_mode=custom_category_v1

7.4 Android 客户端接口声明

尽管后端路径相同,固定分类和自定义分类属于两套不同的数据契约。Android 客户端应声明两个 Retrofit 方法:

客户端方法 后端路径 响应类型 用途
getDishMenu /p/api/getMeal BaseBean<GetDishMenuResponse> 固定分类
getCustomDishMenu /p/api/getMeal BaseBean<GetCustomDishMenuResponse> 自定义分类

两个方法是同一后端接口的两种客户端映射,不代表新增服务端接口。

7.5 固定分类响应

固定分类继续使用现有 GetDishMenuResponse,只承载旧结构:

{
  "code": 0,
  "message": "获取成功",
  "data": {
    "1": [],
    "2": [],
    "3": [],
    "4": [],
    "5": [],
    "6": []
  }
}

7.6 自定义分类响应

新增 GetCustomDishMenuResponse,只承载 custom_category_v1 结构:

{
  "code": 0,
  "message": "获取成功",
  "data": {
    "schema_version": "custom_category_v1",
    "categories": [
      {
        "id": 0,
        "code": "all",
        "name": "全部",
        "status": 1,
        "is_system": 1
      },
      {
        "id": 12,
        "code": null,
        "name": "高蛋白套餐",
        "status": 1,
        "is_system": 0
      },
      {
        "id": 1,
        "code": "other",
        "name": "其他",
        "status": 1,
        "is_system": 1
      }
    ],
    "dishes": [
      {
        "uuid": "DISH-UUID-001",
        "name": "宫保鸡丁",
        "custom_category_id": 12,
        "custom_category_name": "高蛋白套餐",
        "custom_category_status": 1,
        "price": 18,
        "unit": "份",
        "energy_100g": 121
      }
    ]
  }
}

7.7 响应 DTO 分离原则

7.8 统一页面模型

两个网络响应分别转换为统一的页面菜单模型 MenuCatalog

GetDishMenuResponse
→ FixedMenuCatalogMapper
→ MenuCatalog

GetCustomDishMenuResponse
→ CustomMenuCatalogMapper
→ MenuCatalog

MainActivity 只消费 MenuCatalog,不直接依赖两套网络字段结构。MenuCatalog 至少包含:

8. 数据规则

规则 ID 规则名称 可执行规则 优先级
BR-001 默认模式 本地没有有效设置时必须使用 fixed_category P0
BR-002 固定分类请求 固定分类请求禁止提交 group_mode P0
BR-003 自定义分类请求 自定义分类请求必须提交 group_mode=custom_category_v1 P0
BR-004 响应类型隔离 固定与自定义分类必须使用不同响应 DTO P0
BR-005 全部分类 code=all 必须展示 dishes 全量数据,不按 id=0 过滤 P0
BR-006 普通分类 普通分类和 code=other 必须按 dish.custom_category_id == category.id 过滤 P0
BR-007 分类顺序 启用分类必须保持服务端返回顺序 P0
BR-008 分类状态 页面只显示 status=1 的分类 P0
BR-009 异常菜品 分类为空或无法匹配的菜品必须保留在“全部”,禁止错误归类 P0
BR-010 模式稳定性 请求失败或协议异常不得修改本地保存的菜单模式 P0
BR-011 购物车稳定性 分类切换和刷新失败不得清空购物车 P0
BR-012 协议版本 自定义分类响应必须校验 schema_version=custom_category_v1 P0
BR-013 分类名称展示 自定义分类名称超过 6 个 Unicode 字符时,标签必须显示前 6 个字符并追加 ...;完整名称不得被改写 P0

9. 主流程

步骤 角色 动作或系统响应 页面/API 数据或状态变化 验收
M1 设备管理员 进入基础设置 基础设置 读取本地菜单模式 AC-001
M2 设备管理员 选择固定分类或自定义分类 菜单消费模式设置项 保存字符串模式值 AC-002
M3 消费用户 进入菜单消费页面 菜单消费 页面读取已保存模式 AC-003
M4 Android 客户端 根据模式调用对应 Retrofit 方法 POST /p/api/getMeal 发出固定或自定义请求 AC-004AC-005
M5 菜单服务 返回对应的数据契约 接口响应 得到固定或自定义响应 DTO AC-006
M6 Android 客户端 使用对应 Mapper 转换响应 Mapper 生成统一 MenuCatalog AC-007
M7 Android 客户端 显示分类并默认选中“全部” 菜单分类栏 更新当前分类 AC-008
M8 消费用户 点击一个分类 菜单分类栏 按分类过滤菜品 AC-009
M9 Android 客户端 继续执行营养过滤、排序和列表刷新 菜品列表 更新适配器数据 AC-010

10. 分支流程

分支 分支点或条件 系统行为 结果 验收
A1@M4 当前模式为固定分类 调用 getDishMenu,不提交 group_mode 展示现有固定分类 AC-004
A2@M4 当前模式为自定义分类 调用 getCustomDishMenu,提交 custom_category_v1 解析动态分类 AC-005
A3@M7 自定义响应存在 code=all 默认选中该分类并展示全部菜品 全量菜品可见 AC-008
A4@M7 自定义响应没有 code=all 但存在启用分类 默认选中第一个启用分类 对应分类菜品可见 AC-011
A5@M8 用户选择 code=other 按该分类 ID 过滤 展示“其他”菜品 AC-012

11. 异常与恢复流程

异常或恢复 发生条件 用户反馈 数据处理 恢复方式 验收
E1@M4 网络失败或超时 显示现有网络错误提示 保留模式、购物车和已有列表 下拉刷新或点击重试 AC-020
E2@M5 自定义响应的 schema_version 缺失或不匹配 提示“自定义分类数据格式异常” 禁止按新协议继续解析 重新调用固定分类方法临时降级 AC-021
E3@M6 categories 为空但 dishes 非空 页面仍可浏览菜品 临时生成本次展示用“全部”分类 下次刷新重新请求 AC-022
E4@M6 菜品分类为空或找不到对应分类 不单独打断消费流程 菜品仅保留在“全部”并记录日志 后台修正分类后刷新 AC-023
E5@M6 分类 ID 重复或分类名称为空 不展示无效重复项 保留首个有效分类并记录日志 后台修正后刷新 AC-024
E6@M5 业务 code 非 0 或 data 为空 显示接口错误或空状态 不修改设置和购物车 点击重试 AC-025

临时降级只影响本次页面数据,不允许把用户保存的“自定义分类”自动改回“固定分类”。

12. 兼容性与不应影响逻辑

13. 日志与可观测性

客户端应记录以下信息,不记录支付凭证或人员敏感数据:

13.1 分类异常的优先排查顺序

当自定义分类标签减少、只剩“全部/其他”或菜品数量发生明显变化时,必须先排查餐段和接口数据,再排查客户端代码:

  1. 确认问题发生前后是否切换了早餐、午餐、晚餐等餐段,并记录问题时刻对应的当前餐段。
  2. 使用问题设备的同一设备编号,核对该时刻 POST /p/api/getMeal 请求是否携带 group_mode=custom_category_v1
  3. 优先检查原始响应中的 categoriesdishescustom_category_idcustom_category_name,并与另一个餐段的响应进行对比。
  4. 如果响应本身只包含 allother,且菜品均归入 other,应先检查当前餐段的菜谱范围及自定义分类关联配置,不应直接判定为营养展示适配或客户端分类渲染回归。
  5. 只有当接口已经返回普通自定义分类、但页面没有对应标签时,才继续排查响应 DTO、CustomMenuCatalogMapper、动态分类栏渲染和页面刷新逻辑。

“营养展示”只控制营养筛选、排序和热量区域,不负责生成、删除或重排接口返回的自定义分类。排查分类缺失时,应先固定餐段和接口响应,避免把餐段数据变化误判为营养功能回归。

14. 非功能要求

14.1 性能

14.2 安全

14.3 编码和资源

15. 验收标准

AC 关联对象 Given When Then 证据
AC-001 M1/BR-001 本地没有菜单模式设置 打开基础设置 “固定分类”处于选中状态 页面截图、配置回读
AC-002 M2 基础设置已打开 切换菜单模式并重新进入页面 页面恢复最后一次有效选择 页面截图、配置回读
AC-003 M3 已保存一个合法模式 进入菜单消费 页面使用该模式发起菜单请求 请求日志
AC-004 A1/BR-002 当前为固定分类 请求菜单 请求不包含 group_mode,页面保持现有七个分类 抓包、页面截图
AC-005 A2/BR-003 当前为自定义分类 请求菜单 请求包含 group_mode=custom_category_v1 抓包、接口日志
AC-006 M5/BR-004 服务端分别返回旧、新结构 客户端解析 两种响应分别进入对应 DTO,不发生混合字段依赖 单元测试
AC-007 M6 任一种响应解析成功 Mapper 转换 输出统一 MenuCatalog 单元测试
AC-008 A3/BR-005 自定义响应包含 code=all 页面首次展示或刷新成功 默认选中“全部”并展示全部菜品 页面截图、列表计数
AC-009 M8/BR-006 存在普通自定义分类 点击该分类 只展示匹配 custom_category_id 的菜品 页面截图、列表断言
AC-010 M9 已选择分类 使用营养筛选或排序 结果基于当前分类菜品,购物车不变 页面测试
AC-011 A4 响应没有 all 但存在启用分类 页面展示 默认选中第一个启用分类 单元测试、页面测试
AC-012 A5 存在 code=other 点击“其他” 展示分类 ID 匹配的菜品 单元测试、页面测试
AC-013 M7/BR-013 自定义分类名称分别为 6 个和 7 个字符 页面展示分类标签 6 个字符时原样显示;7 个字符时显示前 6 个字符加 ...,点击后仍按原分类 ID 筛选 单元测试、页面截图
AC-020 E1/BR-010/BR-011 页面已有菜品和购物车 刷新发生网络失败 已有列表、购物车和设置均不被清空 断网测试、截图
AC-021 E2/BR-012 自定义响应版本不匹配 客户端处理响应 提示异常并临时请求固定分类,不修改保存模式 Mock 测试、日志
AC-022 E3 分类为空且菜品非空 页面处理响应 生成临时“全部”并展示所有菜品 单元测试
AC-023 E4/BR-009 菜品分类无法匹配 页面处理响应 菜品仍在“全部”中且日志可定位 单元测试、日志
AC-024 E5 分类 ID 重复或名称为空 页面处理响应 无重复或空名称分类项,页面不崩溃 单元测试
AC-025 E6 接口失败或无数据 页面处理响应 显示错误或空状态,可执行重试 页面测试

16. 测试矩阵

Test ID 层级 覆盖对象 预期结果 自动化
UT-MENU-001 单元测试 菜单模式默认值与合法性 空值和非法值返回固定分类
UT-MENU-002 单元测试 固定分类 Mapper 旧响应转换为七个页面分类
UT-MENU-003 单元测试 自定义分类 Mapper 分类顺序、状态和菜品关联正确
UT-MENU-004 单元测试 all 分类 全量菜品不按 ID 过滤
UT-MENU-005 单元测试 异常分类 未匹配菜品保留在“全部”
UT-MENU-006 单元测试 DTO 解析 固定与自定义响应分别解析到对应 DTO
UT-MENU-007 单元测试 自定义分类标签名称格式化 6 个字符原样显示;超长保留前 6 个字符并追加 ...;Unicode 字符不被截断
API-MENU-001 契约测试 固定分类请求 不提交 group_mode 并返回旧结构 是或 MockWebServer
API-MENU-002 契约测试 自定义分类请求 提交协议值并返回新结构 是或 MockWebServer
UI-MENU-001 页面测试 基础设置 默认值、切换和恢复正确 是或人工
UI-MENU-002 页面测试 动态分类栏 超过 6 个字符的名称按规则省略,多分类横向滚动正常 是或人工
E2E-MENU-001 端到端 固定分类消费 选菜、购物车和支付链路正常 人工真机
E2E-MENU-002 端到端 自定义分类消费 分类切换、选菜、购物车和支付链路正常 人工真机
E2E-MENU-003 端到端 网络失败恢复 已有数据保留且重试成功 人工真机

17. 实际接口验证记录

2026-09-07 已使用当前连接设备的实际接口配置验证自定义分类请求。验证时对设备编号进行脱敏记录。排查过程中确认,同一设备在不同餐段会返回不同菜谱和自定义分类集合。

项目 餐段切换前样本(14:20) 餐段切换后样本(14:38)
请求地址 https://zhct.yyangpt.cn/p/api/getMeal https://zhct.yyangpt.cn/p/api/getMeal
设备编号 sfj_sp_*** sfj_sp_***
请求参数 group_mode=custom_category_v1 group_mode=custom_category_v1
业务结果 code=0message=获取成功 code=0message=获取成功
协议版本 custom_category_v1 custom_category_v1
分类 “全部、其他” “全部、养生粥、蛋、其他”
分类数量 2 4
菜品数量 23 41
客户端映射数量 2 4
分类关联异常 0 0

该现象的根因是餐段切换后服务端返回的菜谱范围和分类关联发生变化,不是营养展示适配删除了自定义分类。客户端两次均按响应中的 categories 原顺序展示。后续验收和问题复现必须记录餐段,并分别验证目标餐段的后台分类配置。

18. 追踪矩阵

UC/步骤 页面 API 数据或状态 规则 验收 测试 实现位置
M1-M2 基础设置 不适用 本地菜单模式 BR-001 AC-001AC-002 UT-MENU-001UI-MENU-001 FragmentBasicConstants
A1@M4 菜单消费 getDishMenu 固定响应 DTO BR-002BR-004 AC-004AC-006 API-MENU-001UT-MENU-002 APIServiceRetrofitRequest
A2@M4 菜单消费 getCustomDishMenu 自定义响应 DTO BR-003BR-004 AC-005AC-006 API-MENU-002UT-MENU-006 APIServiceRetrofitRequest
M6-M9 菜单消费 不适用 MenuCatalog BR-005BR-009BR-013 AC-007AC-013 UT-MENU-003UT-MENU-005UT-MENU-007 Mapper、MainActivityMenuCategoryNameFormatter
E1-E6 菜单消费 固定与自定义请求 错误、空、降级状态 BR-010BR-012 AC-020AC-025 E2E-MENU-003、Mock 测试 MainActivity、Mapper

19. 依赖、风险与待确认项

ID 类型 内容 影响 应对措施 状态
RISK-001 测试数据 不同餐段的菜谱和自定义分类配置可能不同 某些餐段只显示“全部/其他”,容易误判为客户端回归 按餐段检查菜谱范围及分类关联,并分别准备验收数据 Open
RISK-002 兼容性 自定义模式可能访问未升级环境 自定义响应版本不匹配 显式校验版本并临时降级固定分类 Accepted
RISK-003 页面布局 分类数量和名称不可控 分类挤压或不可点击 使用横向滚动和最小触控宽度 Accepted
ID 待确认项 影响 负责人 状态
Q-001 补充云效任务编号 已确认任务编号为 VWCG-1327;关联任务操作不在本次范围 产品或需求负责人 Closed
Q-002 确认每个目标餐段都配置了需要验收的普通自定义分类 影响多餐段完整验收,不影响协议和代码设计 后台配置负责人 Open

20. 营养展示兼容补充方案

20.1 为什么需要补充

“固定分类/自定义分类”解决的是菜品如何分组展示;“营养展示”解决的是菜单页面是否提供营养筛选、排序、总热量以及支付后的营养反馈。两者属于相互独立的功能维度,不能因为分类来源发生变化而改变原有营养能力。

本次补充主要解决以下问题:

20.2 需求性质

需求项 性质 说明
基础设置增加“菜单消费模式” 新增功能 原系统没有固定分类与自定义分类的切换能力
支持 custom_category_v1 请求和动态分类 新增功能 增加新的服务端响应模式和页面展示方式
自定义分类继续支持原营养筛选、排序和总热量 兼容性要求 营养能力已经存在,不属于重新开发营养功能
修改营养设置后返回菜单页面立即生效 现有功能缺失修复 当前 MainActivity.onResume() 未重新读取营养设置
关闭营养展示时清除已选营养条件 缺陷修复 防止出现不可见的隐式筛选
明确自定义响应中的完整营养字段 接口契约补充 保证自定义分类达到与固定分类相同的营养能力
支付成功弹窗兼容两种分类模式 兼容性要求 保持现有营养开关语义和支付流程不变

20.3 功能规则

菜单分类模式和营养展示配置必须独立组合生效:

分类模式 营养展示 页面行为
固定分类 关闭 显示固定分类;隐藏营养区域;菜品不受营养条件过滤
固定分类 开启 显示固定分类和营养区域;支持现有营养筛选和排序
自定义分类 关闭 显示动态分类;隐藏营养区域;只按自定义分类过滤
自定义分类 开启 显示动态分类和营养区域;先按分类、再按营养条件处理

营养开关继续复用 Constants.SETTING_NUTRITION_SHOW_SWITCHER,默认值保持为关闭,不增加第二个营养设置项。

开启营养展示时:

关闭营养展示时:

无论采用哪种分类模式,页面统一执行以下数据处理顺序:

接口菜品
  → 按当前分类过滤
  → 按当前营养类型过滤
  → 按营养值升序或降序
  → 更新菜品列表

20.4 设置返回即时生效

管理员从菜单消费页面进入基础设置,修改配置后直接返回时:

20.5 自定义分类接口营养字段

自定义分类响应中的 dishes 应继续提供现有五类营养字段:

{
  "energy_100g": 121,
  "carbohydrate_100g": 12.5,
  "protein_100g": 18,
  "fat_100g": 6.2,
  "dietary_fiber_100g": 2.1
}

字段规则:

20.6 技术落地

MainActivity 增加统一的营养状态刷新方法,例如 refreshNutritionDisplaySetting(),负责:

  1. 读取最新的营养展示配置。
  2. 统一更新三个营养相关区域的可见性。
  3. 关闭营养展示时清除营养选中状态。
  4. 返回是否需要重新刷新本地菜品列表。

调用位置:

推荐的 onResume() 处理顺序:

读取最新分类模式和营养设置
  → 营养关闭时清除隐藏筛选
  → 分类模式是否变化?
      是:按新模式请求一次菜单
      否:营养筛选是否被清除?
          是:刷新本地菜品列表
          否:不处理

现有 DishBeanDishBeanJsonDeserializer 已承载五种营养字段,自定义分类 Mapper 应继续传递同一个 DishBean,禁止复制菜品时丢失营养字段。固定和自定义响应继续通过各自 Mapper 转换为统一 MenuCatalog,页面不得增加两套营养处理分支。

20.7 验收标准

AC 场景 预期结果 证据
AC-NUT-001 固定分类、营养关闭 营养区域隐藏,菜品不受营养条件过滤 页面截图、列表计数
AC-NUT-002 固定分类、营养开启 五类营养筛选和排序保持现有行为 页面测试
AC-NUT-003 自定义分类、营养关闭 页面只按自定义分类展示菜品 页面截图、列表计数
AC-NUT-004 自定义分类、营养开启 先按自定义分类、再按营养条件筛选和排序 页面测试
AC-NUT-005 营养展示由开改为关后返回 立即隐藏营养区域并清除原营养筛选 页面测试、日志
AC-NUT-006 营养展示由关改为开后返回 立即显示营养区域,默认不选营养项 页面测试
AC-NUT-007 分类模式和营养设置同时修改 两项最新配置同时生效,菜单只请求一次 请求日志、页面测试
AC-NUT-008 自定义菜品缺少营养字段 页面不崩溃,缺少字段按无数据处理 单元测试
AC-NUT-009 切换分类或营养条件 购物车内容保持不变 页面测试
AC-NUT-010 支付成功 根据营养开关显示营养版或普通版成功弹窗 真机测试

21. 下一步实施计划

顺序 工作项 具体动作 完成标准 状态
1 需求方案归档 将营养兼容背景、需求性质、接口约束和验收标准同步到 Markdown 与 HTML 文档 两个版本内容一致 已完成
2 补齐页面即时兼容 MainActivity 抽取统一营养状态刷新方法,并接入 initViews()onResume() 设置返回后立即生效;关闭时不存在隐藏筛选 已完成
3 补充自动化测试 增加自定义响应营养字段解析、Mapper 不丢字段及分类名称 6 字省略等单元测试 新增测试和现有测试全部通过 已完成,73 项测试通过
4 编译验证 使用项目兼容 JDK 执行单元测试和 Debug 构建 单元测试通过,Debug APK 构建成功 已完成
5 当前设备真机验收 覆盖固定/自定义分类与营养开/关四种组合,以及设置返回即时生效 AC-NUT-001AC-NUT-010 有可复核结果 部分完成:四种组合、即时生效、隐藏筛选和购物车保持已验证;真实支付、客屏仍待验收
6 更新实施记录 记录实际改动文件、验证命令、结果和仍需后台配合的测试数据 VWCG-1327 实施记录与代码实际行为一致 已完成

当前下一步是完成剩余真机验收:固定并记录目标餐段,逐餐段验证普通业务自定义分类、多分类和长名称;随后使用真实支付回归普通/营养支付成功弹窗、语音和客屏。本计划不包含云效关联任务、Git 提交、推送、合并或发布操作。

22. Definition of Ready 审计

检查项 状态 说明
目标与范围 READY 已明确固定和自定义两种模式
角色与触发 READY 管理员设置、用户消费和刷新入口明确
页面行为 READY 设置项、固定分类和动态分类行为明确
API 契约 READY 同一路径、两个客户端方法、两个响应 DTO 已确认
数据规则 READY all、普通分类、other 和异常菜品规则明确
异常与恢复 READY 网络、协议、空分类和关联异常均已覆盖
验收和测试 READY P0 规则已映射验收和测试
性能指标 READY 本需求限定请求次数;服务端 SLA 沿用现状且不作达标声明
安全 READY 不新增权限和敏感数据
云效任务编号 READY 已确认 VWCG-1327;无需处理关联任务或代码提交
多餐段自定义分类测试数据 DEFERRED 已确认部分餐段有普通自定义分类、部分餐段只有“全部/其他”;需逐餐段补齐完整验收

当前结论:DoR: READY,Android 客户端开发和核心组合验证已完成。Q-002 不阻塞当前实现,但必须在完整真机验收前关闭。

23. 变更记录

版本 日期 变更内容 原因
v1.0 2026-09-07 建立固定分类与自定义分类需求、接口和页面方案 初始需求分析
v1.1 2026-09-07 明确复用同一后端接口路径;Android 客户端使用两个 Retrofit 方法、两个响应 DTO,并统一映射为 MenuCatalog 避免一个响应类混合两套差异较大的协议结构
v1.2 2026-09-07 回填云效任务编号 VWCG-1327,将开发准备状态调整为 READY,并明确不处理关联任务和代码提交流程 用户补充任务编号及流程边界
v1.3 2026-09-07 补充营养展示兼容背景、需求性质、设置返回即时生效、隐藏筛选清理、接口营养字段约束、验收标准和下一步实施计划 明确新增功能与现有功能缺失的边界,防止自定义分类引入营养能力回退
v1.4 2026-09-07 回填营养兼容实现、68 项单元测试、Debug 构建和当前设备四种组合验证状态,更新后续验收计划 保持需求计划与实际实施进度一致
v1.5 2026-09-07 增加餐段切换导致菜谱与自定义分类变化的优先排查流程,并回填同一设备两次实际接口对比 避免将服务端餐段数据变化误判为营养适配或客户端分类回归
v1.6 2026-09-07 增加自定义分类标签名称 6 字展示上限、超长省略规则、Unicode 边界和对应验收测试 避免长分类名称占用过多横向空间,并保持完整分类数据不受展示截断影响