diff --git a/src/api/admin/drama.ts b/src/api/admin/drama.ts index 885227d..abe00bf 100644 --- a/src/api/admin/drama.ts +++ b/src/api/admin/drama.ts @@ -15,6 +15,7 @@ export interface DramaPageParams { keyword?: string status?: string categoryId?: number + categoryIds?: number[] isHot?: boolean dramaTypes?: Array<'ANIME' | 'LIVE'> } diff --git a/src/api/admin/types.ts b/src/api/admin/types.ts index 9e499a5..4040874 100644 --- a/src/api/admin/types.ts +++ b/src/api/admin/types.ts @@ -20,12 +20,15 @@ export interface DramaItem { title: string subtitle?: string categoryId?: number + categoryIds?: number[] + categoryNames?: string[] category?: string genre?: string description?: string cover?: string language?: string dramaType?: 'ANIME' | 'LIVE' + dramaTypes?: Array<'ANIME' | 'LIVE'> episodes?: number freeEpisodes?: number unlockCoin?: number @@ -47,11 +50,13 @@ export interface DramaSaveData { title: string subtitle?: string categoryId?: number + categoryIds?: number[] genre?: string description?: string cover?: string language?: string dramaType?: 'ANIME' | 'LIVE' + dramaTypes?: Array<'ANIME' | 'LIVE'> freeEpisodes?: number unlockCoin?: number favoriteCount?: number diff --git a/src/views/contentManagement/DramaManagementView.vue b/src/views/contentManagement/DramaManagementView.vue index fd63ee5..439ebad 100644 --- a/src/views/contentManagement/DramaManagementView.vue +++ b/src/views/contentManagement/DramaManagementView.vue @@ -29,8 +29,8 @@ const categories = ref([]) const keyword = ref('') const statusFilter = ref(undefined) -const categoryId = ref(undefined) -const dramaTypeFilter = ref(undefined) +const categoryIds = ref([]) +const dramaTypes = ref([]) const hotFilter = ref(undefined) const pageIndex = ref(1) const pageSize = ref(10) @@ -47,8 +47,8 @@ const editingLikeCount = ref(0) const formRef = ref() const form = reactive({ title: '', - categoryId: undefined, - dramaType: 'LIVE', + categoryIds: [], + dramaTypes: ['LIVE'], description: '', freeEpisodes: 3, unlockCoin: 0, @@ -63,8 +63,12 @@ const COVER_TYPES = ['image/jpeg', 'image/png', 'image/webp'] const formRules = { title: [{ required: true, message: '请输入短剧名称', trigger: 'blur' }], - categoryId: [{ required: true, message: '请选择短剧类型', trigger: 'change' }], - dramaType: [{ required: true, message: '请选择内容类型', trigger: 'change' }] + categoryIds: [ + { type: 'array', required: true, min: 1, message: '请至少选择一个类型', trigger: 'change' } + ], + dramaTypes: [ + { type: 'array', required: true, min: 1, message: '请至少选择一个内容类型', trigger: 'change' } + ] } const coverDisplayName = computed( @@ -106,8 +110,8 @@ async function load() { pageSize: pageSize.value, keyword: keyword.value.trim() || undefined, status: statusFilter.value || undefined, - categoryId: categoryId.value, - dramaTypes: dramaTypeFilter.value ? [dramaTypeFilter.value] : undefined, + categoryIds: categoryIds.value.length ? categoryIds.value : undefined, + dramaTypes: dramaTypes.value.length ? dramaTypes.value : undefined, isHot: hotFilter.value }) list.value = res.data?.list || [] @@ -130,8 +134,8 @@ function search() { function resetFilters() { keyword.value = '' statusFilter.value = undefined - categoryId.value = undefined - dramaTypeFilter.value = undefined + categoryIds.value = [] + dramaTypes.value = [] hotFilter.value = undefined search() } @@ -156,8 +160,8 @@ function openCreate() { editingId.value = null Object.assign(form, { title: '', - categoryId: undefined, - dramaType: 'LIVE', + categoryIds: [], + dramaTypes: ['LIVE'], description: '', freeEpisodes: 3, unlockCoin: 0, @@ -178,8 +182,18 @@ function openEdit(row) { editingId.value = row.id Object.assign(form, { title: row.title, - categoryId: row.categoryId || undefined, - dramaType: row.dramaType || 'LIVE', + categoryIds: + Array.isArray(row.categoryIds) && row.categoryIds.length + ? row.categoryIds + : row.categoryId + ? [row.categoryId] + : [], + dramaTypes: + Array.isArray(row.dramaTypes) && row.dramaTypes.length + ? row.dramaTypes + : row.dramaType + ? [row.dramaType] + : ['LIVE'], description: row.description || '', freeEpisodes: row.freeEpisodes ?? 3, unlockCoin: row.unlockCoin ?? 0, @@ -200,6 +214,16 @@ function dramaTypeLabel(value) { return dramaTypeOptions.find((item) => item.value === value)?.label || '真人剧' } +function rowCategoryNames(row) { + const names = Array.isArray(row.categoryNames) ? row.categoryNames.filter(Boolean) : [] + return names.length ? names.join(' / ') : row.genre || '—' +} + +function rowDramaTypes(row) { + if (Array.isArray(row.dramaTypes) && row.dramaTypes.length) return row.dramaTypes + return row.dramaType ? [row.dramaType] : [] +} + async function saveDrama() { if (saving.value || uploadingCover.value) return try { @@ -207,11 +231,13 @@ async function saveDrama() { } catch { return } - const category = categories.value.find((item) => item.id === form.categoryId) + const categoryNames = form.categoryIds + .map((id) => categories.value.find((item) => item.id === id)?.name) + .filter(Boolean) const payload = { ...form, title: form.title.trim(), - genre: category?.name || '' + genre: categoryNames.join(' / ') } saving.value = true try { @@ -366,13 +392,27 @@ onMounted(async () => { :key="item.code" :label="item.text" :value="item.code" /> { >— - - + +
{{ dramaTypeLabel(type) }}
{ - - + + { /> - - + +