135 lines
4.5 KiB
Markdown
135 lines
4.5 KiB
Markdown
# TrackingToolWeb — CLAUDE.md
|
|
|
|
## Tổng quan dự án
|
|
|
|
Hệ thống điểm danh khuôn mặt (Face Check-in) tích hợp với Management System tại `ms.prology.net`. Camera nhận diện khuôn mặt → FastAPI backend so khớp → ghi log → đồng bộ sang hệ thống quản lý.
|
|
|
|
---
|
|
|
|
## Kiến trúc
|
|
|
|
```
|
|
Frontend (React/Vite) → Backend (FastAPI/Python) → MySQL
|
|
↓
|
|
External MS API (ms.prology.net)
|
|
```
|
|
|
|
**Backend**: `main.py` (FastAPI) + `api.py` (external calls) + `sync.py` (data sync)
|
|
**Frontend**: `client/src/` — React 19, TypeScript, TailwindCSS, Zustand
|
|
**Database**: MySQL — database `face_checkin`
|
|
**Deployment**: Backend phục vụ luôn frontend build (`static/`) qua route `/`
|
|
|
|
---
|
|
|
|
## Commands
|
|
|
|
### Backend
|
|
```bash
|
|
# Development
|
|
uvicorn main:app --reload
|
|
|
|
# Production
|
|
nohup uvicorn main:app --host 172.16.6.38 --port 8080 > log.log 2>&1 &
|
|
```
|
|
|
|
### Frontend
|
|
```bash
|
|
cd client
|
|
npm run dev # dev server (Vite HMR)
|
|
npm run build # build to client/dist/
|
|
npm run lint # ESLint
|
|
```
|
|
|
|
### Deploy frontend
|
|
Sau khi build, copy `client/dist/` vào `static/`. Đảm bảo asset paths trong `index.html` dùng prefix `/camera/static/assets/`.
|
|
|
|
---
|
|
|
|
## Cấu hình
|
|
|
|
### Backend (hardcoded — cần đưa vào .env)
|
|
| Biến | Giá trị hiện tại | File |
|
|
|------|-----------------|------|
|
|
| DB URL | `mysql+pymysql://root:123@localhost/face_checkin` | `database.py` |
|
|
| MS API base | `https://ms.prology.net/api/v1` | `api.py` |
|
|
| JWT token | hardcoded string | `api.py` |
|
|
| Face threshold | `0.42` | `main.py:217` |
|
|
| Ratio threshold | `0.85` | `main.py:286` |
|
|
| Recent check window | 0.5 phút | `main.py` |
|
|
|
|
### Frontend (.env trong `client/`)
|
|
```
|
|
VITE_API_BASE_URL=/camera # production (proxy qua nginx)
|
|
VITE_API_BASE_MS=https://ms.prology.net
|
|
```
|
|
|
|
---
|
|
|
|
## API Endpoints
|
|
|
|
| Method | Path | Mô tả |
|
|
|--------|------|-------|
|
|
| GET | `/` | Phục vụ `static/index.html` |
|
|
| POST | `/register` | Đăng ký khuôn mặt (name, email, file ảnh) |
|
|
| POST | `/register-simple` | Đăng ký/cập nhật user không cần ảnh |
|
|
| POST | `/checkin` | Nhận diện & điểm danh (file ảnh, camera_id) |
|
|
| GET | `/logs` | 20 log điểm danh gần nhất |
|
|
| GET | `/users` | Danh sách users + 5 checkpoint gần nhất |
|
|
|
|
---
|
|
|
|
## Database Schema
|
|
|
|
```sql
|
|
students (id, name, email UNIQUE, avatar)
|
|
student_encodings (id, student_id FK, encoding BLOB[1024 bytes = 128 float64], created_at)
|
|
checkin_logs (id, student_id FK, time, camera_id, status[check in/check out])
|
|
```
|
|
|
|
**Encoding format**: `np.float64` array 128 chiều → `.tobytes()` → BLOB 1024 bytes
|
|
**Giải mã**: `np.frombuffer(blob, dtype=np.float64)` — validate `enc.size == 128`
|
|
|
|
---
|
|
|
|
## Logic nhận diện khuôn mặt (`/checkin`)
|
|
|
|
1. Nhận ảnh JPEG → lưu tạm `uploads/checkin.jpg`
|
|
2. `face_recognition.face_encodings()` → encoding 128-dim
|
|
3. Load **tất cả** encodings từ DB → so khớp `face_recognition.face_distance()`
|
|
4. Chọn student có `min_dist` nhỏ nhất
|
|
5. Kiểm tra: `best_distance ≤ 0.42` **AND** `ratio = best/second_best ≤ 0.85`
|
|
6. Kiểm tra recent check (tránh điểm danh 2 lần trong 30 giây)
|
|
7. Ghi `checkin_logs` → `BackgroundTask`: gửi ảnh + tạo history trên MS API
|
|
|
|
**Bottleneck chính**: Bước 3 — load toàn bộ encodings, giải mã numpy, so khớp tuần tự trong request.
|
|
|
|
---
|
|
|
|
## External API (ms.prology.net)
|
|
|
|
- `POST /api/v1/admin/tracking/scan-create` — tạo history check-in
|
|
- `POST /api/v1/admin/tracking/send-image` — upload ảnh check-in
|
|
- `GET /api/v1/admin/timekeeping` — lấy dữ liệu chấm công (dùng trong `sync.py`)
|
|
|
|
Token JWT được hardcode trong `api.py` — cần chuyển sang env variable.
|
|
|
|
---
|
|
|
|
## Frontend State Management
|
|
|
|
**Zustand stores:**
|
|
- `use-app-store.ts` — `isAutoChecking`, `isCountDown`, `refreshLog`, video/canvas refs
|
|
- `use-user-store.ts` — `currentUser` (user được chọn cho checkpoint)
|
|
|
|
**Auto check-in**: interval 3000ms, gọi `/checkin` liên tục khi `isAutoChecking = true`
|
|
|
|
---
|
|
|
|
## Các lưu ý quan trọng
|
|
|
|
- `UPLOAD_DIR = ./uploads/` — lưu ảnh tạm check-in, bị ghi đè mỗi lần (`checkin.jpg`)
|
|
- `images/{YYYY_MM_DD}/` — lưu ảnh vĩnh viễn theo ngày (tạo trong `sync.py`)
|
|
- DB session trong `/checkin` dùng `Depends(get_db)`, các endpoint khác tạo `SessionLocal()` trực tiếp — cần thống nhất
|
|
- Tối đa 10 encodings/user (giới hạn trong `sync.py`)
|
|
- CORS `allow_origins=["*"]` — chấp nhận vì deploy nội bộ
|