"use client"; /** 发帖截止时间:快捷天数 + 自定义时刻 */ export type DeadlineMode = "preset" | "custom"; function pad2(n: number) { return String(n).padStart(2, "0"); } /** datetime-local 值(本地时区) */ export function toLocalInputValue(d: Date): string { return `${d.getFullYear()}-${pad2(d.getMonth() + 1)}-${pad2(d.getDate())}T${pad2(d.getHours())}:${pad2(d.getMinutes())}`; } /** 默认自定义:从现在起 +N 天 */ export function defaultCustomLocal(days = 7): string { const d = new Date(); d.setDate(d.getDate() + days); d.setSeconds(0, 0); return toLocalInputValue(d); } /** 本地 datetime-local → RFC3339(UTC) */ export function localInputToRFC3339(local: string): string | null { const t = Date.parse(local); if (!Number.isFinite(t)) return null; return new Date(t).toISOString().replace(/\.\d{3}Z$/, "Z"); } export function formatLocalPreview(local: string): string { const t = Date.parse(local); if (!Number.isFinite(t)) return ""; try { return new Date(t).toLocaleString("zh-CN"); } catch { return local; } } export default function DeadlinePicker({ label = "截止时间", presets, mode, onModeChange, days, onDaysChange, customLocal, onCustomLocalChange, disabled, hint, }: { label?: string; presets: readonly number[]; mode: DeadlineMode; onModeChange: (m: DeadlineMode) => void; days: number; onDaysChange: (d: number) => void; customLocal: string; onCustomLocalChange: (v: string) => void; disabled?: boolean; hint?: string; }) { const minLocal = toLocalInputValue(new Date(Date.now() + 60 * 60 * 1000)); const maxLocal = toLocalInputValue(new Date(Date.now() + 90 * 24 * 60 * 60 * 1000)); return (
{label}
{mode === "preset" ? (
{presets.map((d) => ( ))}
) : (
onCustomLocalChange(e.target.value)} aria-label="指定截止时刻" /> {customLocal ? (

将于 {formatLocalPreview(customLocal)} 截止

) : null}
)} {hint ?

{hint}

: null}
); }