mirror of
https://github.com/Wei-Shaw/claude-relay-service.git
synced 2026-01-22 16:43:35 +00:00
feat: 仪表盘日期筛选默认今日并记忆用户偏好
This commit is contained in:
@@ -67,22 +67,72 @@ export const useDashboardStore = defineStore('dashboard', () => {
|
|||||||
groupLabel: 'Claude账户'
|
groupLabel: 'Claude账户'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 本地偏好
|
||||||
|
const STORAGE_KEYS = {
|
||||||
|
preset: 'dashboard:date:preset',
|
||||||
|
granularity: 'dashboard:trend:granularity'
|
||||||
|
}
|
||||||
|
const defaultPreset = 'today'
|
||||||
|
const defaultGranularity = 'day'
|
||||||
|
|
||||||
|
const getPresetOptions = (granularity) =>
|
||||||
|
granularity === 'hour'
|
||||||
|
? [
|
||||||
|
{ value: 'last24h', label: '近24小时', hours: 24 },
|
||||||
|
{ value: 'yesterday', label: '昨天', hours: 24 },
|
||||||
|
{ value: 'dayBefore', label: '前天', hours: 24 }
|
||||||
|
]
|
||||||
|
: [
|
||||||
|
{ value: 'today', label: '今日', days: 1 },
|
||||||
|
{ value: '7days', label: '7天', days: 7 },
|
||||||
|
{ value: '30days', label: '30天', days: 30 }
|
||||||
|
]
|
||||||
|
|
||||||
|
const readFromStorage = (key, fallback) => {
|
||||||
|
try {
|
||||||
|
const value = localStorage.getItem(key)
|
||||||
|
return value || fallback
|
||||||
|
} catch (error) {
|
||||||
|
return fallback
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const saveToStorage = (key, value) => {
|
||||||
|
try {
|
||||||
|
localStorage.setItem(key, value)
|
||||||
|
} catch (error) {
|
||||||
|
// 忽略存储错误,避免影响渲染
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const normalizePresetForGranularity = (preset, granularity) => {
|
||||||
|
const options = getPresetOptions(granularity)
|
||||||
|
const hasPreset = options.some((opt) => opt.value === preset)
|
||||||
|
if (hasPreset) return preset
|
||||||
|
return granularity === 'hour' ? 'last24h' : defaultPreset
|
||||||
|
}
|
||||||
|
|
||||||
|
const storedGranularity = readFromStorage(STORAGE_KEYS.granularity, defaultGranularity)
|
||||||
|
const initialGranularity = ['day', 'hour'].includes(storedGranularity)
|
||||||
|
? storedGranularity
|
||||||
|
: defaultGranularity
|
||||||
|
const initialPreset = normalizePresetForGranularity(
|
||||||
|
readFromStorage(STORAGE_KEYS.preset, defaultPreset),
|
||||||
|
initialGranularity
|
||||||
|
)
|
||||||
|
|
||||||
// 日期筛选
|
// 日期筛选
|
||||||
const dateFilter = ref({
|
const dateFilter = ref({
|
||||||
type: 'preset', // preset 或 custom
|
type: 'preset', // preset 或 custom
|
||||||
preset: '7days', // today, 7days, 30days
|
preset: initialPreset, // today, 7days, 30days
|
||||||
customStart: '',
|
customStart: '',
|
||||||
customEnd: '',
|
customEnd: '',
|
||||||
customRange: null,
|
customRange: null,
|
||||||
presetOptions: [
|
presetOptions: getPresetOptions(initialGranularity)
|
||||||
{ value: 'today', label: '今日', days: 1 },
|
|
||||||
{ value: '7days', label: '7天', days: 7 },
|
|
||||||
{ value: '30days', label: '30天', days: 30 }
|
|
||||||
]
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// 趋势图粒度
|
// 趋势图粒度
|
||||||
const trendGranularity = ref('day') // 'day' 或 'hour'
|
const trendGranularity = ref(initialGranularity) // 'day' 或 'hour'
|
||||||
const apiKeysTrendMetric = ref('requests') // 'requests' 或 'tokens'
|
const apiKeysTrendMetric = ref('requests') // 'requests' 或 'tokens'
|
||||||
const accountUsageGroup = ref('claude') // claude | openai | gemini
|
const accountUsageGroup = ref('claude') // claude | openai | gemini
|
||||||
|
|
||||||
@@ -138,6 +188,21 @@ export const useDashboardStore = defineStore('dashboard', () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const persistDatePreferences = (
|
||||||
|
preset = dateFilter.value.preset,
|
||||||
|
granularity = trendGranularity.value
|
||||||
|
) => {
|
||||||
|
saveToStorage(STORAGE_KEYS.preset, preset)
|
||||||
|
saveToStorage(STORAGE_KEYS.granularity, granularity)
|
||||||
|
}
|
||||||
|
|
||||||
|
const getEffectiveGranularity = () =>
|
||||||
|
dateFilter.value.type === 'preset' &&
|
||||||
|
dateFilter.value.preset === 'today' &&
|
||||||
|
trendGranularity.value === 'day'
|
||||||
|
? 'hour'
|
||||||
|
: trendGranularity.value
|
||||||
|
|
||||||
// 方法
|
// 方法
|
||||||
async function loadDashboardData(timeRange = null) {
|
async function loadDashboardData(timeRange = null) {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
@@ -232,7 +297,7 @@ export const useDashboardStore = defineStore('dashboard', () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadUsageTrend(days = 7, granularity = 'day') {
|
async function loadUsageTrend(days = 7, granularity = getEffectiveGranularity()) {
|
||||||
try {
|
try {
|
||||||
let url = '/admin/usage-trend?'
|
let url = '/admin/usage-trend?'
|
||||||
|
|
||||||
@@ -268,6 +333,12 @@ export const useDashboardStore = defineStore('dashboard', () => {
|
|||||||
|
|
||||||
if (dateFilter.value.type === 'preset') {
|
if (dateFilter.value.type === 'preset') {
|
||||||
switch (dateFilter.value.preset) {
|
switch (dateFilter.value.preset) {
|
||||||
|
case 'today': {
|
||||||
|
// 今日:使用系统时区的当日0点-23:59
|
||||||
|
startTime = getSystemTimezoneDay(now, true)
|
||||||
|
endTime = getSystemTimezoneDay(now, false)
|
||||||
|
break
|
||||||
|
}
|
||||||
case 'last24h': {
|
case 'last24h': {
|
||||||
// 近24小时:从当前时间往前推24小时
|
// 近24小时:从当前时间往前推24小时
|
||||||
endTime = new Date(now)
|
endTime = new Date(now)
|
||||||
@@ -318,12 +389,13 @@ export const useDashboardStore = defineStore('dashboard', () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadModelStats(period = 'daily') {
|
async function loadModelStats(period = 'daily', granularity = null) {
|
||||||
|
const currentGranularity = granularity || getEffectiveGranularity()
|
||||||
try {
|
try {
|
||||||
let url = `/admin/model-stats?period=${period}`
|
let url = `/admin/model-stats?period=${period}`
|
||||||
|
|
||||||
// 如果是自定义时间范围或小时粒度,传递具体的时间参数
|
// 如果是自定义时间范围或小时粒度,传递具体的时间参数
|
||||||
if (dateFilter.value.type === 'custom' || trendGranularity.value === 'hour') {
|
if (dateFilter.value.type === 'custom' || currentGranularity === 'hour') {
|
||||||
if (dateFilter.value.customRange && dateFilter.value.customRange.length === 2) {
|
if (dateFilter.value.customRange && dateFilter.value.customRange.length === 2) {
|
||||||
// 将系统时区时间转换为UTC
|
// 将系统时区时间转换为UTC
|
||||||
const convertToUTC = (systemTzTimeStr) => {
|
const convertToUTC = (systemTzTimeStr) => {
|
||||||
@@ -340,12 +412,17 @@ export const useDashboardStore = defineStore('dashboard', () => {
|
|||||||
|
|
||||||
url += `&startDate=${encodeURIComponent(convertToUTC(dateFilter.value.customRange[0]))}`
|
url += `&startDate=${encodeURIComponent(convertToUTC(dateFilter.value.customRange[0]))}`
|
||||||
url += `&endDate=${encodeURIComponent(convertToUTC(dateFilter.value.customRange[1]))}`
|
url += `&endDate=${encodeURIComponent(convertToUTC(dateFilter.value.customRange[1]))}`
|
||||||
} else if (trendGranularity.value === 'hour' && dateFilter.value.type === 'preset') {
|
} else if (currentGranularity === 'hour' && dateFilter.value.type === 'preset') {
|
||||||
// 小时粒度的预设时间范围
|
// 小时粒度的预设时间范围
|
||||||
const now = new Date()
|
const now = new Date()
|
||||||
let startTime, endTime
|
let startTime, endTime
|
||||||
|
|
||||||
switch (dateFilter.value.preset) {
|
switch (dateFilter.value.preset) {
|
||||||
|
case 'today': {
|
||||||
|
startTime = getSystemTimezoneDay(now, true)
|
||||||
|
endTime = getSystemTimezoneDay(now, false)
|
||||||
|
break
|
||||||
|
}
|
||||||
case 'last24h': {
|
case 'last24h': {
|
||||||
endTime = new Date(now)
|
endTime = new Date(now)
|
||||||
startTime = new Date(now.getTime() - 24 * 60 * 60 * 1000)
|
startTime = new Date(now.getTime() - 24 * 60 * 60 * 1000)
|
||||||
@@ -374,7 +451,7 @@ export const useDashboardStore = defineStore('dashboard', () => {
|
|||||||
url += `&startDate=${encodeURIComponent(startTime.toISOString())}`
|
url += `&startDate=${encodeURIComponent(startTime.toISOString())}`
|
||||||
url += `&endDate=${encodeURIComponent(endTime.toISOString())}`
|
url += `&endDate=${encodeURIComponent(endTime.toISOString())}`
|
||||||
}
|
}
|
||||||
} else if (dateFilter.value.type === 'preset' && trendGranularity.value === 'day') {
|
} else if (dateFilter.value.type === 'preset' && currentGranularity === 'day') {
|
||||||
// 天粒度的预设时间范围,需要传递startDate和endDate参数
|
// 天粒度的预设时间范围,需要传递startDate和endDate参数
|
||||||
const now = new Date()
|
const now = new Date()
|
||||||
let startDate, endDate
|
let startDate, endDate
|
||||||
@@ -409,12 +486,13 @@ export const useDashboardStore = defineStore('dashboard', () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadApiKeysTrend(metric = 'requests') {
|
async function loadApiKeysTrend(metric = 'requests', granularity = null) {
|
||||||
|
const currentGranularity = granularity || getEffectiveGranularity()
|
||||||
try {
|
try {
|
||||||
let url = '/admin/api-keys-usage-trend?'
|
let url = '/admin/api-keys-usage-trend?'
|
||||||
let days = 7
|
let days = 7
|
||||||
|
|
||||||
if (trendGranularity.value === 'hour') {
|
if (currentGranularity === 'hour') {
|
||||||
// 小时粒度,计算时间范围
|
// 小时粒度,计算时间范围
|
||||||
url += `granularity=hour`
|
url += `granularity=hour`
|
||||||
|
|
||||||
@@ -446,6 +524,11 @@ export const useDashboardStore = defineStore('dashboard', () => {
|
|||||||
|
|
||||||
if (dateFilter.value.type === 'preset') {
|
if (dateFilter.value.type === 'preset') {
|
||||||
switch (dateFilter.value.preset) {
|
switch (dateFilter.value.preset) {
|
||||||
|
case 'today': {
|
||||||
|
startTime = getSystemTimezoneDay(now, true)
|
||||||
|
endTime = getSystemTimezoneDay(now, false)
|
||||||
|
break
|
||||||
|
}
|
||||||
case 'last24h': {
|
case 'last24h': {
|
||||||
// 近24小时:从当前时间往前推24小时
|
// 近24小时:从当前时间往前推24小时
|
||||||
endTime = new Date(now)
|
endTime = new Date(now)
|
||||||
@@ -511,12 +594,13 @@ export const useDashboardStore = defineStore('dashboard', () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadAccountUsageTrend(group = accountUsageGroup.value) {
|
async function loadAccountUsageTrend(group = accountUsageGroup.value, granularity = null) {
|
||||||
|
const currentGranularity = granularity || getEffectiveGranularity()
|
||||||
try {
|
try {
|
||||||
let url = '/admin/account-usage-trend?'
|
let url = '/admin/account-usage-trend?'
|
||||||
let days = 7
|
let days = 7
|
||||||
|
|
||||||
if (trendGranularity.value === 'hour') {
|
if (currentGranularity === 'hour') {
|
||||||
url += `granularity=hour`
|
url += `granularity=hour`
|
||||||
|
|
||||||
if (dateFilter.value.customRange && dateFilter.value.customRange.length === 2) {
|
if (dateFilter.value.customRange && dateFilter.value.customRange.length === 2) {
|
||||||
@@ -541,6 +625,11 @@ export const useDashboardStore = defineStore('dashboard', () => {
|
|||||||
|
|
||||||
if (dateFilter.value.type === 'preset') {
|
if (dateFilter.value.type === 'preset') {
|
||||||
switch (dateFilter.value.preset) {
|
switch (dateFilter.value.preset) {
|
||||||
|
case 'today': {
|
||||||
|
startTime = getSystemTimezoneDay(now, true)
|
||||||
|
endTime = getSystemTimezoneDay(now, false)
|
||||||
|
break
|
||||||
|
}
|
||||||
case 'last24h': {
|
case 'last24h': {
|
||||||
endTime = new Date(now)
|
endTime = new Date(now)
|
||||||
startTime = new Date(now.getTime() - 24 * 60 * 60 * 1000)
|
startTime = new Date(now.getTime() - 24 * 60 * 60 * 1000)
|
||||||
@@ -603,110 +692,90 @@ export const useDashboardStore = defineStore('dashboard', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 日期筛选相关方法
|
// 日期筛选相关方法
|
||||||
function setDateFilterPreset(preset) {
|
function setDateFilterPreset(preset, options = {}) {
|
||||||
|
const { silent = false, skipSave = false } = options
|
||||||
|
const normalizedPreset = normalizePresetForGranularity(preset, trendGranularity.value)
|
||||||
|
|
||||||
dateFilter.value.type = 'preset'
|
dateFilter.value.type = 'preset'
|
||||||
dateFilter.value.preset = preset
|
dateFilter.value.preset = normalizedPreset
|
||||||
|
|
||||||
// 根据预设计算并设置具体的日期范围
|
const option = dateFilter.value.presetOptions.find((opt) => opt.value === normalizedPreset)
|
||||||
const option = dateFilter.value.presetOptions.find((opt) => opt.value === preset)
|
const now = new Date()
|
||||||
if (option) {
|
let startDate
|
||||||
const now = new Date()
|
let endDate
|
||||||
let startDate, endDate
|
|
||||||
|
|
||||||
if (trendGranularity.value === 'hour') {
|
if (trendGranularity.value === 'hour') {
|
||||||
// 小时粒度的预设
|
switch (normalizedPreset) {
|
||||||
switch (preset) {
|
case 'today': {
|
||||||
case 'last24h': {
|
startDate = getSystemTimezoneDay(now, true)
|
||||||
// 近24小时:从当前时间往前推24小时
|
endDate = getSystemTimezoneDay(now, false)
|
||||||
endDate = new Date(now)
|
break
|
||||||
startDate = new Date(now.getTime() - 24 * 60 * 60 * 1000)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
case 'yesterday': {
|
|
||||||
// 昨天:获取本地时间的昨天
|
|
||||||
const yesterday = new Date()
|
|
||||||
yesterday.setDate(yesterday.getDate() - 1)
|
|
||||||
// 转换为系统时区的昨天0点和23:59
|
|
||||||
startDate = getSystemTimezoneDay(yesterday, true)
|
|
||||||
endDate = getSystemTimezoneDay(yesterday, false)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
case 'dayBefore': {
|
|
||||||
// 前天:获取本地时间的前天
|
|
||||||
const dayBefore = new Date()
|
|
||||||
dayBefore.setDate(dayBefore.getDate() - 2)
|
|
||||||
// 转换为系统时区的前天0点和23:59
|
|
||||||
startDate = getSystemTimezoneDay(dayBefore, true)
|
|
||||||
endDate = getSystemTimezoneDay(dayBefore, false)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
case 'last24h': {
|
||||||
// 天粒度的预设
|
endDate = new Date(now)
|
||||||
startDate = new Date(now)
|
startDate = new Date(now.getTime() - 24 * 60 * 60 * 1000)
|
||||||
endDate = new Date(now)
|
break
|
||||||
|
}
|
||||||
if (preset === 'today') {
|
case 'yesterday': {
|
||||||
// 今日:从凌晨开始
|
const yesterday = new Date()
|
||||||
startDate.setHours(0, 0, 0, 0)
|
yesterday.setDate(yesterday.getDate() - 1)
|
||||||
endDate.setHours(23, 59, 59, 999)
|
startDate = getSystemTimezoneDay(yesterday, true)
|
||||||
} else {
|
endDate = getSystemTimezoneDay(yesterday, false)
|
||||||
// 其他预设:按天数计算
|
break
|
||||||
startDate.setDate(now.getDate() - (option.days - 1))
|
}
|
||||||
startDate.setHours(0, 0, 0, 0)
|
case 'dayBefore': {
|
||||||
endDate.setHours(23, 59, 59, 999)
|
const dayBefore = new Date()
|
||||||
|
dayBefore.setDate(dayBefore.getDate() - 2)
|
||||||
|
startDate = getSystemTimezoneDay(dayBefore, true)
|
||||||
|
endDate = getSystemTimezoneDay(dayBefore, false)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
endDate = new Date(now)
|
||||||
|
startDate = new Date(now.getTime() - 24 * 60 * 60 * 1000)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
startDate = new Date(now)
|
||||||
|
endDate = new Date(now)
|
||||||
|
|
||||||
dateFilter.value.customStart = startDate.toISOString().split('T')[0]
|
if (normalizedPreset === 'today') {
|
||||||
dateFilter.value.customEnd = endDate.toISOString().split('T')[0]
|
startDate.setHours(0, 0, 0, 0)
|
||||||
|
endDate.setHours(23, 59, 59, 999)
|
||||||
// 设置 customRange 为 Element Plus 需要的格式
|
} else if (option?.days) {
|
||||||
// 对于小时粒度的昨天/前天,需要特殊处理显示
|
startDate.setDate(now.getDate() - (option.days - 1))
|
||||||
if (trendGranularity.value === 'hour' && (preset === 'yesterday' || preset === 'dayBefore')) {
|
startDate.setHours(0, 0, 0, 0)
|
||||||
// 获取本地日期
|
endDate.setHours(23, 59, 59, 999)
|
||||||
const targetDate = new Date()
|
|
||||||
if (preset === 'yesterday') {
|
|
||||||
targetDate.setDate(targetDate.getDate() - 1)
|
|
||||||
} else {
|
|
||||||
targetDate.setDate(targetDate.getDate() - 2)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 显示系统时区的完整一天
|
|
||||||
const year = targetDate.getFullYear()
|
|
||||||
const month = String(targetDate.getMonth() + 1).padStart(2, '0')
|
|
||||||
const day = String(targetDate.getDate()).padStart(2, '0')
|
|
||||||
|
|
||||||
dateFilter.value.customRange = [
|
|
||||||
`${year}-${month}-${day} 00:00:00`,
|
|
||||||
`${year}-${month}-${day} 23:59:59`
|
|
||||||
]
|
|
||||||
} else {
|
|
||||||
// 其他情况:近24小时或天粒度
|
|
||||||
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')
|
|
||||||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
|
|
||||||
}
|
|
||||||
|
|
||||||
dateFilter.value.customRange = [
|
|
||||||
formatDateForDisplay(startDate),
|
|
||||||
formatDateForDisplay(endDate)
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 触发数据刷新
|
const formatDateForDisplay = (date) => {
|
||||||
refreshChartsData()
|
// 固定使用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')
|
||||||
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
|
||||||
|
}
|
||||||
|
|
||||||
|
dateFilter.value.customStart = startDate ? startDate.toISOString().split('T')[0] : ''
|
||||||
|
dateFilter.value.customEnd = endDate ? endDate.toISOString().split('T')[0] : ''
|
||||||
|
dateFilter.value.customRange =
|
||||||
|
startDate && endDate ? [formatDateForDisplay(startDate), formatDateForDisplay(endDate)] : null
|
||||||
|
|
||||||
|
if (!skipSave) {
|
||||||
|
persistDatePreferences(dateFilter.value.preset, trendGranularity.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!silent) {
|
||||||
|
refreshChartsData()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onCustomDateRangeChange(value) {
|
function onCustomDateRangeChange(value) {
|
||||||
@@ -751,20 +820,17 @@ export const useDashboardStore = defineStore('dashboard', () => {
|
|||||||
refreshChartsData()
|
refreshChartsData()
|
||||||
} else if (value === null) {
|
} else if (value === null) {
|
||||||
// 清空时恢复默认
|
// 清空时恢复默认
|
||||||
setDateFilterPreset(trendGranularity.value === 'hour' ? 'last24h' : '7days')
|
setDateFilterPreset(trendGranularity.value === 'hour' ? 'last24h' : defaultPreset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setTrendGranularity(granularity) {
|
function setTrendGranularity(granularity, options = {}) {
|
||||||
|
const { silent = false, skipSave = false, presetOverride } = options
|
||||||
trendGranularity.value = granularity
|
trendGranularity.value = granularity
|
||||||
|
|
||||||
// 根据粒度更新预设选项
|
// 根据粒度更新预设选项
|
||||||
if (granularity === 'hour') {
|
if (granularity === 'hour') {
|
||||||
dateFilter.value.presetOptions = [
|
dateFilter.value.presetOptions = getPresetOptions('hour')
|
||||||
{ value: 'last24h', label: '近24小时', hours: 24 },
|
|
||||||
{ value: 'yesterday', label: '昨天', hours: 24 },
|
|
||||||
{ value: 'dayBefore', label: '前天', hours: 24 }
|
|
||||||
]
|
|
||||||
|
|
||||||
// 检查当前自定义日期范围是否超过24小时
|
// 检查当前自定义日期范围是否超过24小时
|
||||||
if (
|
if (
|
||||||
@@ -777,46 +843,53 @@ export const useDashboardStore = defineStore('dashboard', () => {
|
|||||||
const hoursDiff = (end - start) / (1000 * 60 * 60)
|
const hoursDiff = (end - start) / (1000 * 60 * 60)
|
||||||
if (hoursDiff > 24) {
|
if (hoursDiff > 24) {
|
||||||
showToast('小时粒度下日期范围不能超过24小时,已切换到近24小时', 'warning')
|
showToast('小时粒度下日期范围不能超过24小时,已切换到近24小时', 'warning')
|
||||||
setDateFilterPreset('last24h')
|
setDateFilterPreset('last24h', { silent, skipSave })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果当前是天粒度的预设,切换到小时粒度的默认预设
|
|
||||||
if (['today', '7days', '30days'].includes(dateFilter.value.preset)) {
|
|
||||||
setDateFilterPreset('last24h')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// 天粒度
|
// 天粒度
|
||||||
dateFilter.value.presetOptions = [
|
dateFilter.value.presetOptions = getPresetOptions('day')
|
||||||
{ value: 'today', label: '今日', days: 1 },
|
|
||||||
{ value: '7days', label: '7天', days: 7 },
|
|
||||||
{ value: '30days', label: '30天', days: 30 }
|
|
||||||
]
|
|
||||||
|
|
||||||
// 如果当前是小时粒度的预设,切换到天粒度的默认预设
|
|
||||||
if (['last24h', 'yesterday', 'dayBefore'].includes(dateFilter.value.preset)) {
|
|
||||||
setDateFilterPreset('7days')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 触发数据刷新
|
if (dateFilter.value.type === 'custom') {
|
||||||
refreshChartsData()
|
if (!skipSave) {
|
||||||
|
persistDatePreferences(dateFilter.value.preset || defaultPreset, trendGranularity.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!silent) {
|
||||||
|
refreshChartsData()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const nextPreset =
|
||||||
|
presetOverride ||
|
||||||
|
normalizePresetForGranularity(dateFilter.value.preset, trendGranularity.value)
|
||||||
|
|
||||||
|
setDateFilterPreset(nextPreset, { silent: true, skipSave: true })
|
||||||
|
|
||||||
|
if (!skipSave) {
|
||||||
|
persistDatePreferences(dateFilter.value.preset, trendGranularity.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!silent) {
|
||||||
|
refreshChartsData()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function refreshChartsData() {
|
async function refreshChartsData() {
|
||||||
// 根据当前筛选条件刷新数据
|
// 根据当前筛选条件刷新数据
|
||||||
let days
|
let days
|
||||||
let modelPeriod = 'monthly'
|
let modelPeriod = 'monthly'
|
||||||
|
const effectiveGranularity = getEffectiveGranularity()
|
||||||
|
|
||||||
if (dateFilter.value.type === 'preset') {
|
if (dateFilter.value.type === 'preset') {
|
||||||
const option = dateFilter.value.presetOptions.find(
|
const option = dateFilter.value.presetOptions.find(
|
||||||
(opt) => opt.value === dateFilter.value.preset
|
(opt) => opt.value === dateFilter.value.preset
|
||||||
)
|
)
|
||||||
|
|
||||||
if (trendGranularity.value === 'hour') {
|
if (effectiveGranularity === 'hour') {
|
||||||
// 小时粒度
|
// 小时粒度
|
||||||
days = 1 // 小时粒度默认查看1天的数据
|
days = 1 // 小时粒度默认查看1天的数据
|
||||||
modelPeriod = 'daily' // 小时粒度使用日统计
|
modelPeriod = 'daily' // 小时粒度使用日统计
|
||||||
@@ -832,7 +905,7 @@ export const useDashboardStore = defineStore('dashboard', () => {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 自定义日期范围
|
// 自定义日期范围
|
||||||
if (trendGranularity.value === 'hour') {
|
if (effectiveGranularity === 'hour') {
|
||||||
// 小时粒度下的自定义范围,计算小时数
|
// 小时粒度下的自定义范围,计算小时数
|
||||||
const start = new Date(dateFilter.value.customRange[0])
|
const start = new Date(dateFilter.value.customRange[0])
|
||||||
const end = new Date(dateFilter.value.customRange[1])
|
const end = new Date(dateFilter.value.customRange[1])
|
||||||
@@ -845,16 +918,16 @@ export const useDashboardStore = defineStore('dashboard', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
loadUsageTrend(days, trendGranularity.value),
|
loadUsageTrend(days, effectiveGranularity),
|
||||||
loadModelStats(modelPeriod),
|
loadModelStats(modelPeriod, effectiveGranularity),
|
||||||
loadApiKeysTrend(apiKeysTrendMetric.value),
|
loadApiKeysTrend(apiKeysTrendMetric.value, effectiveGranularity),
|
||||||
loadAccountUsageTrend(accountUsageGroup.value)
|
loadAccountUsageTrend(accountUsageGroup.value, effectiveGranularity)
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
function setAccountUsageGroup(group) {
|
function setAccountUsageGroup(group) {
|
||||||
accountUsageGroup.value = group
|
accountUsageGroup.value = group
|
||||||
return loadAccountUsageTrend(group)
|
return loadAccountUsageTrend(group, getEffectiveGranularity())
|
||||||
}
|
}
|
||||||
|
|
||||||
function calculateDaysBetween(start, end) {
|
function calculateDaysBetween(start, end) {
|
||||||
@@ -870,6 +943,10 @@ export const useDashboardStore = defineStore('dashboard', () => {
|
|||||||
return date > new Date()
|
return date > new Date()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 初始化日期筛选:同步本地偏好并填充范围
|
||||||
|
setDateFilterPreset(dateFilter.value.preset, { silent: true, skipSave: true })
|
||||||
|
persistDatePreferences(dateFilter.value.preset, trendGranularity.value)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
// 状态
|
// 状态
|
||||||
loading,
|
loading,
|
||||||
|
|||||||
Reference in New Issue
Block a user