LP6 完善请假采购体验与审批说明

这个提交包含在:
2026-05-12 13:02:00 +08:00
父节点 21887ce28a
当前提交 3d1e4c43f6
共修改 14 个文件,包含 502 行新增和 39 行删除
+46 -3
查看文件
@@ -1,4 +1,4 @@
import { useMemo, useState } from "react";
import { useMemo, useRef, useState } from "react";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { toast } from "sonner";
import { mapApiErrorMessage } from "../api/errorMessages";
@@ -33,6 +33,11 @@ import { Label } from "../components/ui/label";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "../components/ui/table";
import { Textarea } from "../components/ui/textarea";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "../components/ui/tabs";
import {
formatApprovalHistoryTime,
resolveLeaveStatusHint,
workflowActionLabel,
} from "../lib/approvalDisplay";
const PAGE_SIZE = 10;
const CALENDAR_PAGE_SIZE = 100;
@@ -218,6 +223,7 @@ export function LeaveRequestPage() {
const [reason, setReason] = useState("");
const [attachmentFile, setAttachmentFile] = useState<File | null>(null);
const [attachmentInputKey, setAttachmentInputKey] = useState(0);
const attachmentInputRef = useRef<HTMLInputElement | null>(null);
const [editingLeaveRequest, setEditingLeaveRequest] = useState<LeaveRequestItem | null>(null);
const [formError, setFormError] = useState("");
const [withdrawTarget, setWithdrawTarget] = useState<{ id: string; label: string } | null>(null);
@@ -340,6 +346,9 @@ export function LeaveRequestPage() {
setReason("");
setAttachmentFile(null);
setAttachmentInputKey((current) => current + 1);
if (attachmentInputRef.current) {
attachmentInputRef.current.value = "";
}
setFormError("");
}
@@ -353,6 +362,9 @@ export function LeaveRequestPage() {
setReason(item.reason ?? "");
setAttachmentFile(null);
setAttachmentInputKey((current) => current + 1);
if (attachmentInputRef.current) {
attachmentInputRef.current.value = "";
}
setFormError("");
}
@@ -564,7 +576,22 @@ export function LeaveRequestPage() {
</TableCell>
<TableCell>{formatRangeLabel(item)}</TableCell>
<TableCell>{item.requestedDays}</TableCell>
<TableCell><StatusBadge status={item.status} /></TableCell>
<TableCell>
<div className="space-y-1">
<StatusBadge status={item.status} />
<div className="max-w-xs text-xs text-zinc-500" data-testid="leave-status-hint">
{resolveLeaveStatusHint(item)}
</div>
{item.approvalHistory.length ? (
<div className="max-w-xs text-xs text-zinc-400">
最近审批:{workflowActionLabel(item.approvalHistory[0].action)}
{item.approvalHistory[0].comment ? ` · ${item.approvalHistory[0].comment}` : ""}
{" · "}
{formatApprovalHistoryTime(item.approvalHistory[0].createdAt)}
</div>
) : null}
</div>
</TableCell>
<TableCell className="text-xs text-zinc-500">
{item.attachment?.originalName ?? "-"}
</TableCell>
@@ -856,9 +883,11 @@ export function LeaveRequestPage() {
<div className="space-y-2">
<Label htmlFor="leave-attachment">附件</Label>
<Input
<input
key={attachmentInputKey}
ref={attachmentInputRef}
id="leave-attachment"
className="hidden"
type="file"
accept={selectedLeaveType?.attachmentMimeTypes?.join(",") || undefined}
onChange={(event) => {
@@ -866,6 +895,20 @@ export function LeaveRequestPage() {
setAttachmentFile(nextFile);
}}
/>
<div className="flex items-center gap-2 rounded-lg border border-zinc-200 bg-white px-3 py-2">
<Button
type="button"
variant="secondary"
size="sm"
disabled={!selectedLeaveType}
onClick={() => attachmentInputRef.current?.click()}
>
选择附件
</Button>
<span className="min-w-0 flex-1 truncate text-sm text-zinc-500" data-testid="leave-attachment-name">
{currentAttachmentLabel ?? "未选择文件"}
</span>
</div>
<p className="text-xs text-zinc-500">
{selectedLeaveType?.requiresAttachment
? `当前假种要求上传附件(允许:${selectedLeaveType.attachmentMimeTypes.join(", ") || "默认文档/图片"})`