feat(网页端): 流转树在库任务显示『谁转入在库』

- TaskFlowView 在库/入库任务节点显示『📥 转入在库: 创建人中文名』
- TaskResponse 类型补 created_by 字段
This commit is contained in:
2026-08-31 17:20:47 +08:00
parent 0dea116faa
commit 6eb81953f5
2 changed files with 16 additions and 3 deletions

View File

@ -87,13 +87,14 @@ const SIZE_MAP = {
// 极简卡片
// ============================================================
const SlimCard = memo(function SlimCard({
task, assigneeName, active, legacy, onAction, currentUser, onViewRecords, rootMainId, size = "sm",
task, assigneeName, active, legacy, onAction, currentUser, onViewRecords, rootMainId, size = "sm", assigneeNames,
}: {
task: TaskResponse; assigneeName?: string; active: boolean; legacy?: boolean;
onAction: (t: ModalTarget) => void; currentUser?: { username?: string; role?: string } | null;
onViewRecords?: (t: TaskResponse) => void;
rootMainId?: string;
size?: "sm" | "lg";
assigneeNames?: Record<string, string>;
}) {
const cfg = getStatusConfig(task.status);
const sz = SIZE_MAP[size];
@ -101,6 +102,12 @@ const SlimCard = memo(function SlimCard({
const isManager = currentUser?.role === "SUPER_ADMIN" || currentUser?.role === "SUPERVISOR";
const main = isMain(task);
const isNestedSpawn = !main && rootMainId && task.parent_task_id !== rootMainId && !!task.parent_task_id;
// 📥 在库/入库任务:显示"谁转入在库"(创建该任务的人)
const isWarehouse = !!(
task.task_name?.includes("在库") ||
task.task_name?.includes("入库") ||
task.assignee_id === "virtual_warehouse"
);
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" : ""}`}>
@ -117,6 +124,10 @@ const SlimCard = memo(function SlimCard({
</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.created_by && (
<p className={`${sz.sub} text-emerald-600`}>📥 转入在库: {assigneeNames?.[task.created_by] || task.created_by}</p>
)}
{/* 操作按钮 */}
{active && isOwner && (
<div className={`${sz.btnRow} flex gap-1 border-t border-gray-100`}>
@ -191,7 +202,7 @@ export const TaskFlowView = memo(function TaskFlowView({ tasks, onAction, curren
const arrow = side === 'left'
? (<div className="flex items-center"><ArrowLeft color={isLegacy ? "#fdba74" : "#9ca3af"} big={big} /><div className={`${big ? "w-10 border-t-[3px]" : "w-6 border-t-2"} ${isLegacy ? "border-dashed border-orange-300" : "border-solid border-gray-400"}`} /></div>)
: (<div className="flex items-center"><div className={`${big ? "w-10 border-t-[3px]" : "w-6 border-t-2"} ${isLegacy ? "border-dashed border-orange-300" : "border-solid border-gray-400"}`} /><ArrowRight color={isLegacy ? "#fdba74" : "#9ca3af"} big={big} /></div>);
const card = <SlimCard task={node} active={active(node.status)} legacy={isLegacy} assigneeName={assigneeNames?.[node.assignee_id || ""]} onAction={onAction} currentUser={currentUser} onViewRecords={setRecordsTask} rootMainId={rootMainId} size={size} />;
const card = <SlimCard task={node} active={active(node.status)} legacy={isLegacy} assigneeName={assigneeNames?.[node.assignee_id || ""]} onAction={onAction} currentUser={currentUser} onViewRecords={setRecordsTask} rootMainId={rootMainId} size={size} assigneeNames={assigneeNames} />;
const kidsContainer = kids.length > 0 ? (
<div className={`flex flex-col gap-2 ${side === 'left' ? 'items-end' : 'items-start'}`}>
{kids.map(k => renderBranch(k, side, isLegacy, rootMainId))}
@ -251,7 +262,7 @@ export const TaskFlowView = memo(function TaskFlowView({ tasks, onAction, curren
{/* 中央 */}
<div className="shrink-0 z-10 relative">
<SlimCard task={mainTask} active={active(mainTask.status)}
assigneeName={assigneeNames?.[mainTask.assignee_id || ""]} onAction={onAction} currentUser={currentUser} onViewRecords={setRecordsTask} size={size} />
assigneeName={assigneeNames?.[mainTask.assignee_id || ""]} onAction={onAction} currentUser={currentUser} onViewRecords={setRecordsTask} size={size} assigneeNames={assigneeNames} />
{active(mainTask.status) && (
<div className={`absolute -top-1 -left-1 rounded-full bg-green-400 border-2 border-white ${size === "lg" ? "h-4 w-4" : "h-3 w-3"}`} />
)}

View File

@ -40,6 +40,8 @@ export interface TaskSummary {
export interface TaskResponse extends TaskSummary {
child_tasks: TaskResponse[];
records: TaskRecordResponse[];
/** 🔧 任务创建人(追溯谁转交/发起该工序),如"谁转入在库" */
created_by?: string | null;
}
export interface TaskRecordResponse {