From 95ef04c1a3d2a31d3a45fa4cdb1a449cdbcaaec0 Mon Sep 17 00:00:00 2001 From: atoz03 Date: Thu, 4 Dec 2025 17:05:36 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=9D=E6=8C=81=E4=BB=AA=E8=A1=A8?= =?UTF-8?q?=E7=9B=98=E8=B6=8B=E5=8A=BF=E5=9B=BE=E9=9D=9E=E8=B4=9F=E5=B9=B6?= =?UTF-8?q?=E7=BA=A0=E6=AD=A3=E5=B0=8F=E6=97=B6=E5=8C=BA=E9=97=B4=20=20=20?= =?UTF-8?q?-=20=E5=B0=8F=E6=97=B6=E7=B2=92=E5=BA=A6=E8=AF=B7=E6=B1=82?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E7=94=A8=E6=88=B7=E9=80=89=E6=8B=A9=E7=9A=84?= =?UTF-8?q?=E8=B5=B7=E6=AD=A2=E6=97=B6=E9=97=B4=EF=BC=8C=E9=81=BF=E5=85=8D?= =?UTF-8?q?=E8=BF=9124=E5=B0=8F=E6=97=B6=E8=A2=AB=E6=88=AA=E6=88=90?= =?UTF-8?q?=E6=95=B4=E5=A4=A9=20=20=20-=20=E4=BF=AE=E6=AD=A3=E6=97=A5?= =?UTF-8?q?=E6=9C=9F=E5=B1=95=E7=A4=BA=E6=A0=BC=E5=BC=8F=E5=8C=96=E9=80=BB?= =?UTF-8?q?=E8=BE=91=EF=BC=8C=E5=87=8F=E5=B0=91=E6=97=B6=E5=8C=BA=E5=81=8F?= =?UTF-8?q?=E7=A7=BB=E5=AF=BC=E8=87=B4=E7=9A=84=E7=AA=97=E5=8F=A3=E9=94=99?= =?UTF-8?q?=E4=BD=8D=20=20=20-=20=E8=B6=8B=E5=8A=BF=E5=9B=BE=20Y=20?= =?UTF-8?q?=E8=BD=B4=EF=BC=88Token/=E8=AF=B7=E6=B1=82=E6=95=B0/=E8=B4=B9?= =?UTF-8?q?=E7=94=A8=E7=AD=89=EF=BC=89=E5=BC=BA=E5=88=B6=E6=9C=80=E5=B0=8F?= =?UTF-8?q?=E5=80=BC=E4=B8=BA=200=EF=BC=8C=E9=98=B2=E6=AD=A2=E5=87=BA?= =?UTF-8?q?=E7=8E=B0=E8=B4=9F=E5=88=BB=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/admin-spa/src/stores/dashboard.js | 99 +++++------------------ web/admin-spa/src/views/DashboardView.vue | 7 +- 2 files changed, 25 insertions(+), 81 deletions(-) diff --git a/web/admin-spa/src/stores/dashboard.js b/web/admin-spa/src/stores/dashboard.js index 8f47f7eb..76e987b9 100644 --- a/web/admin-spa/src/stores/dashboard.js +++ b/web/admin-spa/src/stores/dashboard.js @@ -306,26 +306,9 @@ export const useDashboardStore = defineStore('dashboard', () => { url += `granularity=hour` if (dateFilter.value.customRange && dateFilter.value.customRange.length === 2) { - // 使用自定义时间范围 - 需要将系统时区时间转换为UTC - const convertToUTC = (systemTzTimeStr) => { - // 固定使用UTC+8,因为后端系统时区是UTC+8 - const systemTz = 8 - // 解析系统时区时间字符串 - const [datePart, timePart] = systemTzTimeStr.split(' ') - const [year, month, day] = datePart.split('-').map(Number) - const [hours, minutes, seconds] = timePart.split(':').map(Number) - - // 创建UTC时间,使其在系统时区显示为用户选择的时间 - // 例如:用户选择 UTC+8 的 2025-07-25 00:00:00 - // 对应的UTC时间是 2025-07-24 16:00:00 - const utcDate = new Date( - Date.UTC(year, month - 1, day, hours - systemTz, minutes, seconds) - ) - return utcDate.toISOString() - } - - url += `&startDate=${encodeURIComponent(convertToUTC(dateFilter.value.customRange[0]))}` - url += `&endDate=${encodeURIComponent(convertToUTC(dateFilter.value.customRange[1]))}` + // 使用自定义时间范围 - 直接按系统时区字符串传递,避免额外时区偏移导致窗口错位 + url += `&startDate=${encodeURIComponent(dateFilter.value.customRange[0])}` + url += `&endDate=${encodeURIComponent(dateFilter.value.customRange[1])}` } else { // 使用预设计算时间范围,与loadApiKeysTrend保持一致 const now = new Date() @@ -397,21 +380,9 @@ export const useDashboardStore = defineStore('dashboard', () => { // 如果是自定义时间范围或小时粒度,传递具体的时间参数 if (dateFilter.value.type === 'custom' || currentGranularity === 'hour') { if (dateFilter.value.customRange && dateFilter.value.customRange.length === 2) { - // 将系统时区时间转换为UTC - const convertToUTC = (systemTzTimeStr) => { - const systemTz = 8 - const [datePart, timePart] = systemTzTimeStr.split(' ') - const [year, month, day] = datePart.split('-').map(Number) - const [hours, minutes, seconds] = timePart.split(':').map(Number) - - const utcDate = new Date( - Date.UTC(year, month - 1, day, hours - systemTz, minutes, seconds) - ) - return utcDate.toISOString() - } - - url += `&startDate=${encodeURIComponent(convertToUTC(dateFilter.value.customRange[0]))}` - url += `&endDate=${encodeURIComponent(convertToUTC(dateFilter.value.customRange[1]))}` + // 按系统时区字符串直传,避免额外时区转换 + url += `&startDate=${encodeURIComponent(dateFilter.value.customRange[0])}` + url += `&endDate=${encodeURIComponent(dateFilter.value.customRange[1])}` } else if (currentGranularity === 'hour' && dateFilter.value.type === 'preset') { // 小时粒度的预设时间范围 const now = new Date() @@ -497,26 +468,9 @@ export const useDashboardStore = defineStore('dashboard', () => { url += `granularity=hour` if (dateFilter.value.customRange && dateFilter.value.customRange.length === 2) { - // 使用自定义时间范围 - 需要将系统时区时间转换为UTC - const convertToUTC = (systemTzTimeStr) => { - // 固定使用UTC+8,因为后端系统时区是UTC+8 - const systemTz = 8 - // 解析系统时区时间字符串 - const [datePart, timePart] = systemTzTimeStr.split(' ') - const [year, month, day] = datePart.split('-').map(Number) - const [hours, minutes, seconds] = timePart.split(':').map(Number) - - // 创建UTC时间,使其在系统时区显示为用户选择的时间 - // 例如:用户选择 UTC+8 的 2025-07-25 00:00:00 - // 对应的UTC时间是 2025-07-24 16:00:00 - const utcDate = new Date( - Date.UTC(year, month - 1, day, hours - systemTz, minutes, seconds) - ) - return utcDate.toISOString() - } - - url += `&startDate=${encodeURIComponent(convertToUTC(dateFilter.value.customRange[0]))}` - url += `&endDate=${encodeURIComponent(convertToUTC(dateFilter.value.customRange[1]))}` + // 使用自定义时间范围 - 按系统时区字符串直传 + url += `&startDate=${encodeURIComponent(dateFilter.value.customRange[0])}` + url += `&endDate=${encodeURIComponent(dateFilter.value.customRange[1])}` } else { // 使用预设计算时间范围,与setDateFilterPreset保持一致 const now = new Date() @@ -604,20 +558,8 @@ export const useDashboardStore = defineStore('dashboard', () => { url += `granularity=hour` if (dateFilter.value.customRange && dateFilter.value.customRange.length === 2) { - const convertToUTC = (systemTzTimeStr) => { - const systemTz = 8 - const [datePart, timePart] = systemTzTimeStr.split(' ') - const [year, month, day] = datePart.split('-').map(Number) - const [hours, minutes, seconds] = timePart.split(':').map(Number) - - const utcDate = new Date( - Date.UTC(year, month - 1, day, hours - systemTz, minutes, seconds) - ) - return utcDate.toISOString() - } - - url += `&startDate=${encodeURIComponent(convertToUTC(dateFilter.value.customRange[0]))}` - url += `&endDate=${encodeURIComponent(convertToUTC(dateFilter.value.customRange[1]))}` + url += `&startDate=${encodeURIComponent(dateFilter.value.customRange[0])}` + url += `&endDate=${encodeURIComponent(dateFilter.value.customRange[1])}` } else { const now = new Date() let startTime @@ -750,17 +692,14 @@ export const useDashboardStore = defineStore('dashboard', () => { } const formatDateForDisplay = (date) => { - // 固定使用UTC+8来显示时间 - const systemTz = 8 - const tzOffset = systemTz * 60 * 60 * 1000 - const localTime = new Date(date.getTime() + tzOffset) - - const year = localTime.getUTCFullYear() - const month = String(localTime.getUTCMonth() + 1).padStart(2, '0') - const day = String(localTime.getUTCDate()).padStart(2, '0') - const hours = String(localTime.getUTCHours()).padStart(2, '0') - const minutes = String(localTime.getUTCMinutes()).padStart(2, '0') - const seconds = String(localTime.getUTCSeconds()).padStart(2, '0') + // 使用本地时间直接格式化,避免多余的时区偏移导致日期错位 + const localTime = new Date(date) + const year = localTime.getFullYear() + const month = String(localTime.getMonth() + 1).padStart(2, '0') + const day = String(localTime.getDate()).padStart(2, '0') + const hours = String(localTime.getHours()).padStart(2, '0') + const minutes = String(localTime.getMinutes()).padStart(2, '0') + const seconds = String(localTime.getSeconds()).padStart(2, '0') return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}` } diff --git a/web/admin-spa/src/views/DashboardView.vue b/web/admin-spa/src/views/DashboardView.vue index 61ac8124..84d60d27 100644 --- a/web/admin-spa/src/views/DashboardView.vue +++ b/web/admin-spa/src/views/DashboardView.vue @@ -1036,6 +1036,7 @@ function createUsageTrendChart() { type: 'linear', display: true, position: 'left', + min: 0, title: { display: true, text: 'Token数量', @@ -1055,6 +1056,7 @@ function createUsageTrendChart() { type: 'linear', display: true, position: 'right', + min: 0, title: { display: true, text: '请求数', @@ -1073,7 +1075,8 @@ function createUsageTrendChart() { y2: { type: 'linear', display: false, // 隐藏费用轴,在tooltip中显示 - position: 'right' + position: 'right', + min: 0 } } } @@ -1253,6 +1256,7 @@ function createApiKeysUsageTrendChart() { }, y: { beginAtZero: true, + min: 0, title: { display: true, text: apiKeysTrendMetric.value === 'tokens' ? 'Token 数量' : '请求次数', @@ -1428,6 +1432,7 @@ function createAccountUsageTrendChart() { }, y: { beginAtZero: true, + min: 0, title: { display: true, text: '消耗金额 (USD)',