fix(family): 加入家庭圈改用短编号 code,接通复制编号
- HomeInfo 补 code 字段(详情接口返回的家庭短编号,joinHome 认 code 而非内部 homeId) - 受邀直达:分享卡携带 code,autoJoin 凭 code 调 joinHome;未登录跳 登录时回跳链接保留 code 参数 - 分享卡 path 附加 code;"家庭编号"行接通复制(code 优先、homeId 兜底)
This commit is contained in:
parent
56e990c028
commit
58561e12e0
|
|
@ -11,6 +11,8 @@ export interface HomeInfo {
|
||||||
memberCount: number
|
memberCount: number
|
||||||
careMemberCount: number
|
careMemberCount: number
|
||||||
deviceCount: number
|
deviceCount: number
|
||||||
|
code?: string // 家庭编号(详情接口返回,如 '1446833'),供他人 joinHome 加入
|
||||||
|
createTime?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
// 成员列表项(2026-09-17 联调实测):role=OWNER 为群主,其余为成员
|
// 成员列表项(2026-09-17 联调实测):role=OWNER 为群主,其余为成员
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,8 @@ export default function FamilyDetail() {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const familyId = router.params.id ?? ''
|
const familyId = router.params.id ?? ''
|
||||||
const isInviteEnter = router.params.invite === '1'
|
const isInviteEnter = router.params.invite === '1'
|
||||||
|
// 分享卡携带的家庭短编号(joinHome 用;homeId 是内部 ID 后端 join 不认)
|
||||||
|
const inviteCode = router.params.code ?? ''
|
||||||
const token = useAppSelector((s) => s.auth.token)
|
const token = useAppSelector((s) => s.auth.token)
|
||||||
const myUserId = useAppSelector((s) => s.auth.userId)
|
const myUserId = useAppSelector((s) => s.auth.userId)
|
||||||
|
|
||||||
|
|
@ -56,6 +58,10 @@ export default function FamilyDetail() {
|
||||||
const [members, setMembers] = useState<HomeMember[]>([])
|
const [members, setMembers] = useState<HomeMember[]>([])
|
||||||
const [caredList, setCaredList] = useState<CareMember[]>([])
|
const [caredList, setCaredList] = useState<CareMember[]>([])
|
||||||
|
|
||||||
|
// 家庭短编号:joinHome 用。优先分享卡带来的 code(受邀场景),
|
||||||
|
// 直达/普通进入时从详情接口响应补取
|
||||||
|
const [homeCode, setHomeCode] = useState(inviteCode)
|
||||||
|
|
||||||
// 转让群主:底部入口仅群主可见,点击后弹选人 Modal
|
// 转让群主:底部入口仅群主可见,点击后弹选人 Modal
|
||||||
const [transferOpen, setTransferOpen] = useState(false)
|
const [transferOpen, setTransferOpen] = useState(false)
|
||||||
const [transferring, setTransferring] = useState(false)
|
const [transferring, setTransferring] = useState(false)
|
||||||
|
|
@ -66,15 +72,16 @@ export default function FamilyDetail() {
|
||||||
// 这两个接口会报权限错,不能因此把整个页面判成「家庭不存在」)
|
// 这两个接口会报权限错,不能因此把整个页面判成「家庭不存在」)
|
||||||
// 返回本次拉到的成员列表(供 autoJoin 用最新数据判断,避免 stale state)
|
// 返回本次拉到的成员列表(供 autoJoin 用最新数据判断,避免 stale state)
|
||||||
const load = async (): Promise<HomeMember[] | null> => {
|
const load = async (): Promise<HomeMember[] | null> => {
|
||||||
// 分享卡直达本页且未登录:先去登录,登录后回跳本页
|
// 分享卡直达本页且未登录:先去登录,登录后回跳本页(保留 code 参数供回跳后自动加入)
|
||||||
if (!token) {
|
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}`)
|
reLaunch(`${ROUTES.LOGIN}?redirect=${target}`)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
try {
|
try {
|
||||||
const home = await getHomeDetail(familyId)
|
const home = await getHomeDetail(familyId)
|
||||||
|
setHomeCode(home.code ?? '')
|
||||||
const [memberList, careList] = await Promise.all([
|
const [memberList, careList] = await Promise.all([
|
||||||
getHomeMemberList(familyId).catch(() => [] as HomeMember[]),
|
getHomeMemberList(familyId).catch(() => [] as HomeMember[]),
|
||||||
getCareMemberList(familyId).catch(() => [] as CareMember[])
|
getCareMemberList(familyId).catch(() => [] as CareMember[])
|
||||||
|
|
@ -99,20 +106,25 @@ export default function FamilyDetail() {
|
||||||
!isInviteEnter || joining || myUserId == null ||
|
!isInviteEnter || joining || myUserId == null ||
|
||||||
!memberList || memberList.length === 0 || memberList.some((m) => m.memberId === myUserId)
|
!memberList || memberList.length === 0 || memberList.some((m) => m.memberId === myUserId)
|
||||||
) return
|
) return
|
||||||
autoJoin(familyId)
|
autoJoin()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// 受邀直达:已登录但非成员时自动加入,无需手点
|
// 受邀直达:已登录但非成员时自动加入,无需手点。code 用分享卡带来的短编号
|
||||||
const autoJoin = async (homeId: string) => {
|
// (homeId 是内部 ID,joinHome 后端不认)
|
||||||
|
const autoJoin = async () => {
|
||||||
if (joining) return
|
if (joining) return
|
||||||
|
if (!homeCode) {
|
||||||
|
showToast('分享卡缺少家庭编号,请重新获取')
|
||||||
|
return
|
||||||
|
}
|
||||||
setJoining(true)
|
setJoining(true)
|
||||||
try {
|
try {
|
||||||
await joinHome(homeId)
|
await joinHome(homeCode)
|
||||||
showToast('已加入家庭')
|
showToast('已加入家庭')
|
||||||
await load()
|
await load()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// 加入失败(如接口异常)也要让页面可退出:详情能拉到就展示,拉不到走「家庭不存在」分支(带返回按钮)
|
// 加入失败(如接口异常)也要让页面可退出:详情能拉到就展示,拉不到走错误分支(带回首页按钮)
|
||||||
showToast(e instanceof Error ? e.message : '加入失败')
|
showToast(e instanceof Error ? e.message : '加入失败')
|
||||||
if (!family) await load()
|
if (!family) await load()
|
||||||
} finally {
|
} finally {
|
||||||
|
|
@ -120,20 +132,32 @@ export default function FamilyDetail() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 邀请分享:接收方点分享卡直达本页,登录后自动加入
|
// 邀请分享:接收方点分享卡直达本页,登录后凭 code 自动加入
|
||||||
const inviterName = () => {
|
const inviterName = () => {
|
||||||
const me = members.find((m) => m.memberId === myUserId)
|
const me = members.find((m) => m.memberId === myUserId)
|
||||||
return memberName(me ?? members[0])
|
return memberName(me ?? members[0])
|
||||||
}
|
}
|
||||||
useShareAppMessage(() => ({
|
useShareAppMessage(() => ({
|
||||||
title: `${inviterName()} 邀请你加入家庭圈「${family?.name ?? ''}」`,
|
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 = () => {
|
const addCared = () => {
|
||||||
navigateTo(`${ROUTES.FAMILY_CONTACT_ADD}?familyId=${familyId}`)
|
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 myMember = members.find((m) => m.memberId === myUserId) ?? null
|
||||||
const isOwner = myMember?.role === 'OWNER'
|
const isOwner = myMember?.role === 'OWNER'
|
||||||
|
|
@ -226,7 +250,6 @@ export default function FamilyDetail() {
|
||||||
|
|
||||||
const caredCount = caredList.length
|
const caredCount = caredList.length
|
||||||
const canAdd = caredCount < MAX_CARED_PER_FAMILY
|
const canAdd = caredCount < MAX_CARED_PER_FAMILY
|
||||||
const stub = (tip: string) => () => showToast(tip)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View className={styles.page}>
|
<View className={styles.page}>
|
||||||
|
|
@ -297,7 +320,12 @@ export default function FamilyDetail() {
|
||||||
|
|
||||||
<View className={styles.section}>
|
<View className={styles.section}>
|
||||||
<ListRowGroup>
|
<ListRowGroup>
|
||||||
<ListRow label="家庭编号" value={family.homeId} onClick={stub('复制成功(占位)')} arrow />
|
<ListRow
|
||||||
|
label="家庭编号"
|
||||||
|
value={family.code || family.homeId}
|
||||||
|
arrow
|
||||||
|
onClick={copyHomeCode}
|
||||||
|
/>
|
||||||
{/* open-type=share 的 Button 铺满整行做命中区,样式与普通 ListRow 一致 */}
|
{/* open-type=share 的 Button 铺满整行做命中区,样式与普通 ListRow 一致 */}
|
||||||
<Button
|
<Button
|
||||||
className={styles.shareRow}
|
className={styles.shareRow}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue