feat(admin): 短剧类型与内容类型多选
This commit is contained in:
1 parent
58380170b0
commit
9e427d485f
3 files changed
+95
-27
No files matched your search
@@ -15,6 +15,7 @@ export interface DramaPageParams {
|
|||||||
keyword?: string
|
keyword?: string
|
||||||
status?: string
|
status?: string
|
||||||
categoryId?: number
|
categoryId?: number
|
||||||
|
categoryIds?: number[]
|
||||||
isHot?: boolean
|
isHot?: boolean
|
||||||
dramaTypes?: Array<'ANIME' | 'LIVE'>
|
dramaTypes?: Array<'ANIME' | 'LIVE'>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,12 +20,15 @@ export interface DramaItem {
|
|||||||
title: string
|
title: string
|
||||||
subtitle?: string
|
subtitle?: string
|
||||||
categoryId?: number
|
categoryId?: number
|
||||||
|
categoryIds?: number[]
|
||||||
|
categoryNames?: string[]
|
||||||
category?: string
|
category?: string
|
||||||
genre?: string
|
genre?: string
|
||||||
description?: string
|
description?: string
|
||||||
cover?: string
|
cover?: string
|
||||||
language?: string
|
language?: string
|
||||||
dramaType?: 'ANIME' | 'LIVE'
|
dramaType?: 'ANIME' | 'LIVE'
|
||||||
|
dramaTypes?: Array<'ANIME' | 'LIVE'>
|
||||||
episodes?: number
|
episodes?: number
|
||||||
freeEpisodes?: number
|
freeEpisodes?: number
|
||||||
unlockCoin?: number
|
unlockCoin?: number
|
||||||
@@ -47,11 +50,13 @@ export interface DramaSaveData {
|
|||||||
title: string
|
title: string
|
||||||
subtitle?: string
|
subtitle?: string
|
||||||
categoryId?: number
|
categoryId?: number
|
||||||
|
categoryIds?: number[]
|
||||||
genre?: string
|
genre?: string
|
||||||
description?: string
|
description?: string
|
||||||
cover?: string
|
cover?: string
|
||||||
language?: string
|
language?: string
|
||||||
dramaType?: 'ANIME' | 'LIVE'
|
dramaType?: 'ANIME' | 'LIVE'
|
||||||
|
dramaTypes?: Array<'ANIME' | 'LIVE'>
|
||||||
freeEpisodes?: number
|
freeEpisodes?: number
|
||||||
unlockCoin?: number
|
unlockCoin?: number
|
||||||
favoriteCount?: number
|
favoriteCount?: number
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ const categories = ref([])
|
|||||||
|
|
||||||
const keyword = ref('')
|
const keyword = ref('')
|
||||||
const statusFilter = ref(undefined)
|
const statusFilter = ref(undefined)
|
||||||
const categoryId = ref(undefined)
|
const categoryIds = ref([])
|
||||||
const dramaTypeFilter = ref(undefined)
|
const dramaTypes = ref([])
|
||||||
const hotFilter = ref(undefined)
|
const hotFilter = ref(undefined)
|
||||||
const pageIndex = ref(1)
|
const pageIndex = ref(1)
|
||||||
const pageSize = ref(10)
|
const pageSize = ref(10)
|
||||||
@@ -47,8 +47,8 @@ const editingLikeCount = ref(0)
|
|||||||
const formRef = ref()
|
const formRef = ref()
|
||||||
const form = reactive({
|
const form = reactive({
|
||||||
title: '',
|
title: '',
|
||||||
categoryId: undefined,
|
categoryIds: [],
|
||||||
dramaType: 'LIVE',
|
dramaTypes: ['LIVE'],
|
||||||
description: '',
|
description: '',
|
||||||
freeEpisodes: 3,
|
freeEpisodes: 3,
|
||||||
unlockCoin: 0,
|
unlockCoin: 0,
|
||||||
@@ -63,8 +63,12 @@ const COVER_TYPES = ['image/jpeg', 'image/png', 'image/webp']
|
|||||||
|
|
||||||
const formRules = {
|
const formRules = {
|
||||||
title: [{ required: true, message: '请输入短剧名称', trigger: 'blur' }],
|
title: [{ required: true, message: '请输入短剧名称', trigger: 'blur' }],
|
||||||
categoryId: [{ required: true, message: '请选择短剧类型', trigger: 'change' }],
|
categoryIds: [
|
||||||
dramaType: [{ required: true, message: '请选择内容类型', trigger: 'change' }]
|
{ type: 'array', required: true, min: 1, message: '请至少选择一个类型', trigger: 'change' }
|
||||||
|
],
|
||||||
|
dramaTypes: [
|
||||||
|
{ type: 'array', required: true, min: 1, message: '请至少选择一个内容类型', trigger: 'change' }
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
const coverDisplayName = computed(
|
const coverDisplayName = computed(
|
||||||
@@ -106,8 +110,8 @@ async function load() {
|
|||||||
pageSize: pageSize.value,
|
pageSize: pageSize.value,
|
||||||
keyword: keyword.value.trim() || undefined,
|
keyword: keyword.value.trim() || undefined,
|
||||||
status: statusFilter.value || undefined,
|
status: statusFilter.value || undefined,
|
||||||
categoryId: categoryId.value,
|
categoryIds: categoryIds.value.length ? categoryIds.value : undefined,
|
||||||
dramaTypes: dramaTypeFilter.value ? [dramaTypeFilter.value] : undefined,
|
dramaTypes: dramaTypes.value.length ? dramaTypes.value : undefined,
|
||||||
isHot: hotFilter.value
|
isHot: hotFilter.value
|
||||||
})
|
})
|
||||||
list.value = res.data?.list || []
|
list.value = res.data?.list || []
|
||||||
@@ -130,8 +134,8 @@ function search() {
|
|||||||
function resetFilters() {
|
function resetFilters() {
|
||||||
keyword.value = ''
|
keyword.value = ''
|
||||||
statusFilter.value = undefined
|
statusFilter.value = undefined
|
||||||
categoryId.value = undefined
|
categoryIds.value = []
|
||||||
dramaTypeFilter.value = undefined
|
dramaTypes.value = []
|
||||||
hotFilter.value = undefined
|
hotFilter.value = undefined
|
||||||
search()
|
search()
|
||||||
}
|
}
|
||||||
@@ -156,8 +160,8 @@ function openCreate() {
|
|||||||
editingId.value = null
|
editingId.value = null
|
||||||
Object.assign(form, {
|
Object.assign(form, {
|
||||||
title: '',
|
title: '',
|
||||||
categoryId: undefined,
|
categoryIds: [],
|
||||||
dramaType: 'LIVE',
|
dramaTypes: ['LIVE'],
|
||||||
description: '',
|
description: '',
|
||||||
freeEpisodes: 3,
|
freeEpisodes: 3,
|
||||||
unlockCoin: 0,
|
unlockCoin: 0,
|
||||||
@@ -178,8 +182,18 @@ function openEdit(row) {
|
|||||||
editingId.value = row.id
|
editingId.value = row.id
|
||||||
Object.assign(form, {
|
Object.assign(form, {
|
||||||
title: row.title,
|
title: row.title,
|
||||||
categoryId: row.categoryId || undefined,
|
categoryIds:
|
||||||
dramaType: row.dramaType || 'LIVE',
|
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 || '',
|
description: row.description || '',
|
||||||
freeEpisodes: row.freeEpisodes ?? 3,
|
freeEpisodes: row.freeEpisodes ?? 3,
|
||||||
unlockCoin: row.unlockCoin ?? 0,
|
unlockCoin: row.unlockCoin ?? 0,
|
||||||
@@ -200,6 +214,16 @@ function dramaTypeLabel(value) {
|
|||||||
return dramaTypeOptions.find((item) => item.value === value)?.label || '真人剧'
|
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() {
|
async function saveDrama() {
|
||||||
if (saving.value || uploadingCover.value) return
|
if (saving.value || uploadingCover.value) return
|
||||||
try {
|
try {
|
||||||
@@ -207,11 +231,13 @@ async function saveDrama() {
|
|||||||
} catch {
|
} catch {
|
||||||
return
|
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 = {
|
const payload = {
|
||||||
...form,
|
...form,
|
||||||
title: form.title.trim(),
|
title: form.title.trim(),
|
||||||
genre: category?.name || ''
|
genre: categoryNames.join(' / ')
|
||||||
}
|
}
|
||||||
saving.value = true
|
saving.value = true
|
||||||
try {
|
try {
|
||||||
@@ -366,13 +392,27 @@ onMounted(async () => {
|
|||||||
:key="item.code"
|
:key="item.code"
|
||||||
:label="item.text"
|
:label="item.text"
|
||||||
:value="item.code" /></el-select
|
:value="item.code" /></el-select
|
||||||
><el-select v-model="categoryId" clearable placeholder="全部类型" @change="search"
|
><el-select
|
||||||
|
v-model="categoryIds"
|
||||||
|
multiple
|
||||||
|
collapse-tags
|
||||||
|
collapse-tags-tooltip
|
||||||
|
clearable
|
||||||
|
placeholder="全部类型"
|
||||||
|
@change="search"
|
||||||
><el-option
|
><el-option
|
||||||
v-for="item in categories"
|
v-for="item in categories"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
:label="item.name"
|
:label="item.name"
|
||||||
:value="item.id" /></el-select
|
:value="item.id" /></el-select
|
||||||
><el-select v-model="dramaTypeFilter" clearable placeholder="全部内容类型" @change="search"
|
><el-select
|
||||||
|
v-model="dramaTypes"
|
||||||
|
multiple
|
||||||
|
collapse-tags
|
||||||
|
collapse-tags-tooltip
|
||||||
|
clearable
|
||||||
|
placeholder="全部内容类型"
|
||||||
|
@change="search"
|
||||||
><el-option
|
><el-option
|
||||||
v-for="item in dramaTypeOptions"
|
v-for="item in dramaTypeOptions"
|
||||||
:key="item.value"
|
:key="item.value"
|
||||||
@@ -416,12 +456,20 @@ onMounted(async () => {
|
|||||||
><span v-else class="table-empty-text">—</span></template
|
><span v-else class="table-empty-text">—</span></template
|
||||||
></el-table-column
|
></el-table-column
|
||||||
>
|
>
|
||||||
<el-table-column prop="genre" label="类型" width="110" />
|
<el-table-column label="类型" min-width="150" show-overflow-tooltip
|
||||||
<el-table-column label="内容类型" width="110"
|
><template #default="{ row }">{{ rowCategoryNames(row) }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="内容类型" min-width="150"
|
||||||
><template #default="{ row }"
|
><template #default="{ row }"
|
||||||
><el-tag :type="row.dramaType === 'ANIME' ? 'warning' : 'info'" effect="light">{{
|
><div class="table-actions"
|
||||||
dramaTypeLabel(row.dramaType)
|
><el-tag
|
||||||
}}</el-tag></template
|
v-for="type in rowDramaTypes(row)"
|
||||||
|
:key="type"
|
||||||
|
:type="type === 'ANIME' ? 'warning' : 'info'"
|
||||||
|
effect="light"
|
||||||
|
>{{ dramaTypeLabel(type) }}</el-tag
|
||||||
|
></div
|
||||||
|
></template
|
||||||
></el-table-column
|
></el-table-column
|
||||||
>
|
>
|
||||||
<el-table-column label="集数" width="90"
|
<el-table-column label="集数" width="90"
|
||||||
@@ -533,8 +581,15 @@ onMounted(async () => {
|
|||||||
<el-form-item label="短剧名称" prop="title">
|
<el-form-item label="短剧名称" prop="title">
|
||||||
<el-input v-model="form.title" maxlength="80" placeholder="请输入短剧名称" />
|
<el-input v-model="form.title" maxlength="80" placeholder="请输入短剧名称" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="类型" prop="categoryId">
|
<el-form-item label="类型" prop="categoryIds">
|
||||||
<el-select v-model="form.categoryId" placeholder="请选择类型">
|
<el-select
|
||||||
|
v-model="form.categoryIds"
|
||||||
|
multiple
|
||||||
|
collapse-tags
|
||||||
|
collapse-tags-tooltip
|
||||||
|
filterable
|
||||||
|
placeholder="请选择类型"
|
||||||
|
>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in categories"
|
v-for="item in categories"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
@@ -543,8 +598,15 @@ onMounted(async () => {
|
|||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="内容类型" prop="dramaType">
|
<el-form-item label="内容类型" prop="dramaTypes">
|
||||||
<el-select v-model="form.dramaType" placeholder="请选择内容类型">
|
<el-select
|
||||||
|
v-model="form.dramaTypes"
|
||||||
|
multiple
|
||||||
|
collapse-tags
|
||||||
|
collapse-tags-tooltip
|
||||||
|
filterable
|
||||||
|
placeholder="请选择内容类型"
|
||||||
|
>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in dramaTypeOptions"
|
v-for="item in dramaTypeOptions"
|
||||||
:key="item.value"
|
:key="item.value"
|
||||||
|
|||||||
Reference in new issue
Block a user