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="已结束" />
|
||||
@ -27,11 +27,7 @@
|
||||
|
||||
<!-- 错误状态 -->
|
||||
<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)">
|
||||
@ -49,10 +45,7 @@
|
||||
|
||||
<!-- 空状态 -->
|
||||
<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">
|
||||
创建课程
|
||||
@ -67,13 +60,8 @@
|
||||
<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';
|
||||
|
||||
@ -159,9 +156,9 @@ const getCourseList = async (forceRefresh: boolean = false) => {
|
||||
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'
|
||||
}));
|
||||
@ -190,7 +187,7 @@ const getCourseList = async (forceRefresh: boolean = false) => {
|
||||
// 显示错误提示
|
||||
message.error(error.value);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
@ -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;
|
||||
}
|
||||
@ -475,206 +473,206 @@ onMounted(async () => {
|
||||
overflow-x: hidden;
|
||||
/* 防止水平滚动 */
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
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;
|
||||
}
|
||||
.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;
|
||||
}
|
||||
.nav-links {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
gap: 12px;
|
||||
}
|
||||
.actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.search-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.search-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.course-container {
|
||||
width: 100%;
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.course-container {
|
||||
width: 100%;
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.loading-container {
|
||||
display: contents;
|
||||
}
|
||||
.loading-container {
|
||||
display: contents;
|
||||
}
|
||||
|
||||
.error-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 400px;
|
||||
width: 100%;
|
||||
padding: 40px 20px;
|
||||
}
|
||||
.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;
|
||||
}
|
||||
.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-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 {
|
||||
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-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;
|
||||
}
|
||||
.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 {
|
||||
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;
|
||||
}
|
||||
.section-title.offline {
|
||||
background: #FF6C17;
|
||||
}
|
||||
|
||||
.more-options {
|
||||
cursor: pointer;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.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;
|
||||
}
|
||||
.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-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 {
|
||||
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-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 */
|
||||
}
|
||||
.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 {
|
||||
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'
|
||||
@ -326,7 +339,19 @@ 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) {
|
||||
@ -389,7 +414,18 @@ 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 || '';
|
||||
@ -676,7 +712,7 @@ const handleSubmit = async () => {
|
||||
question: null
|
||||
}
|
||||
|
||||
if (isEditMode.value) {
|
||||
if (isEditMode.value && !isCopyMode.value) {
|
||||
// 编辑模式
|
||||
const editData = {
|
||||
id: courseId.value,
|
||||
@ -702,7 +738,7 @@ const handleSubmit = async () => {
|
||||
|
||||
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);
|
||||
}
|
||||
@ -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,50 +777,71 @@ 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({
|
||||
label: cls.name,
|
||||
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