fix(admin): 修复日期选择器与选曲日期的 UTC 时差错位
构建并部署 BYW VoiceHub / Preflight 语法与构建检查 (push) Successful in 2m44s
构建并部署 BYW VoiceHub / 构建并推送容器镜像 (push) Successful in 10m19s
构建并部署 BYW VoiceHub / 部署到生产服务器 (push) Successful in 7s

根本原因: 使用 toISOString().split('T')[0] 会按 UTC 时区截断日期,
在 UTC+8 时区下,本地 00:00~07:59 期间会少 1 天,导致:
- AdminDatePicker/AdminMultiDatePicker 横向条、月历选中值错位
- ScheduleManager selectedDate 今日初始化与今日排期过滤错位
- 月历今日高亮与实际日期不匹配

修复方法: 所有 YYYY-MM-DD 格式化统一使用本地时区的
getFullYear/getMonth/getDate + pad, addDays 前先 setHours(0,0,0,0) 归零
避免 DST 与时区偏移导致的跨天误差
This commit is contained in:
2026-09-13 08:36:40 +08:00
parent 19ab33b102
commit 71bbd88bb8
3 changed files with 25 additions and 16 deletions
+6 -5
View File
@@ -172,16 +172,17 @@ const isLastDateVisible = ref(false)
const dateRange = ref({ start: -15, end: 15 })
const showCalendar = ref(false)
const today = new Date()
const pad = (n) => n.toString().padStart(2, '0')
const formatDateStr = (d) => `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`
const addDays = (d, n) => { const x = new Date(d); x.setHours(0, 0, 0, 0); x.setDate(x.getDate() + n); return x }
const sameDay = (a, b) => a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate()
const today = new Date(); today.setHours(0, 0, 0, 0)
const calendarYear = ref(today.getFullYear())
const calendarMonth = ref(today.getMonth())
const weekdayNames = ['日', '一', '二', '三', '四', '五', '六']
const formatDateStr = (d) => d.toISOString().split('T')[0]
const addDays = (d, n) => { const x = new Date(d); x.setDate(x.getDate() + n); return x }
const sameDay = (a, b) => a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate()
const availableDates = computed(() => {
const dates = []
for (let i = dateRange.value.start; i <= dateRange.value.end; i++) {
@@ -195,17 +195,18 @@ const dateRange = ref({ start: 0, end: 45 })
const showCalendar = ref(false)
const lastClickedDate = ref('')
const today = new Date()
const pad = (n) => n.toString().padStart(2, '0')
const formatDateStr = (d) => `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`
const addDays = (d, n) => { const x = new Date(d); x.setHours(0, 0, 0, 0); x.setDate(x.getDate() + n); return x }
const sameDay = (a, b) => a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate()
const sortDates = (arr) => [...new Set(arr)].sort()
const today = new Date(); today.setHours(0, 0, 0, 0)
const calendarYear = ref(today.getFullYear())
const calendarMonth = ref(today.getMonth())
const weekdayNames = ['日', '一', '二', '三', '四', '五', '六']
const formatDateStr = (d) => d.toISOString().split('T')[0]
const addDays = (d, n) => { const x = new Date(d); x.setDate(x.getDate() + n); return x }
const sameDay = (a, b) => a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate()
const sortDates = (arr) => [...new Set(arr)].sort()
const availableDates = computed(() => {
const dates = []
for (let i = dateRange.value.start; i <= dateRange.value.end; i++) {
+11 -4
View File
@@ -974,7 +974,9 @@ const defaultAutoConfig: AutoConfig = {
// 响应式数据
const showCardGenerator = ref(false)
const selectedDate = ref(new Date().toISOString().split('T')[0])
const _pad = (n) => n.toString().padStart(2, '0')
const _today = new Date(); _today.setHours(0, 0, 0, 0)
const selectedDate = ref(`${_today.getFullYear()}-${_pad(_today.getMonth() + 1)}-${_pad(_today.getDate())}`)
const loading = ref(false)
const songSortOption = ref<AutoConfig['songSortOption']>('votes-desc')
const hasChanges = ref(false)
@@ -1695,17 +1697,22 @@ const updateLocalScheduledSongs = () => {
console.log('公开排期数量:', publicSchedules.value.length)
console.log('草稿数量:', drafts.value.length)
const _fmtLocal = (d) => {
const x = new Date(d)
return `${x.getFullYear()}-${_pad(x.getMonth() + 1)}-${_pad(x.getDate())}`
}
// 获取已发布的排期
const todaySchedules = publicSchedules.value.filter((s) => {
if (!s.playDate) return false
const scheduleDateStr = new Date(s.playDate).toISOString().split('T')[0]
const scheduleDateStr = _fmtLocal(s.playDate)
return scheduleDateStr === selectedDate.value
})
// 获取草稿排期
const todayDrafts = drafts.value.filter((draft) => {
if (!draft.playDate) return false
const draftDateStr = new Date(draft.playDate).toISOString().split('T')[0]
const draftDateStr = _fmtLocal(draft.playDate)
return draftDateStr === selectedDate.value
})
@@ -2210,7 +2217,7 @@ const confirmMoveDate = async () => {
const sourceDate = selectedDate.value
const sourceSchedules = [...publicSchedules.value, ...drafts.value].filter((schedule) => {
if (!schedule.playDate) return false
return new Date(schedule.playDate).toISOString().split('T')[0] === sourceDate
return _fmtLocal(schedule.playDate) === sourceDate
})
if (sourceSchedules.length === 0) {