import { ArrowLeft, PlugZap } from "lucide-react"; import { useCallback, useEffect, useState } from "react"; import { platformApiClient } from "../api/client"; import type { GamePluginResponse } from "../api/types"; import { PageFrame } from "../components/PageFrame"; import { ScumOperationsPanel } from "../components/ScumOperationsPanel"; import { EmptyState, ErrorState, LoadingState } from "../components/StateViews"; import type { PageComponentProps } from "../contracts/page"; import { pluginBridgeManifestContractFromResponse } from "../contracts/pluginBridge"; import { resolveScumOperationsPageContract, scumOperationsPluginId, scumOperationsRouteKey } from "../contracts/scumOperations"; import { createPluginBridgeHostContext } from "../utils/pluginBridgeHost"; type PluginPageState = | { status: "loading" } | { status: "error"; reason: string } | { status: "ready"; plugin: GamePluginResponse }; interface PluginPageHostPageProps extends PageComponentProps { initialPlugin?: GamePluginResponse; } export function PluginPageHostPage({ params, onNavigate, initialPlugin }: PluginPageHostPageProps) { const pluginId = params.pluginId ?? ""; const routeKey = params.routeKey ?? ""; const serverId = params.serverId ?? ""; const [state, setState] = useState(() => initialPlugin ? { status: "ready", plugin: initialPlugin } : { status: "loading" }); const load = useCallback(async () => { if (!pluginId || !routeKey) { setState({ status: "error", reason: "插件页面路由缺少 pluginId 或 routeKey。" }); return; } setState({ status: "loading" }); try { const response = await platformApiClient.listGamePlugins(); const plugin = response.items.find((candidate) => candidate.id === pluginId); setState(plugin ? { status: "ready", plugin } : { status: "error", reason: "未找到已注册的插件声明。" }); } catch (error) { setState({ status: "error", reason: error instanceof Error ? error.message : "插件页面声明加载失败。" }); } }, [pluginId, routeKey]); useEffect(() => { if (!initialPlugin) { void load(); } }, [initialPlugin, load]); if (state.status === "loading") { return ; } if (state.status === "error") { return void load()} />; } const page = state.plugin.pages.find((candidate) => candidate.key === routeKey); if (!page) { return ; } const manifestContract = pluginBridgeManifestContractFromResponse(state.plugin); const hostContext = createPluginBridgeHostContext({ plugin: manifestContract, routeKey, serverInstanceId: serverId || undefined, themeTokens: { colorScheme: "dark", accentColor: "#7dd3fc" } }); const isScumOperations = state.plugin.id === scumOperationsPluginId && routeKey === scumOperationsRouteKey; const scumResolution = isScumOperations ? resolveScumOperationsPageContract(state.plugin, serverId) : null; return (
0 ? "success" : "warning" }, { label: "桥接动作", value: String(hostContext.bridgeActions.length), tone: hostContext.bridgeActions.length > 0 ? "success" : "warning" }, { label: "页面路由", value: routeKey, tone: "neutral" } ]} />

{scumResolution && !scumResolution.available && } {scumResolution?.available && (
命令目录 {scumResolution.contract.commands.length} 项,均来自插件 operations 页面声明 快照目录 {scumResolution.contract.snapshots.length} 项,按插件 schemaVersion 投影 查询模板 {scumResolution.contract.queryTemplates.length} 项,仅保留声明式 SQLite 模板引用
)} {!scumResolution && ( )}
{scumResolution?.available && }
); }