216 lines
7.6 KiB
TypeScript
216 lines
7.6 KiB
TypeScript
import { useState } from 'react'
|
||
import { useRouter, useDidShow, useShareAppMessage } from '@tarojs/taro'
|
||
import Taro from '@tarojs/taro'
|
||
import { View, Text, Button } from '@tarojs/components'
|
||
import { useAppSelector } from '@/store/hooks'
|
||
import { Navbar } from '@/components/navbar'
|
||
import { Loading } from '@/components/loading'
|
||
import { StateView } from '@/components/state-view'
|
||
import { FamilyCard } from '@/components/family-card'
|
||
import { ListRow, ListRowGroup } from '@/components/list-row'
|
||
import { getHomeDetail, getHomeMemberList, joinHome, type HomeInfo, type HomeMember } from '@/api/home'
|
||
import { getCareMemberList, type CareMember } from '@/api/careMember'
|
||
import { MAX_CARED_PER_FAMILY } from '@/constants/family'
|
||
import { ROUTES } from '@/constants/routes'
|
||
import { navigateBack, navigateTo, reLaunch } from '@/utils/navigation'
|
||
import { showToast } from '@/utils/toast'
|
||
import styles from './detail.module.scss'
|
||
|
||
// 成员显示名:家庭内昵称优先,未设置回落微信昵称
|
||
const memberName = (m: HomeMember): string => m.nickName ?? m.userNickName ?? '成员'
|
||
|
||
// 关爱对象联系人摘要:最多显示前 2 位姓名,其余以 +N 概括;未填则不显示
|
||
const contactsSummary = (c: CareMember): string => {
|
||
const list = c.contacts ?? []
|
||
if (list.length === 0) return ''
|
||
const head = list.slice(0, 2).map((ct) => ct.name).join('、')
|
||
const rest = list.length > 2 ? ` 等 ${list.length} 人` : ''
|
||
return `${head}${rest}`
|
||
}
|
||
|
||
export default function FamilyDetail() {
|
||
const router = useRouter()
|
||
const familyId = router.params.id ?? ''
|
||
const isInviteEnter = router.params.invite === '1'
|
||
const token = useAppSelector((s) => s.auth.token)
|
||
const myUserId = useAppSelector((s) => s.auth.userId)
|
||
|
||
const [loading, setLoading] = useState(true)
|
||
const [joining, setJoining] = useState(false)
|
||
const [family, setFamily] = useState<HomeInfo | null>(null)
|
||
const [members, setMembers] = useState<HomeMember[]>([])
|
||
const [caredList, setCaredList] = useState<CareMember[]>([])
|
||
|
||
const load = async () => {
|
||
// 分享卡直达本页且未登录:先去登录,登录后回跳本页
|
||
if (!token) {
|
||
const target = encodeURIComponent(`${ROUTES.FAMILY_DETAIL}?id=${familyId}&invite=1`)
|
||
reLaunch(`${ROUTES.LOGIN}?redirect=${target}`)
|
||
return
|
||
}
|
||
setLoading(true)
|
||
try {
|
||
const [home, memberList, careList] = await Promise.all([
|
||
getHomeDetail(familyId),
|
||
getHomeMemberList(familyId),
|
||
getCareMemberList(familyId)
|
||
])
|
||
setFamily(home)
|
||
setMembers(memberList)
|
||
// 上限判定以关爱对象实际列表为准,家庭卡计数仅展示
|
||
setCaredList(careList)
|
||
} catch {
|
||
setFamily(null)
|
||
} finally {
|
||
setLoading(false)
|
||
}
|
||
}
|
||
|
||
// 从添加表单返回时刷新;受邀进入且尚未是成员时自动加入(跳过手动点击步骤)
|
||
useDidShow(() => {
|
||
load().then(() => {
|
||
if (
|
||
!isInviteEnter || joining || myUserId == null ||
|
||
members.length === 0 || members.some((m) => m.memberId === myUserId)
|
||
) return
|
||
autoJoin(familyId)
|
||
})
|
||
})
|
||
|
||
// 受邀直达:已登录但非成员时自动加入,无需手点
|
||
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(() => ({
|
||
title: `${inviterName()} 邀请你加入家庭圈「${family?.name ?? ''}」`,
|
||
path: `${ROUTES.FAMILY_DETAIL}?id=${familyId}&invite=1`
|
||
}))
|
||
|
||
const addCared = () => {
|
||
navigateTo(`${ROUTES.FAMILY_CONTACT_ADD}?familyId=${familyId}`)
|
||
}
|
||
|
||
if (loading) {
|
||
return (
|
||
<View className={styles.page}>
|
||
<Navbar title="关爱对象信息" variant="hero" />
|
||
<View className={styles.stateWrap}><Loading /></View>
|
||
</View>
|
||
)
|
||
}
|
||
|
||
if (!family) {
|
||
return (
|
||
<View className={styles.page}>
|
||
<Navbar title="关爱对象信息" variant="hero" />
|
||
<StateView
|
||
status="error"
|
||
mode="list"
|
||
text="该家庭不存在"
|
||
retryText="返回列表"
|
||
onRetry={() => navigateBack()}
|
||
/>
|
||
</View>
|
||
)
|
||
}
|
||
|
||
const caredCount = caredList.length
|
||
const canAdd = caredCount < MAX_CARED_PER_FAMILY
|
||
const stub = (tip: string) => () => showToast(tip)
|
||
|
||
return (
|
||
<View className={styles.page}>
|
||
<Navbar title="关爱对象信息" variant="hero" />
|
||
|
||
<View className={styles.body}>
|
||
<FamilyCard family={family} />
|
||
|
||
{/* 添加关爱对象卡:达上限后灰化静态 */}
|
||
<View
|
||
className={`${styles.addCared} ${canAdd ? '' : styles.addCaredDisabled}`}
|
||
hoverClass={canAdd ? styles.addCaredPressed : 'none'}
|
||
onClick={canAdd ? addCared : undefined}
|
||
>
|
||
<View className={`${styles.addCaredIcon} ${canAdd ? '' : styles.addCaredIconDisabled}`}>
|
||
<Text
|
||
className={`${styles.addCaredIconText} ${canAdd ? '' : styles.addCaredIconTextDisabled}`}
|
||
>
|
||
+
|
||
</Text>
|
||
</View>
|
||
<Text className={`${styles.addCaredText} ${canAdd ? '' : styles.addCaredTextDisabled}`}>
|
||
{canAdd ? `+ 最多可添加 ${MAX_CARED_PER_FAMILY} 人` : '已达上限'}
|
||
</Text>
|
||
</View>
|
||
|
||
<View className={styles.section}>
|
||
<Text className={styles.sectionTitle}>关爱对象</Text>
|
||
{caredCount === 0 ? (
|
||
<Text className={styles.sectionEmpty}>暂无关爱对象,点击上方卡片添加</Text>
|
||
) : (
|
||
<ListRowGroup>
|
||
{caredList.map((c) => (
|
||
<ListRow
|
||
key={c.memberId}
|
||
label={c.name}
|
||
value={contactsSummary(c)}
|
||
arrow
|
||
onClick={() =>
|
||
navigateTo(`${ROUTES.FAMILY_CONTACT_DETAIL}?familyId=${familyId}&memberId=${c.memberId}`)
|
||
}
|
||
/>
|
||
))}
|
||
</ListRowGroup>
|
||
)}
|
||
</View>
|
||
|
||
<View className={styles.section}>
|
||
<Text className={styles.sectionTitle}>家庭成员</Text>
|
||
{members.length === 0 ? (
|
||
<Text className={styles.sectionEmpty}>暂无其他成员</Text>
|
||
) : (
|
||
<ListRowGroup>
|
||
{members.map((m) => (
|
||
<ListRow key={m.memberId} label={memberName(m)} value={m.role === 'OWNER' ? '群主' : '成员'} />
|
||
))}
|
||
</ListRowGroup>
|
||
)}
|
||
</View>
|
||
|
||
<View className={styles.section}>
|
||
<ListRowGroup>
|
||
<ListRow label="家庭编号" value={family.homeId} onClick={stub('复制成功(占位)')} arrow />
|
||
{/* open-type=share 的 Button 铺满整行做命中区,样式与普通 ListRow 一致 */}
|
||
<Button
|
||
className={styles.shareRow}
|
||
hoverClass={styles.shareRowPressed}
|
||
openType="share"
|
||
>
|
||
<Text className={styles.shareLabel}>邀请他人</Text>
|
||
<Text className={styles.shareArrow}>›</Text>
|
||
</Button>
|
||
<ListRow label="转让群主" arrow onClick={stub('转让功能即将上线')} />
|
||
<ListRow label="修改群昵称" arrow onClick={stub('修改昵称功能即将上线')} />
|
||
</ListRowGroup>
|
||
</View>
|
||
</View>
|
||
</View>
|
||
)
|
||
}
|