fix: 退回报销支持留痕删除(09-04-reimbursement-state-gap-finance-view)
这个提交包含在:
@@ -351,11 +351,11 @@ export function ReimbursementDetailPage() {
|
||||
},
|
||||
onSuccess: async () => {
|
||||
await queryClient.invalidateQueries({ queryKey: ["reimbursements"] });
|
||||
toast.success("草稿已删除");
|
||||
toast.success("报销单已删除");
|
||||
navigate("/reimbursements?status=draft");
|
||||
},
|
||||
onError: (error) => {
|
||||
const message = buildActionErrorMessage(error, "删除草稿失败");
|
||||
const message = buildActionErrorMessage(error, "删除报销单失败");
|
||||
setActionError(message);
|
||||
toast.error(message);
|
||||
},
|
||||
@@ -782,7 +782,8 @@ export function ReimbursementDetailPage() {
|
||||
canViewOwnInvoice;
|
||||
const canUnbindInvoices = canMaintainReimbursement;
|
||||
const canDeleteReimbursement =
|
||||
detail.status === "draft" &&
|
||||
["draft", "rejected"].includes(detail.status) &&
|
||||
!detail.deletedAt &&
|
||||
canDeleteExpense &&
|
||||
isReimbursementParticipant;
|
||||
const precheckStandardChecks = reimbursementPrecheckQuery.data?.standardChecks ?? [];
|
||||
@@ -939,6 +940,7 @@ export function ReimbursementDetailPage() {
|
||||
stage.state === "current" || stage.state === "exception",
|
||||
);
|
||||
const nextStepText = (() => {
|
||||
if (detail.deletedAt) return "已删除,仅供查看历史记录";
|
||||
if (["draft", "rejected"].includes(detail.status)) {
|
||||
if (!isReimbursementParticipant) {
|
||||
return detail.status === "rejected" ? "等待报销人修改后重提" : "等待报销人完善";
|
||||
@@ -1107,7 +1109,7 @@ export function ReimbursementDetailPage() {
|
||||
</>
|
||||
);
|
||||
const workspaceActionPanel = (
|
||||
<BusinessDetailActionPanel status={<StatusBadge status={detail.status} />} primaryAction={primaryAction} secondaryActions={secondaryActions} moreActions={showSecondaryDetail ? <div className="grid gap-2" data-testid="reimbursement-secondary-detail">{detail.status !== "paid" ? <Button asChild variant="secondary"><Link to={"/reimbursements/" + detail.id + "/print"}>打印 / PDF</Link></Button> : null}{canDeleteReimbursement ? <Button data-testid="reimbursement-delete-draft" disabled={deleteReimbursementMutation.isPending} onClick={() => setConfirmDeleteReimbursement(true)} type="button" variant="destructive">删除草稿</Button> : null}</div> : null} summary={<><div>下一步:{nextStepText}</div>{workspaceModel.issueAnchors.map((issue) => <a className="block hover:underline" href={"#" + issue.id} key={issue.label}>{issue.label}</a>)}</>} testId="reimbursement-action-panel">
|
||||
<BusinessDetailActionPanel status={<StatusBadge status={detail.deletedAt ? "deleted" : detail.status} />} primaryAction={primaryAction} secondaryActions={secondaryActions} moreActions={showSecondaryDetail ? <div className="grid gap-2" data-testid="reimbursement-secondary-detail">{detail.status !== "paid" ? <Button asChild variant="secondary"><Link to={"/reimbursements/" + detail.id + "/print"}>打印 / PDF</Link></Button> : null}{canDeleteReimbursement ? <Button data-testid="reimbursement-delete-draft" disabled={deleteReimbursementMutation.isPending} onClick={() => setConfirmDeleteReimbursement(true)} type="button" variant="destructive">删除报销单</Button> : null}</div> : null} summary={<><div>下一步:{nextStepText}</div>{workspaceModel.issueAnchors.map((issue) => <a className="block hover:underline" href={"#" + issue.id} key={issue.label}>{issue.label}</a>)}</>} testId="reimbursement-action-panel">
|
||||
<ReimbursementActions status={detail.status} showSubmitAction={false} showWithdrawAction={isReimbursementParticipant} actionError={["reviewing", "approved"].includes(detail.status) ? actionError : ""} submitDisabled={blockStandardChecks.length > 0} submitHint="" submitNotice="" isPending={mutation.isPending} onSubmit={() => void handleSubmitAction()} onWithdraw={(comment) => mutation.mutate({ action: "withdraw", comment })} />
|
||||
</BusinessDetailActionPanel>
|
||||
);
|
||||
@@ -1115,7 +1117,7 @@ export function ReimbursementDetailPage() {
|
||||
return (
|
||||
<>
|
||||
{downloadReasonDialog}
|
||||
<ReimbursementDesktopWorkspaceShell model={workspaceModel} capabilities={workspaceCapabilities} slots={{ status: <StatusBadge status={detail.status} />, backAction: <Button asChild className="min-h-11 px-2" data-testid="reimbursement-back" variant="ghost"><Link replace to={backSource}><ArrowLeft aria-hidden="true" className="size-4" />{backLabel}</Link></Button>, headerDetails: workspaceHeaderDetails, beforeEvidence: workspaceBeforeEvidence, afterEvidence: workspaceAfterEvidence, actionPanel: workspaceActionPanel }} />
|
||||
<ReimbursementDesktopWorkspaceShell model={workspaceModel} capabilities={workspaceCapabilities} slots={{ status: <StatusBadge status={detail.deletedAt ? "deleted" : detail.status} />, backAction: <Button asChild className="min-h-11 px-2" data-testid="reimbursement-back" variant="ghost"><Link replace to={backSource}><ArrowLeft aria-hidden="true" className="size-4" />{backLabel}</Link></Button>, headerDetails: workspaceHeaderDetails, beforeEvidence: workspaceBeforeEvidence, afterEvidence: workspaceAfterEvidence, actionPanel: workspaceActionPanel }} />
|
||||
<Dialog open={isInvoiceDialogOpen} onOpenChange={handleInvoiceDialogOpenChange}>
|
||||
<DialogContent
|
||||
className="max-h-[85vh] max-w-3xl overflow-y-auto"
|
||||
@@ -1369,9 +1371,9 @@ export function ReimbursementDetailPage() {
|
||||
open={confirmDeleteReimbursement}
|
||||
onOpenChange={setConfirmDeleteReimbursement}
|
||||
title={`确认删除 ${displayCode}?`}
|
||||
description="删除后无法恢复,已添加发票会回到可添加状态。"
|
||||
description="删除后,此单不再出现在日常列表中,符合条件的发票可重新报销;已发生的审批记录仍保留备查。"
|
||||
variant="destructive"
|
||||
confirmLabel="删除草稿"
|
||||
confirmLabel="删除报销单"
|
||||
onConfirm={() => { deleteReimbursementMutation.mutate(); }}
|
||||
/>
|
||||
<AttachmentDeleteConfirmDialog
|
||||
|
||||
在新工单中引用
屏蔽一个用户