feat(family): 邀请体验优化——整行可点拉起分享、分享文案带邀请人、受邀直达自动加入

- 邀请行改为 open-type=share 的 Button 铺满整行,整行任意位置可点,视觉与普通行一致
- 分享标题带邀请人昵称:「XX 邀请你加入家庭圈「XX」」
- 接收方从分享卡进入:未登录先登录回跳,已登录且非成员时自动调 joinHome 完成加入,无需手动点击
This commit is contained in:
ozh 2026-09-17 14:19:59 +08:00
parent 0ef1f490e5
commit 7bef729e93
2 changed files with 59 additions and 30 deletions

View File

@ -74,15 +74,31 @@
margin-top: 24px; margin-top: 24px;
} }
// 邀请行:与 ListRow 同款外观,但右侧为 open-type=share 的原生 Button(触发转发面板) // 邀请行:open-type=share 的原生 Button 铺满整行(整行可点拉起转发面板),样式与 ListRow 一致
.shareRow { .shareRow {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
width: 100%;
min-height: 104px; min-height: 104px;
padding: 0 32px; padding: 0 32px;
box-sizing: border-box;
margin: 0;
background: $color-bg-white; background: $color-bg-white;
border: none;
border-bottom: 1px solid $color-border; border-bottom: 1px solid $color-border;
border-radius: 0;
font-size: inherit;
line-height: inherit;
text-align: left;
&::after {
border: none;
}
}
.shareRowPressed {
background: $color-bg-press;
} }
.shareLabel { .shareLabel {
@ -90,21 +106,6 @@
color: $color-text; color: $color-text;
} }
// 清除小程序 Button 原生样式(边框/底色/行高),仅保留命中区
.shareBtn {
margin: 0;
padding: 0;
width: auto;
min-width: 0;
background: transparent;
border: none;
line-height: inherit;
&::after {
border: none;
}
}
.shareArrow { .shareArrow {
font-size: 36px; font-size: 36px;
color: $color-text-placeholder; color: $color-text-placeholder;

View File

@ -1,5 +1,6 @@
import { useState } from 'react' import { useState } from 'react'
import { useRouter, useDidShow, useShareAppMessage } from '@tarojs/taro' import { useRouter, useDidShow, useShareAppMessage } from '@tarojs/taro'
import Taro from '@tarojs/taro'
import { View, Text, Button } from '@tarojs/components' import { View, Text, Button } from '@tarojs/components'
import { useAppSelector } from '@/store/hooks' import { useAppSelector } from '@/store/hooks'
import { Navbar } from '@/components/navbar' import { Navbar } from '@/components/navbar'
@ -7,7 +8,7 @@ import { Loading } from '@/components/loading'
import { StateView } from '@/components/state-view' import { StateView } from '@/components/state-view'
import { FamilyCard } from '@/components/family-card' import { FamilyCard } from '@/components/family-card'
import { ListRow, ListRowGroup } from '@/components/list-row' import { ListRow, ListRowGroup } from '@/components/list-row'
import { getHomeDetail, getHomeMemberList, type HomeInfo, type HomeMember } from '@/api/home' import { getHomeDetail, getHomeMemberList, joinHome, type HomeInfo, type HomeMember } from '@/api/home'
import { getCareMemberList, type CareMember } from '@/api/careMember' import { getCareMemberList, type CareMember } from '@/api/careMember'
import { MAX_CARED_PER_FAMILY } from '@/constants/family' import { MAX_CARED_PER_FAMILY } from '@/constants/family'
import { ROUTES } from '@/constants/routes' import { ROUTES } from '@/constants/routes'
@ -30,9 +31,12 @@ const contactsSummary = (c: CareMember): string => {
export default function FamilyDetail() { 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 token = useAppSelector((s) => s.auth.token) const token = useAppSelector((s) => s.auth.token)
const myUserId = useAppSelector((s) => s.auth.userId)
const [loading, setLoading] = useState(true) const [loading, setLoading] = useState(true)
const [joining, setJoining] = useState(false)
const [family, setFamily] = useState<HomeInfo | null>(null) const [family, setFamily] = useState<HomeInfo | null>(null)
const [members, setMembers] = useState<HomeMember[]>([]) const [members, setMembers] = useState<HomeMember[]>([])
const [caredList, setCaredList] = useState<CareMember[]>([]) const [caredList, setCaredList] = useState<CareMember[]>([])
@ -62,14 +66,39 @@ export default function FamilyDetail() {
} }
} }
// 从添加表单返回时刷新 // 从添加表单返回时刷新;受邀进入且尚未是成员时自动加入(跳过手动点击步骤)
useDidShow(() => { useDidShow(() => {
load() load().then(() => {
if (
!isInviteEnter || joining || myUserId == null ||
members.length === 0 || members.some((m) => m.memberId === myUserId)
) return
autoJoin(familyId)
})
}) })
// 邀请分享:接收方从分享卡进入本页后点「加入」走 joinHome(code) // 受邀直达:已登录但非成员时自动加入,无需手点
const autoJoin = async (homeId: string) => {
if (joining) return
setJoining(true)
try {
await joinHome(homeId)
showToast('已加入家庭')
await load()
} catch (e) {
showToast(e instanceof Error ? e.message : '加入失败')
} finally {
setJoining(false)
}
}
// 邀请分享:接收方点分享卡直达本页,登录后自动加入
const inviterName = () => {
const me = members.find((m) => m.memberId === myUserId)
return memberName(me ?? members[0])
}
useShareAppMessage(() => ({ useShareAppMessage(() => ({
title: `邀请你加入家庭圈「${family?.name ?? ''}」`, title: `${inviterName()} 邀请你加入家庭圈「${family?.name ?? ''}」`,
path: `${ROUTES.FAMILY_DETAIL}?id=${familyId}&invite=1` path: `${ROUTES.FAMILY_DETAIL}?id=${familyId}&invite=1`
})) }))
@ -167,16 +196,15 @@ 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.homeId} onClick={stub('复制成功(占位)')} arrow />
{/* open-type=share 触发右上角同款转发面板;Button 原生样式清除交由 shareBtn 样式接管 */} {/* open-type=share 的 Button 铺满整行做命中区,样式与普通 ListRow 一致 */}
<View className={styles.shareRow}> <Button
className={styles.shareRow}
hoverClass={styles.shareRowPressed}
openType="share"
>
<Text className={styles.shareLabel}>邀请他人</Text> <Text className={styles.shareLabel}>邀请他人</Text>
<Button <Text className={styles.shareArrow}>›</Text>
className={styles.shareBtn} </Button>
openType="share"
>
<Text className={styles.shareArrow}>›</Text>
</Button>
</View>
<ListRow label="转让群主" arrow onClick={stub('转让功能即将上线')} /> <ListRow label="转让群主" arrow onClick={stub('转让功能即将上线')} />
<ListRow label="修改群昵称" arrow onClick={stub('修改昵称功能即将上线')} /> <ListRow label="修改群昵称" arrow onClick={stub('修改昵称功能即将上线')} />
</ListRowGroup> </ListRowGroup>