chore: 初始版本提交 - 简化架构 + 轮询改造
- 移除 Motia Streams 实时通信,改用 3 秒轮询 - 简化前端代码,移除冗余组件 - 简化后端架构,准备 FastAPI 重构 - 更新 pixi.toml 环境配置 - 保留 bttoxin_digger_v5_repro 作为参考文档 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -2,60 +2,83 @@
|
||||
|
||||
## Overview
|
||||
|
||||
BtToxin Task Monitor - Vue 3 frontend for submitting and monitoring BtToxin pipeline analysis tasks.
|
||||
BtToxin Pipeline Frontend - Vue 3 frontend for submitting and monitoring analysis tasks.
|
||||
|
||||
## Tech Stack
|
||||
|
||||
- **Framework**: Vue 3 (Composition API with `<script setup>`)
|
||||
- **Build Tool**: Vite 7
|
||||
- **Build Tool**: Vite
|
||||
- **UI Library**: Element Plus
|
||||
- **State Management**: Pinia
|
||||
- **Routing**: Vue Router 4
|
||||
- **HTTP Client**: Axios
|
||||
- **Testing**: Vitest + fast-check (property-based testing)
|
||||
- **HTTP Client**: fetch API (polling-based)
|
||||
- **Testing**: Vitest + fast-check
|
||||
- **Linting**: ESLint + Prettier
|
||||
|
||||
## Key Changes (v2.0)
|
||||
|
||||
### Polling vs Real-time Streams
|
||||
|
||||
The previous version used Motia Streams for real-time updates. The current version uses simple HTTP polling:
|
||||
|
||||
- **Old**: SSE/WebSocket streams for real-time updates
|
||||
- **New**: `setInterval` polling every 3 seconds
|
||||
- **Benefit**: Simpler architecture, no external dependencies
|
||||
|
||||
### Task Flow
|
||||
|
||||
```
|
||||
1. Upload .fna file
|
||||
2. POST /api/tasks -> get task_id
|
||||
3. Navigate to /{task_id}
|
||||
4. Poll GET /api/tasks/{task_id} every 3s
|
||||
5. On completion, download results
|
||||
```
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
frontend/
|
||||
├── src/
|
||||
│ ├── api/ # API client modules
|
||||
│ │ ├── http.ts # Axios instance configuration
|
||||
│ │ ├── task.ts # Task API endpoints
|
||||
│ │ ├── bttoxin.ts # BtToxin-specific API
|
||||
│ │ └── types.ts # API type definitions
|
||||
│ ├── components/ # Reusable Vue components
|
||||
│ │ └── task/ # Task-related components
|
||||
│ │ ├── TaskFlowPanel.vue
|
||||
│ │ ├── TaskStatusBar.vue
|
||||
│ │ ├── TaskStepLogDrawer.vue
|
||||
│ │ └── TaskSubmitForm.vue
|
||||
│ ├── composables/ # Vue composables (hooks)
|
||||
│ │ ├── useAsync.ts # Async operation helper
|
||||
│ │ ├── useMotiaStreams.ts # Real-time stream connection
|
||||
│ │ └── useTaskState.ts # Task state management
|
||||
│ ├── stores/ # Pinia stores
|
||||
│ │ └── toxin.ts # Toxin analysis state
|
||||
│ ├── types/ # TypeScript type definitions
|
||||
│ │ └── task.ts # Task-related types
|
||||
│ ├── utils/ # Utility functions
|
||||
│ │ ├── error.ts # Error handling utilities
|
||||
│ │ └── task.ts # Task helper functions
|
||||
│ ├── views/ # Page components
|
||||
│ │ ├
|
||||
/TaskMonitorView.vue # Task monitoring page
|
||||
│ │ └── TaskSubmitView.vue # Task submission page
|
||||
│ ├── router/ # Vue Router configuration
|
||||
│ ├── App.vue # Root component
|
||||
│ └── main.ts # Application entry point
|
||||
├── public/ # Static assets
|
||||
├── package.json # Dependencies and scripts
|
||||
├── vite.config.ts # Vite configuration
|
||||
├── vitest.config.ts # Vitest configuration
|
||||
└── tsconfig.json # TypeScript configuration
|
||||
│ ├── api/
|
||||
│ │ ├── http.ts # Axios instance (deprecated, using fetch)
|
||||
│ │ └── task.ts # Task API functions (polling-based)
|
||||
│ ├── components/
|
||||
│ │ └── task/
|
||||
│ │ ├── TaskSubmitForm.vue # Task submission form
|
||||
│ │ └── (legacy components removed)
|
||||
│ ├── composables/ # Vue composables
|
||||
│ ├── views/
|
||||
│ │ ├── TaskSubmitView.vue # Task submission page
|
||||
│ │ └── TaskMonitorView.vue # Task status page (polling)
|
||||
│ ├── types/
|
||||
│ │ └── task.ts # Task types and utilities
|
||||
│ ├── router/
|
||||
│ │ └── index.ts # Vue Router config
|
||||
│ ├── App.vue # Root component
|
||||
│ └── main.ts # Application entry point
|
||||
├── public/
|
||||
├── package.json
|
||||
├── vite.config.ts
|
||||
└── tsconfig.json
|
||||
```
|
||||
|
||||
## Pages
|
||||
|
||||
### Task Submit Page (`/`)
|
||||
|
||||
- Upload .fna file (drag & drop)
|
||||
- Configure parameters (min_identity, min_coverage, etc.)
|
||||
- Submit and navigate to task page
|
||||
|
||||
### Task Monitor Page (`/{taskId}`)
|
||||
|
||||
- Poll task status every 3 seconds
|
||||
- Display progress bar and current stage
|
||||
- Show estimated time remaining
|
||||
- Download results when complete
|
||||
- 30-day retention notice
|
||||
|
||||
## Development Commands
|
||||
|
||||
### Via pixi (recommended)
|
||||
@@ -82,7 +105,7 @@ pixi run fe-lint
|
||||
```bash
|
||||
cd frontend
|
||||
pnpm install
|
||||
pnpm dev
|
||||
pnpm dev --host
|
||||
pnpm build
|
||||
pnpm test:unit
|
||||
pnpm lint
|
||||
@@ -93,49 +116,109 @@ pnpm lint
|
||||
### Component Patterns
|
||||
|
||||
- Use `<script setup lang="ts">` for all components
|
||||
- Use Composition API with composables for reusable logic
|
||||
- Use Composition API with composables
|
||||
- Prefer `ref()` and `computed()` over reactive objects
|
||||
- Use `defineProps<T>()` and `defineEmits<T>()` for type-safe props/events
|
||||
|
||||
### File Naming
|
||||
|
||||
- Components: PascalCase (`TaskFlowPanel.vue`)
|
||||
- Composables: camelCase with `use` prefix (`useTaskState.ts`)
|
||||
- Utilities: camelCase (`error.ts`)
|
||||
- Components: PascalCase (`TaskSubmitForm.vue`)
|
||||
- Composables: camelCase with `use` prefix
|
||||
- Utilities: camelCase (`task.ts`)
|
||||
- Types: camelCase (`task.ts`)
|
||||
|
||||
### Element Plus Usage
|
||||
|
||||
- Import components via auto-import (unplugin-vue-components)
|
||||
- Use `el-` prefix components directly in templates
|
||||
- Follow Element Plus design patterns for forms and layouts
|
||||
|
||||
### State Management
|
||||
|
||||
- Use Pinia stores for global state
|
||||
- Use composables for component-local reactive state
|
||||
- Use `ref()` for component-local reactive state
|
||||
- Prefer `readonly()` when exposing state to prevent mutations
|
||||
|
||||
## API Integration
|
||||
|
||||
The frontend connects to the FastAPI backend at `VITE_API_BASE_URL` (default: http://localhost:8000).
|
||||
|
||||
```typescript
|
||||
import { createTask, getTaskStatus, downloadResult } from '@/api/task'
|
||||
|
||||
// Create task
|
||||
const response = await createTask(formData)
|
||||
// { task_id, token, status, created_at, expires_at, estimated_duration_seconds }
|
||||
|
||||
// Poll status
|
||||
const status = await getTaskStatus(taskId)
|
||||
// { task_id, status, progress, current_stage, estimated_remaining_seconds, ... }
|
||||
|
||||
// Download results
|
||||
const blob = await downloadResult(taskId)
|
||||
// Blob file for download
|
||||
```
|
||||
|
||||
## Polling Implementation
|
||||
|
||||
```typescript
|
||||
const POLL_INTERVAL = 3000 // 3 seconds
|
||||
|
||||
function startPolling(taskId: string) {
|
||||
// Initial fetch
|
||||
fetchStatus()
|
||||
|
||||
// Set up interval
|
||||
pollTimer.value = window.setInterval(() => {
|
||||
fetchStatus()
|
||||
}, POLL_INTERVAL)
|
||||
}
|
||||
|
||||
function stopPolling() {
|
||||
if (pollTimer.value) {
|
||||
clearInterval(pollTimer.value)
|
||||
pollTimer.value = null
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up on unmount
|
||||
onUnmounted(() => {
|
||||
stopPolling()
|
||||
})
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
Tests are located in `src/__tests__/` and `src/types/*.property.spec.ts`.
|
||||
Tests are located in `src/__tests__/` and `src/types/*.spec.ts`.
|
||||
|
||||
```bash
|
||||
# Run all tests
|
||||
pixi run fe-test
|
||||
|
||||
# Run tests in watch mode (use pnpm directly)
|
||||
# Run tests in watch mode
|
||||
cd frontend && pnpm test:unit
|
||||
```
|
||||
|
||||
### Property-Based Testing
|
||||
## Environment Variables
|
||||
|
||||
Uses fast-check for property-based tests. See `src/types/task.property.spec.ts` for examples.
|
||||
| Variable | Default | Description |
|
||||
|----------|---------|-------------|
|
||||
| `VITE_API_BASE_URL` | http://localhost:8000 | Backend API URL |
|
||||
|
||||
## API Integration
|
||||
## Common Tasks
|
||||
|
||||
The frontend connects to the FastAPI backend at `http://localhost:8000/api/`.
|
||||
### Adding a New Parameter
|
||||
|
||||
- Development proxy configured in `vite.config.ts`
|
||||
- API client in `src/api/http.ts`
|
||||
- Type definitions in `src/api/types.ts`
|
||||
1. Update `TaskFormData` in `TaskSubmitForm.vue`
|
||||
2. Add form field in template
|
||||
3. Update `CreateTaskRequest` in `frontend/src/types/task.ts`
|
||||
4. Update API call in `frontend/src/api/task.ts`
|
||||
|
||||
### Adding a New Pipeline Stage
|
||||
|
||||
1. Add stage to `PIPELINE_STAGES` in `frontend/src/types/task.ts`
|
||||
2. Update stage display in `TaskMonitorView.vue`
|
||||
3. Add stage handling in backend `web/backend/tasks.py`
|
||||
|
||||
## Removed Components
|
||||
|
||||
The following components were removed in v2.0:
|
||||
- `TaskFlowPanel.vue` - Replaced with simpler stage list
|
||||
- `TaskStatusBar.vue` - Integrated into TaskMonitorView
|
||||
- `TaskStepLogDrawer.vue` - No longer needed (no real-time logs)
|
||||
- `useMotiaStreams.ts` - Replaced with simple polling
|
||||
- `useTaskState.ts` - Replaced with direct API calls
|
||||
|
||||
Reference in New Issue
Block a user