AP6 增加审批催办与效率摘要

这个提交包含在:
2026-05-12 10:41:47 +08:00
父节点 f99fbce3d8
当前提交 72e38db4e5
共修改 23 个文件,包含 1362 行新增和 12 行删除
+41 -1
查看文件
@@ -32,6 +32,7 @@ import {
fetchLegalEntities,
fetchSuppliers,
} from "../api/masterData";
import { remindWorkflowTask } from "../api/workflow";
import { useAuth } from "../auth/AuthContext";
import { hasPermission } from "../auth/permissions";
import { PageHeader } from "../components/common/PageHeader";
@@ -201,7 +202,7 @@ function resolveStageAction(stageKey: PurchaseErpStageKey, stage: PurchaseReques
export function PurchaseRequestsPage() {
const queryClient = useQueryClient();
const { permissions } = useAuth();
const { me, permissions } = useAuth();
const [searchParams, setSearchParams] = useSearchParams();
const canCreate = hasPermission(permissions, "procurement.create");
@@ -531,6 +532,24 @@ export function PurchaseRequestsPage() {
},
});
const remindMutation = useMutation({
mutationFn: (taskId: string) => remindWorkflowTask(taskId),
onSuccess: async () => {
await Promise.all([
queryClient.invalidateQueries({ queryKey: ["purchase-requests", "detail", selectedId] }),
queryClient.invalidateQueries({ queryKey: ["workflow", "tasks"] }),
queryClient.invalidateQueries({ queryKey: ["workflow", "tasks", "summary"] }),
queryClient.invalidateQueries({ queryKey: ["notifications"] }),
]);
toast.success("已催办当前审批人");
},
onError: (error) => {
const message = resolveError(error);
setFormError(message);
toast.error(message);
},
});
const archiveMutation = useMutation({
mutationFn: async () => {
if (!selectedId) {
@@ -698,6 +717,16 @@ export function PurchaseRequestsPage() {
const canSubmit = Boolean(detail?.permissions.canSubmit);
const canWithdraw = Boolean(detail?.permissions.canWithdraw);
const canArchiveOrder = Boolean(detail?.permissions.canArchiveOrder && canManage);
const pendingTaskId = detail?.pendingWorkflow?.task?.id ?? null;
const isPurchaseParticipant = Boolean(
detail && me?.id && [detail.applicantId, detail.submitterId].includes(me.id),
);
const canRemindPendingWorkflow = Boolean(
detail?.status === "reviewing" &&
pendingTaskId &&
isPurchaseParticipant &&
detail?.pendingWorkflow?.task?.assigneeId !== me?.id,
);
return (
<div className="space-y-6">
@@ -978,6 +1007,17 @@ export function PurchaseRequestsPage() {
>
{withdrawMutation.isPending ? "撤回中..." : "撤回"}
</Button>
{canRemindPendingWorkflow && pendingTaskId ? (
<Button
data-testid="purchase-remind-workflow"
type="button"
variant="secondary"
disabled={remindMutation.isPending}
onClick={() => remindMutation.mutate(pendingTaskId)}
>
{remindMutation.isPending ? "催办中..." : "催办审批"}
</Button>
) : null}
</div>
</div>