|
@@ -6,11 +6,26 @@
|
|
|
<text class="banner-text">以下食材推荐指数低于 0,建议谨慎食用或避免</text>
|
|
<text class="banner-text">以下食材推荐指数低于 0,建议谨慎食用或避免</text>
|
|
|
</view>
|
|
</view>
|
|
|
|
|
|
|
|
|
|
+ <view class="member-bar" v-if="memberList.length > 1">
|
|
|
|
|
+ <view class="member-tab" :class="{'active': currentMemberId === (item.id || item.userId)}"
|
|
|
|
|
+ v-for="item in memberList" :key="item.id || item.userId"
|
|
|
|
|
+ @tap="switchMember(item)">
|
|
|
|
|
+ <text class="member-name">{{ item.nickname || item.roleLabel || '全部' }}</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+
|
|
|
<scroll-view class="content" scroll-y :refresher-enabled="true" :refresher-triggered="refreshing" @refresherrefresh="onRefresh">
|
|
<scroll-view class="content" scroll-y :refresher-enabled="true" :refresher-triggered="refreshing" @refresherrefresh="onRefresh">
|
|
|
- <view class="food-card" v-for="(item, idx) in foods" :key="idx">
|
|
|
|
|
|
|
+ <view class="food-card" v-for="(item, idx) in foods" :key="getItemKey(item)">
|
|
|
<view class="food-header">
|
|
<view class="food-header">
|
|
|
<text class="food-name">{{ item.foodName }}</text>
|
|
<text class="food-name">{{ item.foodName }}</text>
|
|
|
- <view class="caution-badge">戒备</view>
|
|
|
|
|
|
|
+ <view class="score-badge-group">
|
|
|
|
|
+ <text class="score-value danger">{{ item.indexScore }}</text>
|
|
|
|
|
+ <view class="caution-badge">戒备</view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="change-row" v-if="item.changeDir">
|
|
|
|
|
+ <text class="change-label">较上次</text>
|
|
|
|
|
+ <text :class="item.changeClass">{{ item.changeText }}</text>
|
|
|
</view>
|
|
</view>
|
|
|
<view class="food-meta">
|
|
<view class="food-meta">
|
|
|
<text class="meta-item" v-if="item.category">{{ item.category }}</text>
|
|
<text class="meta-item" v-if="item.category">{{ item.category }}</text>
|
|
@@ -20,10 +35,10 @@
|
|
|
<view class="score-bar-bg">
|
|
<view class="score-bar-bg">
|
|
|
<view class="score-bar-fill danger" :style="'width:' + Math.min(Math.abs(item.indexScore) / 50 * 100, 100) + '%'"></view>
|
|
<view class="score-bar-fill danger" :style="'width:' + Math.min(Math.abs(item.indexScore) / 50 * 100, 100) + '%'"></view>
|
|
|
</view>
|
|
</view>
|
|
|
- <text class="score-value danger">{{ item.indexScore }}</text>
|
|
|
|
|
|
|
+ <text class="score-label">推荐指数</text>
|
|
|
</view>
|
|
</view>
|
|
|
- <text class="score-label">推荐指数</text>
|
|
|
|
|
</view>
|
|
</view>
|
|
|
|
|
+ <mini-trend :data="item.trendPoints" v-if="item.trendPoints && item.trendPoints.length >= 3"></mini-trend>
|
|
|
<view class="food-nutrition" v-if="item.nutrition">
|
|
<view class="food-nutrition" v-if="item.nutrition">
|
|
|
<text class="nut-item">蛋白 {{ item.nutrition.protein }}g</text>
|
|
<text class="nut-item">蛋白 {{ item.nutrition.protein }}g</text>
|
|
|
<text class="nut-item">脂肪 {{ item.nutrition.fat }}g</text>
|
|
<text class="nut-item">脂肪 {{ item.nutrition.fat }}g</text>
|
|
@@ -47,32 +62,68 @@
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
|
<script>
|
|
|
-import { getFoodCautionList } from '../../utils/api.js'
|
|
|
|
|
|
|
+import { getFoodCautionList, getFoodCautionTrend, getCautionFamilyMembers } from '../../utils/api.js'
|
|
|
|
|
+import MiniTrend from './mini-trend.vue'
|
|
|
|
|
|
|
|
export default {
|
|
export default {
|
|
|
|
|
+ components: { MiniTrend },
|
|
|
data() {
|
|
data() {
|
|
|
return {
|
|
return {
|
|
|
foods: [],
|
|
foods: [],
|
|
|
loading: true,
|
|
loading: true,
|
|
|
refreshing: false,
|
|
refreshing: false,
|
|
|
- nutritionCache: {}
|
|
|
|
|
|
|
+ nutritionCache: {},
|
|
|
|
|
+ currentMemberId: null,
|
|
|
|
|
+ memberList: [],
|
|
|
|
|
+ trendMap: {}
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
- onLoad() {
|
|
|
|
|
|
|
+ onLoad: function(options) {
|
|
|
|
|
+ this.currentMemberId = options.memberId ? parseInt(options.memberId) : null
|
|
|
|
|
+ this.loadMemberList()
|
|
|
this.loadFoods()
|
|
this.loadFoods()
|
|
|
},
|
|
},
|
|
|
methods: {
|
|
methods: {
|
|
|
- goBack() {
|
|
|
|
|
|
|
+ getItemKey: function(item) { return item.foodId || item.id || Math.random() },
|
|
|
|
|
+ goBack: function() {
|
|
|
uni.navigateBack()
|
|
uni.navigateBack()
|
|
|
},
|
|
},
|
|
|
|
|
+ switchMember: function(item) {
|
|
|
|
|
+ this.currentMemberId = item.id || item.userId
|
|
|
|
|
+ this.loadFoods()
|
|
|
|
|
+ },
|
|
|
|
|
+ async loadMemberList() {
|
|
|
|
|
+ try {
|
|
|
|
|
+ var res = await getCautionFamilyMembers()
|
|
|
|
|
+ if (res && res.code === 200 && res.data && res.data.length > 0) {
|
|
|
|
|
+ var allItem = { id: -1, userId: -1, nickname: '全部', roleLabel: '全部' }
|
|
|
|
|
+ this.memberList = [allItem].concat(res.data)
|
|
|
|
|
+ if (!this.currentMemberId) {
|
|
|
|
|
+ this.currentMemberId = -1
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch(e) {}
|
|
|
|
|
+ },
|
|
|
async loadFoods() {
|
|
async loadFoods() {
|
|
|
this.loading = true
|
|
this.loading = true
|
|
|
try {
|
|
try {
|
|
|
- var res = await getFoodCautionList()
|
|
|
|
|
|
|
+ var res = await getFoodCautionList(this.currentMemberId > 0 ? this.currentMemberId : null)
|
|
|
if (res && res.code === 200 && res.data) {
|
|
if (res && res.code === 200 && res.data) {
|
|
|
- this.foods = res.data
|
|
|
|
|
- // 批量加载营养数据
|
|
|
|
|
|
|
+ this.foods = (res.data || []).map(function(f) {
|
|
|
|
|
+ return {
|
|
|
|
|
+ foodId: f.foodId || f.id,
|
|
|
|
|
+ foodName: f.foodName,
|
|
|
|
|
+ indexScore: f.indexScore,
|
|
|
|
|
+ category: f.category,
|
|
|
|
|
+ nutrition: null,
|
|
|
|
|
+ changeDir: null,
|
|
|
|
|
+ changeText: '',
|
|
|
|
|
+ changeClass: '',
|
|
|
|
|
+ trendPoints: null
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
this.loadNutrition()
|
|
this.loadNutrition()
|
|
|
|
|
+ this.loadTrends()
|
|
|
} else {
|
|
} else {
|
|
|
this.foods = []
|
|
this.foods = []
|
|
|
}
|
|
}
|
|
@@ -116,7 +167,47 @@ export default {
|
|
|
console.warn('加载营养数据失败', e)
|
|
console.warn('加载营养数据失败', e)
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
- getKnowledgeSection(key) {
|
|
|
|
|
|
|
+ loadTrends: function() {
|
|
|
|
|
+ if (!this.foods.length) return
|
|
|
|
|
+ var self = this
|
|
|
|
|
+ var foodIds = this.foods.map(function(f) { return f.foodId }).filter(function(id) { return id != null })
|
|
|
|
|
+ if (!foodIds.length) return
|
|
|
|
|
+ getFoodCautionTrend(this.currentMemberId > 0 ? this.currentMemberId : null, foodIds).then(function(res) {
|
|
|
|
|
+ if (res && res.code === 200 && res.data) {
|
|
|
|
|
+ var trendMap = {}
|
|
|
|
|
+ var dataArray = res.data || []
|
|
|
|
|
+ for (var i = 0; i < dataArray.length; i++) {
|
|
|
|
|
+ var t = dataArray[i]
|
|
|
|
|
+ trendMap[t.foodId] = t
|
|
|
|
|
+ }
|
|
|
|
|
+ self.trendMap = trendMap
|
|
|
|
|
+ self.foods = self.foods.map(function(item) {
|
|
|
|
|
+ var t = trendMap[item.foodId]
|
|
|
|
|
+ if (!t) return item
|
|
|
|
|
+ var trendPoints = []
|
|
|
|
|
+ var pts = t.trend || []
|
|
|
|
|
+ for (var j = 0; j < pts.length; j++) {
|
|
|
|
|
+ trendPoints.push(pts[j].score)
|
|
|
|
|
+ }
|
|
|
|
|
+ var changeDir = t.changeDir || 'flat'
|
|
|
|
|
+ var changeText = ''
|
|
|
|
|
+ var changeClass = ''
|
|
|
|
|
+ if (changeDir === 'up') { changeText = '↑ 上升'
|
|
|
|
|
+ changeClass = 'change-up' }
|
|
|
|
|
+ else if (changeDir === 'down') { changeText = '↓ 下降'
|
|
|
|
|
+ changeClass = 'change-down' }
|
|
|
|
|
+ return Object.assign({}, item, {
|
|
|
|
|
+ trendPoints: trendPoints.length >= 3 ? trendPoints : null,
|
|
|
|
|
+ changeDir: changeDir,
|
|
|
|
|
+ changeText: changeText,
|
|
|
|
|
+ changeClass: changeClass
|
|
|
|
|
+ })
|
|
|
|
|
+ })
|
|
|
|
|
+ self.$forceUpdate()
|
|
|
|
|
+ }
|
|
|
|
|
+ }).catch(function() {})
|
|
|
|
|
+ },
|
|
|
|
|
+ getKnowledgeSection: function(key) {
|
|
|
return new Promise(function(resolve) {
|
|
return new Promise(function(resolve) {
|
|
|
uni.request({
|
|
uni.request({
|
|
|
url: getApp().globalData.baseApi + '/api/kb/section',
|
|
url: getApp().globalData.baseApi + '/api/kb/section',
|
|
@@ -131,7 +222,7 @@ export default {
|
|
|
})
|
|
})
|
|
|
})
|
|
})
|
|
|
},
|
|
},
|
|
|
- onRefresh() {
|
|
|
|
|
|
|
+ onRefresh: function() {
|
|
|
this.refreshing = true
|
|
this.refreshing = true
|
|
|
this.loadFoods()
|
|
this.loadFoods()
|
|
|
}
|
|
}
|