chore(merge): 剧集列表分页默认每页100条

This commit is contained in:
Zhou Weidong authored and trae-solo-agent committed 2026-10-21 23:00:13 +08:00
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"