fix(小宝预警): 调整详情证据区布局
This commit is contained in:
@@ -233,6 +233,7 @@ function XiaobaoWarningContent() {
|
||||
}
|
||||
|
||||
function XiaobaoWarningDetailPanel({ risk, onNavigate }: { risk: XiaobaoVersionRisk; onNavigate: () => void }) {
|
||||
const [detailTab, setDetailTab] = useState<'reasons' | 'silent' | 'evidence'>('reasons');
|
||||
const evidence = risk.dailyEvidence;
|
||||
const evidenceItems = [
|
||||
...(evidence?.todayDeliveries ?? []),
|
||||
@@ -293,21 +294,38 @@ function XiaobaoWarningDetailPanel({ risk, onNavigate }: { risk: XiaobaoVersionR
|
||||
)}
|
||||
</Section>
|
||||
|
||||
<div className="grid gap-5 xl:grid-cols-2">
|
||||
<Section title="发版预测">
|
||||
<div className="rounded-lg border border-[var(--line)] bg-[var(--bg-card)] p-4 text-[13px] leading-6 text-[var(--ink-soft)]">
|
||||
<div className="grid gap-3 md:grid-cols-3">
|
||||
<p className="flex items-center gap-1.5">
|
||||
<CalendarClock className="h-4 w-4 text-[var(--ink-muted)]" />
|
||||
期望发版:{formatDateTime(risk.expectedReleaseDate)}
|
||||
</p>
|
||||
<p className="mt-1">预测可发:{formatDateTime(risk.forecastReleaseDate)}</p>
|
||||
<p className="mt-1">{risk.trend.summary}</p>
|
||||
<p>预测可发:{formatDateTime(risk.forecastReleaseDate)}</p>
|
||||
<p>预计延期:{risk.delayDays > 0 ? `${risk.delayDays}天` : '0天'}</p>
|
||||
</div>
|
||||
<p className="mt-3 border-t border-[var(--line)] pt-3">{risk.trend.summary}</p>
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
<Section title="风险原因">
|
||||
<Section title="风险证据">
|
||||
<div className="rounded-lg border border-[var(--line)] bg-[var(--bg-card)]">
|
||||
<div className="flex flex-wrap gap-1 border-b border-[var(--line)] bg-[var(--bg-subtle)] p-2">
|
||||
<TabButton active={detailTab === 'reasons'} onClick={() => setDetailTab('reasons')}>
|
||||
风险原因 {risk.reasons.length}
|
||||
</TabButton>
|
||||
<TabButton active={detailTab === 'silent'} onClick={() => setDetailTab('silent')}>
|
||||
静默风险 {risk.silentRisks.length}
|
||||
</TabButton>
|
||||
<TabButton active={detailTab === 'evidence'} onClick={() => setDetailTab('evidence')}>
|
||||
日报与活动证据 {evidenceItems.length}
|
||||
</TabButton>
|
||||
</div>
|
||||
<div className="min-h-[220px] p-3">
|
||||
{detailTab === 'reasons' && (
|
||||
<div className="space-y-2">
|
||||
{risk.reasons.length === 0 ? <Empty text="暂无风险原因" /> : risk.reasons.map((reason) => (
|
||||
<div key={reason.key} className="rounded-lg border border-[var(--line)] bg-[var(--bg-card)] p-3">
|
||||
<div key={reason.key} className="rounded-lg border border-[var(--line)] bg-[var(--bg)] p-3">
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<p className="text-[12px] font-medium text-[var(--ink)]">{reason.title}</p>
|
||||
<span className="rounded-full bg-[var(--bg-subtle)] px-2 py-0.5 text-[10px] text-[var(--ink-muted)]">{reason.severity}</span>
|
||||
@@ -315,29 +333,34 @@ function XiaobaoWarningDetailPanel({ risk, onNavigate }: { risk: XiaobaoVersionR
|
||||
<p className="mt-1 text-[12px] leading-5 text-[var(--ink-soft)]">{reason.detail}</p>
|
||||
</div>
|
||||
))}
|
||||
</Section>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="grid gap-5 xl:grid-cols-2">
|
||||
<Section title="日报与活动证据">
|
||||
{evidenceItems.length === 0 ? <Empty text="暂无近期日报或活动证据" /> : evidenceItems.map((item) => (
|
||||
<div key={item.id} className="rounded-lg border border-[var(--line)] bg-[var(--bg-card)] p-3">
|
||||
<p className="text-[12px] font-medium text-[var(--ink)]">{item.title}</p>
|
||||
<p className="mt-1 text-[12px] leading-5 text-[var(--ink-soft)]">{item.summary}</p>
|
||||
<p className="mt-1 text-[10px] text-[var(--ink-muted)]">{formatDateTime(item.occurredAt)}</p>
|
||||
</div>
|
||||
))}
|
||||
</Section>
|
||||
|
||||
<Section title="静默风险">
|
||||
{detailTab === 'silent' && (
|
||||
<div className="space-y-2">
|
||||
{risk.silentRisks.length === 0 ? <Empty text="暂无静默风险" /> : risk.silentRisks.map((item, index) => (
|
||||
<div key={`${item.key}-${item.itemId ?? index}`} className="rounded-lg border border-amber-200 bg-amber-50 p-3">
|
||||
<p className="text-[12px] font-medium text-amber-900">{item.title}</p>
|
||||
<p className="mt-1 text-[12px] leading-5 text-amber-800">{item.detail}</p>
|
||||
</div>
|
||||
))}
|
||||
</Section>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{detailTab === 'evidence' && (
|
||||
<div className="space-y-2">
|
||||
{evidenceItems.length === 0 ? <Empty text="暂无近期日报或活动证据" /> : evidenceItems.map((item) => (
|
||||
<div key={item.id} className="rounded-lg border border-[var(--line)] bg-[var(--bg)] p-3">
|
||||
<p className="text-[12px] font-medium text-[var(--ink)]">{item.title}</p>
|
||||
<p className="mt-1 text-[12px] leading-5 text-[var(--ink-soft)]">{item.summary}</p>
|
||||
<p className="mt-1 text-[10px] text-[var(--ink-muted)]">{formatDateTime(item.occurredAt)}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</Section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -406,6 +429,22 @@ function FilterButton({ active, onClick, children }: { active: boolean; onClick:
|
||||
);
|
||||
}
|
||||
|
||||
function TabButton({ active, onClick, children }: { active: boolean; onClick: () => void; children: React.ReactNode }) {
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
onClick={onClick}
|
||||
className={`h-8 rounded-md px-3 text-[12px] transition-colors ${
|
||||
active
|
||||
? 'bg-[var(--bg-card)] text-[var(--accent)] shadow-sm'
|
||||
: 'text-[var(--ink-soft)] hover:bg-[var(--bg-card)] hover:text-[var(--ink)]'
|
||||
}`}
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
function Section({ title, children }: { title: string; children: React.ReactNode }) {
|
||||
return (
|
||||
<section>
|
||||
|
||||
Reference in New Issue
Block a user