From 58561e12e0b8fbd7eee35d8bc6c1f4ea087b86e5 Mon Sep 17 00:00:00 2001 From: ozh Date: Fri, 9 Oct 2026 15:54:18 +0800 Subject: [PATCH] =?UTF-8?q?fix(family):=20=E5=8A=A0=E5=85=A5=E5=AE=B6?= =?UTF-8?q?=E5=BA=AD=E5=9C=88=E6=94=B9=E7=94=A8=E7=9F=AD=E7=BC=96=E5=8F=B7?= =?UTF-8?q?=20code=EF=BC=8C=E6=8E=A5=E9=80=9A=E5=A4=8D=E5=88=B6=E7=BC=96?= =?UTF-8?q?=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - HomeInfo 补 code 字段(详情接口返回的家庭短编号,joinHome 认 code 而非内部 homeId) - 受邀直达:分享卡携带 code,autoJoin 凭 code 调 joinHome;未登录跳 登录时回跳链接保留 code 参数 - 分享卡 path 附加 code;"家庭编号"行接通复制(code 优先、homeId 兜底) --- src/api/home.ts | 2 ++ src/pages/family/detail.tsx | 50 +++++++++++++++++++++++++++++-------- 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/src/api/home.ts b/src/api/home.ts index 15bf794..872593b 100644 --- a/src/api/home.ts +++ b/src/api/home.ts @@ -11,6 +11,8 @@ export interface HomeInfo { memberCount: number careMemberCount: number deviceCount: number + code?: string // 家庭编号(详情接口返回,如 '1446833'),供他人 joinHome 加入 + createTime?: string } // 成员列表项(2026-09-17 联调实测):role=OWNER 为群主,其余为成员 diff --git a/src/pages/family/detail.tsx b/src/pages/family/detail.tsx index 871577b..628b656 100644 --- a/src/pages/family/detail.tsx +++ b/src/pages/family/detail.tsx @@ -47,6 +47,8 @@ export default function FamilyDetail() { const router = useRouter() const familyId = router.params.id ?? '' const isInviteEnter = router.params.invite === '1' + // 分享卡携带的家庭短编号(joinHome 用;homeId 是内部 ID 后端 join 不认) + const inviteCode = router.params.code ?? '' const token = useAppSelector((s) => s.auth.token) const myUserId = useAppSelector((s) => s.auth.userId) @@ -56,6 +58,10 @@ export default function FamilyDetail() { const [members, setMembers] = useState([]) const [caredList, setCaredList] = useState([]) + // 家庭短编号:joinHome 用。优先分享卡带来的 code(受邀场景), + // 直达/普通进入时从详情接口响应补取 + const [homeCode, setHomeCode] = useState(inviteCode) + // 转让群主:底部入口仅群主可见,点击后弹选人 Modal const [transferOpen, setTransferOpen] = useState(false) const [transferring, setTransferring] = useState(false) @@ -66,15 +72,16 @@ export default function FamilyDetail() { // 这两个接口会报权限错,不能因此把整个页面判成「家庭不存在」) // 返回本次拉到的成员列表(供 autoJoin 用最新数据判断,避免 stale state) const load = async (): Promise => { - // 分享卡直达本页且未登录:先去登录,登录后回跳本页 + // 分享卡直达本页且未登录:先去登录,登录后回跳本页(保留 code 参数供回跳后自动加入) if (!token) { - const target = encodeURIComponent(`${ROUTES.FAMILY_DETAIL}?id=${familyId}&invite=1`) + const target = encodeURIComponent(`${ROUTES.FAMILY_DETAIL}?id=${familyId}${inviteCode ? `&code=${inviteCode}` : ''}&invite=1`) reLaunch(`${ROUTES.LOGIN}?redirect=${target}`) return null } setLoading(true) try { const home = await getHomeDetail(familyId) + setHomeCode(home.code ?? '') const [memberList, careList] = await Promise.all([ getHomeMemberList(familyId).catch(() => [] as HomeMember[]), getCareMemberList(familyId).catch(() => [] as CareMember[]) @@ -99,20 +106,25 @@ export default function FamilyDetail() { !isInviteEnter || joining || myUserId == null || !memberList || memberList.length === 0 || memberList.some((m) => m.memberId === myUserId) ) return - autoJoin(familyId) + autoJoin() }) }) - // 受邀直达:已登录但非成员时自动加入,无需手点 - const autoJoin = async (homeId: string) => { + // 受邀直达:已登录但非成员时自动加入,无需手点。code 用分享卡带来的短编号 + // (homeId 是内部 ID,joinHome 后端不认) + const autoJoin = async () => { if (joining) return + if (!homeCode) { + showToast('分享卡缺少家庭编号,请重新获取') + return + } setJoining(true) try { - await joinHome(homeId) + await joinHome(homeCode) showToast('已加入家庭') await load() } catch (e) { - // 加入失败(如接口异常)也要让页面可退出:详情能拉到就展示,拉不到走「家庭不存在」分支(带返回按钮) + // 加入失败(如接口异常)也要让页面可退出:详情能拉到就展示,拉不到走错误分支(带回首页按钮) showToast(e instanceof Error ? e.message : '加入失败') if (!family) await load() } finally { @@ -120,20 +132,32 @@ export default function FamilyDetail() { } } - // 邀请分享:接收方点分享卡直达本页,登录后自动加入 + // 邀请分享:接收方点分享卡直达本页,登录后凭 code 自动加入 const inviterName = () => { const me = members.find((m) => m.memberId === myUserId) return memberName(me ?? members[0]) } useShareAppMessage(() => ({ title: `${inviterName()} 邀请你加入家庭圈「${family?.name ?? ''}」`, - path: `${ROUTES.FAMILY_DETAIL}?id=${familyId}&invite=1` + path: `${ROUTES.FAMILY_DETAIL}?id=${familyId}${family?.code ? `&code=${family.code}` : ''}&invite=1` })) const addCared = () => { navigateTo(`${ROUTES.FAMILY_CONTACT_ADD}?familyId=${familyId}`) } + // 复制家庭编号:优先短编号 code(供 joinHome 用),无 code 回落 homeId + const copyHomeCode = async () => { + const code = family?.code || family?.homeId || '' + if (!code) return + try { + await Taro.setClipboardData({ data: code }) + // 微信原生会自带「内容已复制」toast,无需重复提示 + } catch { + showToast('复制失败,请长按手动复制') + } + } + // 我在成员列表里的角色:转让入口只对群主开放 const myMember = members.find((m) => m.memberId === myUserId) ?? null const isOwner = myMember?.role === 'OWNER' @@ -226,7 +250,6 @@ export default function FamilyDetail() { const caredCount = caredList.length const canAdd = caredCount < MAX_CARED_PER_FAMILY - const stub = (tip: string) => () => showToast(tip) return ( @@ -297,7 +320,12 @@ export default function FamilyDetail() { - + {/* open-type=share 的 Button 铺满整行做命中区,样式与普通 ListRow 一致 */}