Просмотр исходного кода

fix: 家庭成员邀请改为小程序原生分享

- 移除已废弃的海报分享入口(SharePoster 组件不再使用)
- 移除 dead code: 无意义的 empty-tip 视图
- 移除无用 import: generateFamilyInviteQrCode
- onInvite 使用 uni.share type=5(小程序原生卡片分享),不再依赖 QR 图片
- 分享卡片带标题+家庭名,被邀请人直接打开 invite/join 页面
Xiaogang Liao 2 месяцев назад
Родитель
Сommit
aaf23ef47b

+ 28 - 3
cfc-backend/src/main/java/com/etotem/cfc/controller/admin/AdminPurchaseFieldController.java

@@ -42,8 +42,33 @@ public class AdminPurchaseFieldController {
     @PostMapping("/save")
     @PostMapping("/save")
     public Result<Void> save(@RequestBody Map<String, Object> params) {
     public Result<Void> save(@RequestBody Map<String, Object> params) {
         Long productId = Long.parseLong(params.get("productId").toString());
         Long productId = Long.parseLong(params.get("productId").toString());
-        @SuppressWarnings("unchecked")
-        List<ProductPurchaseField> fields = (List<ProductPurchaseField>) params.get("fields");
+        List<ProductPurchaseField> fields = convertFieldList(params.get("fields"));
         return purchaseFieldService.save(productId, fields);
         return purchaseFieldService.save(productId, fields);
     }
     }
-}
+
+    @SuppressWarnings("unchecked")
+    private List<ProductPurchaseField> convertFieldList(Object raw) {
+        if (raw == null || !(raw instanceof List)) {
+            return new ArrayList<>();
+        }
+        List<Map<String, Object>> mapList = (List<Map<String, Object>>) raw;
+        List<ProductPurchaseField> list = new ArrayList<>();
+        for (Map<String, Object> m : mapList) {
+            ProductPurchaseField f = new ProductPurchaseField();
+            f.setFieldKey(strVal(m.get("fieldKey")));
+            f.setFieldName(strVal(m.get("fieldName")));
+            f.setIsRequired(intVal(m.get("isRequired")));
+            f.setSortOrder(intVal(m.get("sortOrder")));
+            list.add(f);
+        }
+        return list;
+    }
+
+    private String strVal(Object v) {
+        return v != null ? v.toString() : null;
+    }
+
+    private Integer intVal(Object v) {
+        return v != null ? Integer.parseInt(v.toString()) : null;
+    }
+}

+ 3 - 1
cfc-backend/src/main/java/com/etotem/cfc/controller/family/FamilyInviteController.java

@@ -268,7 +268,9 @@ public class FamilyInviteController {
         }
         }
 
 
         String qrBase64;
         String qrBase64;
-        qrBase64 = wechatService.generateWxacode("invite=" + token, "pages/invite/join");
+        // scene 必须是合法 JSON 字符串(getwxacodeunlimit 限制 64 字节,token 32 字符 → ~46 字节安全)
+        String scene = "{\"t\":\"" + token + "\"}";
+        qrBase64 = wechatService.generateWxacode(scene, "pages/invite/join");
 
 
         Family family = familyMapper.selectById(user.getFamilyId());
         Family family = familyMapper.selectById(user.getFamilyId());
 
 

+ 11 - 2
cfc-frontend/pages/invite/join.vue

