import { useEffect, useState } from 'react' import { useSearchParams } from 'react-router-dom' import type { Device, Publication } from '../../../shared/sharing' import { Button } from './ui/button' import { StatusBadge } from './ui/status-badge' const panel = 'space-y-4 rounded-2xl border border-white/10 bg-[var(--panel)] p-4 sm:p-5' const muted = 'text-sm leading-6 text-[var(--text-muted)]' const control = 'mt-1 w-full min-w-0 rounded-lg border border-white/10 bg-[var(--control)] p-2 text-sm focus-visible:outline-2' type Directory = { devices: Device[]; publications: Publication[] } type LoadState = { status: 'loading' } | { status: 'error'; message: string } | { status: 'loaded'; data: Directory } export function LocalSharing() { const [params, setParams] = useSearchParams() const [attempt, setAttempt] = useState(0) const [state, setState] = useState({ status: 'loading' }) const deviceId = params.get('device') ?? '' const kind = params.get('kind') ?? '' const status = params.get('status') ?? '' const query = params.get('q') ?? '' useEffect(() => { const controller = new AbortController() async function load(resource: string, label: string): Promise { const response = await fetch(`/api/v1/sharing/${resource}`, { signal: controller.signal }) if (!response.ok) { const error = await response.json().catch(() => null) throw new Error(`${label}加载失败(HTTP ${response.status})${typeof error?.code === 'string' ? ` · ${error.code}` : ''}${typeof error?.requestId === 'string' ? ` · 请求 ID:${error.requestId}` : ''}`) } return response.json() as Promise } Promise.all([ load>('devices', '设备'), load>('publications', '发布记录') ]).then(([devices, publications]) => { if (!controller.signal.aborted) setState({ status: 'loaded', data: { ...devices, ...publications } }) }).catch((error: unknown) => { if (!controller.signal.aborted) setState({ status: 'error', message: error instanceof Error ? error.message : '请求失败' }) }) return () => controller.abort() }, [attempt]) const reload = () => { setState({ status: 'loading' }); setAttempt((value) => value + 1) } const update = (key: string, value: string) => { const next = new URLSearchParams(params) if (value) next.set(key, value) else next.delete(key) setParams(next, { replace: true }) } return <>

此页读取当前服务的真实设备和发布元数据,与其他页签的模拟用户、组织数据独立。请在 GoodBuddy 应用中心登记设备、发布或撤销共享内容,再刷新此目录。

登记不代表设备在线;已发布不代表可以调用。来源模式仅为声明,服务器未同步正文。知识权限分别记录声明,尚未执行授权校验;此页不搜索正文、读取原文、下载文件或调用能力。

{state.status === 'loading' &&

正在加载本地服务目录…

} {state.status === 'error' &&

本地服务目录加载失败

{state.message}

请确认本地服务可访问后重试。

} {state.status === 'loaded' && (() => { const { devices, publications } = state.data const visible = publications.filter((item) => (!deviceId || item.deviceId === deviceId) && (!kind || item.kind === kind) && (!status || item.status === status) && [item.name, item.description, item.id, item.deviceId, devices.find((device) => device.id === item.deviceId)?.name].join(' ').toLowerCase().includes(query.trim().toLowerCase())) return <>

当前结果:{visible.length} 项本地发布记录

登记设备 · {devices.length}

{!devices.length &&

尚无登记设备。请在 GoodBuddy 应用中心连接此服务并登记设备。

} {devices.filter((device) => !deviceId || device.id === deviceId).map((device) =>

{device.name}

设备标识:{device.id} · 平台:{device.platform} · 应用版本:{device.appVersion}

登记时间:

)}
{!publications.length ?

尚无发布记录

请在 GoodBuddy 应用中心发布能力或知识库,再刷新目录。

: !visible.length &&

没有符合条件的本地记录

请调整条件或清除筛选。

} {visible.map((item) =>

{item.name}

{item.description || '未提供描述。'}

类型:{item.kind === 'knowledge' ? '知识库' : '能力'} · 提供设备:{devices.find((device) => device.id === item.deviceId)?.name ?? item.deviceId}

发布标识:{item.id} · 设备标识:{item.deviceId}

来源声明:{item.sourceMode === 'server' ? '服务器' : '设备'}(仅描述来源,不代表内容已同步或可取用)

发布时间: · 更新时间:

{item.kind === 'knowledge' &&

知识权限声明(各自独立,未执行授权校验)

搜索:{item.permissions.search ? '声明允许' : '未声明允许'}读取原文:{item.permissions.read ? '声明允许' : '未声明允许'}下载:{item.permissions.download ? '声明允许' : '未声明允许'}
}
)} })()} }