R62 A1-A6:2026年中国法定假期日历
这个提交包含在:
@@ -5,6 +5,7 @@ import { mapApiErrorMessage } from "../api/errorMessages";
|
||||
import {
|
||||
createLeaveRequest,
|
||||
fetchLeaveBalances,
|
||||
fetchLeaveWorkingDaysPreview,
|
||||
fetchLeaveRequests,
|
||||
fetchLeaveTypes,
|
||||
patchLeaveRequest,
|
||||
@@ -221,11 +222,32 @@ export function LeaveRequestPage() {
|
||||
const [formError, setFormError] = useState("");
|
||||
const [withdrawTarget, setWithdrawTarget] = useState<{ id: string; label: string } | null>(null);
|
||||
|
||||
const requestedDaysPreview = useMemo(
|
||||
const localRequestedDaysPreview = useMemo(
|
||||
() => calculateRequestedDaysPreview(startDate, endDate, startSession, endSession),
|
||||
[endDate, endSession, startDate, startSession],
|
||||
);
|
||||
|
||||
const workingDaysPreviewQuery = useQuery({
|
||||
queryKey: [
|
||||
"leave",
|
||||
"working-days-preview",
|
||||
me?.id ?? "anonymous",
|
||||
startDate,
|
||||
endDate,
|
||||
startSession,
|
||||
endSession,
|
||||
],
|
||||
enabled: Boolean(startDate && endDate && localRequestedDaysPreview != null),
|
||||
retry: false,
|
||||
queryFn: () =>
|
||||
fetchLeaveWorkingDaysPreview({
|
||||
startDate,
|
||||
endDate,
|
||||
startSession,
|
||||
endSession,
|
||||
}),
|
||||
});
|
||||
|
||||
const leaveTypesQuery = useQuery({
|
||||
queryKey: ["leave", "types"],
|
||||
queryFn: () => fetchLeaveTypes({ enabled: true }),
|
||||
@@ -279,6 +301,9 @@ export function LeaveRequestPage() {
|
||||
return (leaveTypesQuery.data?.items ?? []).find((item) => item.id === leaveTypeId) ?? null;
|
||||
}, [leaveTypeId, leaveTypesQuery.data?.items]);
|
||||
|
||||
const effectiveRequestedDaysPreview =
|
||||
workingDaysPreviewQuery.data?.requestedDays ?? localRequestedDaysPreview;
|
||||
|
||||
const balanceSummary = useMemo(() => {
|
||||
return (balancesQuery.data?.items ?? []).reduce(
|
||||
(acc, item) => {
|
||||
@@ -340,7 +365,7 @@ export function LeaveRequestPage() {
|
||||
if (!selectedLeaveType) {
|
||||
throw new Error("假期类型不存在或已失效");
|
||||
}
|
||||
if (requestedDaysPreview == null || requestedDaysPreview <= 0) {
|
||||
if (effectiveRequestedDaysPreview == null || effectiveRequestedDaysPreview <= 0) {
|
||||
throw new Error("请检查开始/结束日期与半天时段");
|
||||
}
|
||||
if (
|
||||
@@ -736,7 +761,12 @@ export function LeaveRequestPage() {
|
||||
<MetricCard title="可用额度" value={balanceSummary.available.toFixed(1)} note="按当前启用假种汇总" />
|
||||
<MetricCard title="已冻结" value={balanceSummary.reserved.toFixed(1)} note="审批中申请会占用额度" tone={balanceSummary.reserved > 0 ? "warning" : "neutral"} />
|
||||
<MetricCard title="已使用" value={balanceSummary.used.toFixed(1)} note="通过后计入已使用" />
|
||||
<MetricCard title="本次预估" value={requestedDaysPreview ?? "-"} note="创建草稿前可先预览天数" tone={requestedDaysPreview ? "warning" : "neutral"} />
|
||||
<MetricCard
|
||||
title="本次预估"
|
||||
value={effectiveRequestedDaysPreview ?? "-"}
|
||||
note="创建草稿前可先预览天数"
|
||||
tone={effectiveRequestedDaysPreview ? "warning" : "neutral"}
|
||||
/>
|
||||
</section>
|
||||
|
||||
<div className="page-shell-grid">
|
||||
@@ -748,6 +778,19 @@ export function LeaveRequestPage() {
|
||||
</p>
|
||||
) : null}
|
||||
|
||||
{workingDaysPreviewQuery.isError && startDate && endDate ? (
|
||||
<p className="rounded-lg border border-amber-200 bg-amber-50 px-3 py-2 text-sm text-amber-700">
|
||||
工作日预览失败,提交时将以服务器结果为准
|
||||
</p>
|
||||
) : null}
|
||||
|
||||
{workingDaysPreviewQuery.data && workingDaysPreviewQuery.data.holidayDayCount > 0 ? (
|
||||
<p className="rounded-lg border border-sky-200 bg-sky-50 px-3 py-2 text-sm text-sky-700">
|
||||
选择的日期范围内包含 {workingDaysPreviewQuery.data.holidayDayCount} 天法定假日,实际请假天数为{" "}
|
||||
{workingDaysPreviewQuery.data.requestedDays} 天
|
||||
</p>
|
||||
) : null}
|
||||
|
||||
<div className="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="leave-type">假期类型</Label>
|
||||
@@ -840,7 +883,7 @@ export function LeaveRequestPage() {
|
||||
|
||||
<div className="flex flex-wrap items-center justify-between gap-3 rounded-lg border border-zinc-200 bg-zinc-50 px-4 py-3 text-sm text-zinc-700">
|
||||
<div>
|
||||
预计请假天数:<span className="font-semibold text-zinc-900">{requestedDaysPreview ?? "-"}</span>
|
||||
预计请假天数:<span className="font-semibold text-zinc-900">{effectiveRequestedDaysPreview ?? "-"}</span>
|
||||
</div>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{editingLeaveRequest ? (
|
||||
|
||||
在新工单中引用
屏蔽一个用户