fix(family): 加入家庭圈改用短编号 code,接通复制编号

- HomeInfo 补 code 字段(详情接口返回的家庭短编号,joinHome 认 code
  而非内部 homeId)
- 受邀直达:分享卡携带 code,autoJoin 凭 code 调 joinHome;未登录跳
  登录时回跳链接保留 code 参数
- 分享卡 path 附加 code;"家庭编号"行接通复制(code 优先、homeId 兜底)
This commit is contained in:
ozh 2026-10-09 15:54:18 +08:00
parent 56e990c028
commit 58561e12e0
2 changed files with 41 additions and 11 deletions

View File

@ -11,6 +11,8 @@ export interface HomeInfo {
memberCount: number
careMemberCount: number
deviceCount: number
code?: string // 家庭编号(详情接口返回,如 '1446833'),供他人 joinHome 加入
createTime?: string
}
// 成员列表项(2026-09-17 联调实测):role=OWNER 为群主,其余为成员

View File

@ -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<HomeMember[]>([])
const [caredList, setCaredList] = useState<CareMember[]>([])
// 家庭短编号: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<HomeMember[] | null> => {
// 分享卡直达本页且未登录:先去登录,登录后回跳本页
// 分享卡直达本页且未登录:先去登录,登录后回跳本页(保留 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 (
<View className={styles.page}>
@ -297,7 +320,12 @@ export default function FamilyDetail() {
<View className={styles.section}>
<ListRowGroup>
<ListRow label="家庭编号" value={family.homeId} onClick={stub('复制成功(占位)')} arrow />
<ListRow
label="家庭编号"
value={family.code || family.homeId}
arrow
onClick={copyHomeCode}
/>
{/* open-type=share 的 Button 铺满整行做命中区,样式与普通 ListRow 一致 */}
<Button
className={styles.shareRow}