feat: 全站 PageShell 设计系统与专业 UI 统一

- 新增 PageShell/PageTabs/ContentPanel/PageLoading/PageEmpty 页面骨架
- index.css 设计令牌文档化,布局令牌与纯色主按钮(去除渐变粉彩)
- 全站路由页接入 PageShell,云账单三 Tab 为标杆
- 主题体系:跟随系统 + 主流/开发者分组,新增 Dracula/Tokyo Night,One Dark 暖灰差异化
- 登录页/侧栏/顶栏去渐变光球,企业克制风
- 修复 AIAlertAnalyzer JSX 与构建依赖导入问题
This commit is contained in:
Logan committed 2026-07-01 12:45:38 +08:00
1 parent 1acb0c49af
commit e363ded445
213 files changed
+7148 -6818

No files matched your search

@@ -289,10 +289,10 @@ export function DeploymentEditService({ clusterCode, namespace, deploymentName,
if (loading) {
return (
<Card className="bg-slate-900 border-slate-800">
<Card className="dg-card">
<CardContent className="p-12 text-center">
<Loader2 className="h-6 w-6 animate-spin mx-auto text-slate-500" />
<p className="text-slate-500 mt-3 text-sm">加载中...</p>
<Loader2 className="h-6 w-6 animate-spin mx-auto dg-text-muted" />
<p className="dg-text-muted mt-3 text-sm">加载中...</p>
</CardContent>
</Card>
);
@@ -301,20 +301,20 @@ export function DeploymentEditService({ clusterCode, namespace, deploymentName,
return (
<div className="space-y-4">
{/* Selector 提示 */}
<Card className="bg-slate-900/50 border-slate-800">
<Card className="dg-card">
<CardContent className="p-3">
<div className="flex items-center gap-2 text-xs text-slate-400">
<Network className="h-3.5 w-3.5 text-blue-400" />
<div className="flex items-center gap-2 text-xs dg-text-secondary">
<Network className="h-3.5 w-3.5 dg-text-blue" />
<span>选择器:</span>
<div className="flex flex-wrap gap-1">
{Object.entries(selectorLabels).map(([k, v]) => (
<code key={k} className="bg-slate-800 px-1.5 py-0.5 rounded text-slate-300 text-[11px]">{k}={v}</code>
<code key={k} className="bg-[var(--dg-bg-tertiary)] px-1.5 py-0.5 rounded text-[var(--dg-text-secondary)] text-[11px]">{k}={v}</code>
))}
{Object.keys(selectorLabels).length === 0 && (
<span className="text-slate-600 italic">(无 selector)</span>
<span className="dg-text-muted italic">(无 selector)</span>
)}
</div>
<Button size="sm" variant="ghost" className="h-6 ml-auto text-xs text-slate-400" onClick={load}>
<Button size="sm" variant="ghost" className="h-6 ml-auto text-xs dg-text-secondary" onClick={load}>
<RefreshCw className="h-3 w-3 mr-1" />刷新
</Button>
</div>
@@ -322,15 +322,15 @@ export function DeploymentEditService({ clusterCode, namespace, deploymentName,
</Card>
{/* Services */}
<Card className="bg-slate-900 border-slate-800">
<Card className="dg-card">
<CardHeader className="pb-3">
<div className="flex items-center justify-between">
<CardTitle className="text-sm text-slate-200 flex items-center gap-2">
<Network className="h-4 w-4 text-blue-400" />
<CardTitle className="text-sm text-[var(--dg-text-primary)] flex items-center gap-2">
<Network className="h-4 w-4 dg-text-blue" />
Services
<Badge variant="outline" className="border-slate-700 text-slate-400">{matchedSvcs.length} 个关联</Badge>
<Badge variant="outline" className="border-[var(--dg-border)] dg-text-secondary">{matchedSvcs.length} 个关联</Badge>
</CardTitle>
<Button size="sm" variant="outline" className="h-7 border-slate-700 text-slate-300 text-xs"
<Button size="sm" variant="outline" className="h-7 border-[var(--dg-border)] text-[var(--dg-text-secondary)] text-xs"
onClick={() => {
setSvcForm({ name: `${deploymentName}-svc`, type: 'ClusterIP', ports: [{ name: 'http', port: '8080', targetPort: '8080', protocol: 'TCP', nodePort: '' }] });
setShowCreate('service');
@@ -338,12 +338,12 @@ export function DeploymentEditService({ clusterCode, namespace, deploymentName,
<Plus className="h-3 w-3 mr-1" />创建 Service
</Button>
</div>
<p className="text-xs text-slate-500 mt-1">仅显示 selector 匹配此 Deployment 的关联 Service</p>
<p className="text-xs dg-text-muted mt-1">仅显示 selector 匹配此 Deployment 的关联 Service</p>
</CardHeader>
<CardContent className="pt-0">
{matchedSvcs.length === 0 && showCreate !== 'service' ? (
<div className="text-center py-6 text-slate-500 text-sm border border-dashed border-slate-800 rounded-lg">
<Network className="h-8 w-8 mx-auto mb-2 text-slate-700" />
<div className="text-center py-6 dg-text-muted text-sm border border-dashed border-[var(--dg-border)] rounded-lg">
<Network className="h-8 w-8 mx-auto mb-2 dg-text-muted" />
当前命名空间暂无关联 Service
</div>
) : (
@@ -351,18 +351,18 @@ export function DeploymentEditService({ clusterCode, namespace, deploymentName,
{matchedSvcs.map(svc => {
const matched = selectorMatches(svc.selector);
return (
<div key={svc.name} className={`rounded-lg border p-3 ${matched ? 'border-blue-700/50 bg-blue-950/20' : 'border-slate-800 bg-slate-950/30'}`}>
<div key={svc.name} className={`rounded-lg border p-3 ${matched ? 'border-blue-700/50 bg-blue-950/20' : 'border-[var(--dg-border)] bg-[var(--dg-bg-primary)]/30'}`}>
<div className="flex items-center gap-2 flex-wrap">
{matched ? <CheckCircle className="h-4 w-4 text-blue-400" /> : <Network className="h-4 w-4 text-slate-500" />}
<span className="text-sm font-semibold text-slate-200">{svc.name}</span>
<Badge variant="outline" className="border-slate-700 text-slate-400 text-[10px]">{svc.type}</Badge>
{matched ? <CheckCircle className="h-4 w-4 dg-text-blue" /> : <Network className="h-4 w-4 dg-text-muted" />}
<span className="text-sm font-semibold text-[var(--dg-text-primary)]">{svc.name}</span>
<Badge variant="outline" className="border-[var(--dg-border)] dg-text-secondary text-[10px]">{svc.type}</Badge>
{matched && <Badge className="bg-blue-500/20 text-blue-300 border-blue-500/30 text-[10px]">关联</Badge>}
<code className="text-[11px] text-slate-500 ml-auto">{svc.clusterIP}</code>
<Button size="sm" variant="ghost" className="h-6 text-xs text-emerald-400"
<code className="text-[11px] dg-text-muted ml-auto">{svc.clusterIP}</code>
<Button size="sm" variant="ghost" className="h-6 text-xs dg-text-green"
onClick={() => setVisualEditor({ resource: 'services', name: svc.name })}>
<Pencil className="h-3 w-3 mr-1" />编辑
</Button>
<Button size="sm" variant="ghost" className="h-6 w-6 p-0 text-red-400 hover:text-red-300"
<Button size="sm" variant="ghost" className="h-6 w-6 p-0 dg-text-red hover:dg-text-red"
title="删除 Service" onClick={() => deleteResource('service', svc.name)}>
<Trash2 className="h-3 w-3" />
</Button>
@@ -370,17 +370,17 @@ export function DeploymentEditService({ clusterCode, namespace, deploymentName,
{/* Ports */}
<div className="mt-2 flex flex-wrap gap-1.5 text-[11px]">
{svc.ports.map((p, i) => (
<code key={i} className="bg-slate-800/60 px-1.5 py-0.5 rounded text-slate-300">
{p.name && <span className="text-slate-500">{p.name}: </span>}
<code key={i} className="bg-[var(--dg-bg-tertiary)]/60 px-1.5 py-0.5 rounded text-[var(--dg-text-secondary)]">
{p.name && <span className="dg-text-muted">{p.name}: </span>}
{p.port}→{p.targetPort}{p.nodePort ? `/NodePort:${p.nodePort}` : ''}/{p.protocol}
</code>
))}
</div>
{/* Selector */}
<div className="mt-1 flex flex-wrap gap-1 text-[10px]">
<span className="text-slate-600">selector:</span>
<span className="dg-text-muted">selector:</span>
{Object.entries(svc.selector).map(([k, v]) => (
<code key={k} className="text-slate-500">{k}={v}</code>
<code key={k} className="dg-text-muted">{k}={v}</code>
))}
</div>
</div>
@@ -399,15 +399,15 @@ export function DeploymentEditService({ clusterCode, namespace, deploymentName,
{/* 基本信息 */}
<div className="grid grid-cols-2 gap-2">
<div>
<Label className="text-slate-500 text-[11px]">名称</Label>
<Label className="dg-text-muted text-[11px]">名称</Label>
<Input value={svcForm.name} onChange={e => setSvcForm(s => ({ ...s, name: e.target.value }))}
placeholder={`${deploymentName}-svc`}
className="h-7 mt-0.5 bg-slate-800 border-slate-700 text-slate-300 text-xs font-mono" />
className="h-7 mt-0.5 dg-input text-[var(--dg-text-secondary)] text-xs font-mono" />
</div>
<div>
<Label className="text-slate-500 text-[11px]">类型</Label>
<Label className="dg-text-muted text-[11px]">类型</Label>
<select value={svcForm.type} onChange={e => setSvcForm(s => ({ ...s, type: e.target.value }))}
className="h-7 mt-0.5 w-full bg-slate-800 border border-slate-700 rounded text-xs text-slate-300 px-2">
className="h-7 mt-0.5 w-full bg-[var(--dg-bg-tertiary)] border border-[var(--dg-border)] rounded text-xs text-[var(--dg-text-secondary)] px-2">
<option value="ClusterIP">ClusterIP</option>
<option value="NodePort">NodePort</option>
</select>
@@ -416,15 +416,15 @@ export function DeploymentEditService({ clusterCode, namespace, deploymentName,
{/* 快速预设 */}
<div>
<Label className="text-slate-500 text-[11px] mb-1 block">快速添加常用端口</Label>
<Label className="dg-text-muted text-[11px] mb-1 block">快速添加常用端口</Label>
<div className="flex gap-1.5">
{PORT_PRESETS.map(p => (
<button key={p.name} onClick={() => addPort(p)}
className="flex items-center gap-1 px-2 py-1 rounded text-[10px] font-medium
bg-slate-800 border border-slate-700 text-slate-300 hover:border-blue-500/50 hover:text-blue-300 transition-colors">
bg-[var(--dg-bg-tertiary)] border border-[var(--dg-border)] text-[var(--dg-text-secondary)] hover:border-blue-500/50 hover:text-blue-300 transition-colors">
<Zap className="h-2.5 w-2.5" />
{p.label}
<span className="text-slate-500 text-[9px]">{p.protocol} {p.port}:{p.targetPort}</span>
<span className="dg-text-muted text-[9px]">{p.protocol} {p.port}:{p.targetPort}</span>
</button>
))}
</div>
@@ -432,63 +432,63 @@ export function DeploymentEditService({ clusterCode, namespace, deploymentName,
{/* 端口列表 */}
<div className="space-y-2">
<Label className="text-slate-500 text-[11px]">
端口配置 <span className="text-slate-600">({svcForm.ports.length} 个端口)</span>
<Label className="dg-text-muted text-[11px]">
端口配置 <span className="dg-text-muted">({svcForm.ports.length} 个端口)</span>
</Label>
{svcForm.ports.map((p, i) => (
<div key={i} className="flex items-center gap-1.5 p-2 rounded bg-slate-800/50 border border-slate-700/50">
<div key={i} className="flex items-center gap-1.5 p-2 rounded bg-[var(--dg-bg-tertiary)]/50 border border-[var(--dg-border)]/50">
{/* 名称 */}
<Input value={p.name} onChange={e => updatePort(i, 'name', e.target.value)}
placeholder="http"
className="h-7 w-[72px] bg-slate-800 border-slate-700 text-slate-300 text-xs font-mono" />
className="h-7 w-[72px] dg-input text-[var(--dg-text-secondary)] text-xs font-mono" />
{/* 协议 */}
<select value={p.protocol} onChange={e => updatePort(i, 'protocol', e.target.value)}
className="h-7 bg-slate-800 border border-slate-700 rounded text-xs text-slate-300 px-1.5 w-16">
className="h-7 bg-[var(--dg-bg-tertiary)] border border-[var(--dg-border)] rounded text-xs text-[var(--dg-text-secondary)] px-1.5 w-16">
<option value="TCP">TCP</option>
<option value="UDP">UDP</option>
</select>
{/* port → targetPort */}
<Input value={p.port} onChange={e => updatePort(i, 'port', e.target.value)}
type="number" placeholder="port"
className="h-7 w-[72px] bg-slate-800 border-slate-700 text-slate-300 text-xs font-mono" />
<span className="text-slate-600 text-[10px]">→</span>
className="h-7 w-[72px] dg-input text-[var(--dg-text-secondary)] text-xs font-mono" />
<span className="dg-text-muted text-[10px]">→</span>
<Input value={p.targetPort} onChange={e => updatePort(i, 'targetPort', e.target.value)}
type="number" placeholder="targetPort"
className="h-7 w-[72px] bg-slate-800 border-slate-700 text-slate-300 text-xs font-mono" />
className="h-7 w-[72px] dg-input text-[var(--dg-text-secondary)] text-xs font-mono" />
{/* NodePort (仅 NodePort 类型) */}
{svcForm.type === 'NodePort' && (
<Input value={p.nodePort} onChange={e => updatePort(i, 'nodePort', e.target.value)}
type="number" placeholder="30000-32767"
className="h-7 w-[80px] bg-slate-800 border-slate-700 text-slate-300 text-xs font-mono" />
className="h-7 w-[80px] dg-input text-[var(--dg-text-secondary)] text-xs font-mono" />
)}
{/* 删除 */}
<Button size="icon" variant="ghost" className="h-6 w-6 text-slate-500 hover:text-red-400"
<Button size="icon" variant="ghost" className="h-6 w-6 dg-text-muted hover:dg-text-red"
onClick={() => removePort(i)} disabled={svcForm.ports.length <= 1}>
<Minus className="h-3 w-3" />
</Button>
</div>
))}
{/* 添加自定义端口 */}
<Button size="sm" variant="outline" className="h-7 w-full border-dashed border-slate-700 text-slate-400 text-xs"
<Button size="sm" variant="outline" className="h-7 w-full border-dashed border-[var(--dg-border)] dg-text-secondary text-xs"
onClick={() => addPort()}>
<Plus className="h-3 w-3 mr-1" />添加自定义端口
</Button>
</div>
{/* Selector 预览 */}
<div className="text-[10px] text-slate-500 border-t border-slate-700/50 pt-2">
<span className="text-slate-600">selector (自动检测): </span>
<div className="text-[10px] dg-text-muted border-t border-[var(--dg-border)]/50 pt-2">
<span className="dg-text-muted">selector (自动检测): </span>
{Object.keys(selectorLabels).length > 0 ? (
Object.entries(selectorLabels).map(([k, v]) => (
<code key={k} className="bg-slate-800 px-1 py-0.5 rounded text-slate-400 ml-1">{k}={v}</code>
<code key={k} className="bg-[var(--dg-bg-tertiary)] px-1 py-0.5 rounded dg-text-secondary ml-1">{k}={v}</code>
))
) : (
<span className="text-slate-600 italic">未检测到</span>
<span className="dg-text-muted italic">未检测到</span>
)}
</div>
<div className="flex justify-end gap-2 pt-1">
<Button size="sm" variant="ghost" className="h-7 text-xs text-slate-400" onClick={() => setShowCreate(null)}>取消</Button>
<Button size="sm" variant="ghost" className="h-7 text-xs dg-text-secondary" onClick={() => setShowCreate(null)}>取消</Button>
<Button size="sm" className="h-7 bg-blue-600 hover:bg-blue-700 text-xs" onClick={createService}>创建</Button>
</div>
</div>
@@ -497,15 +497,15 @@ export function DeploymentEditService({ clusterCode, namespace, deploymentName,
</Card>
{/* Ingresses */}
<Card className="bg-slate-900 border-slate-800">
<Card className="dg-card">
<CardHeader className="pb-3">
<div className="flex items-center justify-between">
<CardTitle className="text-sm text-slate-200 flex items-center gap-2">
<GitBranch className="h-4 w-4 text-purple-400" />
<CardTitle className="text-sm text-[var(--dg-text-primary)] flex items-center gap-2">
<GitBranch className="h-4 w-4 dg-text-purple" />
Ingresses (应用路由)
<Badge variant="outline" className="border-slate-700 text-slate-400">{matchedIngs.length}/{ingresses.length}</Badge>
<Badge variant="outline" className="border-[var(--dg-border)] dg-text-secondary">{matchedIngs.length}/{ingresses.length}</Badge>
</CardTitle>
<Button size="sm" variant="outline" className="h-7 border-slate-700 text-slate-300 text-xs"
<Button size="sm" variant="outline" className="h-7 border-[var(--dg-border)] text-[var(--dg-text-secondary)] text-xs"
onClick={() => {
setIngForm(s => ({ ...s, name: `${deploymentName}-ingress`, svcPort: String(matchedSvcs[0]?.ports[0]?.port || 80) }));
setShowCreate('ingress');
@@ -513,12 +513,12 @@ export function DeploymentEditService({ clusterCode, namespace, deploymentName,
<Plus className="h-3 w-3 mr-1" />创建 Ingress
</Button>
</div>
<p className="text-xs text-slate-500 mt-1">backend 指向关联 Service 的 Ingress 自动高亮</p>
<p className="text-xs dg-text-muted mt-1">backend 指向关联 Service 的 Ingress 自动高亮</p>
</CardHeader>
<CardContent className="pt-0">
{ingresses.length === 0 ? (
<div className="text-center py-6 text-slate-500 text-sm border border-dashed border-slate-800 rounded-lg">
<GitBranch className="h-8 w-8 mx-auto mb-2 text-slate-700" />
<div className="text-center py-6 dg-text-muted text-sm border border-dashed border-[var(--dg-border)] rounded-lg">
<GitBranch className="h-8 w-8 mx-auto mb-2 dg-text-muted" />
当前命名空间暂无 Ingress
</div>
) : (
@@ -526,17 +526,17 @@ export function DeploymentEditService({ clusterCode, namespace, deploymentName,
{ingresses.map(ing => {
const matched = matchedIngs.includes(ing);
return (
<div key={ing.name} className={`rounded-lg border p-3 ${matched ? 'border-purple-700/50 bg-purple-950/20' : 'border-slate-800 bg-slate-950/30'}`}>
<div key={ing.name} className={`rounded-lg border p-3 ${matched ? 'border-purple-700/50 bg-purple-950/20' : 'border-[var(--dg-border)] bg-[var(--dg-bg-primary)]/30'}`}>
<div className="flex items-center gap-2 flex-wrap">
{matched ? <CheckCircle className="h-4 w-4 text-purple-400" /> : <GitBranch className="h-4 w-4 text-slate-500" />}
<span className="text-sm font-semibold text-slate-200">{ing.name}</span>
<Badge variant="outline" className="border-slate-700 text-slate-400 text-[10px]">{ing.className}</Badge>
{matched ? <CheckCircle className="h-4 w-4 dg-text-purple" /> : <GitBranch className="h-4 w-4 dg-text-muted" />}
<span className="text-sm font-semibold text-[var(--dg-text-primary)]">{ing.name}</span>
<Badge variant="outline" className="border-[var(--dg-border)] dg-text-secondary text-[10px]">{ing.className}</Badge>
{matched && <Badge className="bg-purple-500/20 text-purple-300 border-purple-500/30 text-[10px]">关联</Badge>}
<Button size="sm" variant="ghost" className="h-6 text-xs text-emerald-400 ml-auto"
<Button size="sm" variant="ghost" className="h-6 text-xs dg-text-green ml-auto"
onClick={() => setVisualEditor({ resource: 'ingresses', name: ing.name })}>
<Pencil className="h-3 w-3 mr-1" />编辑
</Button>
<Button size="sm" variant="ghost" className="h-6 w-6 p-0 text-red-400 hover:text-red-300"
<Button size="sm" variant="ghost" className="h-6 w-6 p-0 dg-text-red hover:dg-text-red"
title="删除 Ingress" onClick={() => deleteResource('ingress', ing.name)}>
<Trash2 className="h-3 w-3" />
</Button>
@@ -545,10 +545,10 @@ export function DeploymentEditService({ clusterCode, namespace, deploymentName,
<div className="mt-2 space-y-1 text-[11px]">
{ing.rules.map((r, i) => (
<div key={i} className="flex items-start gap-1.5">
<Server className="h-3 w-3 text-slate-500 mt-0.5" />
<code className="text-slate-300">{r.host || '*'}</code>
<Server className="h-3 w-3 dg-text-muted mt-0.5" />
<code className="text-[var(--dg-text-secondary)]">{r.host || '*'}</code>
{r.paths.map((p, j) => (
<code key={j} className="bg-slate-800/60 px-1.5 py-0.5 rounded text-slate-400">
<code key={j} className="bg-[var(--dg-bg-tertiary)]/60 px-1.5 py-0.5 rounded dg-text-secondary">
{p.path} → {(p as any).backend?.service}:{(p as any).backend?.port}
</code>
))}
@@ -569,37 +569,37 @@ export function DeploymentEditService({ clusterCode, namespace, deploymentName,
</div>
<div className="grid grid-cols-2 gap-2">
<div>
<Label className="text-slate-500 text-[11px]">名称</Label>
<Label className="dg-text-muted text-[11px]">名称</Label>
<Input value={ingForm.name} onChange={e => setIngForm(s => ({ ...s, name: e.target.value }))}
placeholder={`${deploymentName}-ingress`}
className="h-7 mt-0.5 bg-slate-800 border-slate-700 text-slate-300 text-xs font-mono" />
className="h-7 mt-0.5 dg-input text-[var(--dg-text-secondary)] text-xs font-mono" />
</div>
<div>
<Label className="text-slate-500 text-[11px]">ingressClassName</Label>
<Label className="dg-text-muted text-[11px]">ingressClassName</Label>
<Input value={ingForm.className} onChange={e => setIngForm(s => ({ ...s, className: e.target.value }))}
placeholder="nginx"
className="h-7 mt-0.5 bg-slate-800 border-slate-700 text-slate-300 text-xs font-mono" />
className="h-7 mt-0.5 dg-input text-[var(--dg-text-secondary)] text-xs font-mono" />
</div>
<div>
<Label className="text-slate-500 text-[11px]">host (域名)</Label>
<Label className="dg-text-muted text-[11px]">host (域名)</Label>
<Input value={ingForm.host} onChange={e => setIngForm(s => ({ ...s, host: e.target.value }))}
placeholder="app.example.com"
className="h-7 mt-0.5 bg-slate-800 border-slate-700 text-slate-300 text-xs font-mono" />
className="h-7 mt-0.5 dg-input text-[var(--dg-text-secondary)] text-xs font-mono" />
</div>
<div>
<Label className="text-slate-500 text-[11px]">path</Label>
<Label className="dg-text-muted text-[11px]">path</Label>
<Input value={ingForm.path} onChange={e => setIngForm(s => ({ ...s, path: e.target.value }))}
placeholder="/"
className="h-7 mt-0.5 bg-slate-800 border-slate-700 text-slate-300 text-xs font-mono" />
className="h-7 mt-0.5 dg-input text-[var(--dg-text-secondary)] text-xs font-mono" />
</div>
<div>
<Label className="text-slate-500 text-[11px]">Service 端口</Label>
<Label className="dg-text-muted text-[11px]">Service 端口</Label>
<Input type="number" value={ingForm.svcPort} onChange={e => setIngForm(s => ({ ...s, svcPort: e.target.value }))}
className="h-7 mt-0.5 bg-slate-800 border-slate-700 text-slate-300 text-xs font-mono" />
className="h-7 mt-0.5 dg-input text-[var(--dg-text-secondary)] text-xs font-mono" />
</div>
</div>
<div className="flex justify-end gap-2 pt-1">
<Button size="sm" variant="ghost" className="h-7 text-xs text-slate-400" onClick={() => setShowCreate(null)}>取消</Button>
<Button size="sm" variant="ghost" className="h-7 text-xs dg-text-secondary" onClick={() => setShowCreate(null)}>取消</Button>
<Button size="sm" className="h-7 bg-purple-600 hover:bg-purple-700 text-xs" onClick={createIngress}>创建</Button>
</div>
</div>
@@ -619,7 +619,7 @@ export function DeploymentEditService({ clusterCode, namespace, deploymentName,
)}
<div className="flex justify-end gap-2 pt-2">
<Button size="sm" variant="outline" className="h-7 text-xs border-slate-700 text-slate-400" onClick={onCancel}>返回查看</Button>
<Button size="sm" variant="outline" className="h-7 text-xs border-[var(--dg-border)] dg-text-secondary" onClick={onCancel}>返回查看</Button>
</div>
</div>
);