21c8764993
- LayoutGallery 升级:每模板卡片 = 真实渲染缩略图(scale 0.4),点选看完整预览 - demoPageFrom:由 preview.demoBlocks 构造可渲染 demo 页(预览即真实) - playground 新增 dashboard 布局 + stat-grid widget;app-shell 验证 DefaultLayout 兜底 - 三个模板(admin/dashboard/app-shell)全部 live 渲染验证通过
103 lines
3.4 KiB
TypeScript
103 lines
3.4 KiB
TypeScript
/**
|
|
* playground 业务 widget(真实 React 组件)
|
|
* 演示:注册表 widget → React 组件 → 渲染内核装配
|
|
*/
|
|
import React from 'react'
|
|
|
|
/** 页头 */
|
|
export function PageHeader({ title, subtitle }: { title?: string; subtitle?: string }): React.ReactElement {
|
|
return React.createElement(
|
|
'header',
|
|
{ style: { marginBottom: 16 } },
|
|
React.createElement('h1', { style: { margin: '0 0 4px', fontSize: 20 } }, title ?? '未命名'),
|
|
subtitle ? React.createElement('p', { style: { margin: 0, color: '#6b7280', fontSize: 13 } }, subtitle) : null,
|
|
)
|
|
}
|
|
|
|
/** 数据表格 */
|
|
export function DataTable({
|
|
columns = [],
|
|
rows = [],
|
|
}: {
|
|
columns?: Array<{ key: string; title: string }>
|
|
rows?: Array<Record<string, unknown>>
|
|
}): React.ReactElement {
|
|
return React.createElement(
|
|
'table',
|
|
{ style: { borderCollapse: 'collapse', width: '100%', fontSize: 13 } },
|
|
React.createElement(
|
|
'thead',
|
|
{},
|
|
React.createElement(
|
|
'tr',
|
|
{},
|
|
...(columns as Array<{ key: string; title: string }>).map((c) =>
|
|
React.createElement(
|
|
'th',
|
|
{ key: c.key, style: { textAlign: 'left', padding: '6px 8px', borderBottom: '1px solid #d1d5db' } },
|
|
c.title,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
React.createElement(
|
|
'tbody',
|
|
{},
|
|
...(rows as Array<Record<string, unknown>>).map((r, i) =>
|
|
React.createElement(
|
|
'tr',
|
|
{ key: i },
|
|
...(columns as Array<{ key: string; title: string }>).map((c) =>
|
|
React.createElement('td', { key: c.key, style: { padding: '6px 8px', borderBottom: '1px solid #f3f4f6' } }, String(r[c.key] ?? '')),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
)
|
|
}
|
|
|
|
/** 导航菜单 */
|
|
export function NavMenu({ items = [] }: { items?: Array<{ label: string; active?: boolean }> }): React.ReactElement {
|
|
return React.createElement(
|
|
'ul',
|
|
{ style: { listStyle: 'none', margin: 0, padding: 0 } },
|
|
...(items as Array<{ label: string; active?: boolean }>).map((it, i) =>
|
|
React.createElement(
|
|
'li',
|
|
{ key: i, style: { padding: '6px 8px', borderRadius: 6, marginBottom: 2, background: it.active ? '#e0e7ff' : 'transparent' } },
|
|
it.label,
|
|
),
|
|
),
|
|
)
|
|
}
|
|
|
|
/** 统计卡片(仪表盘用) */
|
|
export function StatCard({
|
|
label,
|
|
value,
|
|
delta,
|
|
}: {
|
|
label?: string
|
|
value?: unknown
|
|
delta?: string
|
|
}): React.ReactElement {
|
|
return React.createElement(
|
|
'div',
|
|
{ style: { border: '1px solid #e5e7eb', borderRadius: 8, padding: 16, background: '#fff' } },
|
|
React.createElement('div', { style: { fontSize: 12, color: '#6b7280' } }, label ?? ''),
|
|
React.createElement('div', { style: { fontSize: 24, fontWeight: 700, margin: '4px 0' } }, String(value ?? '-')),
|
|
delta ? React.createElement('div', { style: { fontSize: 12, color: delta.startsWith('-') ? '#dc2626' : '#16a34a' } }, delta) : null,
|
|
)
|
|
}
|
|
|
|
/** 指标格子容器(dashboard 布局的内容区 demo 用) */
|
|
export function StatGrid({ stats = [] }: { stats?: Array<{ label?: string; value?: unknown; delta?: string }> }): React.ReactElement {
|
|
return React.createElement(
|
|
'div',
|
|
{ style: { display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(160px, 1fr))', gap: 12 } },
|
|
...(stats as Array<{ label?: string; value?: unknown; delta?: string }>).map((s, i) =>
|
|
React.createElement(StatCard, { key: i, label: s.label, value: s.value, delta: s.delta }),
|
|
),
|
|
)
|
|
}
|