课程表应用


欢迎加入开源鸿蒙跨平台社区:
https://openharmonycrossplatform.csdn.net

一、项目概述

运行效果图
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.1 应用简介

课程表是一款专注于学生课程管理的移动应用,为用户提供清晰、便捷的课程安排查看体验。在校园生活中,课程表是学生日常学习的重要工具。本应用帮助用户管理每周课程安排,支持周视图展示、今日课程提醒、课程详情查看等功能,让学习生活更加有序。

应用支持周课程表视图,以网格形式直观展示每周七天的课程安排。今日课程页面突出显示当天课程,并标识当前进行中的课程。课程列表按星期分组展示所有课程,便于快速查找。课程详情页展示完整的课程信息,包括教师、地点、时间、类型等。

1.2 核心功能

功能模块 功能描述 实现方式
周课程表 网格视图展示一周课程 Stack + Positioned
今日课程 当天课程列表与状态 ListView + 时间判断
课程列表 按星期分组展示 ListView + 分组
课程详情 完整课程信息展示 ModalBottomSheet
添加课程 新增课程信息 表单弹窗
周次切换 切换不同周次课表 状态管理

1.3 课程属性

属性 类型 说明
课程ID String 唯一标识
课程名称 String 课程名称
授课教师 String 教师姓名
上课地点 String 教室位置
星期 WeekDay 周一至周日
开始节次 int 开始上课节次
结束节次 int 结束上课节次
开始周次 int 课程开始周
结束周次 int 课程结束周
课程类型 CourseType 必修/选修等
备注 String? 其他说明

1.4 星期枚举

枚举值 标签 数值
monday 周一 1
tuesday 周二 2
wednesday 周三 3
thursday 周四 4
friday 周五 5
saturday 周六 6
sunday 周日 7

1.5 课程类型

类型 颜色 说明
必修 红色 专业必修课程
选修 蓝色 专业选修课程
公共课 绿色 公共基础课程
实践课 橙色 实践教学课程
实验课 紫色 实验教学课程

1.6 技术栈

技术领域 技术选型 版本要求
开发框架 Flutter >= 3.0.0
编程语言 Dart >= 2.17.0
设计规范 Material Design 3 -
状态管理 setState -
日期处理 intl ^0.19.0
目标平台 鸿蒙OS API 21+

1.7 项目结构

lib/
└── main_schedule.dart
    ├── ScheduleApp              # 应用入口
    ├── WeekDay                  # 星期枚举
    ├── CourseType               # 课程类型枚举
    ├── Course                   # 课程数据模型
    └── ScheduleHomePage         # 主页面
        ├── _buildSchedulePage()     # 周课程表页
        ├── _buildTodayPage()        # 今日课程页
        ├── _buildCourseListPage()   # 课程列表页
        ├── _buildSettingsPage()     # 设置页面
        ├── _buildScheduleGrid()     # 课程表网格
        └── _showCourseDetail()      # 课程详情弹窗

二、系统架构

2.1 整体架构图

Data Layer

Business Logic

Presentation Layer

主页面

周课程表Tab

今日课程Tab

课程列表Tab

设置Tab

课程详情弹窗

基本信息

操作按钮

周次管理
切换与显示

课程筛选
按周次/星期

状态判断
进行中/已结束

时间计算
当前节次

Course
课程模型

WeekDay
星期枚举

CourseType
类型枚举

2.2 类图设计

contains

manages

has

has

ScheduleApp

+Widget build()

«enumeration»

WeekDay

monday

tuesday

wednesday

thursday

friday

saturday

sunday

+String label

+int value

«enumeration»

CourseType

required

elective

public

practice

experiment

+String label

+Color color

Course

+String id

+String name

+String teacher

+String location

+WeekDay weekDay

+int startSection

+int endSection

+int startWeek

+int endWeek

+CourseType type

+String note

+int sectionCount

+Color courseColor

ScheduleHomePage

-int _selectedIndex

-int _currentWeek

-List<Course> _courses

-int _totalWeeks

-int _sectionsPerDay

+Widget build()

-void _showAddCourseDialog()

-void _showCourseDetail()

-int _getCurrentSection()

