hookehuyr

feat(teacher/form): 添加课程章节选择功能并优化表单字段显示

- 在作业表单中新增课程章节选择器及相关逻辑
- 将日历图标替换为更符合语义的图标
- 为必填字段添加提示标识
- 优化选择字段的显示样式,增加选中值展示区域
......@@ -2,7 +2,7 @@
* @Author: hookehuyr hookehuyr@gmail.com
* @Date: 2025-01-20 10:00:00
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-06-20 15:43:37
* @LastEditTime: 2025-06-20 16:01:50
* @FilePath: /mlaj/src/views/teacher/formPage.vue
* @Description: 教师作业新增表单页面
-->
......@@ -18,7 +18,7 @@
<van-field
v-model="formData.homework_name"
name="homework_name"
placeholder="请输入作业名称"
placeholder="请输入作业名称(必填)"
required
:border="false"
class="homework-name-field"
......@@ -100,25 +100,52 @@
<div class="mb-6">
<div class="select-row">
<div class="select-item">
<van-icon name="calendar-o" class="select-icon" />
<van-icon name="friends-o" class="select-icon" />
<span class="select-label">所在年级:</span>
<span class="select-value" @click="showGradePicker = true">{{ formData.grade || '请选择年级' }}</span>
<van-icon name="arrow" class="arrow-icon" @click="showGradePicker = true" />
</div>
</div>
<div class="select-row">
<div class="select-item">
<van-icon name="calendar-o" class="select-icon" />
<van-icon name="friends-o" class="select-icon" />
<span class="select-label">所在班级:</span>
<span class="select-value" @click="showClassPicker = true">{{ formData.class_name || '请选择班级' }}</span>
<van-icon name="arrow" class="arrow-icon" @click="showClassPicker = true" />
</div>
</div>
<div class="select-row">
<div class="select-item">
<van-icon name="calendar-o" class="select-icon" />
<van-icon name="friends-o" class="select-icon" />
<span class="select-label">所在课程:</span>
<span class="select-value" @click="showCoursePicker = true">{{ formData.course || '请选择课程' }}</span>
<van-icon name="arrow" class="arrow-icon" @click="showCoursePicker = true" />
</div>
</div>
<div class="select-row" v-if="formData.course">
<div class="select-item">
<van-icon name="bookmark-o" class="select-icon" />
<span class="select-label">课程章节:</span>
<span class="select-value" @click="showChapterPicker = true">{{ formData.chapter || '请选择章节' }}</span>
<van-icon name="arrow" class="arrow-icon" @click="showChapterPicker = true" />
</div>
</div>
<div class="select-row">
<div class="select-item">
<van-icon name="fire-o" class="select-icon" />
<span class="select-label">所在活动:</span>
<span class="select-value" @click="showActivityPicker = true">{{ formData.activity || '请选择活动' }}</span>
<van-icon name="arrow" class="arrow-icon" @click="showActivityPicker = true" />
</div>
</div>
<div class="select-row">
<div class="select-item">
<van-icon name="friends-o" class="select-icon" />
<span class="select-label">所在小组:</span>
<span class="select-value" @click="showGroupPicker = true">{{ formData.group_name || '请选择小组' }}</span>
<van-icon name="arrow" class="arrow-icon" @click="showGroupPicker = true" />
</div>
</div>
</div>
<!-- 提交按钮 -->
......@@ -174,6 +201,17 @@
</div>
</van-popup>
<!-- 课程章节选择器 -->
<van-popup v-model:show="showChapterPicker" position="bottom">
<div class="p-4">
<van-search v-model="chapterSearchValue" placeholder="搜索章节" @search="searchChapter" />
<van-list>
<van-cell v-for="chapter in filteredChapters" :key="chapter.id" :title="chapter.name" is-link :border="false"
@click="onChapterSelect(chapter)" />
</van-list>
</div>
</van-popup>
<!-- 活动选择器 -->
<van-popup v-model:show="showActivityPicker" position="bottom">
<div class="p-4">
......@@ -244,6 +282,7 @@ const formData = ref({
start_time: new Date(),
end_time: new Date(),
course: '',
chapter: '',
activity: '',
grade: '',
class_name: '',
......@@ -259,6 +298,7 @@ const showFrequencyPicker = ref(false);
const showStartTimePicker = ref(false);
const showEndTimePicker = ref(false);
const showCoursePicker = ref(false);
const showChapterPicker = ref(false);
const showActivityPicker = ref(false);
const showGradePicker = ref(false);
const showClassPicker = ref(false);
......@@ -287,6 +327,7 @@ const frequencyOptions = ref([
// 搜索值
const courseSearchValue = ref('');
const chapterSearchValue = ref('');
const activitySearchValue = ref('');
const gradeSearchValue = ref('');
const classSearchValue = ref('');
......@@ -300,6 +341,37 @@ const courses = ref([
{ id: 4, name: '物理课程' }
]);
// 章节数据 - 根据课程动态变化
const chapters = ref([]);
// 各课程对应的章节数据
const courseChapters = {
'数学课程': [
{ id: 1, name: '第一章 数与代数' },
{ id: 2, name: '第二章 几何图形' },
{ id: 3, name: '第三章 统计与概率' },
{ id: 4, name: '第四章 函数与方程' }
],
'语文课程': [
{ id: 1, name: '第一单元 现代文阅读' },
{ id: 2, name: '第二单元 古诗文阅读' },
{ id: 3, name: '第三单元 写作训练' },
{ id: 4, name: '第四单元 口语交际' }
],
'英语课程': [
{ id: 1, name: 'Unit 1 Hello World' },
{ id: 2, name: 'Unit 2 My Family' },
{ id: 3, name: 'Unit 3 School Life' },
{ id: 4, name: 'Unit 4 Hobbies' }
],
'物理课程': [
{ id: 1, name: '第一章 力学基础' },
{ id: 2, name: '第二章 热学原理' },
{ id: 3, name: '第三章 电磁学' },
{ id: 4, name: '第四章 光学现象' }
]
};
const activities = ref([
{ id: 1, name: '春游活动' },
{ id: 2, name: '运动会' },
......@@ -347,6 +419,13 @@ const filteredCourses = computed(() => {
);
});
const filteredChapters = computed(() => {
if (!chapterSearchValue.value) return chapters.value;
return chapters.value.filter(chapter =>
chapter.name.toLowerCase().includes(chapterSearchValue.value.toLowerCase())
);
});
const filteredActivities = computed(() => {
if (!activitySearchValue.value) return activities.value;
return activities.value.filter(activity =>
......@@ -431,11 +510,25 @@ const onEndTimeConfirm = () => {
*/
const onCourseSelect = (course) => {
formData.value.course = course.name;
// 清空之前选择的章节
formData.value.chapter = '';
// 根据选择的课程更新章节数据
chapters.value = courseChapters[course.name] || [];
showCoursePicker.value = false;
courseSearchValue.value = '';
};
/**
* 章节选择
* @param {Object} chapter - 选中的章节
*/
const onChapterSelect = (chapter) => {
formData.value.chapter = chapter.name;
showChapterPicker.value = false;
chapterSearchValue.value = '';
};
/**
* 活动选择
* @param {Object} activity - 选中的活动
*/
......@@ -484,6 +577,14 @@ const searchCourse = (value) => {
};
/**
* 搜索章节
* @param {string} value - 搜索值
*/
const searchChapter = (value) => {
chapterSearchValue.value = value;
};
/**
* 搜索活动
* @param {string} value - 搜索值
*/
......@@ -700,7 +801,16 @@ onMounted(() => {
.select-label {
font-size: 14px;
color: #333;
margin-right: 12px;
min-width: 80px;
}
.select-value {
font-size: 14px;
color: #666;
margin-right: auto;
flex: 1;
text-align: right;
}
/* 提交按钮 */
......