合入家庭共享与设备消息能力

This commit is contained in:
stu2not
2026-05-26 17:12:51 +08:00
parent 555a2ddc16
commit 050bc17f79
40 changed files with 3072 additions and 165 deletions

View File

@@ -4,9 +4,11 @@ import { getCurrentUserId, getToken, handleUnauthorized } from './session'
const BASE_URL = API_BASE_URL
const REQUEST_TIMEOUT_MS = 10000
const DEVICE_UNAVAILABLE_MESSAGE = '设备不在线或处于休眠中,暂时无法执行该操作'
const ERROR_DETAIL_MAP: Record<string, string> = {
'Request failed': '请求失败',
'device is already bound, unbind it before binding again': '设备已绑定,请先解绑后再重新绑定',
'设备不在线或在休眠中': DEVICE_UNAVAILABLE_MESSAGE,
}
class ApiError extends Error {
@@ -71,4 +73,5 @@ async function request<T>(
}
export { request, ApiError, BASE_URL }
export { DEVICE_UNAVAILABLE_MESSAGE }
export { getCurrentUserId, getToken }

View File

@@ -6,6 +6,8 @@ export interface DeviceStatus {
child_id?: number | null
child_name?: string | null
sleep_mode?: number | null
manual_sleep_mode?: number | null
schedule_suppressed_until?: string | null
disable_time_start?: string | null
disable_time_end?: string | null
timezone?: string | null

View File

@@ -0,0 +1,71 @@
import { request } from './api'
export interface FamilyMember {
user_id: number
nickname?: string | null
avatar_url?: string | null
role: 'owner' | 'member'
is_owner: boolean
joined_at?: string | null
}
export interface FamilyMemberListResponse {
device_id: string
max_members: number
total: number
current_user_role: 'owner' | 'member'
items: FamilyMember[]
}
export interface FamilyInvitation {
invite_token: string
device_id: string
child_id?: number | null
child_name?: string | null
status: number
expires_at: string
}
export interface FamilyInvitationCreateResponse {
invite_token: string
device_id: string
expires_at: string
}
export interface FamilyInvitationAcceptResponse {
device_id: string
child_id?: number | null
child_name?: string | null
}
export async function getFamilyMembers(deviceId: string): Promise<FamilyMemberListResponse> {
return request<FamilyMemberListResponse>(`/banban/family/devices/${deviceId}/members`)
}
export async function createFamilyInvitation(deviceId: string): Promise<FamilyInvitationCreateResponse> {
return request<FamilyInvitationCreateResponse>(`/banban/family/devices/${deviceId}/invitations`, {
method: 'POST',
})
}
export async function getFamilyInvitation(inviteToken: string): Promise<FamilyInvitation> {
return request<FamilyInvitation>(`/banban/family/invitations/${inviteToken}`)
}
export async function acceptFamilyInvitation(inviteToken: string): Promise<FamilyInvitationAcceptResponse> {
return request<FamilyInvitationAcceptResponse>(`/banban/family/invitations/${inviteToken}/accept`, {
method: 'POST',
})
}
export async function removeFamilyMember(deviceId: string, memberUserId: number): Promise<void> {
return request<void>(`/banban/family/devices/${deviceId}/members/${memberUserId}`, {
method: 'DELETE',
})
}
export async function leaveFamily(deviceId: string): Promise<void> {
return request<void>(`/banban/family/devices/${deviceId}/me`, {
method: 'DELETE',
})
}