style: 网页端流转树卡片 UI 优化

- 时间精确到分钟(去 split 截断)
- 主线/分支标签改为卡片左上角与状态标签并排
- 操作人前加用户小图标
- 日志入口去掉浅蓝条块,改右下角文本链接 + 蓝色 > 箭头
This commit is contained in:
2026-09-01 14:10:35 +08:00
parent 547c113b09
commit 9d1e6c8466

View File

@ -3,7 +3,7 @@
*/
import { memo, useMemo, useState, useEffect } from "react";
import { Image } from "antd";
import { FileText, X } from "lucide-react";
import { FileText, User, X } from "lucide-react";
import type { TaskResponse } from "../../types/api";
import { TASK_STATUS } from "../../types/api";
import { getStatusConfig } from "../../constants/task";
@ -111,26 +111,31 @@ const SlimCard = memo(function SlimCard({
return (
<div className={`relative shrink-0 rounded-lg border bg-white ${sz.card} ${active ? "border-blue-400 ring-1 ring-blue-100" : "border-gray-200 opacity-75"} ${legacy ? "border-orange-300 animate-pulse" : ""} ${task.is_rework ? "border-l-red-500 border-l-2" : ""}`}>
<div className={`absolute ${sz.badge} rounded font-bold text-white ${main ? "bg-blue-500" : "bg-purple-500"}`}>{main ? "主线" : "分支"}</div>
<p className={`${sz.title} font-bold text-gray-800 truncate`}>{task.task_name}</p>
{/* 左上角:主线/分支标签 + 状态标签并排 */}
<div className={`${sz.metaRow} flex items-center gap-1`}>
<span className={`rounded px-1.5 py-px font-bold text-white ${main ? "bg-blue-500" : "bg-purple-500"}`}>{main ? "主线" : "分支"}</span>
<span className={`rounded-full ${sz.status} font-medium ${cfg.bg} ${cfg.text}`}>{cfg.label}</span>
{/* 在库任务不单独显示负责人,由下方"转入在库"统一展示实际操作人 */}
</div>
<p className={`${sz.title} font-bold text-gray-800 truncate`}>{task.task_name}</p>
{/* 操作人(带用户图标)+ 在库转入人 */}
<div className={`${sz.metaRow} flex items-center gap-1`}>
{!isWarehouse && (
<span className={`${sz.assignee} text-gray-400 truncate`}>{assigneeName || task.assignee_id || "—"}</span>
<span className={`${sz.assignee} text-gray-400 truncate inline-flex items-center gap-0.5`}>
<User className="h-2.5 w-2.5 shrink-0" />{assigneeName || task.assignee_id || "—"}
</span>
)}
{/* 📥 在库任务:显示实际执行"转入在库"的操作人(任务负责人) */}
{isWarehouse && task.assignee_id && (
<span className={`${sz.sub} text-emerald-600`}>📥 : {assigneeName || task.assignee_id}</span>
)}
</div>
{/* 单行时间 */}
{/* 单行时间(精确到分钟) */}
<p className={`${sz.time} text-gray-300`}>
{fmtTime(task.created_at).split(" ")[0]}
{task.completed_at ? `${fmtTime(task.completed_at).split(" ")[0]}` : " → 至今"}
{fmtTime(task.created_at)}
{task.completed_at ? `${fmtTime(task.completed_at)}` : " → 至今"}
</p>
{legacy && <p className={`${sz.sub} text-orange-500`}>: {assigneeName || (findParent(task)?.assignee_id) || "历史任务"}</p>}
{isNestedSpawn && <p className={`${sz.sub} text-purple-500`}>: {findParent(task)?.assignee_id || "—"}</p>}
{/* 📥 在库任务:显示实际执行"转入在库"的操作人(任务负责人) */}
{isWarehouse && task.assignee_id && (
<p className={`${sz.sub} text-emerald-600`}>📥 : {assigneeName || task.assignee_id}</p>
)}
{/* 操作按钮 */}
{active && isOwner && (
<div className={`${sz.btnRow} flex gap-1 border-t border-gray-100`}>
@ -145,10 +150,11 @@ const SlimCard = memo(function SlimCard({
<button onClick={() => onAction({ task, action: "transfer" })} className={`flex-1 rounded border border-orange-200 bg-orange-50 ${sz.btn} text-orange-600`}></button>
</div>
)}
{/* 记录 */}
{/* 记录:右下角普通文本链接 + 蓝色 > 箭头 */}
{task.records && task.records.length > 0 && (
<div onClick={(e) => { e.stopPropagation(); onViewRecords?.(task); }} className={`${sz.record} cursor-pointer rounded bg-blue-50 text-blue-600 hover:bg-blue-100`}>
<FileText className={`mr-0.5 inline ${sz.recordIcon}`} />{task.records.length}
<div onClick={(e) => { e.stopPropagation(); onViewRecords?.(task); }} className={`${sz.record} flex cursor-pointer items-center justify-end gap-0.5 text-blue-600 hover:text-blue-400`}>
<FileText className={sz.recordIcon} />{task.records.length}
<span className="font-bold text-blue-500"></span>
</div>
)}
</div>