2.3 数据流程图

切换周次

查看课程

添加课程

删除课程

用户操作

操作类型

更新当前周

显示课程详情

创建课程对象

移除课程

重新渲染课表

弹出详情面板

添加到课程列表

从列表移除

刷新界面

2.4 课程表渲染流程

渲染引擎 课程数据 课程表页面 用户 渲染引擎 课程数据 课程表页面 用户 打开课程表 获取当前周课程 按星期和节次筛选 返回课程列表 计算位置和大小 渲染课程块 显示周课程表

三、核心模块设计

3.1 数据模型设计

3.1.1 星期枚举 (WeekDay)
enum WeekDay {
  monday('周一', 1),
  tuesday('周二', 2),
  wednesday('周三', 3),
  thursday('周四', 4),
  friday('周五', 5),
  saturday('周六', 6),
  sunday('周日', 7);

  final String label;
  final int value;
  const WeekDay(this.label, this.value);
}
3.1.2 课程类型枚举 (CourseType)
enum CourseType {
  required('必修', Colors.red),
  elective('选修', Colors.blue),
  public('公共课', Colors.green),
  practice('实践课', Colors.orange),
  experiment('实验课', Colors.purple);

  final String label;
  final Color color;
  const CourseType(this.label, this.color);
}
3.1.3 课程模型 (Course)
class Course {
  final String id;              // 唯一标识
  final String name;            // 课程名称
  final String teacher;         // 授课教师
  final String location;        // 上课地点
  final WeekDay weekDay;        // 星期
  final int startSection;       // 开始节次
  final int endSection;         // 结束节次
  final int startWeek;          // 开始周次
  final int endWeek;            // 结束周次
  final CourseType type;        // 课程类型
  final String? note;           // 备注

  int get sectionCount => endSection - startSection + 1;
  Color get courseColor => type.color;
}

3.2 课程表网格布局

3.2.1 布局计算

开始渲染

计算单元格尺寸

绘制网格背景

遍历课程列表

计算课程位置

计算课程大小

渲染课程块

还有课程?

完成渲染

3.2.2 位置计算实现
List<Widget> _buildCourseBlocks() {
  final cellWidth = (MediaQuery.of(context).size.width - 50) / 7 * 1.8;
  final cellHeight = 60.0;

  return _courses.map((course) {
    // 计算左边位置:星期值 * 单元格宽度
    final left = (course.weekDay.value - 1) * cellWidth;
    // 计算顶部位置:(开始节次-1) * 单元格高度
    final top = (course.startSection - 1) * cellHeight;
    // 计算宽度:单元格宽度 - 间距
    final width = cellWidth - 4;
    // 计算高度:节数 * 单元格高度 - 间距
    final height = course.sectionCount * cellHeight - 4;

    return Positioned(
      left: left + 2,
      top: top + 2,
      width: width,
      height: height,
      child: _buildCourseBlock(course),
    );
  }).toList();
}

3.3 当前节次判断

3.3.1 判断逻辑

获取当前时间

转换为分钟数

遍历节次时间表

当前时间在节次范围内?

返回该节次

还有节次?

返回0表示课间

3.3.2 实现代码
int _getCurrentSection() {
  final now = DateTime.now();
  final hour = now.hour;
  final minute = now.minute;

  // 各节次时间表 [开始时, 开始分, 结束时, 结束分]
  final sectionTimes = [
    [8, 0, 8, 45],   // 第1节
    [8, 55, 9, 40],  // 第2节
    [10, 0, 10, 45], // 第3节
    // ...
  ];

  for (int i = 0; i < sectionTimes.length; i++) {
    final startTime = sectionTimes[i][0] * 60 + sectionTimes[i][1];
    final endTime = sectionTimes[i][2] * 60 + sectionTimes[i][3];
    final currentTime = hour * 60 + minute;

    if (currentTime >= startTime && currentTime <= endTime) {
      return i + 1;
    }
  }
  return 0;
}

3.4 页面结构设计

3.4.1 主页面布局

主页面

底部导航栏

IndexedStack

课程表

今日

课程

设置

周课程表页

今日课程页

课程列表页

设置页面

3.5 状态管理

