feat: 校园端排课、教师端预约排课添加套餐选择
- 多套餐时步骤1展示套餐选择器,支持切换套餐后加载对应课程包 - 单套餐时保持原行为,自动选中并展示课程包 - 管理端数据模型已支持一租户多套餐、一套餐多课程 Made-with: Cursor
This commit is contained in:
parent
fb4d63ec99
commit
80246c9dec
@ -25,6 +25,26 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.collection-selector {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
padding: 16px;
|
||||||
|
background: #FAFAFA;
|
||||||
|
border-radius: 8px;
|
||||||
|
|
||||||
|
.selector-label {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.collection-radio-group {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.collection-option {
|
.collection-option {
|
||||||
.collection-name {
|
.collection-name {
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
|||||||
@ -50,8 +50,22 @@
|
|||||||
<!-- 步骤2: 选择课程包 -->
|
<!-- 步骤2: 选择课程包 -->
|
||||||
<div v-show="currentStep === 1" class="step-panel">
|
<div v-show="currentStep === 1" class="step-panel">
|
||||||
<h3>选择课程包</h3>
|
<h3>选择课程包</h3>
|
||||||
|
<!-- 多套餐时:先选套餐 -->
|
||||||
|
<div v-if="collections.length > 1" class="collection-selector">
|
||||||
|
<div class="selector-label">选择课程套餐</div>
|
||||||
|
<a-radio-group v-model:value="formData.collectionId" button-style="solid" class="collection-radio-group" @change="onCollectionChange">
|
||||||
|
<a-radio-button
|
||||||
|
v-for="col in collections"
|
||||||
|
:key="col.id"
|
||||||
|
:value="col.id as number"
|
||||||
|
>
|
||||||
|
{{ col.name }}
|
||||||
|
</a-radio-button>
|
||||||
|
</a-radio-group>
|
||||||
|
</div>
|
||||||
<a-spin :spinning="loadingPackages">
|
<a-spin :spinning="loadingPackages">
|
||||||
<div v-if="selectedCollection && selectedCollection.packages && selectedCollection.packages.length > 0" class="packages-section">
|
<div v-if="selectedCollection && selectedCollection.packages && selectedCollection.packages.length > 0" class="packages-section">
|
||||||
|
<div v-if="collections.length > 1" class="selector-label" style="margin-bottom: 12px">选择课程包</div>
|
||||||
<div class="packages-grid">
|
<div class="packages-grid">
|
||||||
<div
|
<div
|
||||||
v-for="pkg in selectedCollection.packages"
|
v-for="pkg in selectedCollection.packages"
|
||||||
@ -428,14 +442,28 @@ const resetForm = () => {
|
|||||||
classTeacherMap.value = {};
|
classTeacherMap.value = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
// 加载课程套餐列表(租户可拥有多个套餐)
|
// 加载课程套餐列表(租户可拥有多个套餐)
|
||||||
|
=======
|
||||||
|
// 加载课程套餐列表;多套餐时展示选择器,单套餐时自动选中并加载课程包
|
||||||
|
>>>>>>> d300fa4 (feat: 校园端排课、教师端预约排课添加套餐选择)
|
||||||
const loadCollections = async () => {
|
const loadCollections = async () => {
|
||||||
loadingPackages.value = true;
|
loadingPackages.value = true;
|
||||||
try {
|
try {
|
||||||
collections.value = await getCourseCollections();
|
collections.value = await getCourseCollections();
|
||||||
|
<<<<<<< HEAD
|
||||||
// 若仅有一个套餐,自动选中并加载其课程包,提升体验
|
// 若仅有一个套餐,自动选中并加载其课程包,提升体验
|
||||||
if (collections.value.length === 1) {
|
if (collections.value.length === 1) {
|
||||||
await selectCollection(collections.value[0]);
|
await selectCollection(collections.value[0]);
|
||||||
|
=======
|
||||||
|
if (collections.value.length > 0) {
|
||||||
|
const first = collections.value[0];
|
||||||
|
formData.collectionId = first.id as number;
|
||||||
|
await loadPackagesForCollection(first.id);
|
||||||
|
if (!first.packages || first.packages.length === 0) {
|
||||||
|
message.warning(collections.value.length > 1 ? '该套餐暂无课程包' : '暂无课程包');
|
||||||
|
}
|
||||||
|
>>>>>>> d300fa4 (feat: 校园端排课、教师端预约排课添加套餐选择)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('❌ 加载课程套餐失败:', error);
|
console.error('❌ 加载课程套餐失败:', error);
|
||||||
@ -445,13 +473,27 @@ const loadCollections = async () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
// 选择套餐,并加载该套餐下的课程包
|
// 选择套餐,并加载该套餐下的课程包
|
||||||
const selectCollection = async (coll: CourseCollection) => {
|
const selectCollection = async (coll: CourseCollection) => {
|
||||||
formData.collectionId = coll.id as number;
|
formData.collectionId = coll.id as number;
|
||||||
|
=======
|
||||||
|
// 加载指定套餐下的课程包
|
||||||
|
const loadPackagesForCollection = async (collectionId: number | string) => {
|
||||||
|
const col = collections.value.find(c => c.id === collectionId);
|
||||||
|
if (!col) return;
|
||||||
|
const packages = await getCourseCollectionPackages(collectionId);
|
||||||
|
(col as any).packages = packages;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 切换套餐时重新加载课程包并清空已选课程包
|
||||||
|
const onCollectionChange = async () => {
|
||||||
|
>>>>>>> d300fa4 (feat: 校园端排课、教师端预约排课添加套餐选择)
|
||||||
formData.packageId = undefined;
|
formData.packageId = undefined;
|
||||||
formData.courseId = undefined;
|
formData.courseId = undefined;
|
||||||
scheduleRefData.value = [];
|
scheduleRefData.value = [];
|
||||||
lessonTypes.value = [];
|
lessonTypes.value = [];
|
||||||
|
<<<<<<< HEAD
|
||||||
|
|
||||||
if (!coll.id) return;
|
if (!coll.id) return;
|
||||||
loadingPackages.value = true;
|
loadingPackages.value = true;
|
||||||
@ -466,6 +508,16 @@ const selectCollection = async (coll: CourseCollection) => {
|
|||||||
message.error('加载课程包失败');
|
message.error('加载课程包失败');
|
||||||
} finally {
|
} finally {
|
||||||
loadingPackages.value = false;
|
loadingPackages.value = false;
|
||||||
|
=======
|
||||||
|
const colId = formData.collectionId;
|
||||||
|
if (colId) {
|
||||||
|
loadingPackages.value = true;
|
||||||
|
try {
|
||||||
|
await loadPackagesForCollection(colId);
|
||||||
|
} finally {
|
||||||
|
loadingPackages.value = false;
|
||||||
|
}
|
||||||
|
>>>>>>> d300fa4 (feat: 校园端排课、教师端预约排课添加套餐选择)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -50,8 +50,22 @@
|
|||||||
<!-- 步骤2: 选择课程包 -->
|
<!-- 步骤2: 选择课程包 -->
|
||||||
<div v-show="currentStep === 1" class="step-panel">
|
<div v-show="currentStep === 1" class="step-panel">
|
||||||
<h3>选择课程包</h3>
|
<h3>选择课程包</h3>
|
||||||
|
<!-- 多套餐时:先选套餐 -->
|
||||||
|
<div v-if="collections.length > 1" class="collection-selector">
|
||||||
|
<div class="selector-label">选择课程套餐</div>
|
||||||
|
<a-radio-group v-model:value="formData.collectionId" button-style="solid" class="collection-radio-group" @change="onCollectionChange">
|
||||||
|
<a-radio-button
|
||||||
|
v-for="col in collections"
|
||||||
|
:key="col.id"
|
||||||
|
:value="col.id as number"
|
||||||
|
>
|
||||||
|
{{ col.name }}
|
||||||
|
</a-radio-button>
|
||||||
|
</a-radio-group>
|
||||||
|
</div>
|
||||||
<a-spin :spinning="loadingPackages">
|
<a-spin :spinning="loadingPackages">
|
||||||
<div v-if="selectedCollection && selectedCollection.packages && selectedCollection.packages.length > 0" class="packages-section">
|
<div v-if="selectedCollection && selectedCollection.packages && selectedCollection.packages.length > 0" class="packages-section">
|
||||||
|
<div v-if="collections.length > 1" class="selector-label" style="margin-bottom: 12px">选择课程包</div>
|
||||||
<div class="packages-grid">
|
<div class="packages-grid">
|
||||||
<div
|
<div
|
||||||
v-for="pkg in selectedCollection.packages"
|
v-for="pkg in selectedCollection.packages"
|
||||||
@ -383,14 +397,28 @@ const resetForm = () => {
|
|||||||
lessonTypes.value = [];
|
lessonTypes.value = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
// 加载课程套餐列表(租户可拥有多个套餐)
|
// 加载课程套餐列表(租户可拥有多个套餐)
|
||||||
|
=======
|
||||||
|
// 加载课程套餐列表;多套餐时展示选择器,单套餐时自动选中并加载课程包
|
||||||
|
>>>>>>> d300fa4 (feat: 校园端排课、教师端预约排课添加套餐选择)
|
||||||
const loadCollections = async () => {
|
const loadCollections = async () => {
|
||||||
loadingPackages.value = true;
|
loadingPackages.value = true;
|
||||||
try {
|
try {
|
||||||
collections.value = await getCourseCollections();
|
collections.value = await getCourseCollections();
|
||||||
|
<<<<<<< HEAD
|
||||||
// 若仅有一个套餐,自动选中并加载其课程包,提升体验
|
// 若仅有一个套餐,自动选中并加载其课程包,提升体验
|
||||||
if (collections.value.length === 1) {
|
if (collections.value.length === 1) {
|
||||||
await selectCollection(collections.value[0]);
|
await selectCollection(collections.value[0]);
|
||||||
|
=======
|
||||||
|
if (collections.value.length > 0) {
|
||||||
|
const first = collections.value[0];
|
||||||
|
formData.collectionId = first.id as number;
|
||||||
|
await loadPackagesForCollection(first.id);
|
||||||
|
if (!first.packages || first.packages.length === 0) {
|
||||||
|
message.warning(collections.value.length > 1 ? '该套餐暂无课程包' : '暂无课程包');
|
||||||
|
}
|
||||||
|
>>>>>>> d300fa4 (feat: 校园端排课、教师端预约排课添加套餐选择)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('加载课程套餐失败:', error);
|
console.error('加载课程套餐失败:', error);
|
||||||
@ -400,13 +428,27 @@ const loadCollections = async () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
// 选择套餐,并加载该套餐下的课程包
|
// 选择套餐,并加载该套餐下的课程包
|
||||||
const selectCollection = async (coll: CourseCollection) => {
|
const selectCollection = async (coll: CourseCollection) => {
|
||||||
formData.collectionId = coll.id as number;
|
formData.collectionId = coll.id as number;
|
||||||
|
=======
|
||||||
|
// 加载指定套餐下的课程包
|
||||||
|
const loadPackagesForCollection = async (collectionId: number | string) => {
|
||||||
|
const col = collections.value.find(c => c.id === collectionId);
|
||||||
|
if (!col) return;
|
||||||
|
const packages = await getCourseCollectionPackages(collectionId);
|
||||||
|
(col as any).packages = packages;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 切换套餐时重新加载课程包并清空已选课程包
|
||||||
|
const onCollectionChange = async () => {
|
||||||
|
>>>>>>> d300fa4 (feat: 校园端排课、教师端预约排课添加套餐选择)
|
||||||
formData.packageId = undefined;
|
formData.packageId = undefined;
|
||||||
formData.courseId = undefined;
|
formData.courseId = undefined;
|
||||||
scheduleRefData.value = [];
|
scheduleRefData.value = [];
|
||||||
lessonTypes.value = [];
|
lessonTypes.value = [];
|
||||||
|
<<<<<<< HEAD
|
||||||
|
|
||||||
if (!coll.id) return;
|
if (!coll.id) return;
|
||||||
loadingPackages.value = true;
|
loadingPackages.value = true;
|
||||||
@ -421,6 +463,16 @@ const selectCollection = async (coll: CourseCollection) => {
|
|||||||
message.error('加载课程包失败');
|
message.error('加载课程包失败');
|
||||||
} finally {
|
} finally {
|
||||||
loadingPackages.value = false;
|
loadingPackages.value = false;
|
||||||
|
=======
|
||||||
|
const colId = formData.collectionId;
|
||||||
|
if (colId) {
|
||||||
|
loadingPackages.value = true;
|
||||||
|
try {
|
||||||
|
await loadPackagesForCollection(colId);
|
||||||
|
} finally {
|
||||||
|
loadingPackages.value = false;
|
||||||
|
}
|
||||||
|
>>>>>>> d300fa4 (feat: 校园端排课、教师端预约排课添加套餐选择)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -642,6 +694,26 @@ defineExpose({ open, openWithPreset });
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.collection-selector {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
padding: 16px;
|
||||||
|
background: #FAFAFA;
|
||||||
|
border-radius: 8px;
|
||||||
|
|
||||||
|
.selector-label {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.collection-radio-group {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.collection-option {
|
.collection-option {
|
||||||
.collection-name { font-weight: 500; }
|
.collection-name { font-weight: 500; }
|
||||||
.collection-info { font-size: 12px; color: #999; }
|
.collection-info { font-size: 12px; color: #999; }
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user