648 lines
18 KiB
Markdown
648 lines
18 KiB
Markdown
# 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<string, unknown>;
|
||
}
|
||
|
||
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
|