3.5.1 核心状态变量
class _ScheduleHomePageState extends State<ScheduleHomePage> {
  int _selectedIndex = 0;               // 当前Tab索引
  int _currentWeek = 1;                 // 当前周次
  final List<Course> _courses = [];     // 课程列表
  final int _totalWeeks = 16;           // 总周数
  final int _sectionsPerDay = 12;       // 每天节数
}

四、UI设计规范

4.1 配色方案

应用采用深紫色主题风格,体现学术与智慧:

颜色类型 色值 用途
主色 DeepPurple AppBar、强调、按钮
必修 Red 必修课程标识
选修 Blue 选修课程标识
公共课 Green 公共课程标识
实践课 Orange 实践课程标识
实验课 Purple 实验课程标识

4.2 课程类型颜色映射

类型 颜色 说明
必修 红色 专业核心课程
选修 蓝色 专业选修课程
公共课 绿色 通识教育课程
实践课 橙色 实践类课程
实验课 紫色 实验类课程

4.3 组件规范

4.3.1 周课程表网格
┌─────────────────────────────────────────────────────────────┐
│    │ 周一 │ 周二 │ 周三 │ 周四 │ 周五 │ 周六 │ 周日 │
├─────────────────────────────────────────────────────────────┤
│  1 │ ┌──┐ │      │      │ ┌──┐ │ ┌──┐ │      │      │
│  2 │ │高│ │      │      │ │计│ │ │数│ │      │      │
│  3 │ │等│ │ ┌──┐ │ ┌──┐ │ │算│ │ │据│ │ ┌──┐ │      │
│  4 │ │数│ │ │英│ │ │体│ │ │机│ │ │库│ │ │软│ │      │
│  5 │ │学│ │ │语│ │ │育│ │ │网│ │ │原│ │ │件│ │      │
│  6 │ └──┘ │ └──┘ │ └──┘ │ └──┘ │ └──┘ │ └──┘ │      │
│  7 │      │ ┌──┐ │ ┌──┐ │      │      │      │      │
│  8 │      │ │数│ │ │操│ │      │      │      │      │
│  9 │      │ │据│ │ │作│ │      │      │      │      │
│ 10 │      │ │结│ │ │系│ │      │      │      │      │
│ 11 │      │ │构│ │ │统│ │      │      │      │      │
│ 12 │      │ └──┘ │ └──┘ │      │      │      │      │
└─────────────────────────────────────────────────────────────┘
4.3.2 今日课程卡片
┌─────────────────────────────────────────────────────────────┐
│  ┃  第1-2节  [进行中]                                       │
│  ┃  高等数学                                                │
│  ┃  👤 张教授  📍 教学楼A-101                    🎓         │
└─────────────────────────────────────────────────────────────┘
4.3.3 课程详情弹窗
┌─────────────────────────────────────────────────────────────┐
│  高等数学                                              ✕    │
├─────────────────────────────────────────────────────────────┤
│  ┌────────────────────────────────────────────────────┐    │
│  │  🎓  [必修]                                         │    │
│  │      张教授                                         │    │
│  ├────────────────────────────────────────────────────┤    │
│  │  📅 周一    ⏰ 第1-2节    📍 教学楼A-101           │    │
│  └────────────────────────────────────────────────────┘    │
├─────────────────────────────────────────────────────────────┤
│  课程详情                                                   │
│  上课周次    第1-16周                                       │
│  上课节数    2节                                            │
├─────────────────────────────────────────────────────────────┤
│  [编辑]                          [删除]                     │
└─────────────────────────────────────────────────────────────┘

4.4 交互设计

4.4.1 操作方式
操作 手势 效果
查看课程详情 点击课程块 弹出详情面板
切换周次 点击左右箭头 切换上/下周
添加课程 点击+按钮 弹出添加表单
编辑课程 点击编辑按钮 弹出编辑表单
删除课程 点击删除按钮 确认后删除

五、核心功能实现

5.1 主页面构建


