mirror of
https://github.com/ngthanhvu/kr-phim.git
synced 2026-08-10 12:27:47 +00:00
- Implemented AuthModal.vue for user login and registration with form handling. - Created useAuth composable for managing user state and authentication requests. - Added admin route middleware to protect admin routes. - Developed admin login page with authentication checks. - Implemented API endpoints for user management (login, logout, fetch user, register). - Created database migrations for users table and updated movies table. - Added utility functions for password hashing and JWT token management.
306 lines
10 KiB
Markdown
306 lines
10 KiB
Markdown
# CineK
|
|
|
|
CineK là website xem phim Hàn Quốc online với giao diện dark theme, hệ thống admin quản lý phim, đăng ký/đăng nhập thành viên, và đồng bộ dữ liệu từ nhiều nguồn API.
|
|
|
|
## Tính năng
|
|
|
|
### Người dùng
|
|
- Trang chủ với hero carousel phim Hàn Quốc
|
|
- Duyệt phim theo loại (phim bộ, phim lẻ), tìm kiếm, phân trang
|
|
- Trang chi tiết phim với trình phát HLS + Nhúng
|
|
- Đăng ký / Đăng nhập tài khoản thành viên (popup modal)
|
|
- Lịch sử xem, danh sách phim yêu thích (lưu localStorage)
|
|
|
|
### Admin (`/admin`)
|
|
- Dashboard tổng quan (tổng phim, đang hiển thị, chưa hiển thị)
|
|
- Đồng bộ phim từ API (chọn nguồn: OPhim, NguonC, KKPhim)
|
|
- Bật/tắt hiển thị từng phim
|
|
- Chỉnh sửa phim: mô tả, poster, thumbnail, tập phim tuỳ chỉnh
|
|
- Quản lý thành viên: đổi role, bật/tắt, xoá tài khoản
|
|
- Xoá toàn bộ phim
|
|
- Phân quyền: chỉ role `admin` mới truy cập được
|
|
|
|
## Tech Stack
|
|
|
|
- **Framework:** Nuxt 4 (Vue 3)
|
|
- **Styling:** Tailwind CSS 4
|
|
- **Database:** MySQL 8.0 + Drizzle ORM
|
|
- **Cache:** Redis 7
|
|
- **Auth:** JWT (bcryptjs + jsonwebtoken)
|
|
- **Icons:** Lucide Vue Next
|
|
- **Player:** HLS.js
|
|
- **Container:** Docker + Docker Compose
|
|
|
|
## Cấu trúc thư mục
|
|
|
|
```text
|
|
app/
|
|
components/ Components dùng chung (AppHeader, AppLogo, AuthModal, AdminToggle...)
|
|
composables/ Composables (useAuth, useMovieLibrary, useWatchHistory)
|
|
layouts/
|
|
admin.vue Layout cho trang admin (sidebar + header)
|
|
middleware/
|
|
admin.global.ts Middleware chặn route /admin/* nếu chưa đăng nhập admin
|
|
pages/
|
|
index.vue Trang chủ
|
|
phim/ Trang chi tiết phim
|
|
xem/[slug].vue Trang xem phim (player)
|
|
thanh-vien.vue Trang cá nhân thành viên
|
|
yeu-thich.vue Phim yêu thích
|
|
lich-su.vue Lịch sử xem
|
|
dang-nhap.vue Đăng nhập
|
|
dang-ky.vue Đăng ký
|
|
admin/
|
|
login.vue Trang đăng nhập admin
|
|
index.vue Dashboard admin
|
|
phim/index.vue Quản lý phim
|
|
phim/[id].vue Chỉnh sửa phim
|
|
thanh-vien.vue Quản lý thành viên
|
|
cai-dat.vue Cài đặt hệ thống
|
|
|
|
server/
|
|
api/
|
|
movies.get.ts API danh sách phim công khai (chỉ phim active)
|
|
movies/[slug].get.ts API chi tiết phim công khai
|
|
auth/ API xác thực (register, login, logout, me)
|
|
admin/ API admin (sync, movies, thanh-vien, stats)
|
|
database/
|
|
schema.ts Schema Drizzle (bảng users, movies)
|
|
migrations/ File migration SQL
|
|
middleware/
|
|
auth.ts Middleware chặn /api/admin/* nếu chưa đăng nhập admin
|
|
utils/
|
|
auth.ts Tiện ích auth (hash password, JWT sign/verify)
|
|
db.ts Kết nối MySQL
|
|
redis.ts Kết nối Redis
|
|
movies.ts Adapter API phim + chuẩn hoá dữ liệu
|
|
```
|
|
|
|
## Setup & Chạy dự án
|
|
|
|
### Yêu cầu
|
|
|
|
- Docker & Docker Compose
|
|
- Node.js 22+ (nếu chạy ngoài Docker)
|
|
|
|
### 1. Clone & cài dependencies
|
|
|
|
```bash
|
|
git clone <repo-url>
|
|
cd kr-phim
|
|
npm install
|
|
```
|
|
|
|
### 2. Cấu hình biến môi trường
|
|
|
|
Tạo file `.env`:
|
|
|
|
```env
|
|
DATABASE_URL=mysql://cinek:cinekpassword@localhost:3306/cinek
|
|
REDIS_URL=redis://localhost:6379
|
|
JWT_SECRET=your-secret-key-change-this
|
|
```
|
|
|
|
### 3. Chạy MySQL & Redis
|
|
|
|
```bash
|
|
# Chỉ bật MySQL và Redis
|
|
docker compose up -d mysql redis
|
|
```
|
|
|
|
Hoặc chạy tất cả (app + mysql + redis):
|
|
|
|
```bash
|
|
docker compose up -d
|
|
```
|
|
|
|
#### Thông tin kết nối mặc định
|
|
|
|
| Service | Host | Port | User | Password | Database |
|
|
|----------|-----------|------|---------|----------------|----------|
|
|
| MySQL | localhost | 3306 | cinek | cinekpassword | cinek |
|
|
| MySQL | localhost | 3306 | root | rootpassword | - |
|
|
| Redis | localhost | 6379 | - | - | - |
|
|
| App | localhost | 3002 | - | - | - |
|
|
|
|
### 4. Tạo bảng database (migration)
|
|
|
|
```bash
|
|
# Tạo file migration từ schema
|
|
npx drizzle-kit generate
|
|
|
|
# Áp dụng migration vào MySQL
|
|
npx drizzle-kit migrate
|
|
```
|
|
|
|
### 5. Chạy dev server
|
|
|
|
```bash
|
|
npm run dev
|
|
```
|
|
|
|
App chạy tại `http://localhost:3002`. Hot reload tự động khi sửa code.
|
|
|
|
### 6. Tạo tài khoản admin đầu tiên
|
|
|
|
Truy cập `http://localhost:3002` → bấm **Đăng nhập** → chuyển sang tab **Đăng ký**.
|
|
|
|
Tài khoản đầu tiên đăng ký sẽ tự động được gán role **admin**.
|
|
|
|
Sau đó truy cập `http://localhost:3002/admin` để vào trang quản trị.
|
|
|
|
### 7. Đồng bộ phim
|
|
|
|
Vào **Admin → Dashboard** hoặc **Admin → Phim** → bấm **Đồng bộ từ API**.
|
|
|
|
Chọn nguồn muốn đồng bộ (OPhim, NguonC, KKPhim) → bấm **Đồng bộ**.
|
|
|
|
Mặc định phim mới đồng bộ sẽ ở trạng thái **Ẩn**. Bật từng phim để hiển thị ra trang công khai.
|
|
|
|
## Docker
|
|
|
|
### Dev mode (có hot reload)
|
|
|
|
```bash
|
|
docker compose up -d --build
|
|
```
|
|
|
|
File code được mount vào container qua volume, sửa file tự reload.
|
|
|
|
### Production build
|
|
|
|
```bash
|
|
# Build image production
|
|
docker build -t cinek .
|
|
|
|
# Chạy
|
|
docker run -p 3002:3002 \
|
|
-e DATABASE_URL=mysql://cinek:cinekpassword@host.docker.internal:3306/cinek \
|
|
-e REDIS_URL=redis://host.docker.internal:6379 \
|
|
cinek
|
|
```
|
|
|
|
### Dừng & xoá containers
|
|
|
|
```bash
|
|
docker compose down # Dừng containers
|
|
docker compose down -v # Dừng + xoá volumes (mất dữ liệu MySQL/Redis)
|
|
```
|
|
|
|
## Database
|
|
|
|
### Schema
|
|
|
|
**Bảng `users`:**
|
|
|
|
| Cột | Kiểu | Mô tả |
|
|
|-----------|---------------|---------------------------|
|
|
| id | INT (PK) | Tự tăng |
|
|
| name | VARCHAR(200) | Tên hiển thị |
|
|
| email | VARCHAR(255) | Email (unique) |
|
|
| password | VARCHAR(255) | Mật khẩu (bcrypt hash) |
|
|
| role | VARCHAR(50) | admin / moderator / user |
|
|
| avatar | TEXT | URL ảnh đại diện |
|
|
| active | BOOLEAN | Trạng thái tài khoản |
|
|
| created_at| TIMESTAMP | Ngày tạo |
|
|
| updated_at| TIMESTAMP | Ngày cập nhật |
|
|
|
|
**Bảng `movies`:**
|
|
|
|
| Cột | Kiểu | Mô tả |
|
|
|----------------|---------------|----------------------------------|
|
|
| id | INT (PK) | Tự tăng |
|
|
| source | VARCHAR(50) | Nguồn (ophim/nguonc/kkphim) |
|
|
| slug | VARCHAR(500) | Slug phim trên nguồn |
|
|
| name | VARCHAR(500) | Tên phim |
|
|
| origin_name | VARCHAR(500) | Tên gốc |
|
|
| thumb/poster | TEXT | URL ảnh |
|
|
| year | INT | Năm sản xuất |
|
|
| active | BOOLEAN | Hiển thị trên web công khai |
|
|
| custom_poster | TEXT | Poster admin tuỳ chỉnh |
|
|
| custom_thumb | TEXT | Thumbnail admin tuỳ chỉnh |
|
|
| custom_content | TEXT | Mô tả admin tuỳ chỉnh |
|
|
| custom_episodes| JSON | Tập phim admin tuỳ chỉnh |
|
|
| api_updated_at | TIMESTAMP | Thời gian API nguồn cập nhật |
|
|
| synced_at | TIMESTAMP | Thời gian đồng bộ vào DB |
|
|
|
|
### Migration
|
|
|
|
```bash
|
|
# Tạo migration mới (sau khi sửa schema.ts)
|
|
npx drizzle-kit generate
|
|
|
|
# Áp dụng migration
|
|
npx drizzle-kit migrate
|
|
```
|
|
|
|
### Kết nối MySQL trực tiếp
|
|
|
|
```bash
|
|
# Qua Docker
|
|
docker exec -it cinek-mysql mysql -ucinek -pcinekpassword cinek
|
|
|
|
# Hoặc từ host
|
|
mysql -h 127.0.0.1 -P 3306 -ucinek -pcinekpassword cinek
|
|
```
|
|
|
|
### Kết nối Redis trực tiếp
|
|
|
|
```bash
|
|
docker exec -it cinek-redis redis-cli
|
|
```
|
|
|
|
## API Endpoints
|
|
|
|
### Công khai
|
|
|
|
| Method | Endpoint | Mô tả |
|
|
|--------|-----------------------|---------------------------------|
|
|
| GET | /api/movies | Danh sách phim active (có cache)|
|
|
| GET | /api/movies/[slug] | Chi tiết phim active |
|
|
|
|
### Xác thực
|
|
|
|
| Method | Endpoint | Mô tả |
|
|
|--------|-----------------------|---------------------------------|
|
|
| POST | /api/auth/register | Đăng ký (tài khoản đầu = admin) |
|
|
| POST | /api/auth/login | Đăng nhập (trả JWT + cookie) |
|
|
| POST | /api/auth/logout | Đăng xuất (xoá cookie) |
|
|
| GET | /api/auth/me | Thông tin user hiện tại |
|
|
|
|
### Admin (cần role admin)
|
|
|
|
| Method | Endpoint | Mô tả |
|
|
|--------|-----------------------------|-------------------------------|
|
|
| GET | /api/admin/stats | Thống kê tổng phim |
|
|
| POST | /api/admin/sync | Đồng bộ phim từ API nguồn |
|
|
| GET | /api/admin/movies | Danh sách tất cả phim |
|
|
| GET | /api/admin/movies/:id | Chi tiết 1 phim |
|
|
| PATCH | /api/admin/movies/:id | Bật/tắt phim |
|
|
| PUT | /api/admin/movies/:id | Cập nhật custom (poster, tập) |
|
|
| DELETE | /api/admin/movies | Xoá tất cả phim |
|
|
| GET | /api/admin/thanh-vien | Danh sách thành viên |
|
|
| PATCH | /api/admin/thanh-vien/:id | Đổi role / bật/tắt |
|
|
| DELETE | /api/admin/thanh-vien/:id | Xoá thành viên |
|
|
|
|
## Scripts
|
|
|
|
```bash
|
|
npm run dev # Dev server (hot reload)
|
|
npm run build # Build production
|
|
npm run preview # Preview production build
|
|
npm run start # Chạy production server
|
|
npm run db:generate # Tạo migration từ schema
|
|
npm run db:migrate # Áp dụng migration
|
|
```
|
|
|
|
## Nguồn phim
|
|
|
|
Dữ liệu phim được lấy từ 3 API nguồn:
|
|
|
|
- **OPhim** - `https://ophim1.com`
|
|
- **NguonC** - `https://phim.nguonc.com`
|
|
- **KKPhim** - `https://phimapi.com`
|
|
|
|
Chỉ lấy phim quốc gia Hàn Quốc. Dữ liệu bao gồm: tên phim, ảnh, thể loại, tập phim, link embed, link HLS.
|