import { useEffect, useState } from 'react' import { Layout, Card, Tabs, Button, Space, Typography, Tag, message, Spin, Modal, Select } from 'antd' import { ReloadOutlined, ThunderboltOutlined, BranchesOutlined, UserOutlined } from '@ant-design/icons' import { api } from './api' import type { SceneSchema } from './types' import { SceneForm } from './engine/SceneForm' import { TracePanel, ProvenancePanel, ModelViewer, OrdersEventsPanel } from './panels' const { Header, Sider, Content } = Layout const { Title, Text, Paragraph } = Typography export default function App() { const [scenes, setScenes] = useState([]) const [sceneId, setSceneId] = useState('') // 初始不硬编码,待场景列表返回后取首个可渲染场景 const [schema, setSchema] = useState(null) const [loading, setLoading] = useState(false) const [result, setResult] = useState(null) const [refreshKey, setRefreshKey] = useState(0) const [formKey, setFormKey] = useState(0) // 演示态主体(M5 principal):随手切换以观察权限"通过/拒绝"分支;管理员方可热重载/新增客户 const [principal, setPrincipal] = useState('backend_admin') // 拉取场景列表(首个可渲染场景兜底选中;已有选择则保留,以便热重载后停留在当前场景) const loadScenes = () => api.scenes().then((list) => { setScenes(list) setSceneId((cur) => cur || list.find((s: any) => s.hasTemplate)?.sceneId || '') }).catch(() => message.error('无法连接引擎(8080),请先启动后端')) useEffect(() => { loadScenes() }, []) useEffect(() => { if (!sceneId) return setLoading(true); setResult(null) api.sceneSchema(sceneId).then(setSchema).catch((e) => message.error('加载场景失败:' + e.message)).finally(() => setLoading(false)) }, [sceneId, formKey]) async function reloadModels() { try { const r = await api.reload(principal) message.success(r.message) await loadScenes() // 重新拉取场景列表:模板增删 / hasTemplate 变化即时反映到侧栏 setFormKey((k) => k + 1) // 强制重新拉取当前场景 schema + 重挂载表单 } catch (e: any) { message.error('热重载失败:' + e.message) } } const onExecuted = (r: any) => { setResult(r); if (r.success) setRefreshKey((k) => k + 1) } return (
本体驱动 DDD+EDA · 元数据引擎 Demo 改 YAML → 页面与行为随之变