fix: 概览排版优化 + 加班原因改为饼图
1. 参与人员/相关链接排版修复: - 去掉 grid-cols-3 不等高布局 - 改为:总耗时独占一行 + 参与人员/相关链接并排双列 - 不再有被撑高留空白的问题 2. 加班原因占比改为环形饼图: - SVG 环形饼图 + 右侧图例 - 各原因用不同颜色区分 - 图例显示名称 + 百分比 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -365,8 +365,7 @@ export default function VersionDetailPage() {
|
||||
})()}
|
||||
|
||||
{/* 4. 项目总耗时 + 参与人员 + 相关链接 */}
|
||||
<div className="grid grid-cols-3 gap-4">
|
||||
<div className="col-span-2 space-y-4">
|
||||
<div className="space-y-4">
|
||||
<div className="rounded-xl border border-[var(--line)] bg-[var(--bg-card)] p-4">
|
||||
{(() => {
|
||||
// 实际开始日期
|
||||
@@ -426,6 +425,7 @@ export default function VersionDetailPage() {
|
||||
);
|
||||
})()}
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div className="rounded-xl border border-[var(--line)] bg-[var(--bg-card)] p-4">
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<div className="text-[11px] text-[var(--ink-muted)] font-medium">参与人员</div>
|
||||
@@ -449,9 +449,7 @@ export default function VersionDetailPage() {
|
||||
);
|
||||
})()}
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-span-1">
|
||||
<div className="rounded-xl border border-[var(--line)] bg-[var(--bg-card)] p-4 h-full">
|
||||
<div className="rounded-xl border border-[var(--line)] bg-[var(--bg-card)] p-4">
|
||||
<div className="text-[11px] text-[var(--ink-muted)] mb-3 font-medium">相关链接</div>
|
||||
{(() => {
|
||||
const vPlansCompleted = plans.filter((p) => p.versionId === version.id && p.status === 'completed' && p.resultUrl);
|
||||
@@ -507,29 +505,60 @@ export default function VersionDetailPage() {
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* 加班原因占比 */}
|
||||
{/* 加班原因占比 - 饼图 */}
|
||||
<div className="rounded-xl border border-[var(--line)] bg-[var(--bg-card)] p-4">
|
||||
<div className="text-[11px] text-[var(--ink-muted)] mb-3 font-medium">加班原因占比</div>
|
||||
{reasonRanking.length === 0 ? (
|
||||
<span className="text-[12px] text-[var(--ink-muted)]">暂无数据</span>
|
||||
) : (
|
||||
<div className="space-y-2.5">
|
||||
{reasonRanking.map(([reasonId, hours]) => {
|
||||
<div className="flex items-center gap-4">
|
||||
{/* SVG 环形饼图 */}
|
||||
<svg viewBox="0 0 100 100" className="h-28 w-28 shrink-0">
|
||||
{(() => {
|
||||
const colors = ['#3b82f6', '#f97316', '#8b5cf6', '#10b981', '#ef4444', '#f59e0b', '#6366f1', '#ec4899'];
|
||||
let cumPercent = 0;
|
||||
return reasonRanking.map(([reasonId, hours], i) => {
|
||||
const percent = hours / reasonTotal;
|
||||
const startAngle = cumPercent * 360;
|
||||
cumPercent += percent;
|
||||
const endAngle = cumPercent * 360;
|
||||
const largeArc = percent > 0.5 ? 1 : 0;
|
||||
const startRad = ((startAngle - 90) * Math.PI) / 180;
|
||||
const endRad = ((endAngle - 90) * Math.PI) / 180;
|
||||
const x1 = 50 + 40 * Math.cos(startRad);
|
||||
const y1 = 50 + 40 * Math.sin(startRad);
|
||||
const x2 = 50 + 40 * Math.cos(endRad);
|
||||
const y2 = 50 + 40 * Math.sin(endRad);
|
||||
if (percent >= 1) {
|
||||
return <circle key={reasonId} cx="50" cy="50" r="40" fill={colors[i % colors.length]} />;
|
||||
}
|
||||
return (
|
||||
<path
|
||||
key={reasonId}
|
||||
d={`M 50 50 L ${x1} ${y1} A 40 40 0 ${largeArc} 1 ${x2} ${y2} Z`}
|
||||
fill={colors[i % colors.length]}
|
||||
/>
|
||||
);
|
||||
});
|
||||
})()}
|
||||
<circle cx="50" cy="50" r="22" fill="var(--bg-card)" />
|
||||
</svg>
|
||||
{/* 图例 */}
|
||||
<div className="space-y-1.5 flex-1">
|
||||
{reasonRanking.map(([reasonId, hours], i) => {
|
||||
const colors = ['#3b82f6', '#f97316', '#8b5cf6', '#10b981', '#ef4444', '#f59e0b', '#6366f1', '#ec4899'];
|
||||
const percent = Math.round((hours / reasonTotal) * 100);
|
||||
const reasonName = OVERTIME_REASON_LABEL[reasonId] || reasonId;
|
||||
return (
|
||||
<div key={reasonId}>
|
||||
<div className="flex items-center justify-between mb-1">
|
||||
<span className="text-[12px] text-[var(--ink-soft)]">{reasonName}</span>
|
||||
<span className="text-[11px] tabular-nums text-[var(--ink-muted)]">{percent}%</span>
|
||||
</div>
|
||||
<div className="h-1.5 rounded-full bg-[var(--bg-subtle)] overflow-hidden">
|
||||
<div className="h-full rounded-full bg-[var(--accent)] transition-all" style={{ width: `${percent}%` }} />
|
||||
</div>
|
||||
<div key={reasonId} className="flex items-center gap-2 text-[11px]">
|
||||
<span className="h-2.5 w-2.5 rounded-sm shrink-0" style={{ backgroundColor: colors[i % colors.length] }} />
|
||||
<span className="flex-1 text-[var(--ink-soft)] truncate">{reasonName}</span>
|
||||
<span className="tabular-nums text-[var(--ink-muted)]">{percent}%</span>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user