fix(admin): 修复使用记录页面趋势图筛选联动和日期选择问题
修复两个问题: 1. Token使用趋势图和模型分布图未响应筛选条件 2. 上午时段选择今天刷新后日期回退到前一天 前端修改: - 更新 dashboard API 类型定义,添加 model、account_id、group_id、stream 参数支持 - 修改 UsageView 趋势图加载逻辑,传递所有筛选参数到后端 - 修复日期格式化函数,使用本地时区避免 UTC 转换导致的日期偏移 后端修改: - Handler 层:接收并解析所有筛选参数(model、account_id、group_id、stream) - Service 层:传递完整的筛选参数到 Repository 层 - Repository 层:SQL 查询动态添加所有过滤条件 - 更新接口定义和所有调用点以保持一致性 影响范围: - /admin/dashboard/trend 端点现支持完整筛选 - /admin/dashboard/models 端点现支持完整筛选 - 用户在后台使用记录页面选择任意筛选条件时,趋势图和模型分布图会实时响应 - 日期选择器在任何时区下都能正确保持今天的选择
This commit is contained in:
@@ -186,13 +186,16 @@ func (h *DashboardHandler) GetRealtimeMetrics(c *gin.Context) {
|
|||||||
|
|
||||||
// GetUsageTrend handles getting usage trend data
|
// GetUsageTrend handles getting usage trend data
|
||||||
// GET /api/v1/admin/dashboard/trend
|
// GET /api/v1/admin/dashboard/trend
|
||||||
// Query params: start_date, end_date (YYYY-MM-DD), granularity (day/hour), user_id, api_key_id
|
// Query params: start_date, end_date (YYYY-MM-DD), granularity (day/hour), user_id, api_key_id, model, account_id, group_id, stream
|
||||||
func (h *DashboardHandler) GetUsageTrend(c *gin.Context) {
|
func (h *DashboardHandler) GetUsageTrend(c *gin.Context) {
|
||||||
startTime, endTime := parseTimeRange(c)
|
startTime, endTime := parseTimeRange(c)
|
||||||
granularity := c.DefaultQuery("granularity", "day")
|
granularity := c.DefaultQuery("granularity", "day")
|
||||||
|
|
||||||
// Parse optional filter params
|
// Parse optional filter params
|
||||||
var userID, apiKeyID int64
|
var userID, apiKeyID, accountID, groupID int64
|
||||||
|
var model string
|
||||||
|
var stream *bool
|
||||||
|
|
||||||
if userIDStr := c.Query("user_id"); userIDStr != "" {
|
if userIDStr := c.Query("user_id"); userIDStr != "" {
|
||||||
if id, err := strconv.ParseInt(userIDStr, 10, 64); err == nil {
|
if id, err := strconv.ParseInt(userIDStr, 10, 64); err == nil {
|
||||||
userID = id
|
userID = id
|
||||||
@@ -203,8 +206,26 @@ func (h *DashboardHandler) GetUsageTrend(c *gin.Context) {
|
|||||||
apiKeyID = id
|
apiKeyID = id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if accountIDStr := c.Query("account_id"); accountIDStr != "" {
|
||||||
|
if id, err := strconv.ParseInt(accountIDStr, 10, 64); err == nil {
|
||||||
|
accountID = id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if groupIDStr := c.Query("group_id"); groupIDStr != "" {
|
||||||
|
if id, err := strconv.ParseInt(groupIDStr, 10, 64); err == nil {
|
||||||
|
groupID = id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if modelStr := c.Query("model"); modelStr != "" {
|
||||||
|
model = modelStr
|
||||||
|
}
|
||||||
|
if streamStr := c.Query("stream"); streamStr != "" {
|
||||||
|
if streamVal, err := strconv.ParseBool(streamStr); err == nil {
|
||||||
|
stream = &streamVal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
trend, err := h.dashboardService.GetUsageTrendWithFilters(c.Request.Context(), startTime, endTime, granularity, userID, apiKeyID)
|
trend, err := h.dashboardService.GetUsageTrendWithFilters(c.Request.Context(), startTime, endTime, granularity, userID, apiKeyID, accountID, groupID, model, stream)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.Error(c, 500, "Failed to get usage trend")
|
response.Error(c, 500, "Failed to get usage trend")
|
||||||
return
|
return
|
||||||
@@ -220,12 +241,14 @@ func (h *DashboardHandler) GetUsageTrend(c *gin.Context) {
|
|||||||
|
|
||||||
// GetModelStats handles getting model usage statistics
|
// GetModelStats handles getting model usage statistics
|
||||||
// GET /api/v1/admin/dashboard/models
|
// GET /api/v1/admin/dashboard/models
|
||||||
// Query params: start_date, end_date (YYYY-MM-DD), user_id, api_key_id
|
// Query params: start_date, end_date (YYYY-MM-DD), user_id, api_key_id, account_id, group_id, stream
|
||||||
func (h *DashboardHandler) GetModelStats(c *gin.Context) {
|
func (h *DashboardHandler) GetModelStats(c *gin.Context) {
|
||||||
startTime, endTime := parseTimeRange(c)
|
startTime, endTime := parseTimeRange(c)
|
||||||
|
|
||||||
// Parse optional filter params
|
// Parse optional filter params
|
||||||
var userID, apiKeyID int64
|
var userID, apiKeyID, accountID, groupID int64
|
||||||
|
var stream *bool
|
||||||
|
|
||||||
if userIDStr := c.Query("user_id"); userIDStr != "" {
|
if userIDStr := c.Query("user_id"); userIDStr != "" {
|
||||||
if id, err := strconv.ParseInt(userIDStr, 10, 64); err == nil {
|
if id, err := strconv.ParseInt(userIDStr, 10, 64); err == nil {
|
||||||
userID = id
|
userID = id
|
||||||
@@ -236,8 +259,23 @@ func (h *DashboardHandler) GetModelStats(c *gin.Context) {
|
|||||||
apiKeyID = id
|
apiKeyID = id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if accountIDStr := c.Query("account_id"); accountIDStr != "" {
|
||||||
|
if id, err := strconv.ParseInt(accountIDStr, 10, 64); err == nil {
|
||||||
|
accountID = id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if groupIDStr := c.Query("group_id"); groupIDStr != "" {
|
||||||
|
if id, err := strconv.ParseInt(groupIDStr, 10, 64); err == nil {
|
||||||
|
groupID = id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if streamStr := c.Query("stream"); streamStr != "" {
|
||||||
|
if streamVal, err := strconv.ParseBool(streamStr); err == nil {
|
||||||
|
stream = &streamVal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
stats, err := h.dashboardService.GetModelStatsWithFilters(c.Request.Context(), startTime, endTime, userID, apiKeyID)
|
stats, err := h.dashboardService.GetModelStatsWithFilters(c.Request.Context(), startTime, endTime, userID, apiKeyID, accountID, groupID, stream)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.Error(c, 500, "Failed to get model statistics")
|
response.Error(c, 500, "Failed to get model statistics")
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -1400,8 +1400,8 @@ func (r *usageLogRepository) GetBatchAPIKeyUsageStats(ctx context.Context, apiKe
|
|||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUsageTrendWithFilters returns usage trend data with optional user/api_key filters
|
// GetUsageTrendWithFilters returns usage trend data with optional filters
|
||||||
func (r *usageLogRepository) GetUsageTrendWithFilters(ctx context.Context, startTime, endTime time.Time, granularity string, userID, apiKeyID int64) (results []TrendDataPoint, err error) {
|
func (r *usageLogRepository) GetUsageTrendWithFilters(ctx context.Context, startTime, endTime time.Time, granularity string, userID, apiKeyID, accountID, groupID int64, model string, stream *bool) (results []TrendDataPoint, err error) {
|
||||||
dateFormat := "YYYY-MM-DD"
|
dateFormat := "YYYY-MM-DD"
|
||||||
if granularity == "hour" {
|
if granularity == "hour" {
|
||||||
dateFormat = "YYYY-MM-DD HH24:00"
|
dateFormat = "YYYY-MM-DD HH24:00"
|
||||||
@@ -1430,6 +1430,22 @@ func (r *usageLogRepository) GetUsageTrendWithFilters(ctx context.Context, start
|
|||||||
query += fmt.Sprintf(" AND api_key_id = $%d", len(args)+1)
|
query += fmt.Sprintf(" AND api_key_id = $%d", len(args)+1)
|
||||||
args = append(args, apiKeyID)
|
args = append(args, apiKeyID)
|
||||||
}
|
}
|
||||||
|
if accountID > 0 {
|
||||||
|
query += fmt.Sprintf(" AND account_id = $%d", len(args)+1)
|
||||||
|
args = append(args, accountID)
|
||||||
|
}
|
||||||
|
if groupID > 0 {
|
||||||
|
query += fmt.Sprintf(" AND group_id = $%d", len(args)+1)
|
||||||
|
args = append(args, groupID)
|
||||||
|
}
|
||||||
|
if model != "" {
|
||||||
|
query += fmt.Sprintf(" AND model = $%d", len(args)+1)
|
||||||
|
args = append(args, model)
|
||||||
|
}
|
||||||
|
if stream != nil {
|
||||||
|
query += fmt.Sprintf(" AND stream = $%d", len(args)+1)
|
||||||
|
args = append(args, *stream)
|
||||||
|
}
|
||||||
query += " GROUP BY date ORDER BY date ASC"
|
query += " GROUP BY date ORDER BY date ASC"
|
||||||
|
|
||||||
rows, err := r.sql.QueryContext(ctx, query, args...)
|
rows, err := r.sql.QueryContext(ctx, query, args...)
|
||||||
@@ -1452,8 +1468,8 @@ func (r *usageLogRepository) GetUsageTrendWithFilters(ctx context.Context, start
|
|||||||
return results, nil
|
return results, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetModelStatsWithFilters returns model statistics with optional user/api_key filters
|
// GetModelStatsWithFilters returns model statistics with optional filters
|
||||||
func (r *usageLogRepository) GetModelStatsWithFilters(ctx context.Context, startTime, endTime time.Time, userID, apiKeyID, accountID int64) (results []ModelStat, err error) {
|
func (r *usageLogRepository) GetModelStatsWithFilters(ctx context.Context, startTime, endTime time.Time, userID, apiKeyID, accountID, groupID int64, stream *bool) (results []ModelStat, err error) {
|
||||||
query := `
|
query := `
|
||||||
SELECT
|
SELECT
|
||||||
model,
|
model,
|
||||||
@@ -1480,6 +1496,14 @@ func (r *usageLogRepository) GetModelStatsWithFilters(ctx context.Context, start
|
|||||||
query += fmt.Sprintf(" AND account_id = $%d", len(args)+1)
|
query += fmt.Sprintf(" AND account_id = $%d", len(args)+1)
|
||||||
args = append(args, accountID)
|
args = append(args, accountID)
|
||||||
}
|
}
|
||||||
|
if groupID > 0 {
|
||||||
|
query += fmt.Sprintf(" AND group_id = $%d", len(args)+1)
|
||||||
|
args = append(args, groupID)
|
||||||
|
}
|
||||||
|
if stream != nil {
|
||||||
|
query += fmt.Sprintf(" AND stream = $%d", len(args)+1)
|
||||||
|
args = append(args, *stream)
|
||||||
|
}
|
||||||
query += " GROUP BY model ORDER BY total_tokens DESC"
|
query += " GROUP BY model ORDER BY total_tokens DESC"
|
||||||
|
|
||||||
rows, err := r.sql.QueryContext(ctx, query, args...)
|
rows, err := r.sql.QueryContext(ctx, query, args...)
|
||||||
@@ -1767,7 +1791,7 @@ func (r *usageLogRepository) GetAccountUsageStats(ctx context.Context, accountID
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
models, err := r.GetModelStatsWithFilters(ctx, startTime, endTime, 0, 0, accountID)
|
models, err := r.GetModelStatsWithFilters(ctx, startTime, endTime, 0, 0, accountID, 0, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
models = []ModelStat{}
|
models = []ModelStat{}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ type UsageLogRepository interface {
|
|||||||
|
|
||||||
// Admin dashboard stats
|
// Admin dashboard stats
|
||||||
GetDashboardStats(ctx context.Context) (*usagestats.DashboardStats, error)
|
GetDashboardStats(ctx context.Context) (*usagestats.DashboardStats, error)
|
||||||
GetUsageTrendWithFilters(ctx context.Context, startTime, endTime time.Time, granularity string, userID, apiKeyID int64) ([]usagestats.TrendDataPoint, error)
|
GetUsageTrendWithFilters(ctx context.Context, startTime, endTime time.Time, granularity string, userID, apiKeyID, accountID, groupID int64, model string, stream *bool) ([]usagestats.TrendDataPoint, error)
|
||||||
GetModelStatsWithFilters(ctx context.Context, startTime, endTime time.Time, userID, apiKeyID, accountID int64) ([]usagestats.ModelStat, error)
|
GetModelStatsWithFilters(ctx context.Context, startTime, endTime time.Time, userID, apiKeyID, accountID, groupID int64, stream *bool) ([]usagestats.ModelStat, error)
|
||||||
GetAPIKeyUsageTrend(ctx context.Context, startTime, endTime time.Time, granularity string, limit int) ([]usagestats.APIKeyUsageTrendPoint, error)
|
GetAPIKeyUsageTrend(ctx context.Context, startTime, endTime time.Time, granularity string, limit int) ([]usagestats.APIKeyUsageTrendPoint, error)
|
||||||
GetUserUsageTrend(ctx context.Context, startTime, endTime time.Time, granularity string, limit int) ([]usagestats.UserUsageTrendPoint, error)
|
GetUserUsageTrend(ctx context.Context, startTime, endTime time.Time, granularity string, limit int) ([]usagestats.UserUsageTrendPoint, error)
|
||||||
GetBatchUserUsageStats(ctx context.Context, userIDs []int64) (map[int64]*usagestats.BatchUserUsageStats, error)
|
GetBatchUserUsageStats(ctx context.Context, userIDs []int64) (map[int64]*usagestats.BatchUserUsageStats, error)
|
||||||
@@ -266,7 +266,7 @@ func (s *AccountUsageService) getGeminiUsage(ctx context.Context, account *Accou
|
|||||||
}
|
}
|
||||||
|
|
||||||
dayStart := geminiDailyWindowStart(now)
|
dayStart := geminiDailyWindowStart(now)
|
||||||
stats, err := s.usageLogRepo.GetModelStatsWithFilters(ctx, dayStart, now, 0, 0, account.ID)
|
stats, err := s.usageLogRepo.GetModelStatsWithFilters(ctx, dayStart, now, 0, 0, account.ID, 0, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("get gemini usage stats failed: %w", err)
|
return nil, fmt.Errorf("get gemini usage stats failed: %w", err)
|
||||||
}
|
}
|
||||||
@@ -288,7 +288,7 @@ func (s *AccountUsageService) getGeminiUsage(ctx context.Context, account *Accou
|
|||||||
// Minute window (RPM) - fixed-window approximation: current minute [truncate(now), truncate(now)+1m)
|
// Minute window (RPM) - fixed-window approximation: current minute [truncate(now), truncate(now)+1m)
|
||||||
minuteStart := now.Truncate(time.Minute)
|
minuteStart := now.Truncate(time.Minute)
|
||||||
minuteResetAt := minuteStart.Add(time.Minute)
|
minuteResetAt := minuteStart.Add(time.Minute)
|
||||||
minuteStats, err := s.usageLogRepo.GetModelStatsWithFilters(ctx, minuteStart, now, 0, 0, account.ID)
|
minuteStats, err := s.usageLogRepo.GetModelStatsWithFilters(ctx, minuteStart, now, 0, 0, account.ID, 0, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("get gemini minute usage stats failed: %w", err)
|
return nil, fmt.Errorf("get gemini minute usage stats failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,16 +124,16 @@ func (s *DashboardService) GetDashboardStats(ctx context.Context) (*usagestats.D
|
|||||||
return stats, nil
|
return stats, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *DashboardService) GetUsageTrendWithFilters(ctx context.Context, startTime, endTime time.Time, granularity string, userID, apiKeyID int64) ([]usagestats.TrendDataPoint, error) {
|
func (s *DashboardService) GetUsageTrendWithFilters(ctx context.Context, startTime, endTime time.Time, granularity string, userID, apiKeyID, accountID, groupID int64, model string, stream *bool) ([]usagestats.TrendDataPoint, error) {
|
||||||
trend, err := s.usageRepo.GetUsageTrendWithFilters(ctx, startTime, endTime, granularity, userID, apiKeyID)
|
trend, err := s.usageRepo.GetUsageTrendWithFilters(ctx, startTime, endTime, granularity, userID, apiKeyID, accountID, groupID, model, stream)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("get usage trend with filters: %w", err)
|
return nil, fmt.Errorf("get usage trend with filters: %w", err)
|
||||||
}
|
}
|
||||||
return trend, nil
|
return trend, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *DashboardService) GetModelStatsWithFilters(ctx context.Context, startTime, endTime time.Time, userID, apiKeyID int64) ([]usagestats.ModelStat, error) {
|
func (s *DashboardService) GetModelStatsWithFilters(ctx context.Context, startTime, endTime time.Time, userID, apiKeyID, accountID, groupID int64, stream *bool) ([]usagestats.ModelStat, error) {
|
||||||
stats, err := s.usageRepo.GetModelStatsWithFilters(ctx, startTime, endTime, userID, apiKeyID, 0)
|
stats, err := s.usageRepo.GetModelStatsWithFilters(ctx, startTime, endTime, userID, apiKeyID, accountID, groupID, stream)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("get model stats with filters: %w", err)
|
return nil, fmt.Errorf("get model stats with filters: %w", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ func (s *RateLimitService) PreCheckUsage(ctx context.Context, account *Account,
|
|||||||
start := geminiDailyWindowStart(now)
|
start := geminiDailyWindowStart(now)
|
||||||
totals, ok := s.getGeminiUsageTotals(account.ID, start, now)
|
totals, ok := s.getGeminiUsageTotals(account.ID, start, now)
|
||||||
if !ok {
|
if !ok {
|
||||||
stats, err := s.usageRepo.GetModelStatsWithFilters(ctx, start, now, 0, 0, account.ID)
|
stats, err := s.usageRepo.GetModelStatsWithFilters(ctx, start, now, 0, 0, account.ID, 0, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return true, err
|
return true, err
|
||||||
}
|
}
|
||||||
@@ -210,7 +210,7 @@ func (s *RateLimitService) PreCheckUsage(ctx context.Context, account *Account,
|
|||||||
|
|
||||||
if limit > 0 {
|
if limit > 0 {
|
||||||
start := now.Truncate(time.Minute)
|
start := now.Truncate(time.Minute)
|
||||||
stats, err := s.usageRepo.GetModelStatsWithFilters(ctx, start, now, 0, 0, account.ID)
|
stats, err := s.usageRepo.GetModelStatsWithFilters(ctx, start, now, 0, 0, account.ID, 0, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return true, err
|
return true, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,10 @@ export interface TrendParams {
|
|||||||
granularity?: 'day' | 'hour'
|
granularity?: 'day' | 'hour'
|
||||||
user_id?: number
|
user_id?: number
|
||||||
api_key_id?: number
|
api_key_id?: number
|
||||||
|
model?: string
|
||||||
|
account_id?: number
|
||||||
|
group_id?: number
|
||||||
|
stream?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TrendResponse {
|
export interface TrendResponse {
|
||||||
@@ -70,6 +74,10 @@ export interface ModelStatsParams {
|
|||||||
end_date?: string
|
end_date?: string
|
||||||
user_id?: number
|
user_id?: number
|
||||||
api_key_id?: number
|
api_key_id?: number
|
||||||
|
model?: string
|
||||||
|
account_id?: number
|
||||||
|
group_id?: number
|
||||||
|
stream?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ModelStatsResponse {
|
export interface ModelStatsResponse {
|
||||||
|
|||||||
@@ -44,8 +44,14 @@ let abortController: AbortController | null = null; let exportAbortController: A
|
|||||||
const exportProgress = reactive({ show: false, progress: 0, current: 0, total: 0, estimatedTime: '' })
|
const exportProgress = reactive({ show: false, progress: 0, current: 0, total: 0, estimatedTime: '' })
|
||||||
|
|
||||||
const granularityOptions = computed(() => [{ value: 'day', label: t('admin.dashboard.day') }, { value: 'hour', label: t('admin.dashboard.hour') }])
|
const granularityOptions = computed(() => [{ value: 'day', label: t('admin.dashboard.day') }, { value: 'hour', label: t('admin.dashboard.hour') }])
|
||||||
const formatLD = (d: Date) => d.toISOString().split('T')[0]
|
// Use local timezone to avoid UTC timezone issues
|
||||||
const now = new Date(); const weekAgo = new Date(Date.now() - 6 * 86400000)
|
const formatLD = (d: Date) => {
|
||||||
|
const year = d.getFullYear()
|
||||||
|
const month = String(d.getMonth() + 1).padStart(2, '0')
|
||||||
|
const day = String(d.getDate()).padStart(2, '0')
|
||||||
|
return `${year}-${month}-${day}`
|
||||||
|
}
|
||||||
|
const now = new Date(); const weekAgo = new Date(); weekAgo.setDate(weekAgo.getDate() - 6)
|
||||||
const startDate = ref(formatLD(weekAgo)); const endDate = ref(formatLD(now))
|
const startDate = ref(formatLD(weekAgo)); const endDate = ref(formatLD(now))
|
||||||
const filters = ref<AdminUsageQueryParams>({ user_id: undefined, model: undefined, group_id: undefined, start_date: startDate.value, end_date: endDate.value })
|
const filters = ref<AdminUsageQueryParams>({ user_id: undefined, model: undefined, group_id: undefined, start_date: startDate.value, end_date: endDate.value })
|
||||||
const pagination = reactive({ page: 1, page_size: 20, total: 0 })
|
const pagination = reactive({ page: 1, page_size: 20, total: 0 })
|
||||||
@@ -61,8 +67,8 @@ const loadStats = async () => { try { const s = await adminAPI.usage.getStats(fi
|
|||||||
const loadChartData = async () => {
|
const loadChartData = async () => {
|
||||||
chartsLoading.value = true
|
chartsLoading.value = true
|
||||||
try {
|
try {
|
||||||
const params = { start_date: filters.value.start_date || startDate.value, end_date: filters.value.end_date || endDate.value, granularity: granularity.value, user_id: filters.value.user_id }
|
const params = { start_date: filters.value.start_date || startDate.value, end_date: filters.value.end_date || endDate.value, granularity: granularity.value, user_id: filters.value.user_id, model: filters.value.model, api_key_id: filters.value.api_key_id, account_id: filters.value.account_id, group_id: filters.value.group_id, stream: filters.value.stream }
|
||||||
const [trendRes, modelRes] = await Promise.all([adminAPI.dashboard.getUsageTrend(params), adminAPI.dashboard.getModelStats({ start_date: params.start_date, end_date: params.end_date, user_id: params.user_id })])
|
const [trendRes, modelRes] = await Promise.all([adminAPI.dashboard.getUsageTrend(params), adminAPI.dashboard.getModelStats({ start_date: params.start_date, end_date: params.end_date, user_id: params.user_id, model: params.model, api_key_id: params.api_key_id, account_id: params.account_id, group_id: params.group_id, stream: params.stream })])
|
||||||
trendData.value = trendRes.trend || []; modelStats.value = modelRes.models || []
|
trendData.value = trendRes.trend || []; modelStats.value = modelRes.models || []
|
||||||
} catch (error) { console.error('Failed to load chart data:', error) } finally { chartsLoading.value = false }
|
} catch (error) { console.error('Failed to load chart data:', error) } finally { chartsLoading.value = false }
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user