OntologyCanvas.tsx 2.55 KB
import { useEffect, useState } from 'react'
import { Spin, Alert, Button, Typography } from 'antd'
import { ReloadOutlined } from '@ant-design/icons'
import { loadOntology } from '../ontology/build'
import type { Ontology } from '../ontology/types'
import NetworkGraph from './NetworkGraph'
import ERDiagram from './ERDiagram'
import ProcessDiagram from './ProcessDiagram'

const { Title, Text } = Typography

const META: Record<string, { title: string; desc: string }> = {
  network: { title: '本体网络图', desc: '对象 + 行为 + 规则 + 事件的关联网络(M1/M2/ME/MetaRule 动态合成)' },
  er: { title: '数据结构图(ER)', desc: '聚合根/子实体的字段结构、外键引用与组合关系(M1 动态合成)' },
  process: { title: '场景流程图(BPMN)', desc: '端到端场景流程(M4 flowSteps → bpmn-elk-layout 自动布局 → bpmn-js 渲染)' },
}

/** 可视化画布宿主:加载一次本体 IR,全高渲染选中的视图。 */
export function OntologyCanvas({ which }: { which: 'network' | 'er' | 'process' }) {
  const [onto, setOnto] = useState<Ontology | null>(null)
  const [err, setErr] = useState('')
  const [key, setKey] = useState(0)

  useEffect(() => {
    setOnto(null); setErr('')
    loadOntology().then(setOnto).catch((e) => setErr(String(e?.message || e)))
  }, [key])

  const m = META[which]
  return (
    <div style={{ padding: 16 }}>
      <div style={{ display: 'flex', alignItems: 'center', marginBottom: 10 }}>
        <div>
          <Title level={4} style={{ margin: 0 }}>{m.title}</Title>
          <Text type="secondary" style={{ fontSize: 13 }}>{m.desc}</Text>
        </div>
        <div style={{ flex: 1 }} />
        <Button icon={<ReloadOutlined />} onClick={() => setKey((k) => k + 1)}>刷新</Button>
      </div>
      <div style={{ position: 'relative', height: 'calc(100vh - 190px)', minHeight: 420, border: '1px solid #f0f0f0', borderRadius: 10, background: '#fff', overflow: 'hidden' }}>
        {err ? (
          <div style={{ padding: 24 }}><Alert type="error" showIcon message="加载本体失败" description={err} /></div>
        ) : !onto ? (
          <div style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center' }}><Spin tip="合成本体视图…"><div style={{ width: 80, height: 40 }} /></Spin></div>
        ) : which === 'network' ? (
          <NetworkGraph ontology={onto} />
        ) : which === 'er' ? (
          <ERDiagram ontology={onto} />
        ) : (
          <ProcessDiagram ontology={onto} />
        )}
      </div>
    </div>
  )
}