feat(P15B-1,P15B-6): 完成请假V1闭环
这个提交包含在:
@@ -20,6 +20,16 @@ import { StatusBadge } from "../components/common/StatusBadge";
|
||||
import { Button } from "../components/ui/button";
|
||||
import { Textarea } from "../components/ui/textarea";
|
||||
|
||||
function entityTitle(entityType: string | undefined) {
|
||||
if (entityType === "leave") {
|
||||
return "请假申请";
|
||||
}
|
||||
if (entityType === "reimbursement") {
|
||||
return "报销单";
|
||||
}
|
||||
return entityType || "业务单据";
|
||||
}
|
||||
|
||||
export function WorkflowTaskDetailPage() {
|
||||
const { taskId = "" } = useParams();
|
||||
const navigate = useNavigate();
|
||||
@@ -27,7 +37,7 @@ export function WorkflowTaskDetailPage() {
|
||||
const { permissions } = useAuth();
|
||||
|
||||
const [rejectComment, setRejectComment] = useState("请补充必要说明后重提");
|
||||
const [returnComment, setReturnComment] = useState("请补充报销说明并修正后重新提交");
|
||||
const [returnComment, setReturnComment] = useState("请补充必要信息并修正后重新提交");
|
||||
const [transferReason, setTransferReason] = useState("当前事项需转交对应审批人处理,请尽快处理。");
|
||||
const [selectedApprover, setSelectedApprover] = useState("");
|
||||
const [actionError, setActionError] = useState("");
|
||||
@@ -104,9 +114,7 @@ export function WorkflowTaskDetailPage() {
|
||||
}
|
||||
|
||||
if (detailQuery.isLoading) {
|
||||
return (
|
||||
<CardSkeleton lines={8} />
|
||||
);
|
||||
return <CardSkeleton lines={8} />;
|
||||
}
|
||||
|
||||
if (detailQuery.isError || !detailQuery.data) {
|
||||
@@ -133,6 +141,8 @@ export function WorkflowTaskDetailPage() {
|
||||
}
|
||||
|
||||
const detail = detailQuery.data;
|
||||
const isLeaveTask = detail.workflowInstance?.entityType === "leave";
|
||||
const canTransfer = allowedActions.has("transfer");
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
@@ -149,10 +159,30 @@ export function WorkflowTaskDetailPage() {
|
||||
<div className="card-std space-y-2 p-6 text-sm" data-testid="workflow-task-summary">
|
||||
<div>状态:<StatusBadge status={detail.task.status} /></div>
|
||||
<div>实例:{detail.workflowInstance?.id ?? "-"}</div>
|
||||
<div>报销单号:{detail.reimbursement?.formNumber ?? "-"}</div>
|
||||
<div>报销金额:{detail.reimbursement?.totalAmount ?? "-"}</div>
|
||||
<div>提交人:{detail.reimbursement?.submitter?.name ?? "-"}</div>
|
||||
<div>报销人:{detail.reimbursement?.owner?.name ?? "-"}</div>
|
||||
<div>对象类型:{entityTitle(detail.workflowInstance?.entityType)}</div>
|
||||
{detail.reimbursement ? (
|
||||
<>
|
||||
<div>报销单号:{detail.reimbursement.formNumber ?? "-"}</div>
|
||||
<div>报销金额:{detail.reimbursement.totalAmount ?? "-"}</div>
|
||||
<div>提交人:{detail.reimbursement.submitter?.name ?? "-"}</div>
|
||||
<div>报销人:{detail.reimbursement.owner?.name ?? "-"}</div>
|
||||
</>
|
||||
) : null}
|
||||
{detail.leaveRequest ? (
|
||||
<>
|
||||
<div>假期类型:{detail.leaveRequest.leaveType?.name ?? "-"}</div>
|
||||
<div>申请人:{detail.leaveRequest.owner?.name ?? "-"}</div>
|
||||
<div>
|
||||
时间段:
|
||||
{detail.leaveRequest.startDate ?? "-"} {detail.leaveRequest.startSession === "am" ? "上午" : "下午"}
|
||||
{" → "}
|
||||
{detail.leaveRequest.endDate ?? "-"} {detail.leaveRequest.endSession === "am" ? "上午" : "下午"}
|
||||
</div>
|
||||
<div>请假天数:{detail.leaveRequest.requestedDays}</div>
|
||||
<div>说明:{detail.leaveRequest.reason ?? "-"}</div>
|
||||
<div>附件:{detail.leaveRequest.attachment?.originalName ?? "-"}</div>
|
||||
</>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
<div className="card-std space-y-4 p-6">
|
||||
@@ -216,42 +246,44 @@ export function WorkflowTaskDetailPage() {
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2 rounded-lg border border-zinc-200 p-4">
|
||||
<p className="text-sm font-medium text-zinc-800">转审</p>
|
||||
<select
|
||||
className="select-std"
|
||||
data-testid="workflow-task-transfer-to-approver"
|
||||
onChange={(event) => setSelectedApprover(event.target.value)}
|
||||
value={selectedApprover}
|
||||
>
|
||||
<option value="">请选择目标审批人</option>
|
||||
{(approverQuery.data?.items ?? []).map((item) => (
|
||||
<option key={item.id} value={item.id}>
|
||||
{item.name} ({item.employeeNo})
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<Textarea
|
||||
data-testid="workflow-task-transfer-reason"
|
||||
onChange={(event) => setTransferReason(event.target.value)}
|
||||
rows={2}
|
||||
value={transferReason}
|
||||
/>
|
||||
<Button
|
||||
data-testid="workflow-task-transfer"
|
||||
variant="secondary"
|
||||
disabled={
|
||||
!allowedActions.has("transfer") ||
|
||||
mutation.isPending ||
|
||||
!selectedApprover ||
|
||||
transferReason.trim().length < 10
|
||||
}
|
||||
onClick={() => mutation.mutate("transfer")}
|
||||
type="button"
|
||||
>
|
||||
提交转审
|
||||
</Button>
|
||||
</div>
|
||||
{canTransfer && !isLeaveTask ? (
|
||||
<div className="space-y-2 rounded-lg border border-zinc-200 p-4">
|
||||
<p className="text-sm font-medium text-zinc-800">转审</p>
|
||||
<select
|
||||
className="select-std"
|
||||
data-testid="workflow-task-transfer-to-approver"
|
||||
onChange={(event) => setSelectedApprover(event.target.value)}
|
||||
value={selectedApprover}
|
||||
>
|
||||
<option value="">请选择目标审批人</option>
|
||||
{(approverQuery.data?.items ?? []).map((item) => (
|
||||
<option key={item.id} value={item.id}>
|
||||
{item.name} ({item.employeeNo})
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<Textarea
|
||||
data-testid="workflow-task-transfer-reason"
|
||||
onChange={(event) => setTransferReason(event.target.value)}
|
||||
rows={2}
|
||||
value={transferReason}
|
||||
/>
|
||||
<Button
|
||||
data-testid="workflow-task-transfer"
|
||||
variant="secondary"
|
||||
disabled={
|
||||
!allowedActions.has("transfer") ||
|
||||
mutation.isPending ||
|
||||
!selectedApprover ||
|
||||
transferReason.trim().length < 10
|
||||
}
|
||||
onClick={() => mutation.mutate("transfer")}
|
||||
type="button"
|
||||
>
|
||||
提交转审
|
||||
</Button>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
<div className="card-std space-y-3 p-6">
|
||||
|
||||
在新工单中引用
屏蔽一个用户