diff --git a/src/pages/worklog/WorkLogPage.tsx b/src/pages/worklog/WorkLogPage.tsx index bb42fab..f567f82 100644 --- a/src/pages/worklog/WorkLogPage.tsx +++ b/src/pages/worklog/WorkLogPage.tsx @@ -138,6 +138,49 @@ const toNumber = (value: unknown, fallback = 0) => { const formatDay = (value: Dayjs) => value.format(DAY_VALUE_FORMAT); +const NON_WORKING_HOLIDAYS = new Set([ + '2026-01-01', + '2026-02-16', + '2026-02-17', + '2026-02-18', + '2026-02-19', + '2026-02-20', + '2026-04-05', + '2026-05-01', + '2026-05-02', + '2026-05-03', + '2026-06-19', + '2026-09-25', + '2026-10-01', + '2026-10-02', + '2026-10-03', + '2026-10-04', + '2026-10-05', + '2026-10-06', + '2026-10-07', +]); + +const MAKEUP_WORKDAYS = new Set([ + '2026-02-15', + '2026-02-28', + '2026-04-26', + '2026-05-09', + '2026-09-27', + '2026-10-10', +]); + +const isNonWorkingDay = (value: Dayjs) => { + const dayKey = value.format('YYYY-MM-DD'); + if (MAKEUP_WORKDAYS.has(dayKey)) { + return false; + } + if (NON_WORKING_HOLIDAYS.has(dayKey)) { + return true; + } + const weekday = value.day(); + return weekday === 0 || weekday === 6; +}; + const pickProjectBoundaryDate = (row: ProjectRow, keys: Array) => { for (const key of keys) { const raw = row[key]; @@ -1194,6 +1237,7 @@ const WorkLogPage = () => { const dayKey = formatDay(current); const record = monthCellMap.get(dayKey); const isFuture = current.isAfter(dayjs(), 'day'); + const isNonWorking = isNonWorkingDay(current); const hasLog = record !== undefined && toNumber(record.state, -1) !== -1; const isTimeout = record !== undefined && toNumber(record.state, -1) === -1 && current.isBefore(dayjs(), 'day'); const isSelected = current.format('YYYY-MM-DD') === selectedDayOnly; @@ -1202,6 +1246,7 @@ const WorkLogPage = () => { key: dayKey, current, isFuture, + isNonWorking, hasLog, isTimeout, isSelected, @@ -1475,6 +1520,10 @@ const WorkLogPage = () => { 超期未填 + + + 非工作日 + @@ -1485,7 +1534,7 @@ const WorkLogPage = () => { item.isSelected ? 'is-selected' : '', item.hasLog ? 'is-has-log' : '', item.isTimeout ? 'is-timeout' : '', - item.isFuture ? 'is-disabled' : '', + item.isFuture || item.isNonWorking ? 'is-disabled' : '', ] .filter(Boolean) .join(' '); diff --git a/src/pages/worklog/worklog.css b/src/pages/worklog/worklog.css index 4377c6b..da5e671 100644 --- a/src/pages/worklog/worklog.css +++ b/src/pages/worklog/worklog.css @@ -173,6 +173,10 @@ background: #ffb74d; } +.worklog-legend-dot.is-non-working { + background: #c0c4cc; +} + .worklog-calendar-strip { grid-area: meta; border: 1px solid #edf2fb; @@ -219,6 +223,13 @@ box-shadow: none; } +.worklog-strip-day.is-disabled:not(.is-selected) { + color: #c0c4cc; + background: #f8fafc; + border-color: #e5e7eb; + box-shadow: none; +} + .worklog-strip-day.is-selected { background: linear-gradient(135deg, #635bff 0%, #4f46e5 100%); color: #fff; @@ -237,6 +248,12 @@ color: #8b4f00; } +.worklog-strip-day.is-disabled.is-timeout:not(.is-selected) { + color: #c0c4cc; + background: #f8fafc; + border-color: #e5e7eb; +} + .worklog-strip-weekday { font-size: 11px; color: #8190a7; @@ -259,6 +276,11 @@ color: rgba(255, 255, 255, 0.82); } +.worklog-strip-day.is-disabled:not(.is-selected) .worklog-strip-weekday, +.worklog-strip-day.is-disabled:not(.is-selected) .worklog-strip-meta { + color: #a8b3c4; +} + .worklog-main-top { display: grid; grid-template-columns: minmax(0, 1fr) minmax(280px, 360px);