REAL SHOWCASE SOURCEoverlay-feedback

1 个文件 · 158 行 · TypeScript

// ===== showcase/src/examples/components/overlay_feedback.ts ===== import {  NotificationManager,  RenderBorder,  RenderButton,  RenderDrawer,  RenderLoadingHost,  RenderModal,  RenderPageHeader,  RenderStackPanel,  RenderText,  RenderTextBox,  RenderWrapPanel,} from 'ds-ui'import type { ShowcaseExample } from '../../showcase_example' export function createOverlayFeedbackExample(): ShowcaseExample {  const notifications = new NotificationManager()  const status = new RenderText('选择一种反馈方式,观察阻断范围与交互语义。', { role: 'secondary' })   const modal = new RenderModal({    title: '确认提交',    content: '提交后将进入审核流程,是否继续?',    buttons: [      { key: 'cancel', label: '取消' },      { key: 'submit', label: '提交', primary: true },    ],    onClose: key => {      status.text = key === 'submit' ? '已确认提交。' : '已取消提交。'    },  })   const detailsModal = new RenderModal({    title: '错误详情',    content: '请求未完成,请检查网络连接后重试。\n\n错误编号:DEMO-1001',    buttons: [{ key: 'close', label: '关闭', primary: true }],  })  const showErrorDetails = (errorCode: string): void => {    detailsModal.content = `请求未完成,请检查网络连接后重试。\n\n错误编号:${errorCode}`    detailsModal.show()  }   const drawerContent = new RenderStackPanel({ orientation: 'vertical', spacing: 12, crossAxisAlignment: 'stretch' })  drawerContent.addChild(new RenderText('患者详情', { role: 'title', weight: 'semibold' }))  drawerContent.addChild(new RenderTextBox({ value: '李安然', label: '姓名', readonly: true }))  drawerContent.addChild(new RenderTextBox({ value: '呼吸内科', label: '科室', readonly: true }))  drawerContent.addChild(new RenderText('Drawer 可以承载真实组件树,并保留底层页面上下文。', { role: 'secondary' }))  const drawer = new RenderDrawer({ title: '患者详情', side: 'right', width: 420, child: drawerContent })   const loadingPanel = new RenderStackPanel({ orientation: 'vertical', spacing: 8 })  loadingPanel.addChild(new RenderText('局部查询结果', { role: 'title', weight: 'semibold' }))  loadingPanel.addChild(new RenderText('生命体征、检验结果和处置建议仍保留原有布局。', { role: 'secondary' }))  const loadingContent = new RenderBorder({ background: 'muted', padding: 18, child: loadingPanel })  const loadingHost = new RenderLoadingHost({ child: loadingContent, text: '正在刷新患者数据…' })  let loading = false  let loadingButton!: RenderButton  loadingButton = new RenderButton({    label: '开启局部 Loading',    onClick: () => {      loading = !loading      loadingHost.setLoading(loading, loading ? '正在刷新患者数据…' : undefined)      loadingButton.label = loading ? '关闭局部 Loading' : '开启局部 Loading'      loadingButton.markNeedsLayout()      status.text = loading ? '当前只阻断查询结果区域。' : '局部查询已恢复交互。'    },  })   const actions = new RenderWrapPanel({ spacing: 10, runSpacing: 10 })  actions.addChild(new RenderButton({ label: '打开 Modal', variant: 'primary', onClick: () => modal.show() }))  actions.addChild(new RenderButton({ label: '打开 Drawer', onClick: () => drawer.show() }))  actions.addChild(new RenderButton({    label: '仅标题通知',    onClick: () => notifications.notify({ type: 'info', title: '操作已完成', duration: 0 }),  }))  actions.addChild(new RenderButton({ label: '成功通知', onClick: () => notifications.show('success', '保存成功', '病历内容已经保存。') }))  actions.addChild(new RenderButton({ label: '警告通知', onClick: () => notifications.show('warning', '网络较慢', '后台正在自动重试。', 5000) }))  actions.addChild(new RenderButton({    label: '可重试错误',    onClick: () => notifications.notify({      type: 'error',      title: '保存失败',      message: '网络连接异常,请重试。',      action: {        label: '重试',        onInvoke: () => { status.text = '已触发重试。' },      },    }),  }))  actions.addChild(new RenderButton({    label: '错误详情',    onClick: () => notifications.notify({      type: 'error',      title: '处理失败',      message: '错误编号:DEMO-1001',      action: { label: '查看详情', onInvoke: () => showErrorDetails('DEMO-1001') },    }),  }))  actions.addChild(new RenderButton({    label: '三条可查看错误',    onClick: () => {      for (const [index, errorCode] of ['DEMO-2001', 'DEMO-2002', 'DEMO-2003'].entries()) {        notifications.notify({          type: 'error',          title: `处理失败 ${index + 1}`,          message: `错误编号:${errorCode}`,          action: { label: '查看详情', onInvoke: () => showErrorDetails(errorCode) },        })      }    },  }))  actions.addChild(new RenderButton({    label: '长文本通知',    onClick: () => notifications.notify({      type: 'warning',      title: '部分数据未保存',      message: '由于服务端校验未通过,当前修改暂未保存,请检查输入后重试。',    }),  }))  actions.addChild(new RenderButton({    label: '三条堆叠',    onClick: () => {      notifications.notify({ type: 'info', title: '任务已开始', message: '正在准备数据。', duration: 0 })      notifications.notify({ type: 'warning', title: '检查到变更', message: '请留意未保存内容。', duration: 0 })      notifications.notify({ type: 'success', title: '检查完成', message: '共处理 3 项数据。', duration: 0 })    },  }))  actions.addChild(new RenderButton({    label: '异步操作',    onClick: () => notifications.notify({      type: 'info',      title: '可执行操作',      message: '点击提交后观察 pending 状态。',      action: {        label: '提交',        onInvoke: () => new Promise<void>(resolve => {          globalThis.setTimeout(() => {            status.text = '异步操作已完成。'            resolve()          }, 1200)        }),      },    }),  }))  actions.addChild(loadingButton)   const panel = new RenderStackPanel({ orientation: 'vertical', spacing: 18, crossAxisAlignment: 'stretch' })  panel.addChild(new RenderPageHeader({ title: 'Overlay 与反馈语义', description: '同一页面中对比确认、侧栏、非阻断通知和局部加载。' }))  panel.addChild(actions)  loadingHost.height = 150  panel.addChild(loadingHost)  panel.addChild(status)  panel.padding = 24  return {    content: panel,    afterMount: () => drawer.show(),  }}