fix: 课程包详情页标题改为「详情」; 优化课程包编辑页相关逻辑
Made-with: Cursor
This commit is contained in:
parent
877acf33b8
commit
1783706d63
@ -1,36 +1,27 @@
|
||||
<template>
|
||||
<div class="course-detail-view">
|
||||
<!-- 顶部导航 -->
|
||||
<div class="detail-header">
|
||||
<div class="header-left">
|
||||
<a-button type="text" @click="router.back()">
|
||||
<ArrowLeftOutlined />
|
||||
</a-button>
|
||||
<div class="course-title">
|
||||
<h2>{{ course.name || '课程包详情' }}</h2>
|
||||
<a-tag :style="getStatusStyle(course.status)" style="margin-left: 12px;">
|
||||
{{ translateStatus(course.status) }}
|
||||
</a-tag>
|
||||
</div>
|
||||
</div>
|
||||
<a-page-header title="课程包详情" :sub-title="course.name || ''" @back="() => router.back()">
|
||||
<template #extra>
|
||||
<div class="header-actions">
|
||||
<a-button v-if="course.status !== 'PUBLISHED'" @click="editCourse">
|
||||
<a-button v-if="canEdit" @click="editCourse">
|
||||
<EditOutlined /> 编辑
|
||||
</a-button>
|
||||
<a-button @click="viewStats">
|
||||
<BarChartOutlined /> 数据
|
||||
</a-button>
|
||||
<a-popconfirm
|
||||
v-if="course.status === 'DRAFT' || course.status === 'ARCHIVED'"
|
||||
title="确定删除此课程包吗?"
|
||||
@confirm="deleteCourse"
|
||||
>
|
||||
<a-popconfirm v-if="course.status === 'DRAFT' || course.status === 'ARCHIVED'" title="确定删除此课程包吗?"
|
||||
@confirm="deleteCourse">
|
||||
<a-button danger>
|
||||
<DeleteOutlined /> 删除
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template #tags>
|
||||
<a-tag :style="getStatusStyle(course.status)">{{ translateStatus(course.status) }}</a-tag>
|
||||
</template>
|
||||
</a-page-header>
|
||||
|
||||
<a-spin :spinning="loading">
|
||||
<div class="detail-content">
|
||||
@ -223,12 +214,8 @@
|
||||
</div>
|
||||
<div class="section-body">
|
||||
<div class="lesson-cards">
|
||||
<div
|
||||
v-for="lesson in courseLessons"
|
||||
:key="lesson.id"
|
||||
class="lesson-card"
|
||||
:class="'lesson-type-' + lesson.lessonType?.toLowerCase()"
|
||||
>
|
||||
<div v-for="lesson in courseLessons" :key="lesson.id" class="lesson-card"
|
||||
:class="'lesson-type-' + lesson.lessonType?.toLowerCase()">
|
||||
<div class="lesson-header">
|
||||
<div class="lesson-type-badge" :style="{ background: getLessonTypeBgColor(lesson.lessonType) }">
|
||||
{{ translateLessonType(lesson.lessonType) }}
|
||||
@ -254,29 +241,20 @@
|
||||
<div class="lesson-section" v-if="hasLessonResources(lesson)">
|
||||
<div class="lesson-section-title">核心资源</div>
|
||||
<div class="resource-grid">
|
||||
<div
|
||||
v-if="lesson.videoPath"
|
||||
class="resource-item"
|
||||
@click="previewFile(lesson.videoPath, lesson.videoName || '绘本动画')"
|
||||
>
|
||||
<div v-if="lesson.videoPath" class="resource-item"
|
||||
@click="previewFile(lesson.videoPath, lesson.videoName || '绘本动画')">
|
||||
<VideoCameraOutlined class="resource-icon video" />
|
||||
<span class="resource-name">{{ lesson.videoName || '绘本动画' }}</span>
|
||||
<EyeOutlined class="resource-action" />
|
||||
</div>
|
||||
<div
|
||||
v-if="lesson.pptPath"
|
||||
class="resource-item"
|
||||
@click="previewFile(lesson.pptPath, lesson.pptName || '教学课件')"
|
||||
>
|
||||
<div v-if="lesson.pptPath" class="resource-item"
|
||||
@click="previewFile(lesson.pptPath, lesson.pptName || '教学课件')">
|
||||
<FilePptOutlined class="resource-icon ppt" />
|
||||
<span class="resource-name">{{ lesson.pptName || '教学课件' }}</span>
|
||||
<EyeOutlined class="resource-action" />
|
||||
</div>
|
||||
<div
|
||||
v-if="lesson.pdfPath"
|
||||
class="resource-item"
|
||||
@click="previewFile(lesson.pdfPath, lesson.pdfName || '电子绘本')"
|
||||
>
|
||||
<div v-if="lesson.pdfPath" class="resource-item"
|
||||
@click="previewFile(lesson.pdfPath, lesson.pdfName || '电子绘本')">
|
||||
<FilePdfOutlined class="resource-icon pdf" />
|
||||
<span class="resource-name">{{ lesson.pdfName || '电子绘本' }}</span>
|
||||
<EyeOutlined class="resource-action" />
|
||||
@ -333,12 +311,8 @@
|
||||
<VideoCameraOutlined style="color: #722ed1;" /> 视频资源
|
||||
</div>
|
||||
<div class="resource-list">
|
||||
<div
|
||||
v-for="(item, index) in allVideos"
|
||||
:key="'video-' + index"
|
||||
class="resource-item-card"
|
||||
@click="previewFile(item.path, item.name)"
|
||||
>
|
||||
<div v-for="(item, index) in allVideos" :key="'video-' + index" class="resource-item-card"
|
||||
@click="previewFile(item.path, item.name)">
|
||||
<VideoCameraOutlined class="item-icon" style="color: #722ed1;" />
|
||||
<span class="item-name">{{ item.name }}</span>
|
||||
<PlayCircleOutlined class="item-action" />
|
||||
@ -352,12 +326,8 @@
|
||||
<AudioOutlined style="color: #52c41a;" /> 音频资源
|
||||
</div>
|
||||
<div class="resource-list">
|
||||
<div
|
||||
v-for="(item, index) in allAudios"
|
||||
:key="'audio-' + index"
|
||||
class="resource-item-card"
|
||||
@click="previewFile(item.path, item.name)"
|
||||
>
|
||||
<div v-for="(item, index) in allAudios" :key="'audio-' + index" class="resource-item-card"
|
||||
@click="previewFile(item.path, item.name)">
|
||||
<AudioOutlined class="item-icon" style="color: #52c41a;" />
|
||||
<span class="item-name">{{ item.name }}</span>
|
||||
<PlayCircleOutlined class="item-action" />
|
||||
@ -371,12 +341,8 @@
|
||||
<FileTextOutlined style="color: #1890ff;" /> 文档资源
|
||||
</div>
|
||||
<div class="resource-list">
|
||||
<div
|
||||
v-for="(item, index) in allDocuments"
|
||||
:key="'doc-' + index"
|
||||
class="resource-item-card"
|
||||
@click="previewFile(item.path, item.name)"
|
||||
>
|
||||
<div v-for="(item, index) in allDocuments" :key="'doc-' + index" class="resource-item-card"
|
||||
@click="previewFile(item.path, item.name)">
|
||||
<FilePdfOutlined v-if="item.type === 'pdf'" class="item-icon" style="color: #f5222d;" />
|
||||
<FilePptOutlined v-else-if="item.type === 'ppt'" class="item-icon" style="color: #fa8c16;" />
|
||||
<FileTextOutlined v-else class="item-icon" style="color: #1890ff;" />
|
||||
@ -392,14 +358,8 @@
|
||||
<PictureOutlined style="color: #13c2c2;" /> 图片资源
|
||||
</div>
|
||||
<div class="image-grid">
|
||||
<img
|
||||
v-for="(item, index) in allImages"
|
||||
:key="'img-' + index"
|
||||
:src="getFileUrl(item.path)"
|
||||
:alt="item.name"
|
||||
class="image-thumbnail"
|
||||
@click="previewImage(getFileUrl(item.path))"
|
||||
/>
|
||||
<img v-for="(item, index) in allImages" :key="'img-' + index" :src="getFileUrl(item.path)"
|
||||
:alt="item.name" class="image-thumbnail" @click="previewImage(getFileUrl(item.path))" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -414,11 +374,7 @@
|
||||
</a-modal>
|
||||
|
||||
<!-- 文件预览弹窗 -->
|
||||
<FilePreviewModal
|
||||
v-model:open="previewModalVisible"
|
||||
:file-url="previewFileUrl"
|
||||
:file-name="previewFileName"
|
||||
/>
|
||||
<FilePreviewModal v-model:open="previewModalVisible" :file-url="previewFileUrl" :file-name="previewFileName" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -543,6 +499,12 @@ const domainTags = computed(() => {
|
||||
}
|
||||
});
|
||||
|
||||
// 审核中(待审核)不可编辑,仅草稿/已驳回/已下架可编辑
|
||||
const canEdit = computed(() => {
|
||||
const s = course.value.status;
|
||||
return s === 'DRAFT' || s === 'REJECTED' || s === 'ARCHIVED';
|
||||
});
|
||||
|
||||
// 是否有课程介绍内容
|
||||
const hasIntroContent = computed(() => {
|
||||
return course.value.introSummary || course.value.introHighlights ||
|
||||
@ -823,39 +785,10 @@ const fetchCourseDetail = async () => {
|
||||
background: #f0f2f5;
|
||||
}
|
||||
|
||||
.detail-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 16px 24px;
|
||||
background: white;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
|
||||
.header-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
|
||||
.course-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
h2 {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.header-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.detail-content {
|
||||
padding: 24px;
|
||||
@ -1124,9 +1057,17 @@ const fetchCourseDetail = async () => {
|
||||
font-size: 18px;
|
||||
margin-right: 8px;
|
||||
|
||||
&.video { color: #722ed1; }
|
||||
&.ppt { color: #fa8c16; }
|
||||
&.pdf { color: #f5222d; }
|
||||
&.video {
|
||||
color: #722ed1;
|
||||
}
|
||||
|
||||
&.ppt {
|
||||
color: #fa8c16;
|
||||
}
|
||||
|
||||
&.pdf {
|
||||
color: #f5222d;
|
||||
}
|
||||
}
|
||||
|
||||
.resource-name {
|
||||
|
||||
@ -186,6 +186,12 @@ const fetchCourseDetail = async () => {
|
||||
router.push(`/admin/packages/${courseId.value}`);
|
||||
return;
|
||||
}
|
||||
// 审核中(待审核)的课程包不允许编辑
|
||||
if (course?.status === 'PENDING') {
|
||||
message.warning('审核中的课程包不允许编辑,请等待审核完成或先撤销审核');
|
||||
router.push(`/admin/packages/${courseId.value}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// 基本信息
|
||||
formData.basic.name = course.name;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user