# Dashboard Design Specification ## Overview Dashboard 是用户进入系统后的第一个页面,用于快速了解: - 数据标注质量和进度 - 当前模型状态和性能 - 系统最近发生的活动 **目标用户**:使用文档标注系统的客户,需要监控文档处理状态、标注质量和模型训练进度。 --- ## 1. UI Layout ### 1.1 Overall Structure ``` +------------------------------------------------------------------+ | Header: Logo + Navigation + User Menu | +------------------------------------------------------------------+ | | | Stats Cards Row (4 cards, equal width) | | | | +---------------------------+ +------------------------------+ | | | Data Quality Panel (50%) | | Active Model Panel (50%) | | | +---------------------------+ +------------------------------+ | | | | +--------------------------------------------------------------+ | | | Recent Activity Panel (full width) | | | +--------------------------------------------------------------+ | | | | +--------------------------------------------------------------+ | | | System Status Bar (full width) | | | +--------------------------------------------------------------+ | +------------------------------------------------------------------+ ``` ### 1.2 Responsive Breakpoints | Breakpoint | Layout | |------------|--------| | Desktop (>1200px) | 4 cards row, 2-column panels | | Tablet (768-1200px) | 2x2 cards, 2-column panels | | Mobile (<768px) | 1 card per row, stacked panels | --- ## 2. Component Specifications ### 2.1 Stats Cards Row 4 个等宽卡片,显示核心统计数据。 ``` +-------------+ +-------------+ +-------------+ +-------------+ | [icon] | | [icon] | | [icon] | | [icon] | | 38 | | 25 | | 8 | | 5 | | Total Docs | | Complete | | Incomplete | | Pending | +-------------+ +-------------+ +-------------+ +-------------+ ``` | Card | Icon | Value | Label | Color | Click Action | |------|------|-------|-------|-------|--------------| | Total Documents | FileText | `total_documents` | "Total Documents" | Gray | Navigate to Documents page | | Complete | CheckCircle | `annotation_complete` | "Complete" | Green | Navigate to Documents (filter: complete) | | Incomplete | AlertCircle | `annotation_incomplete` | "Incomplete" | Orange | Navigate to Documents (filter: incomplete) | | Pending | Clock | `pending` | "Pending" | Blue | Navigate to Documents (filter: pending) | **Card Design:** - Background: White with subtle border - Icon: 24px, positioned top-left - Value: 32px bold font - Label: 14px muted color - Hover: Slight shadow elevation - Padding: 16px ### 2.2 Data Quality Panel 左侧面板,显示标注完整度和质量指标。 ``` +---------------------------+ | DATA QUALITY | | +-----------+ | | | | | | | 78% | Annotation | | | | Complete | | +-----------+ | | | | Complete: 25 | | Incomplete: 8 | | Pending: 5 | | | | [View Incomplete Docs] | +---------------------------+ ``` **Components:** | Element | Spec | |---------|------| | Title | "DATA QUALITY", 14px uppercase, muted | | Progress Ring | 120px diameter, stroke width 12px | | Percentage | 36px bold, centered in ring | | Label | "Annotation Complete", 14px, below ring | | Stats List | 14px, icon + label + value per row | | Action Button | Text button, primary color | **Progress Ring Colors:** - Complete portion: Green (#22C55E) - Remaining: Gray (#E5E7EB) **Completeness Calculation:** ``` completeness_rate = annotation_complete / (annotation_complete + annotation_incomplete) * 100 ``` ### 2.3 Active Model Panel 右侧面板,显示当前生产模型信息。 ``` +-------------------------------+ | ACTIVE MODEL | | | | v1.2.0 - Invoice Model | | ----------------------------- | | | | mAP Precision Recall | | 95.1% 94% 92% | | | | Activated: 2024-01-20 | | Documents: 500 | | | | [Training] Run-2024-02 [====] | +-------------------------------+ ``` **Components:** | Element | Spec | |---------|------| | Title | "ACTIVE MODEL", 14px uppercase, muted | | Version + Name | 18px bold (version) + 16px regular (name) | | Divider | 1px border, full width | | Metrics Row | 3 columns, equal width | | Metric Value | 24px bold | | Metric Label | 12px muted, below value | | Info Rows | 14px, label: value format | | Training Indicator | Shows when training is running | **Metric Colors:** - mAP >= 90%: Green - mAP 80-90%: Yellow - mAP < 80%: Red **Empty State (No Active Model):** ``` +-------------------------------+ | ACTIVE MODEL | | | | [icon: Model] | | No Active Model | | | | Train and activate a | | model to see stats here | | | | [Go to Training] | +-------------------------------+ ``` **Training In Progress:** ``` | Training: Run-2024-02 | | [=========> ] 45% | | Started 2 hours ago | ``` ### 2.4 Recent Activity Panel 全宽面板,显示最近 10 条系统活动。 ``` +--------------------------------------------------------------+ | RECENT ACTIVITY [See All] | +--------------------------------------------------------------+ | [rocket] Activated model v1.2.0 2 hours ago| | [check] Training complete: Run-2024-01, mAP 95.1% yesterday| | [edit] Modified INV-001.pdf invoice_number yesterday| | [doc] Uploaded INV-005.pdf 2 days ago| | [doc] Uploaded INV-004.pdf 2 days ago| | [x] Training failed: Run-2024-00 3 days ago| +--------------------------------------------------------------+ ``` **Activity Item Layout:** ``` [Icon] [Description] [Timestamp] ``` | Element | Spec | |---------|------| | Icon | 16px, color based on type | | Description | 14px, truncate if too long | | Timestamp | 12px muted, right-aligned | | Row Height | 40px | | Hover | Background highlight | **Activity Types and Icons:** | Type | Icon | Color | Description Format | |------|------|-------|-------------------| | document_uploaded | FileText | Blue | "Uploaded {filename}" | | annotation_modified | Edit | Orange | "Modified {filename} {field_name}" | | training_completed | CheckCircle | Green | "Training complete: {task_name}, mAP {mAP}%" | | training_failed | XCircle | Red | "Training failed: {task_name}" | | model_activated | Rocket | Purple | "Activated model {version}" | **Timestamp Formatting:** - < 1 minute: "just now" - < 1 hour: "{n} minutes ago" - < 24 hours: "{n} hours ago" - < 7 days: "yesterday" / "{n} days ago" - >= 7 days: "Jan 15" (date format) **Empty State:** ``` +--------------------------------------------------------------+ | RECENT ACTIVITY | | | | [icon: Activity] | | No recent activity | | | | Start by uploading documents or creating training jobs | +--------------------------------------------------------------+ ``` ### 2.5 System Status Bar 底部状态栏,显示系统健康状态。 ``` +--------------------------------------------------------------+ | Backend API: [*] Online Database: [*] Connected GPU: [*] Available | +--------------------------------------------------------------+ ``` | Status | Icon | Color | |--------|------|-------| | Online/Connected/Available | Filled circle | Green | | Degraded/Slow | Filled circle | Yellow | | Offline/Error/Unavailable | Filled circle | Red | --- ## 3. API Endpoints ### 3.1 Dashboard Statistics ``` GET /api/v1/admin/dashboard/stats ``` **Response:** ```json { "total_documents": 38, "annotation_complete": 25, "annotation_incomplete": 8, "pending": 5, "completeness_rate": 75.76 } ``` **Calculation Logic:** ```python # annotation_complete: labeled documents with core fields SELECT COUNT(*) FROM admin_documents d WHERE d.status = 'labeled' AND EXISTS ( SELECT 1 FROM admin_annotations a WHERE a.document_id = d.document_id AND a.class_id IN (0, 3) -- invoice_number OR ocr_number ) AND EXISTS ( SELECT 1 FROM admin_annotations a WHERE a.document_id = d.document_id AND a.class_id IN (4, 5) -- bankgiro OR plusgiro ) # annotation_incomplete: labeled but missing core fields SELECT COUNT(*) FROM admin_documents d WHERE d.status = 'labeled' AND NOT (/* above conditions */) # pending: pending + auto_labeling SELECT COUNT(*) FROM admin_documents WHERE status IN ('pending', 'auto_labeling') ``` ### 3.2 Active Model Info ``` GET /api/v1/admin/dashboard/active-model ``` **Response (with active model):** ```json { "model": { "version_id": "uuid", "version": "1.2.0", "name": "Invoice Model", "metrics_mAP": 0.951, "metrics_precision": 0.94, "metrics_recall": 0.92, "document_count": 500, "activated_at": "2024-01-20T15:00:00Z" }, "running_training": { "task_id": "uuid", "name": "Run-2024-02", "status": "running", "started_at": "2024-01-25T10:00:00Z", "progress": 45 } } ``` **Response (no active model):** ```json { "model": null, "running_training": null } ``` ### 3.3 Recent Activity ``` GET /api/v1/admin/dashboard/activity?limit=10 ``` **Response:** ```json { "activities": [ { "type": "model_activated", "description": "Activated model v1.2.0", "timestamp": "2024-01-25T12:00:00Z", "metadata": { "version_id": "uuid", "version": "1.2.0" } }, { "type": "training_completed", "description": "Training complete: Run-2024-01, mAP 95.1%", "timestamp": "2024-01-24T18:30:00Z", "metadata": { "task_id": "uuid", "task_name": "Run-2024-01", "mAP": 0.951 } } ] } ``` **Activity Aggregation Query:** ```sql -- Union all activity sources, ordered by timestamp DESC, limit 10 ( SELECT 'document_uploaded' as type, filename as entity_name, created_at as timestamp, document_id as entity_id FROM admin_documents ORDER BY created_at DESC LIMIT 10 ) UNION ALL ( SELECT 'annotation_modified' as type, -- join to get filename and field name ... FROM annotation_history ORDER BY created_at DESC LIMIT 10 ) UNION ALL ( SELECT CASE WHEN status = 'completed' THEN 'training_completed' WHEN status = 'failed' THEN 'training_failed' END as type, name as entity_name, completed_at as timestamp, task_id as entity_id FROM training_tasks WHERE status IN ('completed', 'failed') ORDER BY completed_at DESC LIMIT 10 ) UNION ALL ( SELECT 'model_activated' as type, version as entity_name, activated_at as timestamp, version_id as entity_id FROM model_versions WHERE activated_at IS NOT NULL ORDER BY activated_at DESC LIMIT 10 ) ORDER BY timestamp DESC LIMIT 10 ``` --- ## 4. UX Interactions ### 4.1 Loading States | Component | Loading State | |-----------|--------------| | Stats Cards | Skeleton placeholder (gray boxes) | | Data Quality Ring | Skeleton circle | | Active Model | Skeleton lines | | Recent Activity | Skeleton list items (5 rows) | **Loading Duration Thresholds:** - < 300ms: No loading state shown - 300ms - 3s: Show skeleton - > 3s: Show skeleton + "Taking longer than expected" message ### 4.2 Error States | Error Type | Display | |------------|---------| | API Error | Toast notification + retry button in affected panel | | Network Error | Full page overlay with retry option | | Partial Failure | Show available data, error badge on failed sections | ### 4.3 Refresh Behavior | Trigger | Behavior | |---------|----------| | Page Load | Fetch all data | | Manual Refresh | Button in header, refetch all | | Auto Refresh | Every 30 seconds for activity panel | | Focus Return | Refetch if page was hidden > 5 minutes | ### 4.4 Click Actions | Element | Action | |---------|--------| | Total Documents card | Navigate to `/documents` | | Complete card | Navigate to `/documents?filter=complete` | | Incomplete card | Navigate to `/documents?filter=incomplete` | | Pending card | Navigate to `/documents?filter=pending` | | "View Incomplete Docs" button | Navigate to `/documents?filter=incomplete` | | Activity item | Navigate to related entity | | "Go to Training" button | Navigate to `/training` | | Active Model version | Navigate to `/models/{version_id}` | ### 4.5 Tooltips | Element | Tooltip Content | |---------|----------------| | Completeness % | "25 of 33 labeled documents have complete annotations" | | mAP metric | "Mean Average Precision at IoU 0.5" | | Precision metric | "Proportion of correct positive predictions" | | Recall metric | "Proportion of actual positives correctly identified" | | Incomplete count | "Documents labeled but missing invoice_number/ocr_number or bankgiro/plusgiro" | --- ## 5. Data Model ### 5.1 TypeScript Types ```typescript // Dashboard Stats interface DashboardStats { total_documents: number; annotation_complete: number; annotation_incomplete: number; pending: number; completeness_rate: number; } // Active Model interface ActiveModelInfo { model: ModelVersion | null; running_training: RunningTraining | null; } interface ModelVersion { version_id: string; version: string; name: string; metrics_mAP: number; metrics_precision: number; metrics_recall: number; document_count: number; activated_at: string; } interface RunningTraining { task_id: string; name: string; status: 'running'; started_at: string; progress: number; } // Activity interface Activity { type: ActivityType; description: string; timestamp: string; metadata: Record; } type ActivityType = | 'document_uploaded' | 'annotation_modified' | 'training_completed' | 'training_failed' | 'model_activated'; // Activity Response interface ActivityResponse { activities: Activity[]; } ``` ### 5.2 React Query Hooks ```typescript // useDashboardStats const useDashboardStats = () => { return useQuery({ queryKey: ['dashboard', 'stats'], queryFn: () => api.get('/admin/dashboard/stats'), refetchInterval: 30000, // 30 seconds }); }; // useActiveModel const useActiveModel = () => { return useQuery({ queryKey: ['dashboard', 'active-model'], queryFn: () => api.get('/admin/dashboard/active-model'), refetchInterval: 60000, // 1 minute }); }; // useRecentActivity const useRecentActivity = (limit = 10) => { return useQuery({ queryKey: ['dashboard', 'activity', limit], queryFn: () => api.get(`/admin/dashboard/activity?limit=${limit}`), refetchInterval: 30000, }); }; ``` --- ## 6. Annotation Completeness Definition ### 6.1 Core Fields A document is **complete** when it has annotations for: | Requirement | Fields | Logic | |-------------|--------|-------| | Identifier | `invoice_number` (class_id=0) OR `ocr_number` (class_id=3) | At least one | | Payment Account | `bankgiro` (class_id=4) OR `plusgiro` (class_id=5) | At least one | ### 6.2 Status Categories | Category | Criteria | |----------|----------| | **Complete** | status=labeled AND has identifier AND has payment account | | **Incomplete** | status=labeled AND (missing identifier OR missing payment account) | | **Pending** | status IN (pending, auto_labeling) | ### 6.3 Filter Implementation ```sql -- Complete documents WHERE status = 'labeled' AND document_id IN ( SELECT document_id FROM admin_annotations WHERE class_id IN (0, 3) ) AND document_id IN ( SELECT document_id FROM admin_annotations WHERE class_id IN (4, 5) ) -- Incomplete documents WHERE status = 'labeled' AND ( document_id NOT IN ( SELECT document_id FROM admin_annotations WHERE class_id IN (0, 3) ) OR document_id NOT IN ( SELECT document_id FROM admin_annotations WHERE class_id IN (4, 5) ) ) ``` --- ## 7. Implementation Checklist ### Backend - [ ] Create `/api/v1/admin/dashboard/stats` endpoint - [ ] Create `/api/v1/admin/dashboard/active-model` endpoint - [ ] Create `/api/v1/admin/dashboard/activity` endpoint - [ ] Add completeness calculation logic to document repository - [ ] Implement activity aggregation query ### Frontend - [ ] Create `DashboardOverview` component - [ ] Create `StatsCard` component - [ ] Create `DataQualityPanel` component with progress ring - [ ] Create `ActiveModelPanel` component - [ ] Create `RecentActivityPanel` component - [ ] Create `SystemStatusBar` component - [ ] Add React Query hooks for dashboard data - [ ] Implement loading skeletons - [ ] Implement error states - [ ] Add navigation actions - [ ] Add tooltips ### Testing - [ ] Unit tests for completeness calculation - [ ] Unit tests for activity aggregation - [ ] Integration tests for dashboard endpoints - [ ] E2E tests for dashboard interactions