Widget build(BuildContext context) {
  return Scaffold(
    body: IndexedStack(
      index: _selectedIndex,
      children: [
        _buildSchedulePage(),
        _buildTodayPage(),
        _buildCourseListPage(),
        _buildSettingsPage(),
      ],
    ),
    bottomNavigationBar: NavigationBar(
      selectedIndex: _selectedIndex,
      onDestinationSelected: (index) {
        setState(() {
          _selectedIndex = index;
        });
      },
      destinations: const [
        NavigationDestination(icon: Icon(Icons.calendar_view_week_outlined), label: '课程表'),
        NavigationDestination(icon: Icon(Icons.today_outlined), label: '今日'),
        NavigationDestination(icon: Icon(Icons.list_outlined), label: '课程'),
        NavigationDestination(icon: Icon(Icons.settings_outlined), label: '设置'),
      ],
    ),
  );
}

5.2 课程表网格

Widget _buildScheduleGrid() {
  return Stack(
    children: [
      _buildGridBackground(),
      ..._buildCourseBlocks(),
    ],
  );
}

List<Widget> _buildCourseBlocks() {
  final cellWidth = (MediaQuery.of(context).size.width - 50) / 7 * 1.8;
  final cellHeight = 60.0;

  return _courses.map((course) {
    final left = (course.weekDay.value - 1) * cellWidth;
    final top = (course.startSection - 1) * cellHeight;
    final width = cellWidth - 4;
    final height = course.sectionCount * cellHeight - 4;

    return Positioned(
      left: left + 2,
      top: top + 2,
      width: width,
      height: height,
      child: _buildCourseBlock(course),
    );
  }).toList();
}

5.3 课程块渲染

Widget _buildCourseBlock(Course course) {
  return GestureDetector(
    onTap: () => _showCourseDetail(course),
    child: Container(
      padding: const EdgeInsets.all(6),
      decoration: BoxDecoration(
        color: course.courseColor.withValues(alpha: 0.15),
        borderRadius: BorderRadius.circular(6),
        border: Border.all(color: course.courseColor, width: 2),
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text(course.name, style: TextStyle(fontSize: 11, fontWeight: FontWeight.bold, color: course.courseColor)),
          if (course.sectionCount > 1)
            Text(course.location, style: TextStyle(fontSize: 9, color: course.courseColor.withValues(alpha: 0.8))),
        ],
      ),
    ),
  );
}

5.4 今日课程状态判断

Widget _buildTodayCourseCard(Course course, int index) {
  final currentSection = _getCurrentSection();
  final isCurrentCourse = currentSection >= course.startSection && currentSection <= course.endSection;
  final isPast = currentSection > course.endSection;

  return Card(
    color: isPast ? Colors.grey[100] : null,
    child: Row(
      children: [
        Container(
          width: 4,
          height: 60,
          decoration: BoxDecoration(
            color: isPast ? Colors.grey : course.courseColor,
            borderRadius: BorderRadius.circular(2),
          ),
        ),
        // ...课程信息
        if (isCurrentCourse)
          Container(child: Text('进行中')),
        if (isPast)
          Container(child: Text('已结束')),
      ],
    ),
  );
}

5.5 课程详情弹窗

void _showCourseDetail(Course course) {
  showModalBottomSheet(
    context: context,
    isScrollControlled: true,
    builder: (context) => DraggableScrollableSheet(
      initialChildSize: 0.6,
      maxChildSize: 0.9,
      minChildSize: 0.5,
      expand: false,
      builder: (context, scrollController) => Container(
        padding: const EdgeInsets.all(20),
        child: ListView(
          controller: scrollController,
          children: [
            _buildCourseInfoCard(course),
            _buildCourseDetails(course),
            Row(
              children: [
                OutlinedButton.icon(onPressed: () => _showEditCourseDialog(course), icon: Icon(Icons.edit), label: Text('编辑')),
                FilledButton.icon(onPressed: () => _deleteCourse(course), icon: Icon(Icons.delete), label: Text('删除')),
              ],
            ),
          ],
        ),
      ),
    ),
  );
}

六、课程管理知识拓展

6.1 高校课程体系

课程体系

公共基础课

专业基础课

专业核心课

专业选修课

实践教学环节

思想政治理论课

大学英语

高等数学

体育

程序设计基础

数据结构

计算机网络

