fix:修复课程删除报错,修复课程编辑字段保存回显问题
This commit is contained in:
parent
568d8fdf47
commit
bff716f6b6
@ -193,9 +193,7 @@ export class TeachCourseApi {
|
||||
try {
|
||||
console.log('🚀 发送删除课程请求:', { url: '/aiol/aiolCourse/delete', id })
|
||||
|
||||
const response = await ApiRequest.delete<any>('/aiol/aiolCourse/delete', {
|
||||
params: { id }
|
||||
})
|
||||
const response = await ApiRequest.delete<any>(`/aiol/aiolCourse/delete?id=${id}`, )
|
||||
|
||||
console.log('🗑️ 删除课程响应:', response)
|
||||
return response
|
||||
|
@ -2,7 +2,7 @@
|
||||
<div class="course-category">
|
||||
<!-- 顶部 -->
|
||||
<div class="top">
|
||||
<n-tabs v-model:value="activeTab" size="large">
|
||||
<n-tabs v-model:value="activeTab" size="large">
|
||||
<n-tab-pane name="ongoing" tab="进行中" />
|
||||
<n-tab-pane name="draft" tab="草稿箱" />
|
||||
<n-tab-pane name="finished" tab="已结束" />
|
||||
@ -24,14 +24,10 @@
|
||||
<n-spin size="large" :show="loading">
|
||||
</n-spin>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- 错误状态 -->
|
||||
<div v-else-if="error" class="error-container">
|
||||
<n-result
|
||||
status="error"
|
||||
title="加载失败"
|
||||
:description="error"
|
||||
>
|
||||
<n-result status="error" title="加载失败" :description="error">
|
||||
<template #footer>
|
||||
<n-space justify="center">
|
||||
<n-button type="primary" @click="getCourseList(true)">
|
||||
@ -46,13 +42,10 @@
|
||||
</template>
|
||||
</n-result>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- 空状态 -->
|
||||
<div v-else-if="courseList.length === 0" class="empty-container">
|
||||
<n-empty
|
||||
description="暂无课程数据"
|
||||
size="large"
|
||||
>
|
||||
<n-empty description="暂无课程数据" size="large">
|
||||
<template #extra>
|
||||
<n-button type="primary" @click="navigateToCreateCourse">
|
||||
创建课程
|
||||
@ -60,20 +53,15 @@
|
||||
</template>
|
||||
</n-empty>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- 课程列表 -->
|
||||
<div v-if="courseList.length > 0" class="course-grid" key="course-list">
|
||||
<div class="course-card" v-for="course in courseList" :key="course.id">
|
||||
<div class="course-image-container">
|
||||
<div class="section-title" :class="{ 'offline': course.status === 0 }">{{ course.statusText }}
|
||||
</div>
|
||||
<n-popselect
|
||||
:options="getOptionsForCourse(course)"
|
||||
trigger="hover"
|
||||
placement="bottom-end"
|
||||
:render-label="renderOptionLabel"
|
||||
@update:value="(value: string) => handleOptionSelect(value, course)"
|
||||
>
|
||||
<n-popselect :options="getOptionsForCourse(course)" trigger="hover" placement="bottom-end"
|
||||
:render-label="renderOptionLabel" @update:value="(value: string) => handleOptionSelect(value, course)">
|
||||
<div class="more-options">
|
||||
<span class="more-icon">
|
||||
<n-icon size="20">
|
||||
@ -117,8 +105,17 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, h, onMounted, watch } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { EllipsisVerticalSharp, Refresh } from '@vicons/ionicons5';
|
||||
import { useMessage, useDialog } from 'naive-ui';
|
||||
import {
|
||||
EllipsisVerticalSharp,
|
||||
Refresh,
|
||||
CloudOfflineOutline, // 下架
|
||||
CreateOutline, // 编辑
|
||||
CopyOutline, // 复制
|
||||
TrashOutline, // 删除
|
||||
CloudUploadOutline, // 发布
|
||||
AddOutline // 加号/添加
|
||||
} from '@vicons/ionicons5';
|
||||
import { useMessage, useDialog, NIcon } from 'naive-ui';
|
||||
import TeachCourseApi, { type TeachCourse } from '@/api/modules/teachCourse';
|
||||
import { useCourseStore } from '@/stores/course';
|
||||
|
||||
@ -148,20 +145,20 @@ const getCourseList = async (forceRefresh: boolean = false) => {
|
||||
loading.value = true;
|
||||
error.value = ''; // 清除之前的错误状态
|
||||
courseList.value = [];
|
||||
|
||||
|
||||
const params = {
|
||||
keyword: searchValue.value,
|
||||
status: getStatusByTab(activeTab.value)
|
||||
};
|
||||
|
||||
|
||||
console.log('🔄 获取课程列表 - Tab:', activeTab.value, 'Status:', params.status, 'Keyword:', params.keyword);
|
||||
|
||||
const response = await TeachCourseApi.getTeacherCourseList(params);
|
||||
loading.value = false;
|
||||
if (response && response.data) {
|
||||
const courseData = response.data.result.map((course: TeachCourse): CourseDisplayItem => ({
|
||||
...course,
|
||||
// 映射状态显示文本
|
||||
const courseData = response.data.result.map((course: TeachCourse): CourseDisplayItem => ({
|
||||
...course,
|
||||
// 映射状态显示文本
|
||||
statusText: getStatusText(course.status),
|
||||
image: course.cover || '/images/teacher/fj.png'
|
||||
}));
|
||||
@ -179,18 +176,18 @@ const getCourseList = async (forceRefresh: boolean = false) => {
|
||||
} catch (err: any) {
|
||||
console.error('获取课程列表失败:', err);
|
||||
loading.value = false;
|
||||
|
||||
|
||||
// 设置错误信息
|
||||
error.value = err.message || ''
|
||||
|
||||
|
||||
// 清空课程列表
|
||||
originalCourseList.value = [];
|
||||
courseList.value = [];
|
||||
|
||||
|
||||
// 显示错误提示
|
||||
message.error(error.value);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
@ -217,16 +214,16 @@ const getStatusByTab = (tab: string): string => {
|
||||
// 过滤课程列表(仅用于本地搜索过滤)
|
||||
const filterCourseList = () => {
|
||||
let filtered = [...originalCourseList.value];
|
||||
|
||||
|
||||
// 根据搜索关键词过滤(状态过滤已经在API层面处理)
|
||||
if (searchValue.value?.trim()) {
|
||||
const keyword = searchValue.value.trim().toLowerCase();
|
||||
filtered = filtered.filter(course =>
|
||||
filtered = filtered.filter(course =>
|
||||
course.name?.toLowerCase().includes(keyword) ||
|
||||
course.description?.toLowerCase().includes(keyword)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
courseList.value = filtered;
|
||||
console.log('📊 过滤后的课程数量:', filtered.length);
|
||||
};
|
||||
@ -236,10 +233,10 @@ const activeTab = ref<string>('ongoing')
|
||||
|
||||
// 监听标签页变化,重新调用接口获取数据
|
||||
watch(activeTab, async () => {
|
||||
|
||||
|
||||
courseList.value = [];
|
||||
originalCourseList.value = [];
|
||||
|
||||
|
||||
await getCourseList(true);
|
||||
});
|
||||
|
||||
@ -251,7 +248,7 @@ watch(searchValue, () => {
|
||||
|
||||
// 跳转到创建课程页面
|
||||
const navigateToCreateCourse = () => {
|
||||
router.push('/teacher/course-create');
|
||||
router.push('/teacher/course-create');
|
||||
};
|
||||
|
||||
// 处理搜索
|
||||
@ -265,21 +262,24 @@ const handleSearch = async () => {
|
||||
const getOptionsForCourse = (course: CourseDisplayItem) => {
|
||||
if (course.status === 1) { // 进行中
|
||||
return [
|
||||
{ label: '下架', value: 'offline', icon: '/images/teacher/下架.png' },
|
||||
{ label: '编辑', value: 'edit', icon: '/images/teacher/小编辑.png' },
|
||||
{ label: '删除', value: 'delete', icon: '/images/teacher/删除.png' }
|
||||
{ label: '下架', value: 'offline', icon: CloudOfflineOutline },
|
||||
{ label: '编辑', value: 'edit', icon: CreateOutline },
|
||||
{ label: '复制', value: 'copy', icon: CopyOutline },
|
||||
{ label: '删除', value: 'delete', icon: TrashOutline }
|
||||
];
|
||||
} else if (course.status === 0) { // 未开始/草稿
|
||||
return [
|
||||
{ label: '发布', value: 'publish', icon: '/images/teacher/加号.png' },
|
||||
{ label: '编辑', value: 'edit', icon: '/images/teacher/小编辑.png' },
|
||||
{ label: '删除', value: 'delete', icon: '/images/teacher/删除.png' }
|
||||
{ label: '发布', value: 'publish', icon: CloudUploadOutline },
|
||||
{ label: '编辑', value: 'edit', icon: CreateOutline },
|
||||
{ label: '复制', value: 'copy', icon: CopyOutline },
|
||||
{ label: '删除', value: 'delete', icon: TrashOutline }
|
||||
];
|
||||
} else if (course.status === 2) { // 已结束
|
||||
return [
|
||||
{ label: '发布', value: 'publish', icon: '/images/teacher/加号.png' },
|
||||
{ label: '编辑', value: 'edit', icon: '/images/teacher/小编辑.png' },
|
||||
{ label: '删除', value: 'delete', icon: '/images/teacher/删除.png' }
|
||||
{ label: '发布', value: 'publish', icon: CloudUploadOutline },
|
||||
{ label: '编辑', value: 'edit', icon: CreateOutline },
|
||||
{ label: '复制', value: 'copy', icon: CopyOutline },
|
||||
{ label: '删除', value: 'delete', icon: TrashOutline }
|
||||
];
|
||||
}
|
||||
return [];
|
||||
@ -294,13 +294,9 @@ const renderOptionLabel = (option: any) => {
|
||||
gap: '6px'
|
||||
}
|
||||
}, [
|
||||
h('img', {
|
||||
src: option.icon,
|
||||
alt: '',
|
||||
style: {
|
||||
width: '13px',
|
||||
height: '13px'
|
||||
}
|
||||
h(NIcon, {
|
||||
size: 16,
|
||||
component: option.icon
|
||||
}),
|
||||
option.label
|
||||
]);
|
||||
@ -312,12 +308,8 @@ const handleOptionSelect = (value: string, course: any) => {
|
||||
// 根据不同的 value 执行对应的操作
|
||||
switch (value) {
|
||||
case 'edit':
|
||||
// 编辑逻辑 - 将课程数据保存到store并跳转到编辑页面
|
||||
console.log('✏️ 编辑课程,准备数据:', course);
|
||||
|
||||
// 保存到store
|
||||
courseStore.setCourseEditData(course);
|
||||
|
||||
// 跳转到课程编辑页面,只传递课程ID
|
||||
router.push(`/teacher/course-create/${course.id}`);
|
||||
break;
|
||||
@ -333,6 +325,12 @@ const handleOptionSelect = (value: string, course: any) => {
|
||||
// 发布逻辑
|
||||
handlePublishCourse(course);
|
||||
break;
|
||||
case 'copy':
|
||||
// 复制逻辑
|
||||
courseStore.setCourseEditData(course);
|
||||
// 跳转到课程编辑页面,只传递课程ID
|
||||
router.push(`/teacher/course-create/${course.id}?type=copy`);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -365,7 +363,7 @@ const handleDeleteCourse = (course: any) => {
|
||||
try {
|
||||
// 调用删除接口
|
||||
await TeachCourseApi.deleteCourse(course.id);
|
||||
|
||||
|
||||
// 从列表中移除
|
||||
const index = courseList.value.findIndex(c => c.id === course.id);
|
||||
if (index > -1) {
|
||||
@ -376,7 +374,7 @@ const handleDeleteCourse = (course: any) => {
|
||||
originalCourseList.value.splice(originalIndex, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
message.success(`课程"${course.name}"已删除`);
|
||||
} catch (error) {
|
||||
console.error('删除课程失败:', error);
|
||||
@ -403,13 +401,13 @@ const handleOfflineCourse = (course: CourseDisplayItem) => {
|
||||
// 通过API下架课程 - 设置状态为已结束
|
||||
const updatedData = {
|
||||
id: course.id!,
|
||||
status: '0',
|
||||
status: '0',
|
||||
};
|
||||
|
||||
await TeachCourseApi.editCourse(updatedData);
|
||||
|
||||
|
||||
await getCourseList();
|
||||
|
||||
|
||||
message.success(`课程"${course.name}"已下架,现在可以删除了`);
|
||||
} catch (error) {
|
||||
console.error('下架课程失败:', error);
|
||||
@ -436,13 +434,13 @@ const handlePublishCourse = (course: CourseDisplayItem) => {
|
||||
// 通过API发布课程 - 设置状态为进行中
|
||||
const updatedData = {
|
||||
id: course.id!,
|
||||
status: '1',
|
||||
status: '1',
|
||||
};
|
||||
|
||||
await TeachCourseApi.editCourse(updatedData);
|
||||
|
||||
|
||||
await getCourseList();
|
||||
|
||||
|
||||
message.success(`课程"${course.name}"已发布`);
|
||||
} catch (error) {
|
||||
console.error('发布课程失败:', error);
|
||||
@ -475,206 +473,206 @@ onMounted(async () => {
|
||||
overflow-x: hidden;
|
||||
/* 防止水平滚动 */
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.top {
|
||||
padding: 10px 20px;
|
||||
white-space: nowrap;
|
||||
/* 进一步减少左右padding */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
width: 100%;
|
||||
/* 确保宽度充满父容器 */
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
|
||||
.search-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.course-container {
|
||||
width: 100%;
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.loading-container {
|
||||
display: contents;
|
||||
}
|
||||
|
||||
.error-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 400px;
|
||||
width: 100%;
|
||||
padding: 40px 20px;
|
||||
}
|
||||
|
||||
.empty-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 400px;
|
||||
width: 100%;
|
||||
padding: 40px 20px;
|
||||
}
|
||||
|
||||
.course-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
/* 默认4列,确保100%缩放下不被截断 */
|
||||
gap: 12px;
|
||||
/* 进一步减少间距 */
|
||||
margin-bottom: 20px;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 0 3px;
|
||||
/* 减少内边距 */
|
||||
}
|
||||
|
||||
.course-card {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
/* aspect-ratio: 190 / 201; */
|
||||
background: #FFFFFF;
|
||||
border: 1px solid #D8D8D8;
|
||||
box-sizing: border-box;
|
||||
transition: all 0.3s ease;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.course-card:hover {
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||
/* transform: translateY(-5px); */
|
||||
}
|
||||
|
||||
.course-image-container {
|
||||
position: relative;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
width: 50px;
|
||||
height: 20px;
|
||||
background: #0288D1;
|
||||
color: white;
|
||||
font-size: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.section-title.offline {
|
||||
background: #FF6C17;
|
||||
}
|
||||
|
||||
.more-options {
|
||||
cursor: pointer;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.more-icon {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
display: flex;
|
||||
line-height: 1;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.course-image-container img {
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
}
|
||||
|
||||
.course-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
flex: 1;
|
||||
box-sizing: border-box;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.course-info img {
|
||||
width: 80%;
|
||||
height: auto;
|
||||
aspect-ratio: 150 / 105;
|
||||
/* 居中 */
|
||||
display: block;
|
||||
margin: 8px auto 10px;
|
||||
position: relative;
|
||||
top: -5px;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
}
|
||||
|
||||
.course-name {
|
||||
width: 80%;
|
||||
font-family: AppleSystemUIFont;
|
||||
font-size: 14px;
|
||||
color: #333333;
|
||||
line-height: 1.5;
|
||||
text-align: center;
|
||||
font-style: normal;
|
||||
text-transform: none;
|
||||
white-space: nowrap;
|
||||
/* 强制文本在一行显示 */
|
||||
overflow: hidden;
|
||||
/* 隐藏超出容器的文本 */
|
||||
text-overflow: ellipsis;
|
||||
/* 溢出部分用省略号表示 */
|
||||
margin-top: 0px;
|
||||
/* 文字往上移动:添加负上边距 */
|
||||
margin-bottom: 10px;
|
||||
/* 减小底部边距从15px到10px */
|
||||
}
|
||||
|
||||
/* 分页样式 */
|
||||
.pagination {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
z-index: 100;
|
||||
margin: 0;
|
||||
margin-top: auto;
|
||||
flex-shrink: 0;
|
||||
.top {
|
||||
padding: 10px 20px;
|
||||
white-space: nowrap;
|
||||
/* 进一步减少左右padding */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
width: 100%;
|
||||
/* 确保宽度充满父容器 */
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.search-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.course-container {
|
||||
width: 100%;
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.loading-container {
|
||||
display: contents;
|
||||
}
|
||||
|
||||
.error-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 400px;
|
||||
width: 100%;
|
||||
padding: 40px 20px;
|
||||
}
|
||||
|
||||
.empty-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 400px;
|
||||
width: 100%;
|
||||
padding: 40px 20px;
|
||||
}
|
||||
|
||||
.course-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
/* 默认4列,确保100%缩放下不被截断 */
|
||||
gap: 12px;
|
||||
/* 进一步减少间距 */
|
||||
margin-bottom: 20px;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 0 3px;
|
||||
/* 减少内边距 */
|
||||
}
|
||||
|
||||
.course-card {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
/* aspect-ratio: 190 / 201; */
|
||||
background: #FFFFFF;
|
||||
border: 1px solid #D8D8D8;
|
||||
box-sizing: border-box;
|
||||
transition: all 0.3s ease;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.course-card:hover {
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||
/* transform: translateY(-5px); */
|
||||
}
|
||||
|
||||
.course-image-container {
|
||||
position: relative;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
width: 50px;
|
||||
height: 20px;
|
||||
background: #0288D1;
|
||||
color: white;
|
||||
font-size: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.section-title.offline {
|
||||
background: #FF6C17;
|
||||
}
|
||||
|
||||
.more-options {
|
||||
cursor: pointer;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.more-icon {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
display: flex;
|
||||
line-height: 1;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.course-image-container img {
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
}
|
||||
|
||||
.course-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
flex: 1;
|
||||
box-sizing: border-box;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.course-info img {
|
||||
width: 80%;
|
||||
height: auto;
|
||||
aspect-ratio: 150 / 105;
|
||||
/* 居中 */
|
||||
display: block;
|
||||
margin: 8px auto 10px;
|
||||
position: relative;
|
||||
top: -5px;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
}
|
||||
|
||||
.course-name {
|
||||
width: 80%;
|
||||
font-family: AppleSystemUIFont;
|
||||
font-size: 14px;
|
||||
color: #333333;
|
||||
line-height: 1.5;
|
||||
text-align: center;
|
||||
font-style: normal;
|
||||
text-transform: none;
|
||||
white-space: nowrap;
|
||||
/* 强制文本在一行显示 */
|
||||
overflow: hidden;
|
||||
/* 隐藏超出容器的文本 */
|
||||
text-overflow: ellipsis;
|
||||
/* 溢出部分用省略号表示 */
|
||||
margin-top: 0px;
|
||||
/* 文字往上移动:添加负上边距 */
|
||||
margin-bottom: 10px;
|
||||
/* 减小底部边距从15px到10px */
|
||||
}
|
||||
|
||||
/* 分页样式 */
|
||||
.pagination {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
z-index: 100;
|
||||
margin: 0;
|
||||
margin-top: auto;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.pagination-content {
|
||||
@ -749,7 +747,7 @@ onMounted(async () => {
|
||||
border-color: #1890ff;
|
||||
}
|
||||
|
||||
:deep(.n-tabs.n-tabs--top .n-tab-pane){
|
||||
:deep(.n-tabs.n-tabs--top .n-tab-pane) {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
@ -3,16 +3,16 @@
|
||||
<div class="form-container">
|
||||
<!-- 表单内容 -->
|
||||
<div class="form-content">
|
||||
<div class="header-left">
|
||||
<n-button quaternary circle size="large" @click="goBack">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<ArrowBackOutline />
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
<h2 class="page-title">{{ pageTitle }}</h2>
|
||||
</div>
|
||||
<div class="header-left">
|
||||
<n-button quaternary circle size="large" @click="goBack">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<ArrowBackOutline />
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
<h2 class="page-title">{{ pageTitle }}</h2>
|
||||
</div>
|
||||
|
||||
<!-- 上半部分:两列布局 -->
|
||||
<div class="form-row">
|
||||
@ -24,7 +24,7 @@
|
||||
<n-input v-model:value="formData.courseName" placeholder="请输入课程名称" class="form-input" />
|
||||
</div>
|
||||
|
||||
<!-- 课程开始时间 -->
|
||||
<!-- 课程开始时间 -->
|
||||
<div class="form-item">
|
||||
<label class="form-label required">课程开始时间:</label>
|
||||
<n-date-picker v-model:value="formData.startTime" type="datetime" placeholder="选择时间" class="form-input" />
|
||||
@ -58,7 +58,7 @@
|
||||
<div class="form-item" v-show="formData.studentType === 'partial'">
|
||||
<label class="form-label required">选择班级:</label>
|
||||
<n-select v-model:value="formData.selectedClasses" multiple :options="classOptions"
|
||||
placeholder="选择班级(可多选)" class="form-input" />
|
||||
placeholder="选择班级(可多选)" class="form-input" :disabled="isEditMode && !isCopyMode" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -200,9 +200,19 @@ const courseStore = useCourseStore()
|
||||
// 判断是否为编辑模式
|
||||
const isEditMode = computed(() => !!route.params.id)
|
||||
const courseId = computed(() => route.params.id as string)
|
||||
// 判断是否为复制模式,数据回显,但是是新增模式
|
||||
const isCopyMode = computed(() => route.query.type === 'copy')
|
||||
|
||||
// 页面标题
|
||||
const pageTitle = computed(() => isEditMode.value ? '编辑课程' : '创建课程')
|
||||
const pageTitle = computed(() => {
|
||||
if (isCopyMode.value) {
|
||||
return '复制课程'
|
||||
} else if (isEditMode.value && !isCopyMode.value) {
|
||||
return '编辑课程'
|
||||
} else {
|
||||
return '新建课程'
|
||||
}
|
||||
})
|
||||
|
||||
// 编辑器实例,必须用 shallowRef
|
||||
const editorRef = shallowRef()
|
||||
@ -214,6 +224,9 @@ const previewUrl = ref('')
|
||||
// 待设置的课程描述内容(用于富文本编辑器初始化后设置)
|
||||
const pendingCourseDescription = ref('')
|
||||
|
||||
// 待回显的班级数据(用于班级选项加载完成后回显)
|
||||
const pendingSelectedClasses = ref<string[]>([])
|
||||
|
||||
const toolbarConfig = {}
|
||||
const editorConfig = { placeholder: '请输入内容...' }
|
||||
const mode = 'default'
|
||||
@ -227,7 +240,7 @@ onBeforeUnmount(() => {
|
||||
|
||||
const handleCreated = (editor: any) => {
|
||||
editorRef.value = editor // 记录 editor 实例,重要!
|
||||
|
||||
|
||||
// 如果有待设置的内容,立即设置到编辑器
|
||||
if (pendingCourseDescription.value) {
|
||||
editor.setHtml(pendingCourseDescription.value);
|
||||
@ -265,21 +278,21 @@ const originalInstructors = ref<string[]>([])
|
||||
const loadCourseTeachers = async (courseId: string) => {
|
||||
try {
|
||||
console.log('🔄 开始获取课程老师列表,课程ID:', courseId)
|
||||
|
||||
|
||||
const response = await TeachCourseApi.getTeacherListInCourse(courseId)
|
||||
|
||||
|
||||
console.log('🔍 课程老师API响应:', response)
|
||||
|
||||
|
||||
if (response.data && response.data.result) {
|
||||
const teachers = response.data.result
|
||||
console.log('✅ 获取到课程老师列表:', teachers)
|
||||
|
||||
|
||||
// 提取老师ID列表
|
||||
const teacherIds = teachers.map((teacher: any) => teacher.id || teacher.userId)
|
||||
|
||||
|
||||
formData.instructors = teacherIds
|
||||
originalInstructors.value = [...teacherIds]
|
||||
|
||||
|
||||
console.log('📝 已设置课程老师ID列表:', teacherIds)
|
||||
} else {
|
||||
console.log('⚠️ 课程暂无绑定老师')
|
||||
@ -301,7 +314,7 @@ const loadCourseData = async () => {
|
||||
try {
|
||||
// 首先检查store中是否有课程编辑数据
|
||||
const storeCourseData = courseStore.courseEditData;
|
||||
|
||||
|
||||
if (storeCourseData) {
|
||||
// 字段映射:从后端数据映射到前端表单字段
|
||||
formData.courseName = storeCourseData.name || storeCourseData.courseName || '';
|
||||
@ -314,7 +327,7 @@ const loadCourseData = async () => {
|
||||
} else {
|
||||
formData.courseCategory = [];
|
||||
}
|
||||
|
||||
|
||||
// 如果是编辑模式且有课程ID,调用API获取当前课程的老师
|
||||
if (isEditMode.value && courseId.value) {
|
||||
await loadCourseTeachers(courseId.value);
|
||||
@ -326,8 +339,20 @@ const loadCourseData = async () => {
|
||||
formData.startTime = storeCourseData.start_time || storeCourseData.startTime || null;
|
||||
formData.endTime = storeCourseData.end_time || storeCourseData.endTime || null;
|
||||
formData.studentType = (storeCourseData.type === 1 || storeCourseData.studentType === 'partial') ? 'partial' : 'all';
|
||||
formData.selectedClasses = storeCourseData.target ? storeCourseData.target.split(',') : (storeCourseData.selectedClasses || []);
|
||||
console.log('huixian:',storeCourseData);
|
||||
|
||||
// 处理班级数据:如果班级选项还没加载完成,先保存到待回显变量
|
||||
const classData = storeCourseData.classId ? storeCourseData.classId.split(',') : (storeCourseData.selectedClasses || []);
|
||||
if (classOptions.value.length > 0) {
|
||||
// 班级选项已加载,直接设置
|
||||
formData.selectedClasses = classData;
|
||||
console.log('直接设置班级数据:', classData);
|
||||
} else {
|
||||
// 班级选项未加载,保存到待回显变量
|
||||
pendingSelectedClasses.value = classData;
|
||||
console.log('保存班级数据到待回显变量:', classData);
|
||||
}
|
||||
|
||||
const tempCourseDescription = storeCourseData.description || storeCourseData.courseDescription || '';
|
||||
if (tempCourseDescription) {
|
||||
if (editorRef.value) {
|
||||
@ -337,35 +362,35 @@ const loadCourseData = async () => {
|
||||
pendingCourseDescription.value = tempCourseDescription;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 视频设置选项:从后端字段映射到前端字段(数字0/1转布尔值)
|
||||
formData.stopOnLeave = storeCourseData.pauseExit !== undefined ?
|
||||
formData.stopOnLeave = storeCourseData.pauseExit !== undefined ?
|
||||
Boolean(Number(storeCourseData.pauseExit)) : true;
|
||||
formData.videoSpeedControl = storeCourseData.allowSpeed !== undefined ?
|
||||
formData.videoSpeedControl = storeCourseData.allowSpeed !== undefined ?
|
||||
Boolean(Number(storeCourseData.allowSpeed)) : false;
|
||||
formData.showVideoText = storeCourseData.showSubtitle !== undefined ?
|
||||
formData.showVideoText = storeCourseData.showSubtitle !== undefined ?
|
||||
Boolean(Number(storeCourseData.showSubtitle)) : true;
|
||||
|
||||
|
||||
// 积分设置
|
||||
formData.pointsEnabled = storeCourseData.pointsEnabled !== undefined ? storeCourseData.pointsEnabled : true;
|
||||
formData.earnPoints = storeCourseData.earnPoints || 60;
|
||||
formData.requiredPoints = storeCourseData.requiredPoints || 60;
|
||||
|
||||
|
||||
if (storeCourseData.cover || storeCourseData.courseCover) {
|
||||
previewUrl.value = storeCourseData.cover || storeCourseData.courseCover;
|
||||
formData.courseCover = null;
|
||||
}
|
||||
|
||||
|
||||
message.success('课程数据加载成功');
|
||||
return; // 如果从store获取到数据,就不需要再调用API
|
||||
}
|
||||
|
||||
|
||||
// 如果store中没有数据,检查是否有通过路由传递的课程数据(向后兼容)
|
||||
const routeCourseData = route.query.courseData;
|
||||
if (routeCourseData) {
|
||||
try {
|
||||
const courseData = JSON.parse(routeCourseData as string);
|
||||
|
||||
|
||||
// 字段映射:从后端数据映射到前端表单字段
|
||||
formData.courseName = courseData.name || courseData.courseName || '';
|
||||
// 处理课程分类:如果是字符串则分割为数组,如果是数组则直接使用
|
||||
@ -377,7 +402,7 @@ const loadCourseData = async () => {
|
||||
} else {
|
||||
formData.courseCategory = [];
|
||||
}
|
||||
|
||||
|
||||
// 如果是编辑模式且有课程ID,调用API获取当前课程的老师
|
||||
if (isEditMode.value && courseId.value) {
|
||||
await loadCourseTeachers(courseId.value);
|
||||
@ -389,8 +414,19 @@ const loadCourseData = async () => {
|
||||
formData.startTime = courseData.start_time || courseData.startTime || null;
|
||||
formData.endTime = courseData.end_time || courseData.endTime || null;
|
||||
formData.studentType = (courseData.type === 1 || courseData.studentType === 'partial') ? 'partial' : 'all';
|
||||
formData.selectedClasses = courseData.target ? courseData.target.split(',') : (courseData.selectedClasses || []);
|
||||
|
||||
// 处理班级数据:如果班级选项还没加载完成,先保存到待回显变量
|
||||
const classData = courseData.target ? courseData.target.split(',') : (courseData.selectedClasses || []);
|
||||
if (classOptions.value.length > 0) {
|
||||
// 班级选项已加载,直接设置
|
||||
formData.selectedClasses = classData;
|
||||
console.log('直接设置班级数据:', classData);
|
||||
} else {
|
||||
// 班级选项未加载,保存到待回显变量
|
||||
pendingSelectedClasses.value = classData;
|
||||
console.log('保存班级数据到待回显变量:', classData);
|
||||
}
|
||||
|
||||
// 处理富文本编辑器内容
|
||||
const tempCourseDescription = courseData.description || courseData.courseDescription || '';
|
||||
if (tempCourseDescription) {
|
||||
@ -403,33 +439,33 @@ const loadCourseData = async () => {
|
||||
pendingCourseDescription.value = tempCourseDescription;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 视频设置选项:从后端字段映射到前端字段(数字0/1转布尔值)
|
||||
formData.stopOnLeave = courseData.pauseExit !== undefined ?
|
||||
formData.stopOnLeave = courseData.pauseExit !== undefined ?
|
||||
Boolean(Number(courseData.pauseExit)) : true;
|
||||
formData.videoSpeedControl = courseData.allowSpeed !== undefined ?
|
||||
formData.videoSpeedControl = courseData.allowSpeed !== undefined ?
|
||||
Boolean(Number(courseData.allowSpeed)) : false;
|
||||
formData.showVideoText = courseData.showSubtitle !== undefined ?
|
||||
formData.showVideoText = courseData.showSubtitle !== undefined ?
|
||||
Boolean(Number(courseData.showSubtitle)) : true;
|
||||
|
||||
|
||||
// 积分设置(使用默认值或数据值)
|
||||
formData.pointsEnabled = courseData.pointsEnabled !== undefined ? courseData.pointsEnabled : true;
|
||||
formData.earnPoints = courseData.earnPoints || 60;
|
||||
formData.requiredPoints = courseData.requiredPoints || 60;
|
||||
|
||||
|
||||
// 如果有课程封面,设置预览URL
|
||||
if (courseData.cover || courseData.courseCover) {
|
||||
previewUrl.value = courseData.cover || courseData.courseCover;
|
||||
formData.courseCover = null; // 现有URL,不是新文件
|
||||
}
|
||||
|
||||
|
||||
message.success('课程数据加载成功');
|
||||
return; // 如果从路由获取到数据,就不需要再调用API
|
||||
} catch (parseError) {
|
||||
// 如果解析失败,继续使用原来的模拟数据逻辑
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 如果既没有store数据也没有路由数据,保持表单为空状态以供新建课程
|
||||
} catch (error) {
|
||||
message.error('加载课程数据失败')
|
||||
@ -500,14 +536,14 @@ const handleCancel = () => {
|
||||
// 格式化时间为 YYYY-MM-DD HH:mm:ss 格式
|
||||
const formatDateTime = (timestamp: number): string => {
|
||||
const date = new Date(timestamp)
|
||||
|
||||
|
||||
const year = date.getFullYear()
|
||||
const month = (date.getMonth() + 1).toString().padStart(2, '0')
|
||||
const day = date.getDate().toString().padStart(2, '0')
|
||||
const hours = date.getHours().toString().padStart(2, '0')
|
||||
const minutes = date.getMinutes().toString().padStart(2, '0')
|
||||
const seconds = date.getSeconds().toString().padStart(2, '0')
|
||||
|
||||
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
|
||||
}
|
||||
|
||||
@ -518,7 +554,7 @@ const handleTeacherChanges = async (courseId: string, isCreateMode: boolean = fa
|
||||
console.log('课程ID:', courseId)
|
||||
console.log('当前老师列表:', formData.instructors)
|
||||
console.log('原始老师列表:', originalInstructors.value)
|
||||
|
||||
|
||||
if (isCreateMode) {
|
||||
// 创建模式:绑定所有选中的老师
|
||||
console.log('📝 创建模式:绑定所有老师')
|
||||
@ -538,15 +574,15 @@ const handleTeacherChanges = async (courseId: string, isCreateMode: boolean = fa
|
||||
} else {
|
||||
// 编辑模式:比较变更并处理
|
||||
console.log('✏️ 编辑模式:比较老师变更')
|
||||
|
||||
|
||||
// 需要添加的老师(在新列表中但不在原列表中)
|
||||
const teachersToAdd = formData.instructors.filter(id => !originalInstructors.value.includes(id))
|
||||
console.log('需要添加的老师:', teachersToAdd)
|
||||
|
||||
|
||||
// 需要移除的老师(在原列表中但不在新列表中)
|
||||
const teachersToRemove = originalInstructors.value.filter(id => !formData.instructors.includes(id))
|
||||
console.log('需要移除的老师:', teachersToRemove)
|
||||
|
||||
|
||||
// 添加新老师
|
||||
for (const instructorId of teachersToAdd) {
|
||||
try {
|
||||
@ -560,7 +596,7 @@ const handleTeacherChanges = async (courseId: string, isCreateMode: boolean = fa
|
||||
console.error('❌ 老师添加失败:', instructorId, error)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 移除老师
|
||||
for (const instructorId of teachersToRemove) {
|
||||
try {
|
||||
@ -575,7 +611,7 @@ const handleTeacherChanges = async (courseId: string, isCreateMode: boolean = fa
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
console.log('✅ 老师变更处理完成')
|
||||
} catch (error) {
|
||||
console.error('❌ 处理老师变更失败:', error)
|
||||
@ -630,11 +666,11 @@ const handleSubmit = async () => {
|
||||
// 只有在有新的文件(File对象)时才需要上传
|
||||
// 如果 courseCover 是 File 对象,说明用户选择了新文件,需要上传
|
||||
// 如果 courseCover 是 null 但 previewUrl 有值,说明是编辑模式使用现有图片
|
||||
|
||||
|
||||
if (formData.courseCover && formData.courseCover instanceof File) {
|
||||
try {
|
||||
const uploadResponse = await UploadApi.uploadCourseThumbnail(formData.courseCover)
|
||||
|
||||
|
||||
if (uploadResponse.data.success) {
|
||||
coverUrl = uploadResponse.data.message
|
||||
} else {
|
||||
@ -675,19 +711,19 @@ const handleSubmit = async () => {
|
||||
status: 1, // 默认状态为进行中
|
||||
question: null
|
||||
}
|
||||
|
||||
if (isEditMode.value) {
|
||||
|
||||
if (isEditMode.value && !isCopyMode.value) {
|
||||
// 编辑模式
|
||||
const editData = {
|
||||
id: courseId.value,
|
||||
...createCourseData
|
||||
}
|
||||
const response = await TeachCourseApi.editCourse(editData)
|
||||
|
||||
|
||||
if (response.data.code === 200) {
|
||||
// 课程更新成功后,处理老师的绑定和解绑
|
||||
await handleTeacherChanges(courseId.value);
|
||||
|
||||
|
||||
message.success('课程更新成功!')
|
||||
// 清除缓存数据
|
||||
courseStore.clearCourseEditData();
|
||||
@ -699,14 +735,14 @@ const handleSubmit = async () => {
|
||||
} else {
|
||||
// 创建模式
|
||||
const response = await TeachCourseApi.createCourse(createCourseData)
|
||||
|
||||
|
||||
if (response.data.code === 200) {
|
||||
// 课程创建成功后,获取新创建的课程ID并绑定老师
|
||||
const newCourseId = response.data.data?.id || response.data.id;
|
||||
const newCourseId = response.data.result;
|
||||
if (newCourseId && formData.instructors.length > 0) {
|
||||
await handleTeacherChanges(newCourseId.toString(), true);
|
||||
}
|
||||
|
||||
|
||||
message.success('课程创建成功!')
|
||||
// 清除缓存数据
|
||||
courseStore.clearCourseEditData();
|
||||
@ -716,7 +752,7 @@ const handleSubmit = async () => {
|
||||
message.error(response.message || '创建失败,请重试')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} catch (error) {
|
||||
const errorMessage = isEditMode.value ? '更新失败,请重试' : '创建失败,请重试'
|
||||
message.error(errorMessage)
|
||||
@ -730,8 +766,9 @@ const goBack = () => {
|
||||
}
|
||||
|
||||
// 获取课程分类
|
||||
const getCourseList = () => {
|
||||
CourseApi.getCategories().then(response => {
|
||||
const getCourseList = async () => {
|
||||
try {
|
||||
const response = await CourseApi.getCategories()
|
||||
categoryOptions.value = response.data.map((category: any) => ({
|
||||
label: category.name,
|
||||
value: category.id
|
||||
@ -740,27 +777,34 @@ const getCourseList = () => {
|
||||
if (formData.courseCategory.length === 0 && categoryOptions.value.length > 0) {
|
||||
formData.courseCategory = [];
|
||||
}
|
||||
}).catch(error => {
|
||||
console.log('课程分类选项加载完成:', categoryOptions.value);
|
||||
} catch (error) {
|
||||
console.error('获取课程列表失败:', error)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 获取老师
|
||||
const getTeacherList = () => {
|
||||
TeachCourseApi.getTeacherList().then(response => {
|
||||
const getTeacherList = async () => {
|
||||
try {
|
||||
const response = await TeachCourseApi.getTeacherList()
|
||||
instructorOptions.value = response.data.result.map((teacher: any) => ({
|
||||
label: teacher.realname,
|
||||
value: teacher.id
|
||||
}))
|
||||
}).catch(error => {
|
||||
console.log('老师选项加载完成:', instructorOptions.value);
|
||||
} catch (error) {
|
||||
console.error('获取老师列表失败:', error)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 获取班级
|
||||
const getClassList = () => {
|
||||
ClassApi.queryClassList({course_id:null}).then(response => {
|
||||
const getClassList = async () => {
|
||||
try {
|
||||
const response = await ClassApi.queryClassList({ course_id: null })
|
||||
console.log('班级列表:', response.data.result);
|
||||
|
||||
// 清空现有的班级选项
|
||||
classOptions.value = []
|
||||
|
||||
response.data.result.forEach((cls: any) => {
|
||||
classOptions.value.push({
|
||||
@ -768,22 +812,36 @@ const getClassList = () => {
|
||||
value: cls.id
|
||||
})
|
||||
})
|
||||
}).catch(error => {
|
||||
|
||||
console.log('班级选项加载完成:', classOptions.value);
|
||||
|
||||
// 班级数据加载完成后,如果有待回显的班级数据,进行回显
|
||||
if (pendingSelectedClasses.value.length > 0) {
|
||||
console.log('开始回显班级数据:', pendingSelectedClasses.value);
|
||||
formData.selectedClasses = [...pendingSelectedClasses.value];
|
||||
pendingSelectedClasses.value = []; // 清空待回显数据
|
||||
console.log('班级回显完成:', formData.selectedClasses);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取班级列表失败:', error)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// 如果是编辑模式(有courseId)、有通过路由传递的课程数据,或者store中有数据
|
||||
onMounted(async () => {
|
||||
// 先加载基础数据(课程分类、老师、班级)
|
||||
await Promise.all([
|
||||
getCourseList(),
|
||||
getTeacherList(),
|
||||
getClassList() // 确保班级数据先加载完成
|
||||
]);
|
||||
|
||||
// 基础数据加载完成后,再加载课程数据进行回显
|
||||
if (isEditMode.value && courseId.value) {
|
||||
loadCourseData()
|
||||
await loadCourseData()
|
||||
} else if (route.query.courseData || courseStore.courseEditData) {
|
||||
// 即使没有ID,也尝试从路由数据或store加载(用于从列表页面直接编辑的情况)
|
||||
loadCourseData()
|
||||
await loadCourseData()
|
||||
}
|
||||
getCourseList()
|
||||
getTeacherList()
|
||||
getClassList()
|
||||
})
|
||||
</script>
|
||||
|
||||
@ -804,28 +862,28 @@ onMounted(() => {
|
||||
|
||||
|
||||
.header-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.page-title {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.title {
|
||||
margin: 0;
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
margin: 0;
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.header-actions {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.form-row {
|
||||
|
@ -151,6 +151,14 @@ const activeSubNavItem = ref(''); // 子菜单激活状态
|
||||
const examMenuExpanded = ref(false); // 考试管理菜单展开状态
|
||||
const studentMenuExpanded = ref(false); // 学员中心菜单展开状态
|
||||
const showTopImage = ref(true); // 控制顶部图片显示/隐藏
|
||||
|
||||
// 需要隐藏顶部图片的路由路径数组
|
||||
const hideTopImageRoutes = [
|
||||
'teacher/chapter-editor-teacher',
|
||||
'teacher/course-editor'
|
||||
// 可以在这里添加更多需要隐藏顶部图片的路由
|
||||
];
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const isAiHovered = ref(false);
|
||||
@ -654,13 +662,29 @@ onMounted(() => {
|
||||
} else {
|
||||
document.documentElement.style.setProperty('--top-height', '0px');
|
||||
}
|
||||
updateTopImageVisibility();
|
||||
});
|
||||
|
||||
// 使用watch监听路由变化
|
||||
watch(route, () => {
|
||||
updateActiveNavItem();
|
||||
updateTopImageVisibility();
|
||||
});
|
||||
|
||||
// 更新顶部图片显示状态
|
||||
const updateTopImageVisibility = () => {
|
||||
const currentPath = route.path;
|
||||
console.log('检查路径是否需要隐藏顶部图片:', currentPath);
|
||||
|
||||
// 检查当前路径是否包含需要隐藏顶部图片的路由
|
||||
const shouldHideTopImage = hideTopImageRoutes.some(routePath =>
|
||||
currentPath.includes(routePath)
|
||||
);
|
||||
|
||||
showTopImage.value = !shouldHideTopImage;
|
||||
console.log('顶部图片显示状态:', showTopImage.value);
|
||||
};
|
||||
|
||||
// 更新激活的导航项
|
||||
const updateActiveNavItem = () => {
|
||||
const path = route.path;
|
||||
@ -704,7 +728,7 @@ const updateActiveNavItem = () => {
|
||||
|
||||
<style scoped>
|
||||
.admin-dashboard {
|
||||
min-height: 100vh;
|
||||
/* min-height: 100vh; */
|
||||
}
|
||||
|
||||
.top-image-container {
|
||||
|
Loading…
x
Reference in New Issue
Block a user