diff --git a/tenant-platform/src/api/bugcollect.ts b/tenant-platform/src/api/bugcollect.ts new file mode 100644 index 0000000..3fd6449 --- /dev/null +++ b/tenant-platform/src/api/bugcollect.ts @@ -0,0 +1,146 @@ +import client from './client' + +// ── Types ─────────────────────────────────────────────────────────────────── + +export interface BugCollectOverview { + totalIssues: number + todayNewIssues: number + affectedUsers: number + crashRate: number + crashRateTrend: { date: string; rate: number }[] + topIssues: { id: string; title: string; type: string; count: number }[] +} + +export interface BugCollectIssue { + id: string + title: string + type: string + platform: string + count: number + affectedUsers: number + lastSeenAt: string + firstSeenAt: string + status: string +} + +export interface BugCollectIssueDetail { + id: string + title: string + type: string + platform: string + appVersion: string + osVersion: string + deviceModel: string + count: number + affectedUsers: number + firstSeenAt: string + lastSeenAt: string + status: string + stackTrace: string + sourceContext?: { line: number; content: string; highlight: boolean }[] + recentEvents: BugCollectEventItem[] +} + +export interface BugCollectEventItem { + id: string + eventName: string + userId: string + timestamp: string + properties: Record +} + +export interface BugCollectIssueRanking { + id: string + title: string + type: string + platform: string + count: number + affectedUsers: number + riskScore?: number + lastSeenAt: string +} + +export interface BugCollectFunnelStep { + eventName: string + count: number + conversionRate: number +} + +export interface BugCollectWebhook { + id: string + url: string + eventTypes: string[] + cooldownSeconds: number + enabled: boolean + createdAt: string + updatedAt: string +} + +export interface BugCollectPageResult { + content: T[] + page: number + size: number + totalElements: number + totalPages: number +} + +// ── API ───────────────────────────────────────────────────────────────────── + +export const bugCollectApi = { + // Overview + overview: () => client.get<{ data: BugCollectOverview }>('/bugcollect/v1/overview'), + + // Issues + issues(params: { + type?: string + platform?: string + startDate?: string + endDate?: string + page?: number + size?: number + }) { + return client.get<{ data: BugCollectPageResult }>('/bugcollect/v1/issues', { params }) + }, + + issueDetail(id: string) { + return client.get<{ data: BugCollectIssueDetail }>(`/bugcollect/v1/issues/${id}`) + }, + + // Rankings + frequencyRanking() { + return client.get<{ data: BugCollectIssueRanking[] }>('/bugcollect/v1/issues/rankings/frequency') + }, + + riskRanking() { + return client.get<{ data: BugCollectIssueRanking[] }>('/bugcollect/v1/issues/rankings/risk') + }, + + // Events + events(params: { + eventName?: string + userId?: string + startDate?: string + endDate?: string + page?: number + size?: number + }) { + return client.get<{ data: BugCollectPageResult }>('/bugcollect/v1/events', { params }) + }, + + // Funnel + funnel(steps: string[]) { + return client.get<{ data: BugCollectFunnelStep[] }>('/bugcollect/v1/events/funnel', { + params: { steps: steps.join(',') }, + }) + }, + + // Webhooks + webhooks: { + list: () => client.get<{ data: BugCollectWebhook[] }>('/bugcollect/v1/webhooks'), + create: (data: Omit) => + client.post<{ data: BugCollectWebhook }>('/bugcollect/v1/webhooks', data), + update: (id: string, data: Partial>) => + client.put<{ data: BugCollectWebhook }>(`/bugcollect/v1/webhooks/${id}`, data), + delete: (id: string) => client.delete(`/bugcollect/v1/webhooks/${id}`), + }, +} diff --git a/tenant-platform/src/router/index.ts b/tenant-platform/src/router/index.ts index 98e73fd..f36c012 100644 --- a/tenant-platform/src/router/index.ts +++ b/tenant-platform/src/router/index.ts @@ -113,38 +113,38 @@ const router = createRouter({ path: 'accounts', component: () => import('@/views/accounts/SubAccountView.vue'), }, - // ── 日志监控 ──────────────────────────────────────────────── + // ── Bug 收集 ───────────────────────────────────────────────── { - path: 'log/overview', - component: () => import('@/views/log-monitor/LogOverview.vue'), + path: 'bugcollect/overview', + component: () => import('@/views/bug-collect/BugCollectOverview.vue'), }, { - path: 'log/issues', - component: () => import('@/views/log-monitor/LogIssues.vue'), + path: 'bugcollect/issues', + component: () => import('@/views/bug-collect/BugCollectIssues.vue'), }, { - path: 'log/issues/:id', - component: () => import('@/views/log-monitor/LogIssueDetail.vue'), + path: 'bugcollect/issues/:id', + component: () => import('@/views/bug-collect/BugCollectIssueDetail.vue'), }, { - path: 'log/events', - component: () => import('@/views/log-monitor/LogEvents.vue'), + path: 'bugcollect/events', + component: () => import('@/views/bug-collect/BugCollectEvents.vue'), }, { - path: 'log/funnels', - component: () => import('@/views/log-monitor/LogFunnels.vue'), + path: 'bugcollect/funnels', + component: () => import('@/views/bug-collect/BugCollectFunnels.vue'), }, { - path: 'log/webhooks', - component: () => import('@/views/log-monitor/LogWebhooks.vue'), + path: 'bugcollect/webhooks', + component: () => import('@/views/bug-collect/BugCollectWebhooks.vue'), }, { - path: 'log/rank/freq', - component: () => import('@/views/log-monitor/LogRankFreq.vue'), + path: 'bugcollect/rank/freq', + component: () => import('@/views/bug-collect/BugCollectRankFreq.vue'), }, { - path: 'log/rank/risk', - component: () => import('@/views/log-monitor/LogRankRisk.vue'), + path: 'bugcollect/rank/risk', + component: () => import('@/views/bug-collect/BugCollectRankRisk.vue'), }, ], }, diff --git a/tenant-platform/src/views/bug-collect/BugCollectEvents.vue b/tenant-platform/src/views/bug-collect/BugCollectEvents.vue new file mode 100644 index 0000000..3e82480 --- /dev/null +++ b/tenant-platform/src/views/bug-collect/BugCollectEvents.vue @@ -0,0 +1,150 @@ + + + + + diff --git a/tenant-platform/src/views/bug-collect/BugCollectFunnels.vue b/tenant-platform/src/views/bug-collect/BugCollectFunnels.vue new file mode 100644 index 0000000..0c6f650 --- /dev/null +++ b/tenant-platform/src/views/bug-collect/BugCollectFunnels.vue @@ -0,0 +1,120 @@ + + + + + diff --git a/tenant-platform/src/views/bug-collect/BugCollectIssueDetail.vue b/tenant-platform/src/views/bug-collect/BugCollectIssueDetail.vue new file mode 100644 index 0000000..2d94887 --- /dev/null +++ b/tenant-platform/src/views/bug-collect/BugCollectIssueDetail.vue @@ -0,0 +1,159 @@ + + + + + diff --git a/tenant-platform/src/views/bug-collect/BugCollectIssues.vue b/tenant-platform/src/views/bug-collect/BugCollectIssues.vue new file mode 100644 index 0000000..d47cc41 --- /dev/null +++ b/tenant-platform/src/views/bug-collect/BugCollectIssues.vue @@ -0,0 +1,151 @@ + + + + + diff --git a/tenant-platform/src/views/bug-collect/BugCollectOverview.vue b/tenant-platform/src/views/bug-collect/BugCollectOverview.vue new file mode 100644 index 0000000..13b198b --- /dev/null +++ b/tenant-platform/src/views/bug-collect/BugCollectOverview.vue @@ -0,0 +1,169 @@ + + + + + diff --git a/tenant-platform/src/views/bug-collect/BugCollectRankFreq.vue b/tenant-platform/src/views/bug-collect/BugCollectRankFreq.vue new file mode 100644 index 0000000..2359a99 --- /dev/null +++ b/tenant-platform/src/views/bug-collect/BugCollectRankFreq.vue @@ -0,0 +1,72 @@ + + + + + diff --git a/tenant-platform/src/views/bug-collect/BugCollectRankRisk.vue b/tenant-platform/src/views/bug-collect/BugCollectRankRisk.vue new file mode 100644 index 0000000..114ea05 --- /dev/null +++ b/tenant-platform/src/views/bug-collect/BugCollectRankRisk.vue @@ -0,0 +1,84 @@ + + + + + diff --git a/tenant-platform/src/views/bug-collect/BugCollectWebhooks.vue b/tenant-platform/src/views/bug-collect/BugCollectWebhooks.vue new file mode 100644 index 0000000..3c338be --- /dev/null +++ b/tenant-platform/src/views/bug-collect/BugCollectWebhooks.vue @@ -0,0 +1,153 @@ + + + + + diff --git a/tenant-platform/src/views/layout/MainLayout.vue b/tenant-platform/src/views/layout/MainLayout.vue index 94ec27d..76bb75d 100644 --- a/tenant-platform/src/views/layout/MainLayout.vue +++ b/tenant-platform/src/views/layout/MainLayout.vue @@ -29,15 +29,15 @@ 数据库管理 操作日志 - - - 概览 - 错误列表 - 事件流水 - 漏斗分析 - 高频排行 - 高危排行 - Webhook + + + 概览 + 错误列表 + 事件流水 + 漏斗分析 + 高频排行 + 高危排行 + Webhook 子账号管理 @@ -79,15 +79,15 @@ 数据库管理 操作日志 - - - 概览 - 错误列表 - 事件流水 - 漏斗分析 - 高频排行 - 高危排行 - Webhook + + + 概览 + 错误列表 + 事件流水 + 漏斗分析 + 高频排行 + 高危排行 + Webhook 子账号管理 @@ -150,7 +150,7 @@ const openedMenus = computed(() => { const menus: string[] = [] if (route.path.startsWith('/services/')) menus.push('services') if (['/system-logs', '/database', '/operation-logs'].includes(route.path)) menus.push('ops') - if (route.path.startsWith('/log/')) menus.push('log-monitor') + if (route.path.startsWith('/bugcollect/')) menus.push('bug-collect') return menus }) diff --git a/tenant-platform/vite.config.ts b/tenant-platform/vite.config.ts index d05ff28..8e67f7d 100644 --- a/tenant-platform/vite.config.ts +++ b/tenant-platform/vite.config.ts @@ -42,7 +42,7 @@ export default defineConfig(({ mode }) => { server: { port: 5173, proxy: { - '/api/log': { + '/api/bugcollect': { target: 'http://127.0.0.1:8087', changeOrigin: true, },