fix(小宝预警): 调整详情证据区布局
This commit is contained in:
@@ -233,6 +233,7 @@ function XiaobaoWarningContent() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function XiaobaoWarningDetailPanel({ risk, onNavigate }: { risk: XiaobaoVersionRisk; onNavigate: () => void }) {
|
function XiaobaoWarningDetailPanel({ risk, onNavigate }: { risk: XiaobaoVersionRisk; onNavigate: () => void }) {
|
||||||
|
const [detailTab, setDetailTab] = useState<'reasons' | 'silent' | 'evidence'>('reasons');
|
||||||
const evidence = risk.dailyEvidence;
|
const evidence = risk.dailyEvidence;
|
||||||
const evidenceItems = [
|
const evidenceItems = [
|
||||||
...(evidence?.todayDeliveries ?? []),
|
...(evidence?.todayDeliveries ?? []),
|
||||||
@@ -293,21 +294,38 @@ function XiaobaoWarningDetailPanel({ risk, onNavigate }: { risk: XiaobaoVersionR
|
|||||||
)}
|
)}
|
||||||
</Section>
|
</Section>
|
||||||
|
|
||||||
<div className="grid gap-5 xl:grid-cols-2">
|
|
||||||
<Section title="发版预测">
|
<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="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">
|
<p className="flex items-center gap-1.5">
|
||||||
<CalendarClock className="h-4 w-4 text-[var(--ink-muted)]" />
|
<CalendarClock className="h-4 w-4 text-[var(--ink-muted)]" />
|
||||||
期望发版:{formatDateTime(risk.expectedReleaseDate)}
|
期望发版:{formatDateTime(risk.expectedReleaseDate)}
|
||||||
</p>
|
</p>
|
||||||
<p className="mt-1">预测可发:{formatDateTime(risk.forecastReleaseDate)}</p>
|
<p>预测可发:{formatDateTime(risk.forecastReleaseDate)}</p>
|
||||||
<p className="mt-1">{risk.trend.summary}</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>
|
</div>
|
||||||
</Section>
|
</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) => (
|
{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">
|
<div className="flex items-center justify-between gap-3">
|
||||||
<p className="text-[12px] font-medium text-[var(--ink)]">{reason.title}</p>
|
<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>
|
<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>
|
<p className="mt-1 text-[12px] leading-5 text-[var(--ink-soft)]">{reason.detail}</p>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</Section>
|
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="grid gap-5 xl:grid-cols-2">
|
{detailTab === 'silent' && (
|
||||||
<Section title="日报与活动证据">
|
<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-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="静默风险">
|
|
||||||
{risk.silentRisks.length === 0 ? <Empty text="暂无静默风险" /> : risk.silentRisks.map((item, index) => (
|
{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">
|
<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="text-[12px] font-medium text-amber-900">{item.title}</p>
|
||||||
<p className="mt-1 text-[12px] leading-5 text-amber-800">{item.detail}</p>
|
<p className="mt-1 text-[12px] leading-5 text-amber-800">{item.detail}</p>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</Section>
|
|
||||||
</div>
|
</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>
|
</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 }) {
|
function Section({ title, children }: { title: string; children: React.ReactNode }) {
|
||||||
return (
|
return (
|
||||||
<section>
|
<section>
|
||||||
|
|||||||
Reference in New Issue
Block a user