- Updated AppHeader.vue to use TypeScript interfaces for member menu items and removed unnecessary type assertions. - Modified AuthModal.vue to enhance styling and improve accessibility with consistent class names and structure. - Enhanced CommentReplies.vue to support deleting replies with a new prop and improved event emission. - Adjusted GifPicker.vue to specify types for fetched data, ensuring better type safety. - Refined HomeMovieCard.vue to handle mouse and focus events more robustly, improving user interaction. - Corrected layout in chinh-sach-bao-mat.vue for better responsiveness and readability. - Updated index.vue to streamline gradient overlays and button positioning for a cleaner UI. - Improved [slug].vue to handle server channels and subtitles more dynamically, enhancing playback experience.
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
adminmớ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
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
git clone <repo-url>
cd kr-phim
npm install
2. Cấu hình biến môi trường
Tạo file .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
# Chỉ bật MySQL và Redis
docker compose up -d mysql redis
Hoặc chạy tất cả (app + mysql + redis):
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)
# 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
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)
docker compose up -d --build
File code được mount vào container qua volume, sửa file tự reload.
Production build
# 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
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ị |
| 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
# 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
# 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
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
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.