- 移除 Motia Streams 实时通信,改用 3 秒轮询 - 简化前端代码,移除冗余组件 - 简化后端架构,准备 FastAPI 重构 - 更新 pixi.toml 环境配置 - 保留 bttoxin_digger_v5_repro 作为参考文档 Co-Authored-By: Claude <noreply@anthropic.com>
225 lines
5.4 KiB
Markdown
225 lines
5.4 KiB
Markdown
# Frontend Agent Guide
|
|
|
|
## Overview
|
|
|
|
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
|
|
- **UI Library**: Element Plus
|
|
- **State Management**: Pinia
|
|
- **Routing**: Vue Router 4
|
|
- **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/
|
|
│ │ ├── 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)
|
|
|
|
```bash
|
|
# Install dependencies
|
|
pixi run fe-install
|
|
|
|
# Start dev server (http://localhost:5173)
|
|
pixi run fe-dev
|
|
|
|
# Build for production
|
|
pixi run fe-build
|
|
|
|
# Run tests
|
|
pixi run fe-test
|
|
|
|
# Lint code
|
|
pixi run fe-lint
|
|
```
|
|
|
|
### Via pnpm directly
|
|
|
|
```bash
|
|
cd frontend
|
|
pnpm install
|
|
pnpm dev --host
|
|
pnpm build
|
|
pnpm test:unit
|
|
pnpm lint
|
|
```
|
|
|
|
## Coding Conventions
|
|
|
|
### Component Patterns
|
|
|
|
- Use `<script setup lang="ts">` for all components
|
|
- 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 (`TaskSubmitForm.vue`)
|
|
- Composables: camelCase with `use` prefix
|
|
- Utilities: camelCase (`task.ts`)
|
|
- Types: camelCase (`task.ts`)
|
|
|
|
### State Management
|
|
|
|
- Use Pinia stores for global 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/*.spec.ts`.
|
|
|
|
```bash
|
|
# Run all tests
|
|
pixi run fe-test
|
|
|
|
# Run tests in watch mode
|
|
cd frontend && pnpm test:unit
|
|
```
|
|
|
|
## Environment Variables
|
|
|
|
| Variable | Default | Description |
|
|
|----------|---------|-------------|
|
|
| `VITE_API_BASE_URL` | http://localhost:8000 | Backend API URL |
|
|
|
|
## Common Tasks
|
|
|
|
### Adding a New Parameter
|
|
|
|
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
|