|
|
@@ -9,6 +9,33 @@
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
+ <!-- 分类筛选 + 排序 -->
|
|
|
+ <view class="filter-bar">
|
|
|
+ <scroll-view class="cat-scroll" scroll-x>
|
|
|
+ <view class="cat-list">
|
|
|
+ <view
|
|
|
+ class="cat-chip"
|
|
|
+ :class="{'cat-chip-active': activeCategory === 'all'}"
|
|
|
+ @tap="switchCategory('all')"
|
|
|
+ >
|
|
|
+ <text class="cat-chip-text">全部</text>
|
|
|
+ </view>
|
|
|
+ <view
|
|
|
+ class="cat-chip"
|
|
|
+ v-for="cat in categories"
|
|
|
+ :key="cat"
|
|
|
+ :class="{'cat-chip-active': activeCategory === cat}"
|
|
|
+ @tap="switchCategory(cat)"
|
|
|
+ >
|
|
|
+ <text class="cat-chip-text">{{ cat }}</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </scroll-view>
|
|
|
+ <view class="sort-btn" @tap="toggleSort">
|
|
|
+ <text class="sort-btn-text">{{ sortDesc ? '↓ 推荐值从高到低' : '↑ 推荐值从低到高' }}</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
<scroll-view class="content" scroll-y>
|
|
|
<view
|
|
|
class="food-card"
|
|
|
@@ -92,38 +119,74 @@ export default {
|
|
|
data() {
|
|
|
return {
|
|
|
reportId: null,
|
|
|
+ memberId: null,
|
|
|
reportData: null,
|
|
|
foods: [],
|
|
|
isEditing: false,
|
|
|
editFoods: [],
|
|
|
searchText: '',
|
|
|
+ activeCategory: 'all',
|
|
|
+ sortDesc: true,
|
|
|
knowledgeVisible: false,
|
|
|
knowledgeData: {},
|
|
|
_kbCache: {}
|
|
|
}
|
|
|
},
|
|
|
computed: {
|
|
|
+ categories: function() {
|
|
|
+ var seen = {}
|
|
|
+ var cats = []
|
|
|
+ var list = this.isEditing ? this.editFoods : this.foods
|
|
|
+ for (var i = 0; i < list.length; i++) {
|
|
|
+ var c = list[i].category || '其它'
|
|
|
+ if (!seen[c]) {
|
|
|
+ seen[c] = true
|
|
|
+ cats.push(c)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return cats
|
|
|
+ },
|
|
|
filteredFoods: function() {
|
|
|
var list = this.isEditing ? this.editFoods : this.foods
|
|
|
var kw = (this.searchText || '').trim()
|
|
|
+ var self = this
|
|
|
if (kw) {
|
|
|
list = list.filter(function(item) {
|
|
|
var name = item.foodName || item.name || ''
|
|
|
return name.indexOf(kw) >= 0
|
|
|
})
|
|
|
}
|
|
|
+ if (this.activeCategory !== 'all') {
|
|
|
+ list = list.filter(function(item) {
|
|
|
+ return (item.category || '其它') === self.activeCategory
|
|
|
+ })
|
|
|
+ }
|
|
|
+ // 按推荐值排序(默认降序)
|
|
|
+ list = list.slice()
|
|
|
+ list.sort(function(a, b) {
|
|
|
+ var sa = parseFloat(a.score) || 0
|
|
|
+ var sb = parseFloat(b.score) || 0
|
|
|
+ return self.sortDesc ? sb - sa : sa - sb
|
|
|
+ })
|
|
|
return list
|
|
|
}
|
|
|
},
|
|
|
onLoad: function(options) {
|
|
|
// 不传 reportId 时取当前用户最新报告的食材推荐
|
|
|
this.reportId = options.reportId ? parseInt(options.reportId) : null
|
|
|
+ this.memberId = options.memberId ? parseInt(options.memberId) : null
|
|
|
this.loadData()
|
|
|
},
|
|
|
methods: {
|
|
|
goBack: function() {
|
|
|
uni.navigateBack()
|
|
|
},
|
|
|
+ switchCategory: function(cat) {
|
|
|
+ this.activeCategory = cat
|
|
|
+ },
|
|
|
+ toggleSort: function() {
|
|
|
+ this.sortDesc = !this.sortDesc
|
|
|
+ },
|
|
|
/** 推荐值 → 背景色分级:<-30 红,>30 绿,中间每 10 换一档 */
|
|
|
_scoreBand: function(score) {
|
|
|
var s = parseFloat(score)
|
|
|
@@ -139,7 +202,7 @@ export default {
|
|
|
},
|
|
|
loadData: function() {
|
|
|
var self = this
|
|
|
- getHealthFoods(self.reportId).then(function(res) {
|
|
|
+ getHealthFoods(self.reportId, self.memberId).then(function(res) {
|
|
|
if (res.code === 200 && res.data) {
|
|
|
// 后端 Food 实体字段:name, category, score;兼容 foodName(旧 draft)
|
|
|
self.foods = (Array.isArray(res.data) ? res.data : []).map(function(item) {
|
|
|
@@ -242,7 +305,7 @@ export default {
|
|
|
.page { min-height: 100vh; background: #f8f8f8; }
|
|
|
|
|
|
/* 搜索框 */
|
|
|
-.search-bar { padding: 20rpx 30rpx; background: #fff; }
|
|
|
+.search-bar { padding: 20rpx 30rpx 8rpx; background: #fff; }
|
|
|
.search-input-wrap {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
@@ -254,7 +317,18 @@ export default {
|
|
|
.search-input { flex: 1; font-size: 28rpx; }
|
|
|
.search-clear { font-size: 28rpx; color: #999; padding: 0 8rpx; }
|
|
|
|
|
|
-.content { padding: 20rpx 30rpx; height: calc(100vh - 120rpx); }
|
|
|
+/* 分类筛选 + 排序 */
|
|
|
+.filter-bar { display: flex; align-items: center; background: #fff; padding: 8rpx 30rpx 16rpx; box-sizing: border-box; width: 100%; }
|
|
|
+.cat-scroll { flex: 1; white-space: nowrap; min-width: 0; }
|
|
|
+.cat-list { display: inline-flex; padding-right: 8rpx; }
|
|
|
+.cat-chip { display: inline-flex; align-items: center; padding: 10rpx 24rpx; margin-right: 12rpx; background: #f5f5f5; border-radius: 30rpx; flex-shrink: 0; }
|
|
|
+.cat-chip-active { background: #4A9BD7; }
|
|
|
+.cat-chip-text { font-size: 24rpx; color: #666; }
|
|
|
+.cat-chip-active .cat-chip-text { color: #fff; }
|
|
|
+.sort-btn { flex-shrink: 0; margin-left: 16rpx; padding: 10rpx 20rpx; background: #FFF1E6; border-radius: 30rpx; }
|
|
|
+.sort-btn-text { font-size: 24rpx; color: #C2410C; }
|
|
|
+
|
|
|
+.content { padding: 20rpx 30rpx; height: calc(100vh - 200rpx); }
|
|
|
|
|
|
.food-card {
|
|
|
border-radius: 16rpx;
|
|
|
@@ -274,8 +348,9 @@ export default {
|
|
|
.score-band-null { background: #f0f0f0; }
|
|
|
|
|
|
.food-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8rpx; }
|
|
|
-.food-name { font-size: 30rpx; font-weight: 600; color: #fff; flex: 1; }
|
|
|
-.food-cat-tag { padding: 4rpx 16rpx; background: rgba(255,255,255,0.3); border-radius: 20rpx; font-size: 22rpx; color: #fff; }
|
|
|
+.food-name { font-size: 30rpx; font-weight: 600; color: #fff; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
|
+.food-cat-tag { padding: 4rpx 16rpx; background: rgba(255,255,255,0.3); border-radius: 20rpx; font-size: 22rpx; color: #fff; flex-shrink: 0; margin-left: 12rpx; max-width: 40%; box-sizing: border-box; }
|
|
|
+.food-cat-tag text { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
|
|
|
|
.food-score-row { display: flex; align-items: baseline; gap: 12rpx; }
|
|
|
.food-score-label { font-size: 22rpx; color: rgba(255,255,255,0.85); }
|