Quellcode durchsuchen

fix: 邀请接受流程缺失 FamilyMember 记录和 avatar 字段

- FamilyInvitationService.acceptInvitation(): 接受令牌/二维码后创建 FamilyMember 记录,头像优先 user.getAvatar() 空回退 /static/avatar.jpg
- FamilyJoinRequestService.approveJoinRequest(): 审批通过补偿创建 FamilyMember 记录,同头像策略
- 两处均检查重复记录(避免 mergeFamily 切换路径下插入双份)
- 新增 FamilyMemberMapper @Resource 注入

Closes: member avatar not showing after family invite join
Sisyphus vor 2 Tagen
Ursprung
Commit
ccfdbdd869

+ 29 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/FamilyInvitationService.java

@@ -6,9 +6,11 @@ import com.etotem.cfc.dto.FamilyStatusDTO;
 import com.etotem.cfc.dto.InviteValidateDTO;
 import com.etotem.cfc.entity.Family;
 import com.etotem.cfc.entity.FamilyInvitation;
+import com.etotem.cfc.entity.FamilyMember;
 import com.etotem.cfc.entity.User;
 import com.etotem.cfc.mapper.FamilyInvitationMapper;
 import com.etotem.cfc.mapper.FamilyMapper;
+import com.etotem.cfc.mapper.FamilyMemberMapper;
 import com.etotem.cfc.mapper.UserMapper;
 import org.springframework.stereotype.Service;
 
@@ -26,6 +28,9 @@ public class FamilyInvitationService {
     @Resource
     private FamilyMapper familyMapper;
 
+    @Resource
+    private FamilyMemberMapper familyMemberMapper;
+
     @Resource
     private UserMapper userMapper;
 
@@ -172,6 +177,30 @@ public class FamilyInvitationService {
         user.setUpdatedAt(new Date());
         userMapper.updateById(user);
 
+        // 【修复】接受邀请后确保该用户在目标家庭有 FamilyMember 记录,成员列表才能显示头像
+        // 1) mergeFamily 切换路径:switchMemberToFamily 已迁移记录,此处跳过避免重复
+        // 2) 无记录路径:创建记录,头像优先取用户本人头像,为空回退默认头像
+        FamilyMember existing = familyMemberMapper.selectOne(
+                new LambdaQueryWrapper<FamilyMember>()
+                        .eq(FamilyMember::getFamilyId, invitation.getFamilyId())
+                        .eq(FamilyMember::getUserId, user.getId())
+                        .last("LIMIT 1"));
+        if (existing == null) {
+            String memberAvatar = (user.getAvatar() != null && !user.getAvatar().isEmpty())
+                    ? user.getAvatar() : "/static/avatar.jpg";
+            FamilyMember newMember = new FamilyMember();
+            newMember.setFamilyId(invitation.getFamilyId());
+            newMember.setUserId(user.getId());
+            newMember.setNickname(user.getNickname());
+            newMember.setAvatar(memberAvatar);
+            newMember.setGender(user.getGender());
+            newMember.setShowToFamily(1);
+            newMember.setTotalPoints(0);
+            newMember.setCreatedAt(new Date());
+            newMember.setUpdatedAt(new Date());
+            familyMemberMapper.insert(newMember);
+        }
+
         return "加入家庭成功";
     }
 

+ 23 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/FamilyJoinRequestService.java

@@ -187,6 +187,29 @@ public class FamilyJoinRequestService {
                 user.setFamilyRole(request.getFamilyRole());
                 user.setUpdatedAt(new Date());
                 userMapper.updateById(user);
+
+                // 【修复】审批通过加入且用户无家庭记录:创建 FamilyMember 确保成员列表显示头像
+                // 头像优先取用户本人头像,为空回退默认头像
+                FamilyMember existing = familyMemberMapper.selectOne(
+                        new LambdaQueryWrapper<FamilyMember>()
+                                .eq(FamilyMember::getFamilyId, family.getId())
+                                .eq(FamilyMember::getUserId, user.getId())
+                                .last("LIMIT 1"));
+                if (existing == null) {
+                    String memberAvatar = (user.getAvatar() != null && !user.getAvatar().isEmpty())
+                            ? user.getAvatar() : "/static/avatar.jpg";
+                    FamilyMember newMember = new FamilyMember();
+                    newMember.setFamilyId(family.getId());
+                    newMember.setUserId(user.getId());
+                    newMember.setNickname(user.getNickname());
+                    newMember.setAvatar(memberAvatar);
+                    newMember.setGender(user.getGender());
+                    newMember.setShowToFamily(1);
+                    newMember.setTotalPoints(0);
+                    newMember.setCreatedAt(new Date());
+                    newMember.setUpdatedAt(new Date());
+                    familyMemberMapper.insert(newMember);
+                }
             }
         }
 

