fix: 修复关注按钮相关问题

- 食谱详情页: 修复 applyDefaultData 中未定义变量 id 的问题
- 帖子详情页: 优化 toggleFollow 方法,提前校验 author.id,兼容多种后端字段
- 为帖子详情页已关注状态添加灰色样式
This commit is contained in:
msh-agent
2026-03-09 18:56:53 +08:00
parent b516089c4f
commit c1857ce852
14 changed files with 3590 additions and 102 deletions

View File

@@ -133,9 +133,10 @@ export default {
}
},
computed: {
// 保证 .food-name-overlay / .nutrient-card / .nutrition-row 在 defaultFoodData 状态下也有非空数据可渲染
// 保证 .food-name-overlay / .nutrient-card / .nutrition-row 在 defaultFoodData 状态下也有非空数据可渲染(不为空字符串/空数组)
displayName() {
return (this.foodData && this.foodData.name) ? this.foodData.name : (this.defaultFoodData.name || '—')
const name = (this.foodData && this.foodData.name) ? this.foodData.name : (this.defaultFoodData && this.defaultFoodData.name) ? this.defaultFoodData.name : '—'
return (name != null && String(name).trim() !== '') ? String(name).trim() : '—'
},
displayCategory() {
return (this.foodData && this.foodData.category) ? this.foodData.category : (this.defaultFoodData.category || '—')
@@ -149,14 +150,16 @@ export default {
displayKeyNutrients() {
const arr = this.foodData && this.foodData.keyNutrients
if (Array.isArray(arr) && arr.length > 0) return arr
const def = this.defaultFoodData.keyNutrients
return Array.isArray(def) && def.length > 0 ? def : [{ name: '—', value: '—', unit: '', status: '—' }]
const def = this.defaultFoodData && this.defaultFoodData.keyNutrients
if (Array.isArray(def) && def.length > 0) return def
return [{ name: '—', value: '—', unit: '', status: '—' }]
},
displayNutritionTable() {
const arr = this.foodData && this.foodData.nutritionTable
if (Array.isArray(arr) && arr.length > 0) return arr
const def = this.defaultFoodData.nutritionTable
return Array.isArray(def) && def.length > 0 ? def : [{ name: '—', value: '—', unit: '', level: 'low', levelText: '—' }]
const def = this.defaultFoodData && this.defaultFoodData.nutritionTable
if (Array.isArray(def) && def.length > 0) return def
return [{ name: '—', value: '—', unit: '', level: 'low', levelText: '—' }]
}
},
onLoad(options) {
@@ -171,21 +174,23 @@ export default {
name: (displayName !== undefined && displayName !== '') ? String(displayName) : ''
}
// 打印入参便于排查:后端详情接口仅接受 Long 类型 id传 name 会导致 400
console.log('[food-detail] onLoad options:', options)
console.log('[food-detail] onLoad pageParams (id/name):', this.pageParams)
console.log('[food-detail] onLoad options:', JSON.stringify(options))
console.log('[food-detail] onLoad pageParams (id/name):', JSON.stringify(this.pageParams))
const isNumericId = rawId !== undefined && rawId !== '' && !isNaN(Number(rawId))
if (isNumericId) {
const numId = Number(rawId)
console.log('[food-detail] 使用数字 id 请求详情,不传 name 字段:', numId)
console.log('[food-detail] 使用数字 id 请求详情:', { id: numId, idType: typeof numId, name: this.pageParams.name })
this.loadFoodData(numId)
} else if (this.pageParams.name) {
// 无有效 id、仅有 name 时,不请求接口(避免传 name 导致后端 NumberFormatException直接展示默认数据 + 当前名称
console.log('[food-detail] 无数字 id仅用 name 展示默认数据,不请求详情接口')
this.loadError = '暂无该食物详情数据,展示参考数据'
this.applyDefaultFoodData(false)
try {
this.foodData.name = decodeURIComponent(this.pageParams.name)
} catch (e) {}
} else {
console.log('[food-detail] 无 id 与 name展示默认数据')
this.applyDefaultFoodData()
}
},
@@ -225,12 +230,26 @@ export default {
async loadFoodData(id) {
this.loading = true
this.loadError = ''
// 打印 API 请求参数便于确认(后端需要 Long 类型 id
console.log('[food-detail] getFoodDetail request param:', { id, type: typeof id })
// 打印 API 请求参数便于确认(后端需要 Long 类型 id,传 name 会 400
console.log('[food-detail] getFoodDetail API 请求参数:', {
id,
idType: typeof id,
pageParamsId: this.pageParams.id,
pageParamsName: this.pageParams.name
})
try {
const res = await getFoodDetail(id)
// 打印响应结构便于确认request 成功时 resolve 的是 res.data即 { code: 200, data: {...} }
console.log('[food-detail] getFoodDetail 响应结构:', res ? { hasData: !!res.data, code: res.code, keys: Object.keys(res || {}) } : null)
console.log('[food-detail] getFoodDetail 响应结构:', res ? { hasData: !!(res && res.data), code: res && res.code, keys: Object.keys(res || {}) } : null)
if (!res) {
this.loadError = '接口未返回数据'
this.applyDefaultFoodData(false)
if (this.pageParams && this.pageParams.name) {
try { this.foodData.name = decodeURIComponent(String(this.pageParams.name)) } catch (e) {}
}
uni.showToast({ title: '数据加载失败', icon: 'none' })
return
}
const data = res.data != null ? res.data : res
console.log('[food-detail] getFoodDetail 解析后 data:', data ? { hasName: !!data.name, hasImage: !!data.image, keys: Object.keys(data) } : null)
if (data && data.name) {
@@ -258,9 +277,11 @@ export default {
uni.showToast({ title: '数据加载失败', icon: 'none' })
}
} catch (error) {
// a. 将 loadError 置为具体错误信息(用于调试):兼容 Error、{ message/msg }、字符串
// a. 将 loadError 置为具体错误信息(用于调试):兼容 Error、{ message/msg }、字符串、后端 res.data 对象
const errMsg = (error && (error.message || error.msg || error.errMsg))
? String(error.message || error.msg || error.errMsg)
: (error && error.data && (error.data.message || error.data.msg))
? String(error.data.message || error.data.msg)
: (typeof error === 'string' ? error : (error ? String(error) : '未知错误'))
console.error('[food-detail] 加载食物数据失败:', error)
console.error('[food-detail] loadError(用于调试):', errMsg)
@@ -273,7 +294,8 @@ export default {
this.foodData.name = decodeURIComponent(String(this.pageParams.name))
} catch (e) {}
}
// c. 页面通过 v-if="loadError" 显示「当前数据来自缓存,可能不是最新」;再弹出轻提示
console.log('[food-detail] 已用 defaultFoodData 填充页面loadError=', this.loadError)
// c. 页面 v-if="loadError" 会显示「当前数据来自缓存,可能不是最新」;同时弹出轻提示
uni.showToast({
title: '数据加载失败',
icon: 'none'