chore(merge): 剧集列表分页默认每页100条
This commit is contained in:
commit
c2a76a593a
1 file changed
+63
-10
@@ -15,6 +15,9 @@ import BatchUploadDialog from './upload/BatchUploadDialog.vue'
|
|||||||
import EpisodeFormDialog from './upload/EpisodeFormDialog.vue'
|
import EpisodeFormDialog from './upload/EpisodeFormDialog.vue'
|
||||||
import { listPendingSessions } from './upload/uploadSessions'
|
import { listPendingSessions } from './upload/uploadSessions'
|
||||||
|
|
||||||
|
const DEFAULT_PAGE_SIZE = 100
|
||||||
|
const PAGE_SIZE_OPTIONS = [50, 100, 200]
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const { can } = useRbac()
|
const { can } = useRbac()
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
@@ -23,6 +26,8 @@ const loading = ref(false)
|
|||||||
const dramas = ref([])
|
const dramas = ref([])
|
||||||
const episodes = ref([])
|
const episodes = ref([])
|
||||||
const selectedDramaId = ref(undefined)
|
const selectedDramaId = ref(undefined)
|
||||||
|
const pageIndex = ref(1)
|
||||||
|
const pageSize = ref(DEFAULT_PAGE_SIZE)
|
||||||
const batchUploadVisible = ref(false)
|
const batchUploadVisible = ref(false)
|
||||||
const previewVisible = ref(false)
|
const previewVisible = ref(false)
|
||||||
const previewEpisode = ref(null)
|
const previewEpisode = ref(null)
|
||||||
@@ -34,6 +39,17 @@ const existingEpisodeNumbers = computed(() =>
|
|||||||
episodes.value.map((item) => Number(item.number)).filter((n) => Number.isFinite(n))
|
episodes.value.map((item) => Number(item.number)).filter((n) => Number.isFinite(n))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const pagedEpisodes = computed(() => {
|
||||||
|
const start = (pageIndex.value - 1) * pageSize.value
|
||||||
|
return episodes.value.slice(start, start + pageSize.value)
|
||||||
|
})
|
||||||
|
|
||||||
|
const showPagination = computed(() => {
|
||||||
|
const total = episodes.value.length
|
||||||
|
if (total <= 0) return false
|
||||||
|
return Math.ceil(total / pageSize.value) > 1
|
||||||
|
})
|
||||||
|
|
||||||
async function loadDramas() {
|
async function loadDramas() {
|
||||||
const res = await pageDramasApi({ pageIndex: 1, pageSize: 200 })
|
const res = await pageDramasApi({ pageIndex: 1, pageSize: 200 })
|
||||||
dramas.value = res.data?.list || []
|
dramas.value = res.data?.list || []
|
||||||
@@ -55,11 +71,19 @@ async function loadEpisodes() {
|
|||||||
try {
|
try {
|
||||||
const res = await listEpisodesApi(selectedDramaId.value)
|
const res = await listEpisodesApi(selectedDramaId.value)
|
||||||
episodes.value = res.data || []
|
episodes.value = res.data || []
|
||||||
|
clampPageIndex()
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false
|
loading.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 刷新后若当前页越界(如删除末页最后一条),夹到最后一页。 */
|
||||||
|
function clampPageIndex() {
|
||||||
|
const total = episodes.value.length
|
||||||
|
const maxPage = Math.max(1, Math.ceil(total / pageSize.value) || 1)
|
||||||
|
if (pageIndex.value > maxPage) pageIndex.value = maxPage
|
||||||
|
}
|
||||||
|
|
||||||
function nextNumber() {
|
function nextNumber() {
|
||||||
return episodes.value.reduce((max, item) => Math.max(max, item.number || 0), 0) + 1
|
return episodes.value.reduce((max, item) => Math.max(max, item.number || 0), 0) + 1
|
||||||
}
|
}
|
||||||
@@ -122,10 +146,24 @@ function stopThumb(event) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function episodeIndexInFullList(row) {
|
||||||
|
return episodes.value.findIndex((item) => item.id === row.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
function canMoveUp(row) {
|
||||||
|
return episodeIndexInFullList(row) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
function canMoveDown(row) {
|
||||||
|
const index = episodeIndexInFullList(row)
|
||||||
|
return index >= 0 && index < episodes.value.length - 1
|
||||||
|
}
|
||||||
|
|
||||||
/** 上移/下移后把新顺序整表提交,由后端重排 sort。 */
|
/** 上移/下移后把新顺序整表提交,由后端重排 sort。 */
|
||||||
async function move(index, offset) {
|
async function move(row, offset) {
|
||||||
|
const index = episodeIndexInFullList(row)
|
||||||
const target = index + offset
|
const target = index + offset
|
||||||
if (target < 0 || target >= episodes.value.length) return
|
if (index < 0 || target < 0 || target >= episodes.value.length) return
|
||||||
const next = [...episodes.value]
|
const next = [...episodes.value]
|
||||||
const [moved] = next.splice(index, 1)
|
const [moved] = next.splice(index, 1)
|
||||||
next.splice(target, 0, moved)
|
next.splice(target, 0, moved)
|
||||||
@@ -135,10 +173,15 @@ async function move(index, offset) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function onDramaChange() {
|
async function onDramaChange() {
|
||||||
|
pageIndex.value = 1
|
||||||
await loadEpisodes()
|
await loadEpisodes()
|
||||||
openBatchIfPendingSessions()
|
openBatchIfPendingSessions()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleSizeChange() {
|
||||||
|
pageIndex.value = 1
|
||||||
|
}
|
||||||
|
|
||||||
/** 进入页面或切换短剧时,若有 24h 内未完成上传则打开批量上传弹窗以提示续传。 */
|
/** 进入页面或切换短剧时,若有 24h 内未完成上传则打开批量上传弹窗以提示续传。 */
|
||||||
function openBatchIfPendingSessions() {
|
function openBatchIfPendingSessions() {
|
||||||
if (!selectedDramaId.value || !can('episode:upload')) return
|
if (!selectedDramaId.value || !can('episode:upload')) return
|
||||||
@@ -202,11 +245,10 @@ onMounted(async () => {
|
|||||||
<div class="episode-toolbar"
|
<div class="episode-toolbar"
|
||||||
><div
|
><div
|
||||||
><h2>剧集列表({{ episodes.length }})</h2><p>按列表顺序播放</p></div
|
><h2>剧集列表({{ episodes.length }})</h2><p>按列表顺序播放</p></div
|
||||||
></div
|
></div>
|
||||||
>
|
|
||||||
<el-table
|
<el-table
|
||||||
v-loading="loading"
|
v-loading="loading"
|
||||||
:data="episodes"
|
:data="pagedEpisodes"
|
||||||
row-key="id"
|
row-key="id"
|
||||||
empty-text="该短剧暂无剧集"
|
empty-text="该短剧暂无剧集"
|
||||||
class="drama-el-table episode-el-table"
|
class="drama-el-table episode-el-table"
|
||||||
@@ -278,7 +320,7 @@ onMounted(async () => {
|
|||||||
></el-table-column
|
></el-table-column
|
||||||
>
|
>
|
||||||
<el-table-column label="操作" width="250" fixed="right"
|
<el-table-column label="操作" width="250" fixed="right"
|
||||||
><template #default="{ row, $index }"
|
><template #default="{ row }"
|
||||||
><div class="table-actions"
|
><div class="table-actions"
|
||||||
><el-button
|
><el-button
|
||||||
v-if="can('episode:upload')"
|
v-if="can('episode:upload')"
|
||||||
@@ -289,14 +331,14 @@ onMounted(async () => {
|
|||||||
><el-button
|
><el-button
|
||||||
v-if="can('episode:sort')"
|
v-if="can('episode:sort')"
|
||||||
size="small"
|
size="small"
|
||||||
:disabled="$index === 0"
|
:disabled="!canMoveUp(row)"
|
||||||
@click="move($index, -1)"
|
@click="move(row, -1)"
|
||||||
>上移</el-button
|
>上移</el-button
|
||||||
><el-button
|
><el-button
|
||||||
v-if="can('episode:sort')"
|
v-if="can('episode:sort')"
|
||||||
size="small"
|
size="small"
|
||||||
:disabled="$index === episodes.length - 1"
|
:disabled="!canMoveDown(row)"
|
||||||
@click="move($index, 1)"
|
@click="move(row, 1)"
|
||||||
>下移</el-button
|
>下移</el-button
|
||||||
><el-button
|
><el-button
|
||||||
v-if="can('episode:upload')"
|
v-if="can('episode:upload')"
|
||||||
@@ -309,6 +351,17 @@ onMounted(async () => {
|
|||||||
></el-table-column
|
></el-table-column
|
||||||
>
|
>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
<div v-if="showPagination" class="pagination"
|
||||||
|
><el-pagination
|
||||||
|
v-model:current-page="pageIndex"
|
||||||
|
v-model:page-size="pageSize"
|
||||||
|
:page-sizes="PAGE_SIZE_OPTIONS"
|
||||||
|
:total="episodes.length"
|
||||||
|
:pager-count="7"
|
||||||
|
layout="total, sizes, prev, pager, next, jumper"
|
||||||
|
background
|
||||||
|
@size-change="handleSizeChange"
|
||||||
|
/></div>
|
||||||
</section>
|
</section>
|
||||||
<EpisodeFormDialog
|
<EpisodeFormDialog
|
||||||
ref="formDialogRef"
|
ref="formDialogRef"
|
||||||
|
|||||||
Reference in new issue
Block a user