🎓 高考倒计时桌面伴侣 — 倒计时 · 课表 · 考试 · 天气 · 提醒 · 远程管理 · 自动化任务 · 白板 · 屏幕批注 · PDF 阅读 基于 Avalonia + FluentAvalonia 构建,WinUI 3 风格界面 | 当前版本:v3.0.2
📦 框架迁移已完成(WPF → Avalonia);旧 WPF 版已确认淘汰(2026-09-05),不再维护,源码归档于
LegacyWPF/(本地保留、不入库) 🔐 老师账号密码采用 PBKDF2 哈希存储(v2.7.0 起),settings.json 不再保存明文密码
- ⏳ 实时倒计时 — 天/时/分/秒精确刷新,支持设置小数位数
- 🌐 中英双语 — 中文 + 英文双行倒计时显示,各行独立开关
- 📊 高中进度条 — 可视化展示高中生活已过百分比,百分比文字独立开关
- 🎬 数字脉冲动画 — 每秒轻量缩放脉冲,可开关
- ✨ 入场动画 — 启动/恢复时数字滚动 + 进度条平滑过渡
- 💡 数字发光 — 数字带发光效果,颜色随设置同步
- 📝 考试全屏倒计时 — 科目名称/剩余时间/进度条/下一场信息,最后 5 分钟蜂鸣提醒
- 🏁 考后自动恢复 — 最后一场考试结束 3 秒后自动退出,恢复主窗口
- 🔄 双击/F11 切换 — 考试窗口全屏↔窗口一键切换
- 🚀 开考自动进入 — 当天有考试时自动进入全屏考试模式(可开关)
- 📅 课表胶囊 — 主窗口内显示当天课程,上课自动收缩为进度条、下课自动展开
- ⏰ 下课倒计时 — 栏内置 60 秒倒计时,到设定秒数自动展开 + 提示音
- ⏱ 下课延迟展开 — 下课后等 2 分钟再展开栏,给老师留操作窗口
- 🔄 调休/调课/代课 — 调休(整天复制)、调课(格子交换/移动)、代课(老师替换)
- 📆 按天独立作息 — 每个星期几可单独配一套时刻(如周六无大课间/无眼保健操),提醒与自动化自动跟随
- 🎵 听力播放器(内置) — 听力录音用内置播放器播:整份播完自动关窗;记下听到哪一份(听一半关掉不算「听过」,下次续播);英语周考(全校广播)那天自动跳过且不动进度;可把录音文件/文件夹直接拖进播放器,或一键播桌面上的录音;主窗口胶囊栏能看到「听到哪一份」(v2.27.0 → v2.28.0)
- 🎧 按科目设置(提示音 / 上课显示) — 给指定科目单独设:静音(不出声但保留进度条)/上课不显示/完全安静;没配的科目按全局开关走(v2.26.0 —— 补回 WPF 版有、迁移时丢失的「按科目隐藏」,并扩展出静音档)
- 🔔 预备铃适配 — 提前 2 分钟自动进入上课模式(窗口隐藏 + 栏收缩)
- 🎨 字体与字号 — 全部自定义,支持系统已安装字体
- 🎨 配色方案 — 数字/文字/进度条/考试全屏颜色自由调整,内置颜色选择器
- 🔍 透明度 — 滑杆调节主窗口与课表胶囊透明度
- 📝 文本定制 — 中英文标签文字可自由修改
- 📐 6 种预设 — 顶部 / 中上 / 居中 / 中下 / 底部 / 自定义
- 🖱 拖动定位 — 自定义模式拖动窗口,坐标实时保存
- 📏 Y 偏移 — 精细微调垂直位置
- 👻 点击穿透 — 预设模式下鼠标事件穿透,不阻挡操作
- 🖥 多显示器 — 主窗口按预设定位到指定显示器
- ☁ 实时天气 — 主窗口与考试模式内置天气显示(描述/风/湿度/温度,可设刷新间隔)
- 💬 每日一言 — API 励志语录随机展示,可自定义 API 地址与字段
- 📦 系统托盘 — 任务栏托盘常驻,右键菜单快捷操作
- 🧩 拼图式规则 — 像拼积木一样把「① 触发条件」与「② 要做的动作」两块拼起来,无需写配置
- ⏰ 触发拼块 — 固定时间(每天/指定星期)· 上课前 N 分钟 · 下课时 · 放学时(当天末节下课)· 闲置 N 分钟 · 软件启动后
- ⚙️ 动作拼块 — 打开文件 · 打开科目课件(自动取课件目录最新文件)· 播放音频 · 熄屏 · 关机/重启(倒计时可取消)· 弹出提醒 · 关闭软件 · 打开白板
- 🔢 智能识别课件序号 — 文件名里是
01/unit1/第1讲还是一、第二讲十一都能识别,自动按顺序播/打开 - 🛡 防误触 — 考试模式/上课时段不触发闲置熄屏;自习班会课前不自动开课件;每条规则独立启停 + 全局总开关
- 💾 独立配置 — 规则存 automations.json(随软件文件夹分发,「恢复默认设置」不会误删)
- 🖥 局域网 HTTP 服务 — 启动软件自动开启(可关),老师浏览器访问
http://本机IP:8080 - 👥 多老师账号 — 语数英物化生 6 位老师 + 管理员,登录页下拉选账号;删掉即永久失效(v2.29.0 起不再有「删不掉的内置账号」)
- 📚 课表远程管理 — 周课表可视化编辑(选科限定,模态框选课),双击改、一键保存
- 📎 课件投递 — 拖拽/点击上传(500MB,白名单后缀),班级电脑自动打开,可设桌面/课件等预设目录
- 📊 班级状态 — IP / 磁盘剩余 / 最近上传 / 运行指示灯(15s 自动刷新)
- 📋 操作日志 — 登录/改课表/上传全记录(按老师显示名),管理员可查
- 🏫 班级信息 — 班级名 / 老师名网页端与设置页均可改
- 🔐 安全 — Token 持久化登录、登录限速(同 IP 错 5 次锁 2 分钟)、PBKDF2 密码哈希(v2.7.0,旧明文登录后自动迁移)、账号名不外泄、IP 白名单可选开关、默认弱口令红字告警 + 新账号随机密码 + 内置账号兜底已终止(v2.29.0)
- ⌨️ 全局快捷键 — Ctrl+Shift+H 显隐主窗 / Ctrl+Shift+E 考试模式 / Ctrl+Shift+W 白板 / Ctrl+Alt+D 屏幕批注 / Ctrl+Shift+P PDF 阅读 / Ctrl+Shift+K 编辑课表
- 🎯 始终置顶 — 可选始终置顶或正常窗口层级
- 🚀 自动更新 — 发现新版本自动静默更新(不弹窗):走国内加速镜像下载,进度显示在顶部课表胶囊栏(「正在下载新版本 / 正在解压 / 重启」),有未导出的板书时会等你关掉再重启;AOT / 框架依赖版自动匹配(v2.13.1 修:更新程序改从临时目录运行,不再出现"某个 DLL 正被占用"导致更新失败)
- 🔒 单实例 — 重复启动时激活已有窗口(按进程名校验,不误激活同名窗口)
- 💾 配置持久化 — JSON 文件存储(settings.json / schedule.json / automations.json),重启不丢失;支持一键备份/恢复
- ⚡ 低开销常驻(v2.30.0 / v2.30.1)— 课表查询加缓存(主窗口每秒的刷新链原来要重算课表 10 次/秒)、主题色与日期不再每秒重新解析、画笔复用同一实例(原来每秒都触发一次无谓重绘)。内存侧经实测确认无泄漏:窗口关掉后能完整回收;标题栏图标与周视图装饰画笔改为共享实例;GC 调为「内存吃紧时更积极归还」,长时间使用占用更平稳
- 📝 白板 — 独立板书画布,画笔 / 荧光笔 / 橡皮 / 激光笔,7 色板 + 4 档粗细,多页切换,5 种背景(白板 / 网格 / 横线 / 点阵 / 黑板)
- ↩️ 笔迹级撤销重做 — Ctrl+Z / Ctrl+Y(撤销栈 200 步)
- 🖼 导出 PNG — 2× 超采样导出当前页,可存档或发学生
- 🎯 屏幕批注 — 全屏透明覆盖层,可在任意应用(PDF / PPT / 网页)之上直接圈画
- 🖱 穿透模式 — 批注时捕获指针、一键切穿透让下层应用继续操作
- 📸 截屏保存 — 抓取屏幕并与墨迹合成,一键另存 PNG(零第三方依赖)
- 🖐 触屏友好 — 手指 / 触控笔 / 鼠标都能写(白板与屏幕批注没有滚动内容,手指直接书写);工具栏按钮 44px 触屏热区
- ⌨️ 快捷键 — Ctrl+Shift+W 打开白板 / Ctrl+Alt+D 开关屏幕批注(托盘与右键菜单同入口)
- 📖 内置 PDF 阅读器 — 打开本地 PDF 直接看,不依赖 WPS / Office / 浏览器
- ✍️ 直接在页面上批注 — 画笔 / 荧光笔 / 橡皮 / 激光笔 + 颜色,与白板同一套墨迹引擎
- 🧭 墨迹跟着内容走 — 滚动、缩放时笔迹始终贴在原本那一页的位置上,不会漂移
- 🖐 触屏友好 — 手指、触控笔都能写(v2.13.1 修:原来手指被排给滚动,触屏上写不出字);双指拖动 = 滚动,鼠标滚轮/滚动条照旧;底部还有一个「手指滚动 / 手指书写」一键切换(想用单指滑屏时切过去);缩放/翻页按钮 44px 热区
- ⚡ 大文件不卡 — 只渲染当前可见页(前后各留一页缓冲),渲染在后台线程;已渲染页面按需淘汰
- 🔖 自动续读 — 记住每个 PDF 上次读到第几页,下次打开直接跳回去
- 💾 导出当前页 — 页面与批注合成一张 PNG 带走
- 🧾 页码跳转 — 直接输入页码按回车即可跳转
- ⌨️ 快捷键 — Ctrl+Shift+P 打开(托盘与右键菜单同入口)
| 技术 | 说明 |
|---|---|
| .NET 10 | 目标框架 |
| Avalonia 12 | 跨平台桌面 UI 框架 |
| FluentAvaloniaUI 3 | WinUI 3 风格主题(Mica/圆角/Fluent 控件) |
| C# | 开发语言 |
| AXAML | 界面标记语言 |
| Avalonia.Controls.DataGrid | 课表/考试表格编辑 |
| Avalonia.Controls.ColorPicker | 颜色选择 |
| Avalonia.Fonts.Inter | 默认字体 |
| 高德天气 API | 实时天气数据 |
注:点击穿透 / 托盘 / 自启动注册表 / 全局快捷键等使用 Win32 P/Invoke,当前仅 Windows 生效(Avalonia 框架本身跨平台,非 Windows 平台对应功能自动降级为 no-op)。
- Windows 10/11 x64
- .NET 10 SDK
git clone https://github.com/XEKernel/StudyJourney.git
cd StudyJourney/StudyJourney.Avalonia
dotnet run推荐:NativeAOT(免装 .NET,约 28 MB,启动最快)。更新程序也要一起 AOT 编译,否则它会靠自带的 ~190 个运行时文件把"单文件分发"变成假象:
dotnet publish StudyJourney.Avalonia/StudyJourney.Avalonia.csproj -c Release -r win-x64 -p:PublishAot=true -o publish/aot
dotnet publish Updater/StudyJourney.Updater.csproj -c Release -r win-x64 -p:PublishAot=true -o publish/updater-aot⚠ AOT 产物目录里会带很大的 .pdb 调试符号(主程序约 191 MB,是程序本体的 6 倍),分发前务必删掉:
Get-ChildItem publish/aot -Recurse -Filter *.pdb | Remove-Item -Force兜底:框架依赖(需安装 .NET 10 桌面运行时):
dotnet publish StudyJourney.Avalonia/StudyJourney.Avalonia.csproj -c Release -r win-x64 --self-contained false
dotnet publish Updater/StudyJourney.Updater.csproj -c Release -r win-x64 --self-contained false更新程序 Updater/ 单独编译,产物要与主程序放进同一个目录再分发。
升级路径(2026-10-01,v3.0.2 起):比 v3.0.1 更旧的程序会被要求先升级到 v3.0.1, 再由它升到最新版。原因是 v3.0.1 携带了更新线路本身的修复(形态判定 / 装错包保险), 而更旧的程序跑的是旧代码 —— 放它们直达最新,等于让旧代码自己决定装什么(v3.0.0 就会挑到需要装 .NET 的包)。 老师不需要做任何事:升级时会多一次自动重启。取不到中间版本时程序本轮不更新(不会退回直连最新那条路)。 这两端是一件事:客户端
UpdateService.UpgradeWaypointVersion(管跑新代码的机器)+ CIUPGRADE_WAYPOINT(把-fd.zip固定成门槛版本的构建,这才是管得住老机器的机制)。
分发形态过渡(2026-10-01,v3.0.1):CI 里的开关
FD_ASSET_IS_AOT_ALIAS(.github/workflows/dotnet-desktop.yml的env)现为true—— 兼容包-fd.zip里放的也是 AOT 构建。原因:v3.0.0 的形态判定只按「有没有 coreclr.dll」二分,AOT 版没有该文件 → 被判成 "框架依赖" → 已装 v3.0.0 的机器下次更新会来下-fd包(需装 .NET)。那些机器跑的是旧代码、 改不了,所以过渡期让-fd也指向 AOT 构建,误下也能正常用。 等所有在用的机器都跑过一次 ≥ v3.0.1 之后,把开关改回false即恢复真·框架依赖包。
| 你现在是什么 | 该怎么办 |
|---|---|
v2.17 及更早(自包含,程序目录一大堆 System.*.dll) |
直接下推荐包(免装 .NET)→ 关掉旧程序 → 解压到一个新文件夹 → 把下表中你的数据文件拷进去 → 运行新的 |
| v2.18 ~ v2.30.1(同样自带运行时) | 让程序自己更新即可(会自动下推荐包);也可按上一行手动换 |
| v3.0.0(AOT 版) | 自动更新会先装 v3.0.1(必经中间版本),再由它升到最新;也可手动装一次 v3.0.1(更快) |
升级时务必带走的数据(都在程序目录里;自动更新会保护它们,手动替换时要自己拷):
settings.json 设置(账号 / 上传目录 / 更新镜像…) records/ 上课活动记录(开了"记录上课活动"才有)
schedule.json 课表 backups/ 「恢复默认设置」前的自动备份
automations.json 自动化规则
open-state.json 打开类动作的运行状态
pdf-state.json PDF 阅读进度
listening.json 听力播放进度
老师自己放进程序目录的其它文件不会被删:更新只删"上一次随包装进来、这次包里已经没有"的文件;
如果程序目录里没有上一次的 install-manifest.txt(v2.18.0 之前装的),本次更新一个文件都不删,
只是旧运行时文件会留在目录里(不影响使用,可手动删)。
⚠ v3.0.0 的已知缺陷(v3.0.1 已修):判断"自己是哪种安装形态"时只看了「程序目录有没有 coreclr.dll」,
而 AOT 版没有这个文件 → 被判成"框架依赖版" → 它下一次更新会自动去下需要装 .NET 的那个包,
教室里没装 .NET 时会更新失败。v3.0.1 改成三态判定(AOT / 自包含 / 框架依赖,用"能否动态生成代码"识别 AOT),
并加了一道保险:万一包需要 .NET 而本机没有 → 拒绝安装并说明原因,绝不会把自己换成打不开的状态。
StudyJourney.Avalonia/
├── App.axaml / App.axaml.cs # 应用入口(托盘/快捷键/自动更新/考试模式统一入口)
├── Program.cs # Main 入口(单实例 Mutex)
├── StudyJourney.Avalonia.csproj # 项目文件
├── Assets/ # 图标(icon.ico / icon.png)
│
├── Models/ # 数据模型(纯数据,无 UI 依赖)
│ ├── AppSettings.cs # 应用设置(JSON 持久化;含 TeacherAccount 与选科)
│ ├── ScheduleEntry.cs # 课表/考试条目/时段模板/课程表网格行
│ ├── ScheduleManager.cs # 课表与考试数据管理(加载/保存/查询/导入)
│ ├── AutomationRule.cs # 自动化规则(触发/动作拼块枚举 + automations.json 存储)
│ ├── OpenState.cs # 打开类动作运行期状态(open-state.json:顺序记忆/已打开进程/待打开)
│ └── PdfReadingState.cs # PDF 阅读进度(pdf-state.json:路径 → 上次页码)
│
├── Services/ # 服务层(业务逻辑)
│ ├── ReminderService.cs # 提醒调度服务(上课/下课/考试/课间语义)
│ ├── AutomationService.cs # 自动化任务调度(触发判定/动作执行/闲置与熄屏 P/Invoke)
│ ├── HttpServerService.cs # 远程管理 Minimal API(内嵌教师端 Web 控制台)
│ ├── WeatherService.cs # 天气服务(HTTP + JSON 解析)
│ └── UpdateService.cs # GitHub Release 更新检查/下载
│
├── Helpers/ # 公共工具
│ ├── AppLogger.cs # 轻量日志(Debug + 文件,超限轮转)
│ ├── FileAtomic.cs # 原子写文件(settings/schedule/tokens/automations)
│ ├── PasswordHasher.cs # 密码哈希(PBKDF2-SHA256,登录凭据存储)
│ ├── ColorUtils.cs # 颜色解析/天气表情符号
│ ├── GlobalHotKeyManager.cs # 全局快捷键(Win32 RegisterHotKey)
│ ├── WindowEnumerator.cs # 顶层窗口标题枚举(顺序记忆/连堂幂等)
│ ├── FileSequence.cs # 文件名自然序号解析(01/unit1/第1讲)
│ ├── InkLayer.cs # 墨迹模型层(InkStroke/InkDocument/IInkSurface/InkGeometry)
│ ├── InkCanvas.cs # 墨迹绘制控件(指针分流/采样过滤/激光笔/分层重绘)
│ ├── BoardRenderer.cs # 白板背景绘制 + 离屏 PNG 导出
│ └── PdfRenderer.cs # PDF 渲染(PDFium/Docnet.Core 封装)
│
├── Views/ # 窗口与页面(UI 层)
│ ├── MainWindow.axaml(.cs) # 主窗口(灵动岛:时间/课表/天气/倒计时/一言,含上课收缩)
│ ├── ExamModeWindow.axaml(.cs) # 考试全屏倒计时
│ ├── SettingsWindow.axaml(.cs) # 设置窗口(FAAppWindow + NavigationView 8 页)
│ ├── ScheduleEditorWindow.axaml(.cs) # 课表/考试编辑(DataGrid + 周视图调课)
│ ├── WhiteboardWindow.cs # 白板(多页/5 背景/导出 PNG)
│ ├── ScreenAnnotationWindow.cs # 屏幕批注全屏透明覆盖层(穿透/截屏)
│ ├── PdfReaderWindow.cs # PDF 阅读器(滚动/缩放/批注/续读)
│ ├── ScreenOffPromptWindow.cs # 熄屏前可取消倒计时提示
│ ├── UpdateProgressWindow.cs # 更新下载进度窗(进度条 + 取消)
│ ├── ColorPickerDialog.axaml(.cs)# 颜色选择对话框
│ └── Settings/ # 8 个设置页
│ ├── CountdownPage.axaml(.cs) # 倒计时
│ ├── PositionPage.axaml(.cs) # 位置
│ ├── ApiPage.axaml(.cs) # API(一言/天气)
│ ├── SchedulePage.axaml(.cs) # 课表/提醒
│ ├── ExamPage.axaml(.cs) # 考试
│ ├── ServerPage.axaml(.cs) # 服务器(远程管理/账号/科目/日志)
│ ├── AutomationPage.axaml(.cs) # 自动化(拼图式规则)
│ ├── AboutPage.axaml(.cs) # 关于(版本/更新)
│ └── ISettingsPage.cs # 设置页接口(Load/Apply/IsDirty)
│
└── Updater/ # 独立更新程序(StudyJourney.Updater)
| 页面 | 功能 |
|---|---|
| ⏳ 倒计时 | 字体、字号、颜色、透明度、可见内容、时间精度/小数位、动画、中英文文本、目标/起算日期、自定义倒计时 |
| 📐 位置 | 6 种预设 + 自定义坐标 + Y 偏移 + 始终置顶 + 上课隐藏 + 自启动 |
| 🔌 API | 每日一言 API + 实时天气(城市/颜色/刷新间隔) |
| 📋 课表 | 提醒开关(预备铃/上课/课间/下课等)、提示音、提醒方式(胶囊弹窗 / Windows 通知)、课表编辑入口 |
| 📝 考试 | 考试模式开关、自动进入、字号、颜色、字体 |
| 🌐 服务器 | 远程服务开关/自启、课件存放位置(预设+自定义)、班级信息、老师账号(密码加密存储)、可选科目、操作日志 |
| 🧩 自动化 | 总开关、规则列表(增删/启停)、拼图式编辑器(触发块 + 动作块 + 实时预览 + 智能打开选项) |
| ℹ 关于 | 版本信息、检查更新、GitHub 仓库 |
- 课表编辑:设置 → 📋 课表 →「编辑课表」→ 周视图网格填课程名,或 DataGrid 平铺编辑
- 时段模板:定义节次时间;「适用」可选全周通用(默认)或某个星期几单独一套(如周六),点「应用」写入课表
- 调休:选来源星期 → 目标星期 → 应用,一键复制课表
- 调课:单击格子选源 → 再单击选目标 → 交换/移动/代课(双击格子可直接改课程名)
- 课表胶囊:主窗口内显示当天课程;上课自动收缩为进度条,距下课 1 分钟显示倒计时并展开
- 考试模式:设置 → 📝 考试 → 添加考试 + 科目 → 托盘菜单 → 进入考试模式
- 导入导出:课表/考试 JSON 一键导入导出,支持数据备份/恢复
详见 GitHub Releases: https://github.com/XEKernel/StudyJourney/releases
MIT License
Copyright (c) 2025 XEKernel