+
+
+
+
+
+ C
+
+
+ CineK Admin
+ Quản lý hệ thống
+
+
+
Đăng nhập để tiếp tục
-
CineK Admin
+
+
-
Đăng nhập để quản lý hệ thống
-
-
-
diff --git a/app/pages/admin/phim/[id].vue b/app/pages/admin/phim/[id].vue
index ffd767c..a567ed4 100644
--- a/app/pages/admin/phim/[id].vue
+++ b/app/pages/admin/phim/[id].vue
@@ -56,8 +56,17 @@ const expandedSources = ref>({})
const selectedTargetServer = ref(0)
const collapsedServers = ref>({})
const expandedLinks = ref>({})
+const activeSection = ref<"info" | "content" | "actors" | "images" | "episodes">("info")
+const sections = [
+ { key: "info" as const, label: "Thông tin", icon: "info" as const },
+ { key: "content" as const, label: "Mô tả", icon: "type" as const },
+ { key: "actors" as const, label: "Diễn viên", icon: "users" as const },
+ { key: "images" as const, label: "Hình ảnh", icon: "image" as const },
+ { key: "episodes" as const, label: "Tập phim", icon: "server" as const },
+]
const saving = ref(false)
const saved = ref(false)
+const { bust } = useCacheBust()
watch(movie, (m) => {
if (m) {
@@ -69,9 +78,9 @@ watch(movie, (m) => {
: []
customServers.value = m.customServers?.length
? m.customServers.map((server: any) => ({
- name: server.name || '',
- episodes: (server.episodes || []).map((ep: any) => ({ name: ep.name || '', linkEmbed: ep.linkEmbed || '', linkM3u8: ep.linkM3u8 || '' })),
- }))
+ name: server.name || '',
+ episodes: (server.episodes || []).map((ep: any) => ({ name: ep.name || '', linkEmbed: ep.linkEmbed || '', linkM3u8: ep.linkM3u8 || '' })),
+ }))
: []
}
}, { immediate: true })
@@ -229,6 +238,7 @@ async function handleSave() {
},
})
saved.value = true
+ bust() // Invalidate cached data across all pages
await refresh()
setTimeout(() => { saved.value = false }, 2500)
} catch (err) {
@@ -265,424 +275,490 @@ function useApiActors() {
-
+
+ class="inline-flex items-center gap-2 text-sm font-medium text-zinc-400 transition hover:text-white">
Quay lại danh sách phim
-
-
Đang tải...
+
-
-
-
-
{{ movie.name }}
-
- {{ movie.originName }} · {{ movie.source?.toUpperCase() }} · {{ movie.year || 'N/A' }}
-
+
+
+
+
+
+
+
![]()
+
+
+
+
+
{{ movie.name }}
+
+ {{ movie.originName }} · {{ movie.source?.toUpperCase() }} · {{ movie.year || 'N/A' }}
+
+
+
+ {{ movie.active ? 'Đang hiển thị' : 'Ẩn' }}
+
+ {{ movie.quality }}
+ {{ movie.episode || '—' }} tập
+
+
-
+ class="flex items-center gap-2 rounded-xl border border-emerald-400/20 bg-emerald-400/10 px-4 py-3 text-sm font-semibold text-emerald-400">
Đã lưu thành công
-
-
-
-
-
-
-
-
-
-
Mô tả phim
-
- {{ customContent ? 'Mô tả tuỳ chỉnh (Đã áp dụng)' : 'Mô tả mặc định từ API' }}
-
-
-
-
-
-
-
-
-
-
-
-
- Nội dung từ API nguồn
-
-
-
- {{ apiContent || 'Chưa có mô tả từ nguồn API.' }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Diễn viên
-
Danh sách diễn viên của phim ({{ customActors.length }})
-
-
-
-
-
-
-
-
-
-
-
Chưa có diễn viên nào. Bấm "Thêm diễn viên" hoặc "Import từ API" để bắt đầu.
-
-
-
-
-
-
-
-
-
-
Server & tập phim
-
Danh sách server phát hiển thị trên website
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
{{ episodeIndex + 1 }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Chưa có server nào. Bấm "Thêm server" để bắt đầu.
-
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
+
-
Thông tin phim
-
Thông tin chi tiết từ hệ thống
+
Thông tin chi tiết
+
Dữ liệu từ hệ thống
-
+
-
- Nguồn
- - {{ movie.source?.toUpperCase() }}
+ - Nguồn
+ - {{ movie.source?.toUpperCase() }}
-
- Slug
- - {{ movie.slug }}
+ - Slug
+ - {{ movie.slug }}
-
- Năm phát hành
- - {{ movie.year || '—' }}
+ - Năm phát hành
+ - {{ movie.year || '—' }}
-
- Số tập
- - {{ movie.episode || '—' }}
+ - Số tập
+ - {{ movie.episode || '—' }}
-
- Chất lượng
- - {{ movie.quality || '—' }}
+ - Chất lượng
+ - {{ movie.quality || '—' }}
-
- Trạng thái
- -
+
- Trạng thái
+ -
{{ movie.active ? 'Đang hiển thị' : 'Ẩn' }}
-
- Đồng bộ gần nhất
- - {{ new Date(movie.syncedAt).toLocaleDateString('vi-VN') }}
+ - Đồng bộ gần nhất
+ - {{ new Date(movie.syncedAt).toLocaleString('vi-VN') }}
-
-
Thể loại
-
+
+
Thể loại
+
- {{ cat }}
-
+ class="rounded-full bg-white/[0.06] px-2.5 py-0.5 text-xs font-medium text-zinc-300">{{ cat }}
-
-
-
-
-
-
Hình ảnh
-
Poster & Thumbnail tuỳ chỉnh
-
-
-
-
-
-
-
-
![]()
-
-
-
-
-
-
-
-
![]()
-
-
-
-
-
-
-
-
+
+
-
-
+
-
Nguồn API có sẵn
-
Dữ liệu tập phim từ các API
+
Mô tả phim
+
{{ customContent ? 'Tuỳ chỉnh · Đang áp dụng' : 'Mặc định từ API' }}
+
+
+
+
+
+
+
+
Nội dung API
+
+ {{ apiContent || 'Chưa có mô tả từ nguồn API.' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Diễn viên
+
{{ customActors.length }} diễn viên
+
+
+
+
+
+
+
+
+
+
Chưa có diễn viên. Bấm "Thêm" hoặc "Import" để bắt đầu.
+
+
+
+
+
+
+
+
+
Poster
+
Tỷ lệ 16:9 · ảnh ngang
+
+
Tuỳ chỉnh
+
Mặc định
+
+
+
+
![]()
+
+
+
+
+
+
+
+
Thumbnail
+
Tỷ lệ 2:3 · ảnh dọc
+
+
Tuỳ chỉnh
+
Mặc định
+
+
+
+
![]()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Server & tập phim
+
Danh sách server hiển thị trên website
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ episodeIndex + 1
+ }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Chưa có server. Bấm "Thêm server" để bắt đầu.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
{{ server.name }}
-
-
-
-
-
{{ ep.name || `Tập ${epIndex + 1}` }}
-
{{ ep.linkM3u8 }}
-
{{ ep.linkEmbed }}
-
+
+
+
+
+
+
+
Nguồn API có sẵn
+
Thêm nhanh tập từ API
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ server.name }}
+
+
+
+
+
{{ ep.name || `Tập ${epIndex + 1}` }}
+
+
{{ ep.linkM3u8 }}
+
{{ ep.linkEmbed }}
+
+
+
+
+
+
Chưa có nguồn API hoặc chưa đồng bộ tập phim.
+
-
-
Chưa có nguồn API nào hoặc chưa đồng bộ tập phim.
-
+
+
+
+
diff --git a/app/pages/admin/phim/index.vue b/app/pages/admin/phim/index.vue
index 33d9dba..ce9bcbb 100644
--- a/app/pages/admin/phim/index.vue
+++ b/app/pages/admin/phim/index.vue
@@ -22,6 +22,8 @@ const deleteConfirmOpen = ref(false)
const syncSources = ref({ ophim: true, nguonc: true, kkphim: true })
const syncResult = ref<{ total: number, created: number, updated: number, sourceStats: Record
} | null>(null)
+const { bust } = useCacheBust()
+
let searchTimeout: ReturnType | undefined
watch(searchInput, (val) => {
@@ -72,6 +74,7 @@ async function toggleActive(movie: any) {
method: 'PATCH',
body: { active: movie.active },
})
+ bust()
await refresh()
}
@@ -90,6 +93,7 @@ async function handleSync() {
body: { sources },
})
syncResult.value = result
+ bust() // Invalidate cached data across all pages
await refresh()
} catch (err) {
console.error('Sync failed:', err)
@@ -103,6 +107,7 @@ async function handleDeleteAll() {
try {
await $fetch('/api/admin/movies', { method: 'DELETE' })
deleteConfirmOpen.value = false
+ bust() // Invalidate cached data across all pages
await refresh()
} catch (err) {
console.error('Delete failed:', err)
@@ -192,151 +197,143 @@ function formatRelativeTime(dateValue?: string | number | Date | null) {
}
return 'Vừa xong'
}
+
+function sortIcon(column: string): string {
+ if (sortBy.value !== column) return 'chevron-down'
+ return sortOrder.value === 'asc' ? 'chevron-up' : 'chevron-down'
+}
+
+const syncSourceOptions = [
+ { key: 'ophim', label: 'OPhim', domain: 'ophim1.com' },
+ { key: 'nguonc', label: 'NguonC', domain: 'phim.nguonc.com' },
+ { key: 'kkphim', label: 'KKPhim', domain: 'phimapi.com' },
+] as const
-
Quản lý phim
-
Quản lý phim hiển thị trên CineK ({{ data?.total || 0 }} phim)
+
Quản lý phim
+
Quản lý phim hiển thị trên CineK ({{ data?.total || 0 }} phim)
-
-
-
+
+
-
-
+
-
+
Trang {{ currentPage }} / {{ totalPages }}
- ‹
+
-
- ...
-
+ ...
{{ page }}
- ›
+
@@ -389,50 +383,34 @@ function formatRelativeTime(dateValue?: string | number | Date | null) {
-
+
-
Đồng bộ phim
-
Chọn nguồn để đồng bộ phim vào hệ thống
+
+
Đồng bộ phim
+
Chọn nguồn để đồng bộ phim vào hệ thống
+
-
-