文章、课程标签的默认封面

This commit is contained in:
2025-12-24 15:44:07 +08:00
parent 46464f36a0
commit 878133fb40
22 changed files with 1278 additions and 25 deletions

View File

@@ -161,6 +161,48 @@
placeholder="请输入标签描述"
/>
</el-form-item>
<el-form-item label="默认封面">
<div class="default-covers-section">
<div class="covers-tip">为该标签配置多张默认封面资源没有封面时会随机显示其中一张</div>
<!-- 已上传的封面列表 -->
<div class="covers-list" v-if="defaultCovers.length > 0">
<div v-for="(cover, index) in defaultCovers" :key="cover.id || index" class="cover-item">
<img :src="cover.coverImage" alt="默认封面" class="cover-preview" />
<div class="cover-actions">
<el-switch
v-model="cover.isActive"
:active-value="1"
:inactive-value="0"
active-text="启用"
inactive-text="禁用"
/>
<el-button
type="danger"
size="small"
@click="removeCover(index)"
:icon="Delete"
>
删除
</el-button>
</div>
</div>
</div>
<!-- 添加封面 -->
<FileUpload
list-type="cover"
:cover-url="''"
@update:cover-url="handleAddCover"
accept="image/*"
:max-size="5"
module="tag-cover"
:as-dialog="false"
tip="点击上传默认封面图片"
/>
</div>
</el-form-item>
</el-form>
<template #footer>
@@ -175,10 +217,13 @@
<script setup lang="ts">
import { ref, onMounted, computed } from 'vue';
import { ElMessage, ElMessageBox, type FormInstance, type FormRules } from 'element-plus';
import { Delete } from '@element-plus/icons-vue';
import { resourceTagApi } from '@/apis/resource';
import type { Tag } from '@/types/resource';
import { TagType } from '@/types/resource';
import {AdminLayout} from '@/views/admin';
import { AdminLayout } from '@/views/admin';
import {FileUpload} from '@/components';
import { FILE_DOWNLOAD_URL } from '@/config';
defineOptions({
name: 'TagManagementView'
@@ -198,6 +243,9 @@ const currentTag = ref<Partial<Tag>>({
description: ''
});
// 默认封面列表
const defaultCovers = ref<any[]>([]);
// 按类型分类的标签
const articleTags = computed(() => {
return tags.value.filter(tag => tag.tagType === TagType.ARTICLE_CATEGORY);
@@ -256,16 +304,65 @@ function showCreateDialog() {
color: '#409EFF',
description: ''
};
defaultCovers.value = [];
dialogVisible.value = true;
}
// 编辑标签
function editTag(row: Tag) {
async function editTag(row: Tag) {
isEdit.value = true;
currentTag.value = { ...row };
// 加载默认封面
await loadDefaultCovers(row.tagID!);
dialogVisible.value = true;
}
// 加载默认封面
async function loadDefaultCovers(tagID: string) {
try {
const result = await resourceTagApi.getAllDefaultCovers(tagID);
console.log('加载默认封面结果:', result);
if (result.success && result.dataList) {
defaultCovers.value = result.dataList.map((cover: any) => ({
...cover,
coverImage: FILE_DOWNLOAD_URL + cover.coverImage
}));
console.log('处理后的封面列表:', defaultCovers.value);
} else {
defaultCovers.value = [];
}
} catch (error) {
console.error('加载默认封面失败:', error);
defaultCovers.value = [];
}
}
// 添加封面
function handleAddCover(fileIdOrUrl: string) {
if (fileIdOrUrl) {
// 如果是完整URL提取fileId否则直接使用
let fileId = fileIdOrUrl;
// 如果包含FILE_DOWNLOAD_URL说明是完整URL需要提取fileId
if (fileIdOrUrl.includes(FILE_DOWNLOAD_URL)) {
fileId = fileIdOrUrl.replace(FILE_DOWNLOAD_URL, '');
}
defaultCovers.value.push({
coverImage: FILE_DOWNLOAD_URL + fileId,
isActive: 1,
orderNum: defaultCovers.value.length
});
}
}
// 删除封面
function removeCover(index: number) {
defaultCovers.value.splice(index, 1);
}
// 删除标签
async function deleteTag(row: Tag) {
try {
@@ -310,6 +407,17 @@ async function handleSubmit() {
}
if (result.success) {
// 保存默认封面
let tagID = currentTag.value.tagID;
if (!tagID && result.data) {
// 新建标签从返回数据中获取tagID
tagID = typeof result.data === 'string' ? result.data : result.data.tagID;
}
if (tagID) {
await saveDefaultCovers(tagID);
}
ElMessage.success(isEdit.value ? '更新成功' : '创建成功');
dialogVisible.value = false;
loadTags();
@@ -323,9 +431,36 @@ async function handleSubmit() {
}
}
// 保存默认封面
async function saveDefaultCovers(tagID: string) {
try {
// 编辑模式下,先删除旧的默认封面
if (isEdit.value) {
await resourceTagApi.deleteDefaultCoversByTagId(tagID);
}
// 准备要保存的封面数据
const coversToSave = defaultCovers.value.map((cover, index) => ({
tagID: tagID,
coverImage: cover.coverImage.replace(FILE_DOWNLOAD_URL, ''),
isActive: cover.isActive,
orderNum: index
}));
// 批量添加新的默认封面
if (coversToSave.length > 0) {
await resourceTagApi.batchAddDefaultCovers(coversToSave);
}
} catch (error) {
console.error('保存默认封面失败:', error);
ElMessage.warning('默认封面保存失败');
}
}
// 对话框关闭处理
function handleDialogClose() {
formRef.value?.resetFields();
defaultCovers.value = [];
}
</script>
@@ -577,4 +712,48 @@ function handleDialogClose() {
grid-template-columns: 1fr;
}
}
.default-covers-section {
display: flex;
flex-direction: column;
gap: 16px;
width: 100%;
}
.covers-tip {
font-size: 12px;
color: #909399;
line-height: 1.5;
}
.covers-list {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 12px;
margin-bottom: 12px;
}
.cover-item {
display: flex;
flex-direction: column;
gap: 8px;
padding: 8px;
border: 1px solid #e0e0e0;
border-radius: 8px;
background: #f9f9f9;
}
.cover-preview {
width: 100%;
height: 120px;
object-fit: cover;
border-radius: 4px;
}
.cover-actions {
display: flex;
justify-content: space-between;
align-items: center;
gap: 8px;
}
</style>