fix: 日历月份切换在UTC+8时区跳两个月
toISOString() 使用UTC时间,在UTC+8时区下 new Date(y,m-2,1) 会回退到前一天导致月份-1。 改用本地时间格式化函数 fmtMonth/fmtDate 替代所有 toISOString().slice() 调用。
This commit is contained in:
@@ -44,15 +44,20 @@ const PRIORITY_DOT: Record<string, string> = {
|
||||
|
||||
const WEEKDAYS = ['日', '一', '二', '三', '四', '五', '六']
|
||||
|
||||
/** 本地日期格式化为 YYYY-MM-DD,避免 toISOString() 的 UTC 时区偏移 */
|
||||
const fmtDate = (d: Date) => `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`
|
||||
/** 本地月份格式化为 YYYY-MM */
|
||||
const fmtMonth = (d: Date) => `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}`
|
||||
|
||||
export default function Calendar() {
|
||||
const queryClient = useQueryClient()
|
||||
const [calendarMonth, setCalendarMonth] = useState(new Date().toISOString().slice(0, 7))
|
||||
const [calendarMonth, setCalendarMonth] = useState(`${new Date().getFullYear()}-${String(new Date().getMonth() + 1).padStart(2, '0')}`)
|
||||
const [showEventForm, setShowEventForm] = useState(false)
|
||||
const [selectedDate, setSelectedDate] = useState<string | null>(null)
|
||||
const [typeFilter, setTypeFilter] = useState<string | null>(null)
|
||||
const [eventForm, setEventForm] = useState({
|
||||
title: '',
|
||||
date: new Date().toISOString().slice(0, 10),
|
||||
date: `${new Date().getFullYear()}-${String(new Date().getMonth() + 1).padStart(2, '0')}-${String(new Date().getDate()).padStart(2, '0')}`,
|
||||
type: 'CUSTOM',
|
||||
priority: 'medium',
|
||||
location: '',
|
||||
@@ -81,7 +86,7 @@ export default function Calendar() {
|
||||
queryClient.invalidateQueries({ queryKey: ['custom-events'] })
|
||||
queryClient.invalidateQueries({ queryKey: ['calendar'] })
|
||||
setShowEventForm(false)
|
||||
setEventForm({ title: '', date: selectedDate || new Date().toISOString().slice(0, 10), type: 'CUSTOM', priority: 'medium', location: '', description: '' })
|
||||
setEventForm({ title: '', date: selectedDate || fmtDate(new Date()), type: 'CUSTOM', priority: 'medium', location: '', description: '' })
|
||||
toast.success('事件已创建')
|
||||
},
|
||||
onError: () => toast.error('创建事件失败'),
|
||||
@@ -102,7 +107,7 @@ export default function Calendar() {
|
||||
const lastDay = new Date(year, mon, 0)
|
||||
const startWeekday = firstDay.getDay()
|
||||
const daysInMonth = lastDay.getDate()
|
||||
const todayStr = new Date().toISOString().slice(0, 10)
|
||||
const todayStr = fmtDate(new Date())
|
||||
const cells: Array<{ day: number | null; date: string | null; events: any[]; isToday: boolean }> = []
|
||||
for (let i = 0; i < startWeekday; i++) cells.push({ day: null, date: null, events: [], isToday: false })
|
||||
for (let d = 1; d <= daysInMonth; d++) {
|
||||
@@ -131,14 +136,14 @@ export default function Calendar() {
|
||||
const prevMonth = () => {
|
||||
const [y, m] = calendarMonth.split('-').map(Number)
|
||||
const d = new Date(y, m - 2, 1)
|
||||
setCalendarMonth(d.toISOString().slice(0, 7))
|
||||
setCalendarMonth(fmtMonth(d))
|
||||
}
|
||||
const nextMonth = () => {
|
||||
const [y, m] = calendarMonth.split('-').map(Number)
|
||||
const d = new Date(y, m, 1)
|
||||
setCalendarMonth(d.toISOString().slice(0, 7))
|
||||
setCalendarMonth(fmtMonth(d))
|
||||
}
|
||||
const goToday = () => setCalendarMonth(new Date().toISOString().slice(0, 7))
|
||||
const goToday = () => setCalendarMonth(fmtMonth(new Date()))
|
||||
|
||||
const handleDayClick = (date: string | null) => {
|
||||
if (!date) return
|
||||
@@ -183,7 +188,7 @@ export default function Calendar() {
|
||||
<ChevronRight className="w-4 h-4" />
|
||||
</Button>
|
||||
<Button variant="secondary" size="sm" onClick={goToday}>今天</Button>
|
||||
<Button size="sm" onClick={() => { setEventForm({ ...eventForm, date: new Date().toISOString().slice(0, 10) }); setShowEventForm(true) }}>
|
||||
<Button size="sm" onClick={() => { setEventForm({ ...eventForm, date: fmtDate(new Date()) }); setShowEventForm(true) }}>
|
||||
<Plus className="w-4 h-4 mr-1" />新建事件
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user