Files
msh-system/msh_single_uniapp/pages/tool/food-detail.vue

553 lines
13 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="food-detail-page">
<!-- 分享按钮 -->
<view class="share-btn-top" @tap="handleShare">
<image class="share-icon" :src="iconShare" mode="aspectFit"></image>
</view>
<!-- 内容区域 -->
<scroll-view class="content-scroll" scroll-y>
<!-- 食物大图 -->
<view class="food-image-section">
<image class="food-image" :src="foodData.image" mode="aspectFill"></image>
<view class="image-overlay"></view>
<view class="food-info-overlay">
<view class="food-name-overlay">{{ foodData.name }}</view>
<view class="food-tags">
<view class="food-tag category">{{ foodData.category }}</view>
<view class="food-tag safe">{{ foodData.safetyTag }}</view>
</view>
</view>
</view>
<!-- 关键营养成分 -->
<view class="key-nutrients-section">
<view class="section-header">
<text class="section-title">关键营养成分</text>
<view class="unit-badge">每100g</view>
</view>
<view class="key-nutrients-grid">
<view
class="nutrient-card"
v-for="(nutrient, index) in foodData.keyNutrients"
:key="index"
>
<text class="nutrient-name">{{ nutrient.name }}</text>
<view class="nutrient-value">
<text class="value-number">{{ nutrient.value }}</text>
<text class="value-unit">{{ nutrient.unit }}</text>
</view>
<text class="nutrient-status">{{ nutrient.status }}</text>
</view>
</view>
</view>
<!-- 营养成分表 -->
<view class="nutrition-table-section">
<view class="section-header">
<text class="section-title">营养成分表</text>
<text class="unit-text">每100g</text>
</view>
<view class="nutrition-table">
<view
class="nutrition-row"
v-for="(item, index) in foodData.nutritionTable"
:key="index"
>
<view class="nutrition-left">
<view class="nutrition-dot" :class="item.level"></view>
<text class="nutrition-label">{{ item.name }}</text>
<view class="nutrition-badge" :class="item.level">
<text>{{ item.levelText }}</text>
</view>
</view>
<view class="nutrition-right">
<text class="nutrition-value" :class="item.level">{{ item.value }}</text>
<text class="nutrition-unit">{{ item.unit }}</text>
</view>
</view>
</view>
</view>
<!-- 查看相似食物按钮 -->
<view class="similar-foods-btn" @click="viewSimilarFoods">
<image class="btn-icon" :src="iconSearch" mode="aspectFit"></image>
<text>查看相似食物</text>
</view>
<!-- 底部安全距离 -->
<view class="safe-bottom"></view>
</scroll-view>
</view>
</template>
<script>
import { getFoodDetail } from '@/api/tool.js';
export default {
data() {
return {
iconShare: 'https://www.figma.com/api/mcp/asset/f9f0d7b9-89c0-48d4-9e04-7140229e42f0',
iconSearch: 'https://www.figma.com/api/mcp/asset/aa6bb75b-0a9d-43cb-aaa4-6a71993fbd4d',
loading: false,
foodData: {
name: '',
category: '',
categoryType: '',
safetyTag: '',
image: '',
keyNutrients: [],
nutritionTable: []
},
// 默认展示数据API 未返回时使用)
defaultFoodData: {
name: '五谷香',
category: '谷薯类',
categoryType: 'grain',
safetyTag: '放心吃',
image: 'https://www.figma.com/api/mcp/asset/bf4ff04c-1322-474a-bd03-5b8a49fe33ad',
keyNutrients: [
{ name: '磷', value: '13', unit: 'mg', status: '正常' },
{ name: '钾', value: '7', unit: 'mg', status: '正常' },
{ name: '钠', value: '2', unit: 'mg', status: '正常' },
{ name: '嘌呤', value: '15', unit: 'mg', status: '正常' }
],
nutritionTable: [
{ name: '钾', value: '7', unit: 'mg', level: 'low', levelText: '低' },
{ name: '钙', value: '2', unit: 'mg', level: 'low', levelText: '低' },
{ name: '磷', value: '13', unit: 'mg', level: 'low', levelText: '低' },
{ name: '蛋白质', value: '9.9', unit: 'g', level: 'medium', levelText: '中' },
{ name: '钠', value: '2', unit: 'mg', level: 'low', levelText: '低' },
{ name: '嘌呤', value: '15', unit: 'mg', level: 'low', levelText: '低' }
]
}
}
},
onLoad(options) {
if (options.id) {
this.loadFoodData(options.id)
} else if (options.name) {
this.loadFoodData(options.name)
} else {
// 无参数时使用默认数据
this.foodData = { ...this.defaultFoodData }
}
},
methods: {
handleShare() {
uni.showToast({
title: '分享功能开发中',
icon: 'none'
})
},
viewSimilarFoods() {
uni.navigateTo({
url: `/pages/tool/food-encyclopedia?category=${this.foodData.categoryType || 'all'}`
})
},
async loadFoodData(id) {
this.loading = true
try {
const res = await getFoodDetail(id)
const data = res.data || res
if (data && data.name) {
// 解析API返回的食物数据
this.foodData = {
name: data.name || '',
category: data.category || data.categoryName || '',
categoryType: data.categoryType || data.categoryCode || 'all',
safetyTag: data.safetyTag || data.safety || this.getSafetyTag(data),
image: data.image || data.imageUrl || data.coverImage || this.defaultFoodData.image,
keyNutrients: this.parseKeyNutrients(data),
nutritionTable: this.parseNutritionTable(data)
}
} else {
// API 返回空数据,使用默认数据
this.foodData = { ...this.defaultFoodData }
}
} catch (error) {
console.error('加载食物数据失败:', error)
// 加载失败使用默认数据
this.foodData = { ...this.defaultFoodData }
uni.showToast({
title: '数据加载失败',
icon: 'none'
})
} finally {
this.loading = false
}
},
getSafetyTag(data) {
// 根据营养数据判断安全标签
if (data.safetyLevel === 'safe' || data.safetyLevel === 1) return '放心吃'
if (data.safetyLevel === 'caution' || data.safetyLevel === 2) return '少量吃'
if (data.safetyLevel === 'danger' || data.safetyLevel === 3) return '不宜吃'
return '放心吃'
},
parseKeyNutrients(data) {
if (data.keyNutrients && Array.isArray(data.keyNutrients)) {
return data.keyNutrients
}
// 从详细营养数据中提取关键营养素
const nutrients = data.nutrients || data.nutritionData || {}
const keyList = []
if (nutrients.phosphorus !== undefined) keyList.push({ name: '磷', value: String(nutrients.phosphorus), unit: 'mg', status: this.getStatus(nutrients.phosphorus, 'phosphorus') })
if (nutrients.potassium !== undefined) keyList.push({ name: '钾', value: String(nutrients.potassium), unit: 'mg', status: this.getStatus(nutrients.potassium, 'potassium') })
if (nutrients.sodium !== undefined) keyList.push({ name: '钠', value: String(nutrients.sodium), unit: 'mg', status: this.getStatus(nutrients.sodium, 'sodium') })
if (nutrients.purine !== undefined) keyList.push({ name: '嘌呤', value: String(nutrients.purine), unit: 'mg', status: this.getStatus(nutrients.purine, 'purine') })
return keyList.length > 0 ? keyList : this.defaultFoodData.keyNutrients
},
parseNutritionTable(data) {
if (data.nutritionTable && Array.isArray(data.nutritionTable)) {
return data.nutritionTable
}
const nutrients = data.nutrients || data.nutritionData || {}
const table = []
const items = [
{ key: 'potassium', name: '钾', unit: 'mg', thresholds: [200, 500] },
{ key: 'calcium', name: '钙', unit: 'mg', thresholds: [100, 300] },
{ key: 'phosphorus', name: '磷', unit: 'mg', thresholds: [100, 300] },
{ key: 'protein', name: '蛋白质', unit: 'g', thresholds: [5, 15] },
{ key: 'sodium', name: '钠', unit: 'mg', thresholds: [100, 500] },
{ key: 'purine', name: '嘌呤', unit: 'mg', thresholds: [50, 150] }
]
items.forEach(item => {
const val = nutrients[item.key]
if (val !== undefined) {
const level = val <= item.thresholds[0] ? 'low' : (val <= item.thresholds[1] ? 'medium' : 'high')
const levelText = level === 'low' ? '低' : (level === 'medium' ? '中' : '高')
table.push({ name: item.name, value: String(val), unit: item.unit, level, levelText })
}
})
return table.length > 0 ? table : this.defaultFoodData.nutritionTable
},
getStatus(value, type) {
// 简易的营养素状态判断
return '正常'
}
}
}
</script>
<style lang="scss" scoped>
.food-detail-page {
min-height: 100vh;
background: #f4f5f7;
display: flex;
flex-direction: column;
}
/* 分享按钮 */
.share-btn-top {
position: fixed;
top: calc(var(--status-bar-height, 0) + 20rpx);
right: 32rpx;
z-index: 100;
width: 72rpx;
height: 72rpx;
background: rgba(255, 255, 255, 0.95);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
.share-icon {
width: 40rpx;
height: 40rpx;
}
}
/* 内容滚动区域 */
.content-scroll {
flex: 1;
padding: 0;
}
/* 食物大图区域 */
.food-image-section {
position: relative;
width: 100%;
height: 576rpx;
background: linear-gradient(180deg, #f4f5f7 0%, #ffffff 100%);
overflow: hidden;
.food-image {
width: 100%;
height: 100%;
object-fit: cover;
}
.image-overlay {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 200rpx;
background: linear-gradient(to top, rgba(0, 0, 0, 0.2) 0%, rgba(0, 0, 0, 0) 50%, rgba(0, 0, 0, 0) 100%);
}
.food-info-overlay {
position: absolute;
bottom: 32rpx;
left: 32rpx;
right: 32rpx;
display: flex;
flex-direction: column;
gap: 16rpx;
}
.food-name-overlay {
font-size: 48rpx;
color: #ffffff;
font-weight: 500;
text-shadow: 0 8rpx 16rpx rgba(0, 0, 0, 0.15);
}
.food-tags {
display: flex;
gap: 16rpx;
}
.food-tag {
height: 48rpx;
border-radius: 12rpx;
padding: 8rpx 24rpx;
font-size: 24rpx;
display: flex;
align-items: center;
justify-content: center;
&.category {
background: rgba(255, 255, 255, 0.95);
color: #ff6b35;
}
&.safe {
background: rgba(255, 107, 53, 0.9);
color: #ffffff;
}
}
}
/* 关键营养成分 */
.key-nutrients-section {
padding: 32rpx;
display: flex;
flex-direction: column;
gap: 32rpx;
}
.section-header {
display: flex;
align-items: center;
justify-content: space-between;
.section-title {
font-size: 32rpx;
color: #2e3e5c;
font-weight: 500;
}
.unit-badge {
background: #f4f5f7;
border-radius: 16rpx;
padding: 8rpx 24rpx;
font-size: 24rpx;
color: #9fa5c0;
}
.unit-text {
font-size: 24rpx;
color: #9fa5c0;
}
}
.key-nutrients-grid {
display: flex;
gap: 16rpx;
justify-content: space-between;
}
.nutrient-card {
background: #ffffff;
border: 2rpx solid #d0dbea;
border-radius: 32rpx;
padding: 34rpx;
display: flex;
flex-direction: column;
align-items: center;
gap: 12rpx;
flex: 1;
min-width: 0;
.nutrient-name {
font-size: 40rpx;
color: #ff6b35;
font-weight: 500;
}
.nutrient-value {
display: flex;
align-items: baseline;
gap: 4rpx;
.value-number {
font-size: 24rpx;
color: #9fa5c0;
}
.value-unit {
font-size: 20rpx;
color: #9fa5c0;
}
}
.nutrient-status {
font-size: 20rpx;
color: #ff6b35;
}
}
/* 营养成分表 */
.nutrition-table-section {
padding: 0 32rpx 32rpx;
display: flex;
flex-direction: column;
gap: 24rpx;
}
.nutrition-table {
background: #ffffff;
border: 1rpx solid #d0dbea;
border-radius: 32rpx;
overflow: hidden;
}
.nutrition-row {
display: flex;
align-items: center;
justify-content: space-between;
padding: 26rpx 32rpx;
border-bottom: 1rpx solid #d0dbea;
&:last-child {
border-bottom: none;
}
}
.nutrition-left {
display: flex;
align-items: center;
gap: 24rpx;
flex: 1;
min-width: 0;
}
.nutrition-dot {
width: 12rpx;
height: 12rpx;
border-radius: 50%;
flex-shrink: 0;
&.low {
background: #ff6b35;
}
&.medium {
background: #ffa500;
}
}
.nutrition-label {
font-size: 28rpx;
color: #2e3e5c;
flex-shrink: 0;
}
.nutrition-badge {
height: 34rpx;
border-radius: 12rpx;
padding: 2rpx 16rpx;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
&.low {
background: linear-gradient(180deg, #fff5f0 0%, #ffe8dc 100%);
border: 1rpx solid rgba(255, 107, 53, 0.3);
text {
font-size: 24rpx;
color: #ff6b35;
font-weight: 500;
}
}
&.medium {
background: linear-gradient(180deg, #fff8e1 0%, #fff4e6 100%);
border: 1rpx solid rgba(255, 165, 0, 0.3);
text {
font-size: 24rpx;
color: #ffa500;
font-weight: 500;
}
}
}
.nutrition-right {
display: flex;
align-items: baseline;
gap: 8rpx;
flex-shrink: 0;
}
.nutrition-value {
font-size: 32rpx;
color: #ff6b35;
font-weight: 500;
&.medium {
color: #ffa500;
}
}
.nutrition-unit {
font-size: 24rpx;
color: #9fa5c0;
}
/* 查看相似食物按钮 */
.similar-foods-btn {
background: #ffffff;
border: 2rpx solid #ff6b35;
border-radius: 50rpx;
height: 104rpx;
margin: 0 32rpx 32rpx;
display: flex;
align-items: center;
justify-content: center;
gap: 16rpx;
box-shadow: 0 2rpx 6rpx rgba(0, 0, 0, 0.1);
.btn-icon {
width: 32rpx;
height: 32rpx;
}
text {
font-size: 28rpx;
color: #ff6b35;
font-weight: 500;
}
}
/* 底部安全距离 */
.safe-bottom {
height: 40rpx;
}
</style>