feat(home): 当前家庭选择持久化,三页共享恢复逻辑统一

- 新增 store/currentHome.ts:storage 持久化 homeId,resolveCurrentHome
  优先恢复已存选择、失效回落第一条并重新落盘
- 设备列表/房间管理/添加设备三页统一走 resolveCurrentHome,
  切换家庭时同步 setCurrentHomeId
- 详情页隐藏 BLE 网络配置/设备配置入口(联调未完成),清理无用跳转函数
- 心率波形纵轴最小跨度 20 BPM,避免小波动被归一化放大成满幅曲线
This commit is contained in:
ozh 2026-09-21 14:42:36 +08:00
parent 05d46368d1
commit 213d61bbf6
6 changed files with 42 additions and 7 deletions

View File

@ -4,6 +4,9 @@ import Taro from '@tarojs/taro'
const V_PADDING = 8 const V_PADDING = 8
const HEIGHT = 110 const HEIGHT = 110
// 纵轴最小跨度(BPM):心率生理波动常只有个位数,若按 min/max 归一化会把
// 数 BPM 的微小起伏放大成满幅曲线,视觉误导为剧烈波动
const MIN_SPAN = 20
interface Props { interface Props {
points: number[] points: number[]
@ -63,8 +66,13 @@ export function VitalWave({ points, canvasId = 'vitalWave' }: Props) {
function drawWave(canvasId: string, w: number, h: number, pts: number[]) { function drawWave(canvasId: string, w: number, h: number, pts: number[]) {
const ctx = Taro.createCanvasContext(canvasId) const ctx = Taro.createCanvasContext(canvasId)
const min = Math.min(...pts) let min = Math.min(...pts)
const max = Math.max(...pts) let max = Math.max(...pts)
if (max - min < MIN_SPAN) {
const mid = (min + max) / 2
min = mid - MIN_SPAN / 2
max = mid + MIN_SPAN / 2
}
const span = max - min || 1 const span = max - min || 1
const xAt = (i: number) => (pts.length <= 1 ? 0 : (i / (pts.length - 1)) * w) const xAt = (i: number) => (pts.length <= 1 ? 0 : (i / (pts.length - 1)) * w)
const yAt = (v: number) => h - V_PADDING - ((v - min) / span) * (h - V_PADDING * 2) const yAt = (v: number) => h - V_PADDING - ((v - min) / span) * (h - V_PADDING * 2)

View File

@ -8,6 +8,7 @@ import { StateView } from '@/components/state-view'
import { addHomeDevice } from '@/api/homeDevice' import { addHomeDevice } from '@/api/homeDevice'
import { getHomeList, type HomeInfo } from '@/api/home' import { getHomeList, type HomeInfo } from '@/api/home'
import { getRoomList, type HomeRoom } from '@/api/homeRoom' import { getRoomList, type HomeRoom } from '@/api/homeRoom'
import { resolveCurrentHome, setCurrentHomeId } from '@/store/currentHome'
import { showToast } from '@/utils/toast' import { showToast } from '@/utils/toast'
import { navigateBack } from '@/utils/navigation' import { navigateBack } from '@/utils/navigation'
import styles from './add.module.scss' import styles from './add.module.scss'
@ -33,9 +34,10 @@ export default function DeviceAdd() {
setLoadError(false) setLoadError(false)
getHomeList() getHomeList()
.then(async (list) => { .then(async (list) => {
const first = list[0] ?? null const first = resolveCurrentHome(list)
if (cancelled) return if (cancelled) return
setHome(first) setHome(first)
if (first) setCurrentHomeId(first.homeId)
if (!first) return if (!first) return
const roomList = await getRoomList(first.homeId) const roomList = await getRoomList(first.homeId)
if (cancelled) return if (cancelled) return

View File

@ -86,7 +86,7 @@ export default function Detail() {
const fmt = (v: number | undefined): string => (v === undefined || v === null ? '--' : String(v)) const fmt = (v: number | undefined): string => (v === undefined || v === null ? '--' : String(v))
const goBleConfig = () => navigateTo(ROUTES.DEVICE_BLE_CONFIG) const goBleConfig = () => navigateTo(ROUTES.DEVICE_BLE_CONFIG)
const goWifiConfig = () => navigateTo(ROUTES.DEVICE_BLE_CONFIG) void goBleConfig
return ( return (
<View className={styles.page}> <View className={styles.page}>
@ -157,8 +157,10 @@ export default function Detail() {
<ListRow label="设备型号" value={deviceModel || '-'} /> <ListRow label="设备型号" value={deviceModel || '-'} />
<ListRow label="设备 ID" value={installId || '-'} /> <ListRow label="设备 ID" value={installId || '-'} />
<ListRow label="安装房间" value={device?.roomName ?? '-'} /> <ListRow label="安装房间" value={device?.roomName ?? '-'} />
{/* BLE 配置流程联调未完成,暂隐藏两个配置入口
<ListRow label="网络配置" arrow onClick={goWifiConfig} /> <ListRow label="网络配置" arrow onClick={goWifiConfig} />
<ListRow label="设备配置" arrow onClick={goBleConfig} /> <ListRow label="设备配置" arrow onClick={goBleConfig} />
*/}
</ListRowGroup> </ListRowGroup>
</View> </View>
</View> </View>

View File

@ -9,6 +9,7 @@ import { BottomSheet } from '@/components/bottom-sheet'
import { getHomeDeviceList, unbindHomeDevice, type HomeDevice } from '@/api/homeDevice' import { getHomeDeviceList, unbindHomeDevice, type HomeDevice } from '@/api/homeDevice'
import { getRoomList, type HomeRoom } from '@/api/homeRoom' import { getRoomList, type HomeRoom } from '@/api/homeRoom'
import { getHomeList, type HomeInfo } from '@/api/home' import { getHomeList, type HomeInfo } from '@/api/home'
import { resolveCurrentHome, setCurrentHomeId } from '@/store/currentHome'
import { ROUTES } from '@/constants/routes' import { ROUTES } from '@/constants/routes'
import { navigateTo } from '@/utils/navigation' import { navigateTo } from '@/utils/navigation'
import { showToast } from '@/utils/toast' import { showToast } from '@/utils/toast'
@ -61,10 +62,11 @@ export default function DeviceList() {
try { try {
const list = await getHomeList() const list = await getHomeList()
setFamilies(list) setFamilies(list)
// 若当前未选中,默认选第一条 // 未选中时按持久化的 homeId 恢复,失效则回落第一条
setCurrentFamily((prev) => { setCurrentFamily((prev) => {
const next = prev ?? list[0] ?? null const next = prev ?? resolveCurrentHome(list)
if (next && next.homeId !== prev?.homeId) { if (next && next.homeId !== prev?.homeId) {
setCurrentHomeId(next.homeId)
setFilterRoomId('') setFilterRoomId('')
loadDevices(next.homeId) loadDevices(next.homeId)
loadRooms(next.homeId) loadRooms(next.homeId)
@ -154,6 +156,7 @@ export default function DeviceList() {
const confirmFamilySheet = () => { const confirmFamilySheet = () => {
if (pendingFamily && pendingFamily.homeId !== currentFamily?.homeId) { if (pendingFamily && pendingFamily.homeId !== currentFamily?.homeId) {
setCurrentFamily(pendingFamily) setCurrentFamily(pendingFamily)
setCurrentHomeId(pendingFamily.homeId)
setFilterRoomId('') setFilterRoomId('')
loadDevices(pendingFamily.homeId) loadDevices(pendingFamily.homeId)
loadRooms(pendingFamily.homeId) loadRooms(pendingFamily.homeId)

View File

@ -7,6 +7,7 @@ import { Empty } from '@/components/empty'
import { StateView } from '@/components/state-view' import { StateView } from '@/components/state-view'
import { BottomSheet } from '@/components/bottom-sheet' import { BottomSheet } from '@/components/bottom-sheet'
import { getHomeList, type HomeInfo } from '@/api/home' import { getHomeList, type HomeInfo } from '@/api/home'
import { resolveCurrentHome, setCurrentHomeId } from '@/store/currentHome'
import { import {
getRoomList, addRoom, updateRoom, deleteRoom, ROOM_SENCE_MAP, type HomeRoom getRoomList, addRoom, updateRoom, deleteRoom, ROOM_SENCE_MAP, type HomeRoom
} from '@/api/homeRoom' } from '@/api/homeRoom'
@ -45,8 +46,9 @@ export default function SceneSelect() {
setLoadError(false) setLoadError(false)
try { try {
const homes = await getHomeList() const homes = await getHomeList()
const first = homes[0] ?? null const first = resolveCurrentHome(homes)
setHome(first) setHome(first)
if (first) setCurrentHomeId(first.homeId)
if (!first) { if (!first) {
setList([]) setList([])
return return

18
src/store/currentHome.ts Normal file
View File

@ -0,0 +1,18 @@
import { storage } from '@/utils/storage'
import type { HomeInfo } from '@/api/home'
// 当前选中家庭持久化 key:设备列表 / 房间管理 / 添加设备三页共享
const KEY = 'currentHomeId'
export function setCurrentHomeId(homeId: string): void {
storage.set(KEY, homeId)
}
// 从家庭列表解析当前家庭:优先已持久化的选择,失效(不在列表,如切换账号)时回落第一条并重新落盘
export function resolveCurrentHome(homes: HomeInfo[]): HomeInfo | null {
if (homes.length === 0) return null
const stored = storage.get<string>(KEY)
const next = homes.find((h) => h.homeId === stored) ?? homes[0]
storage.set(KEY, next.homeId)
return next
}