@@ -171,13 +171,22 @@ export default {
     }
     }
   },
   },
   onLoad(query) {
   onLoad(query) {
-    // token:优先从 query 参数,其次从场景值(invite=xxx)
+    // token:优先从 query 参数,其次从场景值
     var token = query.token || query.inviteToken || ''
     var token = query.token || query.inviteToken || ''
     if (!token) {
     if (!token) {
       var scene = query.scene
       var scene = query.scene
       if (scene) {
       if (scene) {
         var sceneDecoded = decodeURIComponent(scene)
         var sceneDecoded = decodeURIComponent(scene)
-        if (sceneDecoded.indexOf('invite=') === 0) {
+        // 新格式:JSON 场景值 {"t":"TOKEN"}
+        if (sceneDecoded.indexOf('{') === 0) {
+          try {
+            var sceneObj = JSON.parse(sceneDecoded)
+            token = sceneObj.t || sceneObj.token || ''
+          } catch (e) {
+            token = ''
+          }
+        } else if (sceneDecoded.indexOf('invite=') === 0) {
+          // 旧格式兼容
           token = sceneDecoded.substring(7)
           token = sceneDecoded.substring(7)
         }
         }
       }
       }

+ 3 - 9
cfc-frontend/pages/profile-extra/family-members.vue

@@ -31,9 +31,6 @@
       <button class="empty-invite-btn" @click="onInvite">📨 邀请家人</button>
       <button class="empty-invite-btn" @click="onInvite">📨 邀请家人</button>
     </view>
     </view>
 
 
-    <!-- ===== 分享邀请卡海报 ===== -->
-    <view v-else class="empty-tip">暂无家庭成员,正在为您创建家庭...</view>
-
     <!-- ===== 成员详情弹窗 ===== -->
     <!-- ===== 成员详情弹窗 ===== -->
     <view class="modal-mask" v-if="showMemberDetailModal" @click="closeMemberDetail">
     <view class="modal-mask" v-if="showMemberDetailModal" @click="closeMemberDetail">
       <view class="member-detail-card" @click.stop>
       <view class="member-detail-card" @click.stop>
@@ -108,7 +105,6 @@ import {
   listFamilyMembers,
   listFamilyMembers,
   switchToFamilyMember,
   switchToFamilyMember,
   kickFamilyMemberById,
   kickFamilyMemberById,
-  generateFamilyInviteQrCode,
   generateFamilyInvite,
   generateFamilyInvite,
   getFamilyMembers,
   getFamilyMembers,
   updateFamilyMember
   updateFamilyMember
@@ -280,26 +276,24 @@ export default {
         var res = await generateFamilyInvite()
         var res = await generateFamilyInvite()
         if (res.code === 200 && res.data) {
         if (res.code === 200 && res.data) {
           var token = res.data.token
           var token = res.data.token
-          var qrCode = res.data.qrCodeBase64
-          // 分享小程序码
           uni.share({
           uni.share({
             provider: 'weixin',
             provider: 'weixin',
             scene: 'WXSceneSession',
             scene: 'WXSceneSession',
             type: 5,
             type: 5,
-            imageUrl: qrCode ? qrCode.replace('data:image/png;base64,', '') : '',
+            title: '加入「' + (this.familyName || '我的家庭') + '」',
             miniProgram: {
             miniProgram: {
               id: '',
               id: '',
               path: 'pages/invite/join?token=' + token,
               path: 'pages/invite/join?token=' + token,
               type: 0,
               type: 0,
               webUrl: 'https://cfc.etotem.com.cn/invite/join?token=' + token
               webUrl: 'https://cfc.etotem.com.cn/invite/join?token=' + token
             },
             },
-            success: function(shareRes) {
+            success: function() {
               uni.hideLoading()
               uni.hideLoading()
               uni.showToast({ title: '分享成功', icon: 'success' })
               uni.showToast({ title: '分享成功', icon: 'success' })
             },
             },
             fail: function(err) {
             fail: function(err) {
               uni.hideLoading()
               uni.hideLoading()
-              // 如果分享失败,复制链接
+              if (err.errMsg.indexOf('cancel') >= 0) return
               uni.setClipboardData({
               uni.setClipboardData({
                 data: 'https://cfc.etotem.com.cn/invite/join?token=' + token,
                 data: 'https://cfc.etotem.com.cn/invite/join?token=' + token,
                 success: function() {
                 success: function() {

+ 1 - 1
cfc-web/.last_build_commit

@@ -1 +1 @@
-7f90e362c10a3e61967d7547d7f121365870433f
+5d433f5b5282ff51bd22fcbe10bfa6becfe75cef