BUG-003 已按你的要求修好,修改总结如下。 --- ## 1. 问题原因 - **后端列表接口**(`getFoodList` / `searchFood`)返回的是:`id, name, image, energy, protein, suitabilityLevel`,没有 `nutrition` 数组,也没有 `category`、`potassium`、`phosphorus`。 - 模板里用的是 `item.image`、`item.nutrition`。当接口替换掉本地 mock 后,`item.nutrition` 为 `undefined`,营养简介不渲染;图片若为空也没有占位。 ## 2. 修改内容 ### 前端 `msh_single_uniapp/pages/tool/food-encyclopedia.vue` **模板:** - **`.food-image` 的 `:src`**:改为 `getFoodImage(item)`,内部使用 `item.imageUrl || item.image || item.img`,都没有时用占位图。 - **`.nutrition-item` 的 `v-for`**:改为 `v-for="(nut, idx) in (item.nutrition || [])"`,并给 `nut.colorClass` 加了默认 `'green'`,避免无数据或缺字段时报错。 - **分类与安全标签**:`item.category` 为空时不渲染分类徽章(`v-if="item.category"`);安全标签增加 `item.safetyClass || 'safe'`、`item.safety || '—'` 兜底。 - **列表 `:key`**:改为 `item.id != null ? item.id : index`,便于接口数据稳定渲染。 **逻辑:** - **`defaultPlaceholder`**:在 `data()` 里增加灰色 SVG 的 data URL,作为无图时的占位图(与 `.food-image-wrapper` 的灰色风格一致)。 - **`getFoodImage(item)`**:返回 `item.imageUrl || item.image || item.img`,若都为空则返回 `defaultPlaceholder`。 - **`normalizeFoodItem(item)`**:把接口数据统一成列表项结构: - 图片:沿用 `image` / `imageUrl` / `img`(展示由 `getFoodImage` 处理)。 - 安全:若已有 `safety`/`safetyClass` 则保留,否则按 `suitabilityLevel` 映射(suitable→放心吃/safe,moderate→限量吃/limited,restricted/forbidden→谨慎吃/careful)。 - 营养:若已有 `item.nutrition` 数组则直接用;否则用接口字段组装:能量、蛋白质、钾、磷(有值才加),格式为 `{ label, value, colorClass }`。 - **列表赋值**:`loadFoodList` 和搜索分支里,对 `result.data.list` 做 `(result.data.list || []).map(item => this.normalizeFoodItem(item))` 再赋给 `foodList`,保证每条都有 `nutrition` 和可用的图片、安全、分类展示。 ### 后端 `msh_crmeb_22/.../ToolFoodServiceImpl.java` - 列表/搜索的 map 中增加:`category`、`potassium`、`phosphorus`,这样前端 `normalizeFoodItem` 能拼出更完整的营养简介,分类徽章也能显示。 效果: - 配图:有图用接口的 `image`(或 `imageUrl`/`img`),无图用灰色占位图。 - 营养简介:接口有 `nutrition` 用接口的,没有则用能量/蛋白质/钾/磷自动组一条,`.nutrition-item` 始终有稳定数据源可遍历。