#跟着若城学鸿蒙# HarmonyOS NEXT学习之Select案例四:实际业务场景应用
·

一、案例介绍
本案例将展示Select组件在实际业务场景中的综合应用,通过实现一个在线课程选择系统,展示如何在复杂业务场景中灵活运用Select组件的各种特性。
二、代码实现
@Entry
@Component
struct CourseSelectionExample {
@State selectedSemester: string = ''
@State selectedDepartment: string = ''
@State selectedMajor: string = ''
@State selectedCourse: string = ''
@State selectedTeacher: string = ''
@State selectedTime: string = ''
@State semesterIndex: number = -1
@State departmentIndex: number = -1
@State majorIndex: number = -1
@State courseIndex: number = -1
@State teacherIndex: number = -1
@State timeIndex: number = -1
@State departments: string[] = []
@State majors: string[] = []
@State courses: string[] = []
@State teachers: string[] = []
@State times: string[] = []
@State selectedCourses: Array<{
semester: string,
course: string,
teacher: string,
time: string,
credits: number
}> = []
private readonly semesters: string[] = ['2024春季学期', '2024秋季学期']
private readonly departmentMap: Map<string, string[]> = new Map([
['2024春季学期', ['计算机学院', '经济学院', '外国语学院']],
['2024秋季学期', ['计算机学院', '经济学院', '外国语学院']]
])
private readonly majorMap: Map<string, string[]> = new Map([
['计算机学院', ['计算机科学', '软件工程', '人工智能']],
['经济学院', ['经济学', '金融学', '国际贸易']],
['外国语学院', ['英语', '日语', '法语']]
])
private readonly courseMap: Map<string, Array<{
name: string,
credits: number
}>> = new Map([
['计算机科学', [
{ name: '数据结构', credits: 4 },
{ name: '操作系统', credits: 4 },
{ name: '计算机网络', credits: 3 }
]],
['软件工程', [
{ name: '软件工程导论', credits: 3 },
{ name: '需求分析', credits: 3 },
{ name: '软件测试', credits: 4 }
]]
])
private readonly teacherMap: Map<string, string[]> = new Map([
['数据结构', ['王教授', '李教授', '张教授']],
['操作系统', ['刘教授', '陈教授', '孙教授']],
['计算机网络', ['赵教授', '钱教授', '孙教授']]
])
private readonly timeMap: Map<string, string[]> = new Map([
['王教授', ['周一 1-2节', '周三 3-4节', '周五 5-6节']],
['李教授', ['周二 1-2节', '周四 3-4节', '周五 7-8节']],
['张教授', ['周一 3-4节', '周三 5-6节', '周五 1-2节']]
])
build() {
Column() {
Text('在线选课系统')
.fontSize(24)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 20 })
// 学期选择
this.SelectItem(
'学期:',
this.selectedSemester || '请选择学期',
this.semesters,
this.semesterIndex,
(index: number) => {
this.semesterIndex = index
this.selectedSemester = this.semesters[index]
this.departments = this.departmentMap.get(this.selectedSemester) || []
this.resetDepartmentAndBelow()
}
)
// 院系选择
if (this.departments.length > 0) {
this.SelectItem(
'院系:',
this.selectedDepartment || '请选择院系',
this.departments,
this.departmentIndex,
(index: number) => {
this.departmentIndex = index
this.selectedDepartment = this.departments[index]
this.majors = this.majorMap.get(this.selectedDepartment) || []
this.resetMajorAndBelow()
}
)
}
// 专业选择
if (this.majors.length > 0) {
this.SelectItem(
'专业:',
this.selectedMajor || '请选择专业',
this.majors,
this.majorIndex,
(index: number) => {
this.majorIndex = index
this.selectedMajor = this.majors[index]
this.courses = (this.courseMap.get(this.selectedMajor) || []).map(course => course.name)
this.resetCourseAndBelow()
}
)
}
// 课程选择
if (this.courses.length > 0) {
this.SelectItem(
'课程:',
this.selectedCourse || '请选择课程',
this.courses,
this.courseIndex,
(index: number) => {
this.courseIndex = index
this.selectedCourse = this.courses[index]
this.teachers = this.teacherMap.get(this.selectedCourse) || []
this.resetTeacherAndBelow()
}
)
}
// 教师选择
if (this.teachers.length > 0) {
this.SelectItem(
'教师:',
this.selectedTeacher || '请选择教师',
this.teachers,
this.teacherIndex,
(index: number) => {
this.teacherIndex = index
this.selectedTeacher = this.teachers[index]
this.times = this.timeMap.get(this.selectedTeacher) || []
this.resetTime()
}
)
}
// 时间选择
if (this.times.length > 0) {
this.SelectItem(
'时间:',
this.selectedTime || '请选择时间',
this.times,
this.timeIndex,
(index: number) => {
this.timeIndex = index
this.selectedTime = this.times[index]
}
)
}
// 已选课程列表
if (this.selectedCourses.length > 0) {
Column() {
Text('已选课程')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.margin({ top: 30, bottom: 10 })
List() {
ForEach(this.selectedCourses, (course, index) => {
ListItem() {
Row() {
Column() {
Text(course.course)
.fontSize(16)
.fontWeight(FontWeight.Medium)
.margin({ bottom: 4 })
Row() {
Text(`${course.teacher} | ${course.time}`)
.fontSize(14)
.fontColor('#666666')
Text(`学分:${course.credits}`)
.fontSize(14)
.fontColor('#666666')
.margin({ left: 16 })
}
}
.alignItems(HorizontalAlign.Start)
.layoutWeight(1)
Button({ type: ButtonType.Circle }) {
Image($r('app.media.ic_delete'))
.width(20)
.height(20)
}
.backgroundColor('#FFE8E8')
.onClick(() => {
this.removeCourse(index)
})
}
.width('100%')
.padding(16)
.backgroundColor(Color.White)
.borderRadius(8)
.margin({ bottom: 8 })
}
})
}
}
.width('100%')
.padding(16)
.backgroundColor('#F5F5F5')
.borderRadius(8)
}
// 选课按钮
Button('添加课程')
.width('100%')
.height(50)
.backgroundColor('#007DFF')
.borderRadius(8)
.fontSize(18)
.fontColor(Color.White)
.margin({ top: 20 })
.enabled(this.canAddCourse())
.opacity(this.canAddCourse() ? 1 : 0.5)
.onClick(() => {
this.addCourse()
})
}
.width('100%')
.height('100%')
.padding(16)
}
@Builder
SelectItem(label: string, value: string, options: string[], selectedIndex: number, onSelectCallback: (index: number) => void) {
Row() {
Text(label)
.fontSize(16)
.width(80)
Select({
value: value,
selected: selectedIndex,
options: options
})
.width('70%')
.height(40)
.backgroundColor(selectedIndex === -1 ? '#F5F5F5' : '#E6F2FF')
.borderRadius(8)
.fontColor(selectedIndex === -1 ? '#999999' : '#007DFF')
.onSelect((index: number) => {
onSelectCallback(index)
})
}
.width('100%')
.margin({ bottom: 20 })
}
private resetDepartmentAndBelow() {
this.selectedDepartment = ''
this.selectedMajor = ''
this.selectedCourse = ''
this.selectedTeacher = ''
this.selectedTime = ''
this.departmentIndex = -1
this.majorIndex = -1
this.courseIndex = -1
this.teacherIndex = -1
this.timeIndex = -1
this.majors = []
this.courses = []
this.teachers = []
this.times = []
}
private resetMajorAndBelow() {
this.selectedMajor = ''
this.selectedCourse = ''
this.selectedTeacher = ''
this.selectedTime = ''
this.majorIndex = -1
this.courseIndex = -1
this.teacherIndex = -1
this.timeIndex = -1
this.courses = []
this.teachers = []
this.times = []
}
private resetCourseAndBelow() {
this.selectedCourse = ''
this.selectedTeacher = ''
this.selectedTime = ''
this.courseIndex = -1
this.teacherIndex = -1
this.timeIndex = -1
this.teachers = []
this.times = []
}
private resetTeacherAndBelow() {
this.selectedTeacher = ''
this.selectedTime = ''
this.teacherIndex = -1
this.timeIndex = -1
this.times = []
}
private resetTime() {
this.selectedTime = ''
this.timeIndex = -1
}
private canAddCourse(): boolean {
return this.selectedSemester !== '' &&
this.selectedDepartment !== '' &&
this.selectedMajor !== '' &&
this.selectedCourse !== '' &&
this.selectedTeacher !== '' &&
this.selectedTime !== ''
}
private addCourse() {
const courseInfo = this.courseMap.get(this.selectedMajor)?.find(course => course.name === this.selectedCourse)
if (courseInfo) {
// 检查时间冲突
if (this.checkTimeConflict(this.selectedTime)) {
AlertDialog.show({
title: '提示',
message: '所选时间与已选课程时间冲突',
confirm: {
value: '确定',
action: () => {}
}
})
return
}
this.selectedCourses.push({
semester: this.selectedSemester,
course: this.selectedCourse,
teacher: this.selectedTeacher,
time: this.selectedTime,
credits: courseInfo.credits
})
// 重置选择
this.resetCourseAndBelow()
}
}
private removeCourse(index: number) {
this.selectedCourses.splice(index, 1)
}
private checkTimeConflict(newTime: string): boolean {
return this.selectedCourses.some(course => course.time === newTime)
}
}
三、总结
本案例通过一个在线课程选择系统,展示了 Select 组件在实际业务场景中的综合应用。通过多级选择(学期、院系、专业、课程、教师、时间),实现了复杂的课程选择逻辑。通过状态管理(如 @State 管理选中值和索引),确保了用户选择的实时更新。通过已选课程列表和选课按钮,提供了用户友好的交互体验。这种设计不仅展示了 Select 组件的灵活性和易用性,还提供了丰富的交互效果,开发者可以参考此案例,快速实现类似的在线课程选择系统。
更多推荐




所有评论(0)