+ 11 - 9
cfc-frontend/pages/invite/join-form.vue

@@ -177,8 +177,8 @@ export default {
 	margin-bottom: 30rpx;
 }
 .form-item {
-	margin-bottom: 30rpx;
-}
+				margin-bottom: 40rpx;
+			}
 .form-item:last-child {
 	margin-bottom: 0;
 }
@@ -192,13 +192,15 @@ export default {
 	color: #f44336;
 }
 .input, .picker-input {
-	padding: 20rpx;
-	background: #f5f5f5;
-	border-radius: 12rpx;
-	font-size: 28rpx;
-	box-sizing: border-box;
-	width: 100%;
-}
+				padding: 20rpx;
+				background: #f5f5f5;
+				border-radius: 12rpx;
+				font-size: 28rpx;
+				box-sizing: border-box;
+				width: 100%;
+				min-height: 72rpx;
+				line-height: 1.5;
+			}
 .avatar-upload {
 	width: 150rpx;
 	height: 150rpx;

+ 54 - 8
cfc-frontend/pages/invite/join.vue

@@ -82,7 +82,7 @@
 </template>
 
 <script>
-import { validateInvitation, validateFamilyCode, checkUserFamily, bindReferral } from '@/utils/api.js'
+import { validateInvitation, validateFamilyCode, checkUserFamily, bindReferral, getMyJoinRequest } from '@/utils/api.js'
 
 export default {
   data() {
@@ -99,6 +99,7 @@ export default {
       isLoggedIn: false,
       inviteInfo: null,
       familyStatus: null,
+      joinRequest: null,
       error: '',
       // 动态文案
       tipText: '',
@@ -224,13 +225,11 @@ export default {
             this.$store && this.$store.commit('setFamilyId', res.data.familyId)
             uni.setStorageSync('familyId', res.data.familyId)
           }
-          // 已在目标家庭 -> 直接进首页
-          if (this.inviteInfo && this.familyStatus.inFamily && 
+          // 已在目标家庭
+          if (this.inviteInfo && this.familyStatus.inFamily &&
               this.familyStatus.familyId === this.inviteInfo.familyId) {
-            this.setRedirectInfo(true)
-            this.loading = false
-            // 延迟跳转,让用户看到成功提示
-            setTimeout(() => this.goHome(), 1000)
+            // 检查加入请求状态
+            await this.checkJoinRequestStatus()
             return
           }
           // 不在目标家庭 -> 去完善个人信息页提交申请
@@ -247,6 +246,45 @@ export default {
       }
     },
 
+    // 检查加入请求状态
+    async checkJoinRequestStatus() {
+      try {
+        var reqRes = await getMyJoinRequest()
+        if (reqRes && reqRes.data) {
+          var req = reqRes.data
+          if (req && req.status === 'pending') {
+            // 已提交申请但等待审批
+            this.tipText = '您的加入申请已提交,等待邀请人同意'
+            this.btnText = '查看申请状态'
+            this.joinRequest = req
+            this.loading = false
+            return
+          } else if (req && req.status === 'approved') {
+            // 已批准,直接进入成员管理页面
+            this.loading = false
+            uni.redirectTo({
+              url: '/pages/profile-extra/family-members'
+            })
+            return
+          } else if (req && req.status === 'rejected') {
+            // 已拒绝
+            this.tipText = '您的加入申请已被拒绝,如需重新申请请联系邀请人'
+            this.btnText = '返回首页'
+            this.loading = false
+            return
+          }
+        }
+        // 无请求记录,视为已是正式成员
+        this.setRedirectInfo(true)
+        this.loading = false
+      } catch (e) {
+        console.log('检查加入请求状态失败', e)
+        // 降级处理:直接进入首页
+        this.setRedirectInfo(true)
+        this.loading = false
+      }
+    },
+
     setRedirectInfo(isInTargetFamily) {
       if (isInTargetFamily) {
         this.tipText = '您已是该家庭成员'
@@ -262,9 +300,17 @@ export default {
       if (this.redirecting) return
       this.redirecting = true
 
-      // 已在目标家庭 -> 直接进首页
+      // 已在目标家庭且请求已批准 -> 直接进入成员管理页面
       if (this.inviteInfo && this.familyStatus && this.familyStatus.inFamily &&
           this.familyStatus.familyId === this.inviteInfo.familyId) {
+        if (this.joinRequest && this.joinRequest.status === 'approved') {
+          this.redirecting = false
+          uni.redirectTo({
+            url: '/pages/profile-extra/family-members'
+          })
+          return
+        }
+        // 已在家庭但请求 pending,不重复跳转,直接返回首页
         this.redirecting = false
         this.goHome()
         return