很多同学都依赖信息北航来查询课程,但是信息北航的课程表没有提醒上课的功能。也有些同学使用一些 App,但是这些 App 冗余信息过多,往往存在广告。
经过调研,我发现可以利用系统自带的“日历” App 来满足同学们对于课程查看和提醒的需求。为此,我开发了这个 App,用于查看课程信息,并可以将其导入系统原生的“日历” App。
本 App 使用了 SwiftUI 2.0 编写。
App 主要可以分为三个界面,分别是主界面,“登陆”界面和“课程详细信息”界面。
主界面由日历头部,日历和课程列表三部分构成。
其中,header 包括了当前月份显示以及三个按钮,三个按钮分别用于“添加课程事项到系统日历”,“更新课程列表”和“用户登录”。
日历界面可以单击对应的日期来切换课程列表的显示;左右划动日历界面可以切换月份。当选中其他日期时,当天日期会用一个阴影来突出强调。
课程列表可以显示选中日期的课程列表。其中不同的课程会用不同的颜色来表示。点击相应的课程可以进入“课程详细信息”界面。
登录界面是一个 sheet,包括四部分。
其中,最上面是提示文字,会根据不同的登录情况显示不同的信息。
- 如果用户是第一次使用,则会显示“登录信息北航”。
- 如果用户以前登录过,但是现在没有处于登录状态,则会显示“当前用户” + 学号 + “(未登录)”
- 如果用户以前登录过,但是现在处于登录状态,则会显示“当前用户” + 学号 + “(已登录)”
接下来分别是用户输入学号(numberPad
)和密码的输入框(SecureField
)。
最后是一个“登录”按钮。只有当用户输入了学号和密码时,“登录”按钮才可用。
点击“登录”按钮后的界面逻辑有三种:
- 当用户已经登录了账号时,点击登录按钮会显示一个 alert “检测到您已经登录账号,是否切换用户?”。
- 确认登录后,如果登录不成功,则显示一个 alert “请检查学号和密码是否输入正确”。
- 如果登录成功则进入一个加载界面(ProgressView),同时更新课程。
课程详细信息界面在单击课程项目时显示。
显示课程详细信息时,背景会进行高斯模糊,同时课程卡片会使用阴影来突出显示内容。
项目采用 MVVM 架构。
/ViewModels
: 存储 ViewModelsLoginViewModel.swift
: 用于登录的逻辑AddEventToCalendarViewModel.swift
: 用于将课程添加到系统日历UpdatingViewModel.swift
: 用于更新课程操作
/Views
: 存储 SwiftUI 描述的界面PagerView.swift
:CalendarList.swift
: 日历界面和课程列表界面LoginSheet.swift
: 登陆界面/Components
: 包括 UI 中用到的各种组件/EventCard
: 课程卡片的 UIEventCard.swift
: 课程卡片 UIEventCardDetailModal.swift
: 课程详细信息的 UI
/Calendar
: 日历 UICalendarMonthView.swift
: 月份CalendarMonthHeader.swift
: 日历头部(星期)CalendarViewDay.swift
: 单天的按钮
/Utilities
: 逻辑组件DataStorage.swift
: 存储用户信息CalendarUtils.swift
: 日期时间运算ExtensionColor.swift
: 颜色处理
Models
: 定义数据 ModelsCalendarEventModel.swift
: 定义某一天的时间 ModelCalendarEventDataModel.swift
: 某个课程的信息 ModelCalendarMonthModel.swift
: 某一个月份的数据 Model
ContentView.swift
: 课程内容BUAACalApp.swift
: App 主体
本文件包含了一个类 LoginViewModel
,用于存储登录的相关信息。与 LoginSheet.swift
相对应。
LoginViewModel
@Published
变量currentUserId
: 当前用户的 Id,打开 App 时会自动调用DataStorage.loadUserId()
从UserDefaults
中读取用户学号信息userId
:存储用户输入的学号password
:存储用户输入的密码isLogin
:保存用户是否登录
- 函数
login(:LoginSheet)
:传入绑定的LoginSheet
,进行登录
本文件包含了一个类 AddEventToCalendarViewModel
,用于添加事件到系统日历。
AddEventToCalendarViewModel
@Published
变量isFinished
: 返回是否添加成功
- 函数
addEventToCalendar()[Date: [CalendarEvent<CalendarEventDataModel>]]
:添加事件到日历
本文件包含了一个类 UpdatingViewModel
,用于更新课程列表。
UpdatingViewModel
@Published
变量isUpdating
:是否正在更新events
:存储所有的课程信息cntFinished
:存储当前有几个异步任务已经完成(用于判断是否所有任务都已经完成)
- 函数
updateEvents
:更新课程
本文件用于存储某一课程的数据,用于 UI 显示。
CalendarEvent
date: Date
:课程所在日期data: T
:课程详细数据calendar: Calendar
:日历
本文件用于存储某一课程的详细数据。
CalendarEventDataModel
courseID: String
:课程编号eventName: String
:课程名称startTime: Date
:课程开始时间endTime: Date
:课程结束时间weeks: String
:上课的星期courseType: String
:课程类型credit: Double
:课程学分examType: Int
:课程考核方式lessons: String
:上课的节数indicatorName: String
:教师名称locationName: String
:上课地点courseHour: String
:上课时长brightColorNumber: Int
:日间模式颜色darkColorNumber: Int
:夜间模式颜色
本文件用于进行存储操作。
DataStorage
saveData([Date: [CalendarEvent<CalendarEventDataModel>]])
:存储课程数据saveData() -> [Date: [CalendarEvent<CalendarEventDataModel>]]
:读取课程数据saveUserId(String)
:存储用户学号loadUserId() -> String
:读取用户学号