操作系统

数据库原理

软件工程

6.2 学分与学时关系

学分 理论学时 实验学时 说明
1学分 16学时 - 理论课程
1学分 - 32学时 实验课程
1学分 12学时 8学时 理论+实验

6.3 课程时间安排

上午 第1-2节 8:00-9:40 第3-4节 10:00-11:40 下午 第5-6节 14:00-15:40 第7-8节 16:00-17:40 晚上 第9-10节 19:00-20:40 第11-12节 20:50-22:30 高校课程时间安排

6.4 课程冲突检测

冲突类型 检测条件 处理方式
时间冲突 同一时间段多门课程 提示用户选择
地点冲突 同一教室同时段 自动检测提示
周次冲突 课程周次不重叠 不视为冲突

七、扩展功能规划

7.1 后续版本规划

2024-01-07 2024-01-14 2024-01-21 2024-01-28 2024-02-04 2024-02-11 2024-02-18 2024-02-25 2024-03-03 2024-03-10 2024-03-17 2024-03-24 周课程表功能 今日课程功能 课程管理功能 课程提醒功能 课表导入功能 数据持久化 成绩管理功能 考试安排功能 分享导出功能 V1.0 基础版本 V1.1 增强版本 V1.2 进阶版本 课程表应用开发计划

7.2 功能扩展建议

7.2.1 课程提醒
功能 说明
上课提醒 提前N分钟提醒
作业提醒 作业截止日期提醒
考试提醒 考试时间提醒
7.2.2 课表导入
功能 说明
教务系统导入 对接学校教务系统
图片识别导入 OCR识别课表图片
Excel导入 导入Excel课表
7.2.3 成绩管理
功能 说明
成绩录入 录入各科成绩
GPA计算 自动计算绩点
成绩分析 成绩趋势分析

八、注意事项

8.1 开发注意事项

  1. 颜色处理:使用 withValues(alpha:) 替代已废弃的 withOpacity()

  2. 日期格式化:使用intl包的DateFormat进行日期格式化

  3. 网格布局:使用Stack + Positioned实现课程块定位

  4. 状态同步:课程增删改后需要setState刷新界面

  5. 周次判断:需要考虑课程的有效周次范围

8.2 用户体验优化

📚 用户体验建议 📚

  • 课程表视图清晰直观
  • 今日课程突出显示
  • 课程状态实时更新
  • 操作流程简单便捷

8.3 常见问题

问题 原因 解决方案
课程块位置错误 单元格尺寸计算错误 检查计算公式
课程重叠显示 未检测冲突 添加冲突检测
当前节次不准确 时间表配置错误 校对时间表
周次切换不刷新 setState未调用 检查状态更新

九、运行说明

9.1 环境要求

环境 版本要求
Flutter SDK >= 3.0.0
Dart SDK >= 2.17.0
intl包 ^0.19.0
鸿蒙OS API 21+

9.2 运行命令

# 查看可用设备
flutter devices

# 运行到鸿蒙设备
flutter run -d 127.0.0.1:5555 lib/main_schedule.dart

# 运行到Windows
flutter run -d windows -t lib/main_schedule.dart

# 代码分析
flutter analyze lib/main_schedule.dart

十、总结

课程表应用通过完善的功能设计,帮助学生高效管理课程安排。应用支持周课程表视图,以网格形式直观展示每周七天的课程安排,课程块按类型着色,便于快速识别。周次切换功能支持查看不同周次的课程安排。

今日课程页面突出显示当天课程,通过时间判断标识当前进行中的课程和已结束的课程,让学生对当天的学习安排一目了然。课程列表按星期分组展示所有课程,便于快速查找特定课程。

课程详情页展示完整的课程信息,包括教师、地点、时间、类型等,支持编辑和删除操作。添加课程功能通过表单弹窗收集课程信息,支持选择星期、节次、类型等属性。

界面设计采用深紫色主题风格,体现学术与智慧。课程块通过类型颜色区分不同课程类型,网格背景提供清晰的时间参考。应用采用Material Design 3设计规范,遵循Flutter最佳实践,代码结构清晰,易于维护和扩展。

规划学习,高效生活!

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