feat(web): 支持后台列表图片大图预览

This commit is contained in:
Zhou Weidong committed 2026-10-19 13:42:28 +08:00
1 parent 046400ae4a
commit 8a84f24baf
10 files changed
+202 -13

No files matched your search

@@ -1,9 +1,10 @@
<!-- Author: fruit.com.cn -->
<script setup>
import { onMounted, reactive, ref } from 'vue'
import { computed, onMounted, reactive, ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { AppIcons } from '@/constants/icons'
import { AppImage } from '@/components/AppImage'
import {
createBannerApi,
deleteBannerApi,
@@ -53,6 +54,12 @@ const linkTypeOptions = [
{ code: 'URL', text: '打开链接' }
]
const bannerPreviewList = computed(() => list.value.map((item) => item.imageUrl).filter(Boolean))
function bannerPreviewIndex(row) {
return Math.max(0, bannerPreviewList.value.indexOf(row.imageUrl))
}
async function load() {
loading.value = true
try {
@@ -253,7 +260,15 @@ onMounted(async () => {
>
<el-table-column label="预览" width="190">
<template #default="{ row }">
<img v-if="row.imageUrl" :src="row.imageUrl" class="banner-thumb" />
<AppImage
v-if="row.imageUrl"
:src="row.imageUrl"
:preview-list="bannerPreviewList"
:initial-index="bannerPreviewIndex(row)"
fit="cover"
class="banner-thumb"
:alt="row.title"
/>
<div v-else class="banner-thumb-empty">暂无图片</div>
</template>
</el-table-column>
@@ -5,6 +5,7 @@ import { computed, nextTick, onMounted, reactive, ref } from 'vue'
import { useRouter } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'
import { AppIcons } from '@/constants/icons'
import { AppImage } from '@/components/AppImage'
import {
changeDramaStatusApi,
createDramaApi,
@@ -63,6 +64,12 @@ const coverDisplayName = computed(
() => coverFileName.value || (form.cover ? coverBasename(form.cover) : '尚未选择封面')
)
const pageCoverPreviewList = computed(() => list.value.map((item) => item.cover).filter(Boolean))
function coverPreviewIndex(row) {
return Math.max(0, pageCoverPreviewList.value.indexOf(row.cover))
}
const statusOptions = [
{ code: 'draft', text: '草稿' },
{ code: 'reviewing', text: '审核中' },
@@ -354,10 +361,15 @@ onMounted(async () => {
<el-table-column label="短剧名称" min-width="220"
><template #default="{ row }"
><div class="drama-cell"
><img v-if="row.cover" :src="row.cover" class="drama-cover-image" /><div
v-else
class="drama-cover"
>暂无封面</div
><AppImage
v-if="row.cover"
:src="row.cover"
:preview-list="pageCoverPreviewList"
:initial-index="coverPreviewIndex(row)"
fit="cover"
class="drama-cover-image"
:alt="row.title"
/><div v-else class="drama-cover">暂无封面</div
><div
><b>{{ row.title }}</b></div
></div
+19 -1
View File
@@ -1,7 +1,9 @@
<!-- Author: fruit.com.cn -->
<script setup>
import { computed } from 'vue'
import { AppIcons } from '@/constants/icons'
import { AppImage } from '@/components/AppImage'
import PageHeading from '@/views/components/PageHeading.vue'
import CreatorCenterPage from './components/CreatorCenterPage.vue'
import { useRbac } from '@/stores/rbac'
@@ -47,6 +49,14 @@ const {
withdraw
} = useDramaEdit()
const episodeCoverPreviewList = computed(() =>
episodes.value.map((row) => row.cover).filter(Boolean)
)
function episodeCoverPreviewIndex(row) {
return Math.max(0, episodeCoverPreviewList.value.indexOf(row.cover))
}
function back() {
window.history.back()
}
@@ -193,7 +203,15 @@ function requestDramaCover(options) {
<el-table-column label="封面" width="88">
<template #default="{ row }">
<div class="creator-episode-cover">
<img v-if="row.cover" :src="row.cover" alt="" />
<AppImage
v-if="row.cover"
:src="row.cover"
:preview-list="episodeCoverPreviewList"
:initial-index="episodeCoverPreviewIndex(row)"
fit="cover"
class="creator-episode-image"
:alt="row.title"
/>
<span v-else>无</span>
</div>
</template>
+19 -2
View File
@@ -1,9 +1,10 @@
<!-- Author: fruit.com.cn -->
<script setup>
import { ref } from 'vue'
import { computed, ref } from 'vue'
import { useRouter } from 'vue-router'
import { AppIcons } from '@/constants/icons'
import { AppImage } from '@/components/AppImage'
import PageHeading from '@/views/components/PageHeading.vue'
import CreatorCenterPage from './components/CreatorCenterPage.vue'
import { useCreatorAccess } from './composables/useCreatorAccess'
@@ -43,6 +44,14 @@ const {
const activeTab = ref('dramas')
const workspaceCoverPreviewList = computed(() =>
(dramas.rows || []).map((row) => row.cover).filter(Boolean)
)
function workspaceCoverPreviewIndex(row) {
return Math.max(0, workspaceCoverPreviewList.value.indexOf(row.cover))
}
function onTabChange(name) {
if (name === 'notices' && !notices.loaded) loadNotices()
}
@@ -149,7 +158,15 @@ function openEdit(row) {
<template #default="{ row }">
<div class="creator-drama-cell">
<div class="creator-drama-cover">
<img v-if="row.cover" :src="row.cover" alt="" />
<AppImage
v-if="row.cover"
:src="row.cover"
:preview-list="workspaceCoverPreviewList"
:initial-index="workspaceCoverPreviewIndex(row)"
fit="cover"
class="creator-drama-image"
:alt="row.title"
/>
<span v-else>{{ (row.title || '?').slice(0, 1) }}</span>
</div>
<div class="creator-drama-meta">
+25 -2
View File
@@ -3,6 +3,7 @@
<script setup>
import { computed } from 'vue'
import { AppIcons } from '@/constants/icons'
import { AppImage } from '@/components/AppImage'
import PageHeading from '@/views/components/PageHeading.vue'
import { useRbac } from '@/stores/rbac'
import {
@@ -70,6 +71,12 @@ function avatarText(row) {
return name.slice(0, 1).toUpperCase()
}
const avatarPreviewList = computed(() => users.value.map((row) => row.avatarUrl).filter(Boolean))
function avatarPreviewIndex(row) {
return Math.max(0, avatarPreviewList.value.indexOf(row.avatarUrl))
}
function canBeBanned(row) {
return row.status !== 'banned' && row.status !== 'deactivated'
}
@@ -145,7 +152,15 @@ function canBeBanned(row) {
<template #default="{ row }">
<div class="app-user-cell">
<span class="app-user-avatar">
<img v-if="row.avatarUrl" :src="row.avatarUrl" alt="" />
<AppImage
v-if="row.avatarUrl"
:src="row.avatarUrl"
:preview-list="avatarPreviewList"
:initial-index="avatarPreviewIndex(row)"
fit="cover"
class="app-user-avatar-image"
:alt="row.nickname || row.uid"
/>
<template v-else>{{ avatarText(row) }}</template>
</span>
<div class="app-user-meta">
@@ -217,7 +232,15 @@ function canBeBanned(row) {
<template v-if="detail">
<div class="app-user-summary">
<span class="app-user-avatar">
<img v-if="detail.avatarUrl" :src="detail.avatarUrl" alt="" />
<AppImage
v-if="detail.avatarUrl"
:src="detail.avatarUrl"
:preview-list="avatarPreviewList"
:initial-index="avatarPreviewIndex(detail)"
fit="cover"
class="app-user-avatar-image"
:alt="detail.nickname || detail.uid"
/>
<template v-else>{{ avatarText(detail) }}</template>
</span>
<div class="app-user-meta">