Browse Source

fix(diet): 共餐配置页修复页面溢出、选中态醒目、添加按钮唯一化

- 全局 box-sizing + 约束成员项宽度,修复页面右侧溢出
- 选中项加橙色 ✓ 角标 + 强化高亮(粗边框/外发光/头像变色)
- 改用 mealGroups 计算属性,去除模板内 isMemberSelected 方法调用
- 3 个餐次添加按钮收敛为唯一入口,点击跳转成员管理页
liaoxg 3 weeks ago
parent
commit
a1add80b79
1 changed files with 114 additions and 28 deletions
  1. 114 28
      cfc-frontend/pages/diet/meal-config.vue

+ 114 - 28
cfc-frontend/pages/diet/meal-config.vue

@@ -12,21 +12,29 @@
         </view>
       </view>
 
+      <!-- 添加共餐人入口(唯一) -->
+      <view class="add-member-entry" @tap="goManageMembers">
+        <text class="add-member-entry-icon">+</text>
+        <text class="add-member-entry-text">添加共餐人</text>
+        <text class="add-member-entry-arrow">›</text>
+      </view>
+
       <!-- 餐次配置 -->
-      <view class="meal-section" v-for="meal in mealTypes" :key="meal.value">
+      <view class="meal-section" v-for="meal in mealGroups" :key="meal.value">
         <view class="meal-header">
           <text class="meal-icon">{{ meal.icon }}</text>
           <text class="meal-name">{{ meal.label }}</text>
         </view>
         <view class="member-list">
-          <view class="member-item" v-for="member in familyMembers" :key="member.id"
-            :class="{'member-selected': isMemberSelected(meal.value, member.id)}"
+          <view class="member-item" v-for="member in meal.members" :key="member.id"
+            :class="{'member-selected': member.selected}"
             @tap="toggleMember(meal.value, member.id)">
+            <view class="member-check" v-if="member.selected">✓</view>
             <text class="member-avatar">{{ member.nickname ? member.nickname.substring(0, 1) : '?' }}</text>
             <text class="member-name">{{ member.nickname || '未知' }}</text>
           </view>
-          <view class="add-member-btn" @tap="addMember(meal.value)">
-            <text>+</text>
+          <view class="member-empty" v-if="meal.members.length === 0">
+            <text class="member-empty-text">暂无可选的共餐人</text>
           </view>
         </view>
       </view>
@@ -64,6 +72,36 @@ export default {
       saving: false
     }
   },
+  computed: {
+    // 将「餐次 × 成员」组装为可直接渲染的列表,成员带 selected 标记(避免模板内方法调用)
+    mealGroups: function() {
+      var self = this
+      return this.mealTypes.map(function(meal) {
+        var config = self.mealConfigs[meal.value]
+        var ids = []
+        if (config && config.participantMemberIds) {
+          try {
+            ids = JSON.parse(config.participantMemberIds)
+          } catch (e) {
+            ids = []
+          }
+        }
+        var members = self.familyMembers.map(function(m) {
+          return {
+            id: m.id,
+            nickname: m.nickname,
+            selected: ids.indexOf(m.id) >= 0
+          }
+        })
+        return {
+          value: meal.value,
+          label: meal.label,
+          icon: meal.icon,
+          members: members
+        }
+      })
+    }
+  },
   onLoad: function() {
     this.loadMembers()
     this.loadConfigs()
@@ -103,16 +141,6 @@ export default {
       this.dateType = type
       this.loadConfigs()
     },
-    isMemberSelected: function(mealType, memberId) {
-      var config = this.mealConfigs[mealType]
-      if (!config || !config.participantMemberIds) return false
-      try {
-        var ids = JSON.parse(config.participantMemberIds)
-        return ids.indexOf(memberId) >= 0
-      } catch (e) {
-        return false
-      }
-    },
     toggleMember: function(mealType, memberId) {
       var config = this.mealConfigs[mealType] || {}
       var ids = []
@@ -131,9 +159,8 @@ export default {
       
       this.mealConfigs[mealType] = Object.assign({}, config, { participantMemberIds: JSON.stringify(ids) })
     },
-    addMember: function(mealType) {
-      // 简化的添加成员逻辑
-      this.toggleMember(mealType, this.familyMembers[0] && this.familyMembers[0].id)
+    goManageMembers: function() {
+      uni.navigateTo({ url: '/pages/profile-extra/family-members' })
     },
     saveConfig: function() {
       var self = this
@@ -170,6 +197,9 @@ export default {
   display: flex;
   flex-direction: column;
 }
+.meal-config-page, .meal-config-page * {
+  box-sizing: border-box;
+}
 .nav-placeholder {
   width: 80rpx;
 }
@@ -227,23 +257,46 @@ export default {
   padding: 24rpx 30rpx;
 }
 .member-item {
+  position: relative;
   display: flex;
   flex-direction: column;
   align-items: center;
-  padding: 16rpx 24rpx;
-  border: 1rpx solid #ddd;
+  justify-content: center;
+  padding: 16rpx 20rpx;
+  border: 2rpx solid #E0E0E0;
   border-radius: 16rpx;
   background-color: #FAFAFA;
+  min-width: 132rpx;
+  max-width: 100%;
+  transition: all 0.15s ease;
 }
 .member-selected {
   border-color: #FF8C42;
+  border-width: 3rpx;
   background-color: #FFF5EB;
+  box-shadow: 0 0 0 4rpx rgba(255, 140, 66, 0.18);
+}
+.member-check {
+  position: absolute;
+  top: -10rpx;
+  right: -10rpx;
+  width: 36rpx;
+  height: 36rpx;
+  border-radius: 50%;
+  background-color: #FF8C42;
+  color: #FFFFFF;
+  font-size: 22rpx;
+  font-weight: 700;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  z-index: 2;
 }
 .member-avatar {
   width: 60rpx;
   height: 60rpx;
   border-radius: 50%;
-  background-color: #FF8C42;
+  background-color: #C8CDD4;
   color: #FFFFFF;
   display: flex;
   align-items: center;
@@ -252,20 +305,53 @@ export default {
   font-weight: 600;
   margin-bottom: 8rpx;
 }
+.member-selected .member-avatar {
+  background-color: #FF8C42;
+}
 .member-name {
   font-size: 22rpx;
   color: #666;
+  max-width: 120rpx;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
 }
-.add-member-btn {
-  width: 80rpx;
-  height: 80rpx;
-  border: 2rpx dashed #ddd;
-  border-radius: 16rpx;
+.member-selected .member-name {
+  color: #FF8C42;
+  font-weight: 600;
+}
+.member-empty {
+  width: 100%;
+  padding: 20rpx 0;
+}
+.member-empty-text {
+  font-size: 24rpx;
+  color: #999;
+}
+.add-member-entry {
   display: flex;
   align-items: center;
   justify-content: center;
-  font-size: 40rpx;
-  color: #999;
+  background-color: #FFFFFF;
+  border: 2rpx dashed #FF8C42;
+  border-radius: 20rpx;
+  padding: 24rpx 30rpx;
+  margin-bottom: 30rpx;
+}
+.add-member-entry-icon {
+  font-size: 30rpx;
+  color: #FF8C42;
+  margin-right: 12rpx;
+}
+.add-member-entry-text {
+  font-size: 28rpx;
+  color: #FF8C42;
+  font-weight: 600;
+}
+.add-member-entry-arrow {
+  font-size: 30rpx;
+  color: #FF8C42;
+  margin-left: 8rpx;
 }
 .tip-card {
   background-color: #E3F2FD;