REAL SHOWCASE SOURCEtabbed-workspace-clinical

2 个文件 · 127 行 · TypeScript

// ===== showcase/src/examples/components/tabbed_workspace.ts ===== import {  RenderButton,  RenderPageHeader,  RenderStackPanel,  RenderTabbedWorkspace,  RenderText,  RenderWrapPanel,  TabbedDocumentManager,} from 'ds-ui'import { createClinicalWorkspaceDocument } from './workspace_shared' export function createTabbedWorkspaceExample(): RenderStackPanel {  const manager = new TabbedDocumentManager()  const status = new RenderText('', { role: 'secondary' })  const workspace = new RenderTabbedWorkspace({    manager,    emptyTitle: '暂无打开的临床模块',    emptyDescription: '使用上方按钮打开患者总览、医嘱录入或检验结果。',    disposeManagerOnDispose: true,  })   const openDocument = (key: 'overview' | 'orders' | 'labs'): void => {    const definitions = {      overview: {        tabId: 'patient-overview',        title: '患者总览',        icon: 'window' as const,        content: createClinicalWorkspaceDocument('患者总览', '集中查看生命体征、诊断和当前治疗计划。'),      },      orders: {        tabId: 'medical-orders',        title: '医嘱录入',        icon: 'plus' as const,        dirty: true,        content: createClinicalWorkspaceDocument('医嘱录入', '未保存文档会在标签标题中显示 dirty 状态。', 'warning'),      },      labs: {        tabId: 'lab-results',        title: '检验结果',        icon: 'search' as const,        content: createClinicalWorkspaceDocument('检验结果', '查看最近检验数据和危急值处理状态。', 'success'),      },    }    const definition = definitions[key]    if (manager.hasDocument(definition.tabId)) manager.activateDocument(definition.tabId)    else manager.openDocument(definition)  }   manager.subscribe(() => {    status.text = `已打开 ${manager.documents.length} 个文档;当前:${manager.activeDocument?.title ?? '无'}。`  })  openDocument('overview')  openDocument('orders')  openDocument('labs')   const actions = new RenderWrapPanel({ spacing: 8, runSpacing: 8 })  actions.addChild(new RenderButton({ label: '患者总览', onClick: () => openDocument('overview') }))  actions.addChild(new RenderButton({ label: '医嘱录入', onClick: () => openDocument('orders') }))  actions.addChild(new RenderButton({ label: '检验结果', onClick: () => openDocument('labs') }))  actions.addChild(new RenderButton({    label: '下一个文档',    onClick: () => manager.activateRelativeDocument(1),  }))  actions.addChild(new RenderButton({    label: '保存当前',    variant: 'primary',    onClick: () => {      const active = manager.activeDocument      if (active) manager.updateDocument(active.tabId, { dirty: false })    },  }))  actions.addChild(new RenderButton({    label: '关闭当前',    onClick: () => { void manager.closeActiveDocument() },  }))   const panel = new RenderStackPanel({ orientation: 'vertical', spacing: 12, crossAxisAlignment: 'stretch' })  panel.addChild(new RenderPageHeader({    title: 'TabbedWorkspace 多文档临床工作区',    description: '管理文档打开、去重、激活、重排、dirty 状态、关闭保护和 Ctrl+Tab/Ctrl+W。',  }))  panel.addChild(actions)  panel.addChild(status)  panel.addChild(workspace, 1)  panel.padding = 18  return panel} // ===== showcase/src/examples/components/workspace_shared.ts ===== import {  RenderBadge,  RenderBorder,  RenderStackPanel,  RenderText,} from 'ds-ui' export function createClinicalWorkspaceDocument(  title: string,  description: string,  status: 'primary' | 'success' | 'warning' | 'danger' = 'primary',): RenderStackPanel {  const heading = new RenderStackPanel({ orientation: 'horizontal', spacing: 10, crossAxisAlignment: 'center' })  heading.addChild(new RenderBadge({ value: 'LIVE', status, compact: true }))  heading.addChild(new RenderText(title, { role: 'title', size: 'large', weight: 'semibold' }))   const metrics = new RenderStackPanel({ orientation: 'horizontal', spacing: 12, crossAxisAlignment: 'stretch' })  metrics.addChild(createMetric('患者', '李安然'), 1)  metrics.addChild(createMetric('就诊号', 'MZ20260717018'), 1)  metrics.addChild(createMetric('接诊医生', '林医生'), 1)   const panel = new RenderStackPanel({ orientation: 'vertical', spacing: 14, crossAxisAlignment: 'stretch' })  panel.addChild(heading)  panel.addChild(new RenderText(description, { role: 'secondary' }))  panel.addChild(metrics)  panel.padding = 18  return panel} function createMetric(label: string, value: string): RenderBorder {  const content = new RenderStackPanel({ orientation: 'vertical', spacing: 4 })  content.addChild(new RenderText(label, { role: 'secondary', size: 'small' }))  content.addChild(new RenderText(value, { role: 'title', weight: 'semibold' }))  return new RenderBorder({ background: 'panel', padding: 12, child: content })}