feat(family,ui): Family.role 字段与 BottomSheet 底部抽屉组件

Family 接口加可选 role: '管理员' | '群主',SEED_DATA 各家庭填角色,addFamily/joinFamily 新建家庭默认 '群主'。新建 BottomSheet 通用底部抽屉组件(遮罩+圆角面板+handle+标题+关闭钮),用于智能设备页"切换家庭圈"弹层。
This commit is contained in:
ozh 2026-09-09 16:40:15 +08:00
parent 1f3c9c842a
commit d6333beda9
3 changed files with 109 additions and 6 deletions

View File

@ -13,6 +13,7 @@ export interface Family {
caredLabel: string caredLabel: string
address: string address: string
deviceCount: number deviceCount: number
role?: '管理员' | '群主' // 当前用户在家庭圈的角色,弹层显示用
} }
export interface EmergencyContact { export interface EmergencyContact {
@ -55,10 +56,10 @@ interface FamilyData {
const SEED_DATA: FamilyData = { const SEED_DATA: FamilyData = {
families: [ families: [
{ id: '846443196293189', name: 'JollyPlace', memberCount: 6, caredCount: 1, caredLabel: 'Jay', address: '--', deviceCount: 24 }, { id: '846443196293189', name: 'JollyPlace', memberCount: 6, caredCount: 1, caredLabel: 'Jay', address: '--', deviceCount: 24, role: '管理员' },
{ id: '735201884550361', name: '我的家庭圈', memberCount: 4, caredCount: 0, caredLabel: '--', address: '--', deviceCount: 1 }, { id: '735201884550361', name: '我的家庭圈', memberCount: 4, caredCount: 0, caredLabel: '--', address: '--', deviceCount: 1, role: '群主' },
{ id: '628934071266852', name: '康乐之家', memberCount: 1, caredCount: 0, caredLabel: '--', address: '--', deviceCount: 21 }, { id: '628934071266852', name: '康乐之家', memberCount: 1, caredCount: 0, caredLabel: '--', address: '--', deviceCount: 21, role: '群主' },
{ id: '519027468331740', name: '平安庭院', memberCount: 1, caredCount: 0, caredLabel: '--', address: '--', deviceCount: 0 } { id: '519027468331740', name: '平安庭院', memberCount: 1, caredCount: 0, caredLabel: '--', address: '--', deviceCount: 0, role: '群主' }
], ],
cared: [ cared: [
{ {
@ -137,7 +138,8 @@ export async function addFamily(name: string): Promise<Family> {
caredCount: 0, caredCount: 0,
caredLabel: '--', caredLabel: '--',
address: '--', address: '--',
deviceCount: 0 deviceCount: 0,
role: '群主'
} }
data.families = [...data.families, family] data.families = [...data.families, family]
saveData(data) saveData(data)
@ -155,7 +157,8 @@ export async function joinFamily(code: string): Promise<Family> {
caredCount: 0, caredCount: 0,
caredLabel: '--', caredLabel: '--',
address: '--', address: '--',
deviceCount: 0 deviceCount: 0,
role: '群主'
} }
data.families = [...data.families, family] data.families = [...data.families, family]
saveData(data) saveData(data)

View File

@ -0,0 +1,69 @@
.mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: $color-mask;
z-index: 100;
}
.panel {
position: fixed;
left: 0;
right: 0;
bottom: 0;
background: $color-bg-white;
border-radius: $radius-lg $radius-lg 0 0;
padding-bottom: env(safe-area-inset-bottom, 0);
z-index: 101;
max-height: 80vh;
display: flex;
flex-direction: column;
}
.handle {
width: 80px;
height: 8px;
border-radius: $radius-pill;
background: $color-bg-disabled;
margin: 16px auto;
}
.header {
position: relative;
padding: 16px 32px 24px;
display: flex;
align-items: center;
justify-content: center;
}
.title {
font-size: 34px;
font-weight: 600;
color: $color-text;
}
.close {
position: absolute;
right: 24px;
top: 50%;
transform: translateY(-50%);
width: 60px;
height: 60px;
display: flex;
align-items: center;
justify-content: center;
}
.closeIcon {
font-size: 40px;
color: $color-text-secondary;
line-height: 1;
}
.body {
flex: 1;
overflow-y: auto;
padding: 0 32px 32px;
}

View File

@ -0,0 +1,31 @@
import { View, Text } from '@tarojs/components'
import type { ReactNode } from 'react'
import styles from './index.module.scss'
interface Props {
visible: boolean
title?: string
onClose: () => void
children: ReactNode
}
export function BottomSheet({ visible, title, onClose, children }: Props) {
if (!visible) return null
return (
<>
<View className={styles.mask} onClick={onClose} />
<View className={styles.panel}>
<View className={styles.handle} />
{title && (
<View className={styles.header}>
<Text className={styles.title}>{title}</Text>
<View className={styles.close} onClick={onClose}>
<Text className={styles.closeIcon}>×</Text>
</View>
</View>
)}
<View className={styles.body}>{children}</View>
</View>
</>
)
}