polish frontend
This commit is contained in:
parent
f1ba9ff742
commit
d272a38247
214
CLAUDE.md
Normal file
214
CLAUDE.md
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
# CLAUDE.md
|
||||||
|
|
||||||
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||||
|
|
||||||
|
## Project Architecture
|
||||||
|
|
||||||
|
This is a distributed meteor monitoring network with a microservices architecture:
|
||||||
|
|
||||||
|
### Core Services
|
||||||
|
- **meteor-frontend/** - Next.js 15 frontend with React 19, TypeScript, TailwindCSS 4, and React Query
|
||||||
|
- **meteor-web-backend/** - NestJS backend API with PostgreSQL, TypeORM, JWT auth, and Stripe payments
|
||||||
|
- **meteor-compute-service/** - Go microservice for event processing with AWS SDK and PostgreSQL
|
||||||
|
- **meteor-edge-client/** - Rust edge client for Raspberry Pi devices with camera integration
|
||||||
|
|
||||||
|
### Key Technologies
|
||||||
|
- **Frontend**: Next.js 15, React 19, TypeScript, TailwindCSS 4, React Query, React Hook Form, Recharts
|
||||||
|
- **Backend**: NestJS, TypeORM, PostgreSQL, JWT, Stripe, AWS SDK (S3, SQS, CloudWatch), Pino logging
|
||||||
|
- **Processing**: Go 1.24, PostgreSQL (pgx), AWS SDK, structured logging
|
||||||
|
- **Edge**: Rust, Tokio, Serde, Reqwest, OpenCV (optional), cross-compilation for ARM64
|
||||||
|
|
||||||
|
## Development Commands
|
||||||
|
|
||||||
|
### Full Stack Development
|
||||||
|
```bash
|
||||||
|
# Start all services (frontend + backend)
|
||||||
|
npm run dev
|
||||||
|
|
||||||
|
# Start individual services
|
||||||
|
npm run dev:frontend # Next.js on port 3000
|
||||||
|
npm run dev:backend # NestJS on port 3000 (with CORS for frontend)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Building
|
||||||
|
```bash
|
||||||
|
npm run build # Build all services
|
||||||
|
npm run build:frontend # Build Next.js app
|
||||||
|
npm run build:backend # Build NestJS app
|
||||||
|
```
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
```bash
|
||||||
|
# Complete test suite
|
||||||
|
npm run test:fullstack # All tests: unit + integration + e2e
|
||||||
|
|
||||||
|
# Individual test types
|
||||||
|
npm run test # Unit tests for both frontend and backend
|
||||||
|
npm run test:frontend # Jest tests for React components
|
||||||
|
npm run test:backend # Jest tests for NestJS services
|
||||||
|
npm run test:e2e # Playwright E2E tests
|
||||||
|
npm run test:integration # Backend integration tests with real DB
|
||||||
|
|
||||||
|
# Test setup and teardown
|
||||||
|
./test-setup.sh # Initialize test environment with Docker
|
||||||
|
npm run setup:test # Alternative test setup command
|
||||||
|
npm run clean:test # Clean up test containers
|
||||||
|
```
|
||||||
|
|
||||||
|
### Linting
|
||||||
|
```bash
|
||||||
|
npm run lint # Lint all code
|
||||||
|
npm run lint:frontend # Next.js ESLint
|
||||||
|
npm run lint:backend # NestJS ESLint with Prettier
|
||||||
|
```
|
||||||
|
|
||||||
|
### Database Operations (Backend)
|
||||||
|
```bash
|
||||||
|
cd meteor-web-backend
|
||||||
|
npm run migrate:up # Run pending migrations
|
||||||
|
npm run migrate:down # Rollback last migration
|
||||||
|
npm run migrate:create <name> # Create new migration
|
||||||
|
```
|
||||||
|
|
||||||
|
### Edge Client (Rust)
|
||||||
|
```bash
|
||||||
|
cd meteor-edge-client
|
||||||
|
cargo build --release # Native build
|
||||||
|
cargo build --target=aarch64-unknown-linux-gnu # ARM64 build for Pi
|
||||||
|
./build.sh # Cross-compile for Raspberry Pi
|
||||||
|
./demo_integration_test.sh # Integration test
|
||||||
|
```
|
||||||
|
|
||||||
|
## Database Architecture
|
||||||
|
|
||||||
|
### Entity Relationships
|
||||||
|
- **Users**: UserProfile + UserIdentity (supports multiple auth methods)
|
||||||
|
- **Devices**: Device + InventoryDevice (ownership tracking)
|
||||||
|
- **Events**: RawEvent → ValidatedEvent (processing pipeline)
|
||||||
|
- **Analysis**: AnalysisResult (AI/ML analysis data)
|
||||||
|
- **Weather**: WeatherStation + WeatherObservation + WeatherForecast
|
||||||
|
- **Camera**: CameraDevice (hardware management)
|
||||||
|
- **Subscriptions**: SubscriptionPlan + UserSubscription + SubscriptionHistory + PaymentRecord
|
||||||
|
|
||||||
|
### Migration System
|
||||||
|
- Uses node-pg-migrate for schema management
|
||||||
|
- All entities defined in `meteor-web-backend/src/entities/`
|
||||||
|
- Migrations in `meteor-web-backend/migrations/`
|
||||||
|
|
||||||
|
## Authentication & Authorization
|
||||||
|
|
||||||
|
### JWT-based Authentication
|
||||||
|
- Login/Register endpoints in AuthController
|
||||||
|
- JWT strategy with passport-jwt
|
||||||
|
- Subscription-based authorization via SubscriptionGuard
|
||||||
|
- Password hashing with bcrypt
|
||||||
|
|
||||||
|
### API Structure
|
||||||
|
- Base path: `/api/v1/`
|
||||||
|
- Protected routes require Bearer token
|
||||||
|
- CORS enabled for localhost:3000 (frontend)
|
||||||
|
|
||||||
|
## Event Processing Pipeline
|
||||||
|
|
||||||
|
### Data Flow
|
||||||
|
1. **Edge Client** (Rust) captures meteor events via camera
|
||||||
|
2. **Raw Event Upload** to backend API with media files
|
||||||
|
3. **SQS Queue** triggers processing in Go compute service
|
||||||
|
4. **Validation** using MVP or Classical CV providers
|
||||||
|
5. **Analysis Results** stored and exposed via API
|
||||||
|
6. **Frontend Gallery** displays validated events with infinite scroll
|
||||||
|
|
||||||
|
### File Storage
|
||||||
|
- AWS S3 for media storage (images/videos)
|
||||||
|
- LocalStack for development/testing
|
||||||
|
- Multipart upload support in backend
|
||||||
|
|
||||||
|
## Testing Architecture
|
||||||
|
|
||||||
|
### Three-Layer Testing
|
||||||
|
1. **Unit Tests**: Jest for both frontend and backend components
|
||||||
|
2. **Integration Tests**: Full API workflows with test database
|
||||||
|
3. **E2E Tests**: Playwright for user interactions
|
||||||
|
|
||||||
|
### Test Environment
|
||||||
|
- Docker Compose setup with test services
|
||||||
|
- Separate PostgreSQL instance (port 5433)
|
||||||
|
- LocalStack for AWS service mocking
|
||||||
|
- Test data generation scripts
|
||||||
|
|
||||||
|
### Gallery Testing
|
||||||
|
- Complete E2E coverage for authentication, infinite scroll, responsive design
|
||||||
|
- Integration tests for upload → processing → display workflow
|
||||||
|
- Performance testing with large datasets
|
||||||
|
|
||||||
|
## Frontend Architecture
|
||||||
|
|
||||||
|
### Next.js App Router Structure
|
||||||
|
- Pages in `src/app/` (gallery, dashboard, settings, etc.)
|
||||||
|
- Components organized by domain (`auth/`, `gallery/`, `charts/`, `ui/`)
|
||||||
|
- React Query for server state management
|
||||||
|
- Context-based auth state management
|
||||||
|
|
||||||
|
### UI Components
|
||||||
|
- Custom UI components in `components/ui/`
|
||||||
|
- Chart components using Recharts
|
||||||
|
- Form handling with React Hook Form + Zod validation
|
||||||
|
- Responsive design with TailwindCSS 4
|
||||||
|
|
||||||
|
## Backend Architecture
|
||||||
|
|
||||||
|
### NestJS Module Structure
|
||||||
|
- Domain-driven modules: Auth, Devices, Events, Payments, etc.
|
||||||
|
- TypeORM entities with PostgreSQL
|
||||||
|
- Structured logging with Pino
|
||||||
|
- Prometheus metrics collection
|
||||||
|
- Health checks and observability
|
||||||
|
|
||||||
|
### Key Services
|
||||||
|
- **EventsService**: Core event processing and pagination
|
||||||
|
- **AuthService**: JWT token management and user validation
|
||||||
|
- **PaymentsService**: Stripe integration for subscriptions
|
||||||
|
- **AnalysisService**: AI/ML result processing
|
||||||
|
- **WeatherService**: Environmental data correlation
|
||||||
|
|
||||||
|
## Development Workflow
|
||||||
|
|
||||||
|
### Adding New Features
|
||||||
|
1. Create/update database entities and migrations
|
||||||
|
2. Implement backend service and controller with tests
|
||||||
|
3. Add frontend components and API integration
|
||||||
|
4. Update E2E tests for user workflows
|
||||||
|
5. Run full test suite before committing
|
||||||
|
|
||||||
|
### Running Single Tests
|
||||||
|
```bash
|
||||||
|
# Backend unit test for specific service
|
||||||
|
cd meteor-web-backend && npm test -- --testPathPattern=events.service
|
||||||
|
|
||||||
|
# Frontend component test
|
||||||
|
cd meteor-frontend && npm test -- --testPathPattern=gallery
|
||||||
|
|
||||||
|
# Single E2E test
|
||||||
|
cd meteor-frontend && npx playwright test --grep="Gallery page"
|
||||||
|
|
||||||
|
# Integration test for specific feature
|
||||||
|
cd meteor-web-backend && npm run test:integration -- --testPathPattern=events
|
||||||
|
```
|
||||||
|
|
||||||
|
## Production Deployment
|
||||||
|
|
||||||
|
### Docker Support
|
||||||
|
- Dockerfiles for all services
|
||||||
|
- Next.js standalone output mode
|
||||||
|
- Multi-stage builds for optimization
|
||||||
|
|
||||||
|
### Infrastructure
|
||||||
|
- Terraform configurations in `infrastructure/`
|
||||||
|
- AWS services: RDS, S3, SQS, CloudWatch
|
||||||
|
- Environment-based configuration
|
||||||
|
|
||||||
|
### Observability
|
||||||
|
- Structured JSON logging throughout stack
|
||||||
|
- Metrics collection with Prometheus
|
||||||
|
- Health check endpoints
|
||||||
|
- Correlation IDs for request tracking
|
||||||
@ -5,6 +5,7 @@ import { BarChart2, Clock, Star, Map, Camera, List, Calendar, Eye } from 'lucide
|
|||||||
import { StatCard } from '@/components/ui/stat-card';
|
import { StatCard } from '@/components/ui/stat-card';
|
||||||
import { LoadingSpinner } from '@/components/ui/loading-spinner';
|
import { LoadingSpinner } from '@/components/ui/loading-spinner';
|
||||||
import { AppLayout } from '@/components/layout/app-layout';
|
import { AppLayout } from '@/components/layout/app-layout';
|
||||||
|
import { PageLoading } from '@/components/ui/page-loading';
|
||||||
import { MeteorTypePieChart } from '@/components/charts/meteor-type-pie-chart';
|
import { MeteorTypePieChart } from '@/components/charts/meteor-type-pie-chart';
|
||||||
import { StationDistributionChart } from '@/components/charts/station-distribution-chart';
|
import { StationDistributionChart } from '@/components/charts/station-distribution-chart';
|
||||||
import { TimeDistributionChart } from '@/components/charts/time-distribution-chart';
|
import { TimeDistributionChart } from '@/components/charts/time-distribution-chart';
|
||||||
@ -218,9 +219,7 @@ export default function AnalysisPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return (
|
return <PageLoading text="加载分析数据中..." />;
|
||||||
<LoadingSpinner size="lg" text="加载分析数据中..." className="h-64" />
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -73,12 +73,17 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
background: linear-gradient(135deg, #0a0a23 0%, #1a1a3a 50%, #2a2a4a 100%);
|
background: #f9fafb;
|
||||||
color: var(--foreground);
|
color: var(--foreground);
|
||||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 为主页保留星空背景 */
|
||||||
|
body.starfield-background {
|
||||||
|
background: linear-gradient(135deg, #0a0a23 0%, #1a1a3a 50%, #2a2a4a 100%);
|
||||||
|
}
|
||||||
|
|
||||||
.starfield {
|
.starfield {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
|||||||
@ -10,6 +10,13 @@ export default function Home() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
createStarfield()
|
createStarfield()
|
||||||
|
// Add starfield background class to body for home page
|
||||||
|
document.body.classList.add('starfield-background')
|
||||||
|
|
||||||
|
// Cleanup on unmount
|
||||||
|
return () => {
|
||||||
|
document.body.classList.remove('starfield-background')
|
||||||
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const createStarfield = () => {
|
const createStarfield = () => {
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import { CloudLightning, Filter, Search, Calendar, RefreshCw, Thermometer, Cloud
|
|||||||
import { StatCard } from '@/components/ui/stat-card';
|
import { StatCard } from '@/components/ui/stat-card';
|
||||||
import { LoadingSpinner } from '@/components/ui/loading-spinner';
|
import { LoadingSpinner } from '@/components/ui/loading-spinner';
|
||||||
import { AppLayout } from '@/components/layout/app-layout';
|
import { AppLayout } from '@/components/layout/app-layout';
|
||||||
|
import { PageLoading } from '@/components/ui/page-loading';
|
||||||
import { getAllWeatherData, getWeatherSummary, type WeatherData, type WeatherSummary } from '@/services/weather';
|
import { getAllWeatherData, getWeatherSummary, type WeatherData, type WeatherSummary } from '@/services/weather';
|
||||||
|
|
||||||
export default function WeatherPage() {
|
export default function WeatherPage() {
|
||||||
@ -87,9 +88,7 @@ export default function WeatherPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return (
|
return <PageLoading text="加载天气数据中..." />;
|
||||||
<LoadingSpinner size="lg" text="加载天气数据中..." className="h-64" />
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
27
meteor-frontend/src/components/ui/page-loading.tsx
Normal file
27
meteor-frontend/src/components/ui/page-loading.tsx
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import { AppLayout } from '@/components/layout/app-layout';
|
||||||
|
import { LoadingSpinner } from '@/components/ui/loading-spinner';
|
||||||
|
|
||||||
|
interface PageLoadingProps {
|
||||||
|
text?: string;
|
||||||
|
withLayout?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const PageLoading: React.FC<PageLoadingProps> = ({
|
||||||
|
text = "加载中...",
|
||||||
|
withLayout = true
|
||||||
|
}) => {
|
||||||
|
const content = (
|
||||||
|
<div className="p-4 md:p-6 bg-gray-50 dark:bg-gray-900 min-h-screen">
|
||||||
|
<LoadingSpinner size="lg" text={text} className="h-64" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
if (withLayout) {
|
||||||
|
return <AppLayout>{content}</AppLayout>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return content;
|
||||||
|
};
|
||||||
Loading…
x
Reference in New Issue
Block a user