mirror of
https://github.com/Wei-Shaw/claude-relay-service.git
synced 2026-01-23 21:17:30 +00:00
fix(admin-spa): 修复仪表板时区处理 - 前端显示系统时区,发送UTC时间
- 简化 getSystemTimezoneDay 函数,正确处理系统时区到UTC的转换 - 修复 setDateFilterPreset 中昨天/前天的计算逻辑,使用本地时间计算日期 - 确保自定义时间选择器显示系统时区时间,但发送UTC时间给后端 - API Keys页面已经使用正确的时间范围参数,无需修改
This commit is contained in:
@@ -1 +0,0 @@
|
||||
pre[data-v-3d91f349]{white-space:pre-wrap;word-wrap:break-word}.tab-content[data-v-518dfd83]{min-height:calc(100vh - 300px)}.table-container[data-v-518dfd83]{overflow-x:auto;border-radius:12px;border:1px solid rgba(0,0,0,.05)}.table-row[data-v-518dfd83]{transition:all .2s ease}.table-row[data-v-518dfd83]:hover{background-color:#00000005}.loading-spinner[data-v-518dfd83]{width:24px;height:24px;border:2px solid #e5e7eb;border-top:2px solid #3b82f6;border-radius:50%;animation:spin-518dfd83 1s linear infinite}@keyframes spin-518dfd83{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.api-key-date-picker[data-v-518dfd83] .el-input__inner{--tw-border-opacity: 1;border-color:rgb(209 213 219 / var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.api-key-date-picker[data-v-518dfd83] .el-input__inner:focus{--tw-border-opacity: 1;border-color:rgb(59 130 246 / var(--tw-border-opacity, 1));--tw-ring-opacity: 1;--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity, 1))}.api-key-date-picker[data-v-518dfd83] .el-range-separator{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}
|
||||
2
web/admin-spa/dist/index.html
vendored
2
web/admin-spa/dist/index.html
vendored
@@ -18,7 +18,7 @@
|
||||
<link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin>
|
||||
<link rel="dns-prefetch" href="https://cdn.jsdelivr.net">
|
||||
<link rel="dns-prefetch" href="https://cdnjs.cloudflare.com">
|
||||
<script type="module" crossorigin src="/admin-next/assets/index-CJ53_Ylg.js"></script>
|
||||
<script type="module" crossorigin src="/admin-next/assets/index-DiDOcr6H.js"></script>
|
||||
<link rel="modulepreload" crossorigin href="/admin-next/assets/vue-vendor-CKToUHZx.js">
|
||||
<link rel="modulepreload" crossorigin href="/admin-next/assets/vendor-BDiMbLwQ.js">
|
||||
<link rel="modulepreload" crossorigin href="/admin-next/assets/element-plus-B8Fs_0jW.js">
|
||||
|
||||
@@ -91,29 +91,27 @@ export const useDashboardStore = defineStore('dashboard', () => {
|
||||
}
|
||||
|
||||
// 辅助函数:获取系统时区某一天的起止UTC时间
|
||||
// 输入:一个日期(以用户本地时间表示)
|
||||
// 输入:一个系统时区的日期对象
|
||||
// 输出:该日期在系统时区的0点/23:59对应的UTC时间
|
||||
function getSystemTimezoneDay(localDate, startOfDay = true) {
|
||||
function getSystemTimezoneDay(systemTzDate, startOfDay = true) {
|
||||
const offset = dashboardData.value.systemTimezone || 8
|
||||
|
||||
// 获取用户本地日期的年月日
|
||||
const year = localDate.getFullYear()
|
||||
const month = localDate.getMonth()
|
||||
const day = localDate.getDate()
|
||||
// 获取系统时区日期的年月日
|
||||
const year = systemTzDate.getFullYear()
|
||||
const month = systemTzDate.getMonth()
|
||||
const day = systemTzDate.getDate()
|
||||
|
||||
// 创建UTC时间,表示系统时区的该日期
|
||||
// 创建系统时区的日期时间
|
||||
if (startOfDay) {
|
||||
// 系统时区YYYY-MM-DD 00:00:00 对应的UTC时间
|
||||
const utcDate = new Date(Date.UTC(year, month, day, 0, 0, 0, 0))
|
||||
// 减去系统时区偏移得到UTC时间
|
||||
utcDate.setUTCHours(utcDate.getUTCHours() - offset)
|
||||
return utcDate
|
||||
// 系统时区 YYYY-MM-DD 00:00:00
|
||||
const systemDateTime = new Date(year, month, day, 0, 0, 0, 0)
|
||||
// 转换为UTC时间:减去时区偏移
|
||||
return new Date(systemDateTime.getTime() - offset * 3600000)
|
||||
} else {
|
||||
// 系统时区YYYY-MM-DD 23:59:59.999 对应的UTC时间
|
||||
const utcDate = new Date(Date.UTC(year, month, day, 23, 59, 59, 999))
|
||||
// 减去系统时区偏移得到UTC时间
|
||||
utcDate.setUTCHours(utcDate.getUTCHours() - offset)
|
||||
return utcDate
|
||||
// 系统时区 YYYY-MM-DD 23:59:59.999
|
||||
const systemDateTime = new Date(year, month, day, 23, 59, 59, 999)
|
||||
// 转换为UTC时间:减去时区偏移
|
||||
return new Date(systemDateTime.getTime() - offset * 3600000)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,9 +180,24 @@ export const useDashboardStore = defineStore('dashboard', () => {
|
||||
url += `granularity=hour`
|
||||
|
||||
if (dateFilter.value.customRange && dateFilter.value.customRange.length === 2) {
|
||||
// 使用自定义时间范围
|
||||
url += `&startDate=${encodeURIComponent(dateFilter.value.customRange[0])}`
|
||||
url += `&endDate=${encodeURIComponent(dateFilter.value.customRange[1])}`
|
||||
// 使用自定义时间范围 - 需要将系统时区时间转换为UTC
|
||||
const convertToUTC = (systemTzTimeStr) => {
|
||||
const systemTz = dashboardData.value.systemTimezone || 8
|
||||
// 解析系统时区时间字符串
|
||||
const [datePart, timePart] = systemTzTimeStr.split(' ')
|
||||
const [year, month, day] = datePart.split('-').map(Number)
|
||||
const [hours, minutes, seconds] = timePart.split(':').map(Number)
|
||||
|
||||
// 创建系统时区的Date对象
|
||||
const systemDate = new Date(year, month - 1, day, hours, minutes, seconds)
|
||||
|
||||
// 转换为UTC
|
||||
const utcTime = systemDate.getTime() - (systemTz * 3600000)
|
||||
return new Date(utcTime).toISOString()
|
||||
}
|
||||
|
||||
url += `&startDate=${encodeURIComponent(convertToUTC(dateFilter.value.customRange[0]))}`
|
||||
url += `&endDate=${encodeURIComponent(convertToUTC(dateFilter.value.customRange[1]))}`
|
||||
} else {
|
||||
// 使用预设计算时间范围,与loadApiKeysTrend保持一致
|
||||
const now = new Date()
|
||||
@@ -199,14 +212,14 @@ export const useDashboardStore = defineStore('dashboard', () => {
|
||||
break
|
||||
case 'yesterday':
|
||||
// 昨天:基于系统时区的昨天
|
||||
const yesterday = new Date(now)
|
||||
const yesterday = new Date()
|
||||
yesterday.setDate(yesterday.getDate() - 1)
|
||||
startTime = getSystemTimezoneDay(yesterday, true)
|
||||
endTime = getSystemTimezoneDay(yesterday, false)
|
||||
break
|
||||
case 'dayBefore':
|
||||
// 前天:基于系统时区的前天
|
||||
const dayBefore = new Date(now)
|
||||
const dayBefore = new Date()
|
||||
dayBefore.setDate(dayBefore.getDate() - 2)
|
||||
startTime = getSystemTimezoneDay(dayBefore, true)
|
||||
endTime = getSystemTimezoneDay(dayBefore, false)
|
||||
@@ -260,9 +273,24 @@ export const useDashboardStore = defineStore('dashboard', () => {
|
||||
url += `granularity=hour`
|
||||
|
||||
if (dateFilter.value.customRange && dateFilter.value.customRange.length === 2) {
|
||||
// 使用自定义时间范围
|
||||
url += `&startDate=${encodeURIComponent(dateFilter.value.customRange[0])}`
|
||||
url += `&endDate=${encodeURIComponent(dateFilter.value.customRange[1])}`
|
||||
// 使用自定义时间范围 - 需要将系统时区时间转换为UTC
|
||||
const convertToUTC = (systemTzTimeStr) => {
|
||||
const systemTz = dashboardData.value.systemTimezone || 8
|
||||
// 解析系统时区时间字符串
|
||||
const [datePart, timePart] = systemTzTimeStr.split(' ')
|
||||
const [year, month, day] = datePart.split('-').map(Number)
|
||||
const [hours, minutes, seconds] = timePart.split(':').map(Number)
|
||||
|
||||
// 创建系统时区的Date对象
|
||||
const systemDate = new Date(year, month - 1, day, hours, minutes, seconds)
|
||||
|
||||
// 转换为UTC
|
||||
const utcTime = systemDate.getTime() - (systemTz * 3600000)
|
||||
return new Date(utcTime).toISOString()
|
||||
}
|
||||
|
||||
url += `&startDate=${encodeURIComponent(convertToUTC(dateFilter.value.customRange[0]))}`
|
||||
url += `&endDate=${encodeURIComponent(convertToUTC(dateFilter.value.customRange[1]))}`
|
||||
} else {
|
||||
// 使用预设计算时间范围,与setDateFilterPreset保持一致
|
||||
const now = new Date()
|
||||
@@ -277,14 +305,14 @@ export const useDashboardStore = defineStore('dashboard', () => {
|
||||
break
|
||||
case 'yesterday':
|
||||
// 昨天:基于系统时区的昨天
|
||||
const yesterday = new Date(now)
|
||||
const yesterday = new Date()
|
||||
yesterday.setDate(yesterday.getDate() - 1)
|
||||
startTime = getSystemTimezoneDay(yesterday, true)
|
||||
endTime = getSystemTimezoneDay(yesterday, false)
|
||||
break
|
||||
case 'dayBefore':
|
||||
// 前天:基于系统时区的前天
|
||||
const dayBefore = new Date(now)
|
||||
const dayBefore = new Date()
|
||||
dayBefore.setDate(dayBefore.getDate() - 2)
|
||||
startTime = getSystemTimezoneDay(dayBefore, true)
|
||||
endTime = getSystemTimezoneDay(dayBefore, false)
|
||||
@@ -346,18 +374,20 @@ export const useDashboardStore = defineStore('dashboard', () => {
|
||||
startDate = new Date(now.getTime() - 24 * 60 * 60 * 1000)
|
||||
break
|
||||
case 'yesterday':
|
||||
// 昨天:基于系统时区的昨天
|
||||
const yesterday2 = new Date(now)
|
||||
yesterday2.setDate(yesterday2.getDate() - 1)
|
||||
startDate = getSystemTimezoneDay(yesterday2, true)
|
||||
endDate = getSystemTimezoneDay(yesterday2, false)
|
||||
// 昨天:获取本地时间的昨天
|
||||
const yesterday = new Date()
|
||||
yesterday.setDate(yesterday.getDate() - 1)
|
||||
// 转换为系统时区的昨天0点和23:59
|
||||
startDate = getSystemTimezoneDay(yesterday, true)
|
||||
endDate = getSystemTimezoneDay(yesterday, false)
|
||||
break
|
||||
case 'dayBefore':
|
||||
// 前天:基于系统时区的前天
|
||||
const dayBefore2 = new Date(now)
|
||||
dayBefore2.setDate(dayBefore2.getDate() - 2)
|
||||
startDate = getSystemTimezoneDay(dayBefore2, true)
|
||||
endDate = getSystemTimezoneDay(dayBefore2, false)
|
||||
// 前天:获取本地时间的前天
|
||||
const dayBefore = new Date()
|
||||
dayBefore.setDate(dayBefore.getDate() - 2)
|
||||
// 转换为系统时区的前天0点和23:59
|
||||
startDate = getSystemTimezoneDay(dayBefore, true)
|
||||
endDate = getSystemTimezoneDay(dayBefore, false)
|
||||
break
|
||||
}
|
||||
} else {
|
||||
@@ -381,19 +411,21 @@ export const useDashboardStore = defineStore('dashboard', () => {
|
||||
dateFilter.value.customEnd = endDate.toISOString().split('T')[0]
|
||||
|
||||
// 设置 customRange 为 Element Plus 需要的格式
|
||||
const formatDate = (date) => {
|
||||
const year = date.getFullYear()
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(date.getDate()).padStart(2, '0')
|
||||
const hours = String(date.getHours()).padStart(2, '0')
|
||||
const minutes = String(date.getMinutes()).padStart(2, '0')
|
||||
const seconds = String(date.getSeconds()).padStart(2, '0')
|
||||
// 显示系统时区的时间
|
||||
const formatDateForDisplay = (utcDate) => {
|
||||
const systemTzDate = getDateInSystemTimezone(utcDate)
|
||||
const year = systemTzDate.getUTCFullYear()
|
||||
const month = String(systemTzDate.getUTCMonth() + 1).padStart(2, '0')
|
||||
const day = String(systemTzDate.getUTCDate()).padStart(2, '0')
|
||||
const hours = String(systemTzDate.getUTCHours()).padStart(2, '0')
|
||||
const minutes = String(systemTzDate.getUTCMinutes()).padStart(2, '0')
|
||||
const seconds = String(systemTzDate.getUTCSeconds()).padStart(2, '0')
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
|
||||
}
|
||||
|
||||
dateFilter.value.customRange = [
|
||||
formatDate(startDate),
|
||||
formatDate(endDate)
|
||||
formatDateForDisplay(startDate),
|
||||
formatDateForDisplay(endDate)
|
||||
]
|
||||
}
|
||||
|
||||
@@ -409,9 +441,19 @@ export const useDashboardStore = defineStore('dashboard', () => {
|
||||
dateFilter.value.customStart = value[0].split(' ')[0]
|
||||
dateFilter.value.customEnd = value[1].split(' ')[0]
|
||||
|
||||
// 检查日期范围限制
|
||||
const start = new Date(value[0])
|
||||
const end = new Date(value[1])
|
||||
// 检查日期范围限制 - value中的时间已经是系统时区时间
|
||||
const systemTz = dashboardData.value.systemTimezone || 8
|
||||
|
||||
// 解析系统时区时间
|
||||
const parseSystemTime = (timeStr) => {
|
||||
const [datePart, timePart] = timeStr.split(' ')
|
||||
const [year, month, day] = datePart.split('-').map(Number)
|
||||
const [hours, minutes, seconds] = timePart.split(':').map(Number)
|
||||
return new Date(year, month - 1, day, hours, minutes, seconds)
|
||||
}
|
||||
|
||||
const start = parseSystemTime(value[0])
|
||||
const end = parseSystemTime(value[1])
|
||||
|
||||
if (trendGranularity.value === 'hour') {
|
||||
// 小时粒度:限制 24 小时
|
||||
@@ -433,7 +475,7 @@ export const useDashboardStore = defineStore('dashboard', () => {
|
||||
refreshChartsData()
|
||||
} else if (value === null) {
|
||||
// 清空时恢复默认
|
||||
setDateFilterPreset(trendGranularity.value === 'hour' ? '7days' : '7days')
|
||||
setDateFilterPreset(trendGranularity.value === 'hour' ? 'last24h' : '7days')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user