从 Excel 到班主任工作台:一次本地优先桌面应用实践

记录 class 在 8 月 10—11 日的第一版桌面实践:把班主任日常流程接到本地 SQLite,处理跨日请假、重复积分与数据关联,并完成导出回读和桌面冷启动验收。

—次点击5分钟阅读

班主任的很多工作都有表格:学生名册、考试成绩、作业登记、请假记录,还有谈话和家校沟通。单独看,每一份都不复杂;放到一个学期里,同一名学生的信息却会散落在不同文件中,查找和重复填写逐渐变成负担。

8 月 10 日到 11 日,我把这些日常流程整理成了 class 的第一版「班主任工作台」。目标很具体:在自己的电脑上打开就能用,录入的数据关掉后还在,需要交材料时能够导出来。这篇记录的是当时的本地桌面版本。

先把一天的工作连起来

设计入口时,我更关心老师下一步要做什么。早上查看当天请假,收作业时更新提交状态,考试后导入成绩,需要沟通时找到学生此前的记录。学生是贯穿这些事情的同一个对象,修改名册后,关联页面应该继续指向同一人。

所以,名册成为基础,成绩、作业、请假、谈话和座位围绕它组织。家校沟通、班级活动和待办则接住后续安排。这样做也让数据模型有了约束:一条请假不能只剩一段姓名文本,考试成绩需要明确属于哪次考试、哪个科目、哪名学生。

8 月 11 日收尾时,SQLite 中共有 34 张表,数据库迁移版本为 2。这个数字只是当时的实现快照。更有意义的是,同一份学生资料可以被多个业务使用,新增和修改都有持久化落点。

本地优先,要把运行环境一起交付

这一版采用 React + Vite 构建界面,Bun 提供本地 API,Drizzle 管理 SQLite 数据层,再由 Wails 承载桌面窗口。各部分分工如下:

部分

在这个项目中的职责

React + Vite

表单、名册、图表与日常操作界面

Bun API

业务校验、导入导出、事务与数据访问

Drizzle + SQLite

数据结构、迁移和本地持久化

Wails

桌面窗口、本地服务启动和文件保存入口

最容易忽略的差别,是开发者能运行与老师能打开之间还隔着一段路。开发时可以启动终端服务;交付桌面应用时,就应该把这件事收进应用内部。

我用 Bun 的 --compile 把 API、依赖和运行时编成独立可执行文件,再随桌面应用打包。用户不需要另装 Bun。这个打包机制可以参考 Bun 独立可执行文件文档。

桌面端启动后选择空闲的本机回环端口,API 只监听 127.0.0.1,界面拿到实际地址再访问。SQLite 放在 macOS 用户的 Application Support 目录,和应用包分开。程序更新与业务数据因此有了各自的位置。

这套组合也有代价:需要处理服务启动失败、端口分配、数据目录和桌面包内资源,不能只维护网页。我的取舍是保留熟悉的 Web 开发方式,同时把启动与保存做成完整的桌面流程。Wails 的介绍可以帮助理解它在其中承担的角色。

真正的难点藏在业务边界里

第一轮页面都能打开后,审查仍然找出了会影响日常使用的问题。其中三个很有代表性。

跨日请假。 如果“今日请假”只匹配开始日期,昨天开始、明天结束的请假今天就会消失。再叠加 UTC 与本地日期差异,凌晨附近还可能错一天。这类统计应该按本地业务日期判断时间区间是否覆盖今天,并把跨日场景放进回归用例。

重复累计积分。 作业状态从未交改成已交,再撤销、重新提交,如果每次操作都直接追加奖励,同一份作业就可能贡献多次积分。验收必须走完状态来回变化的过程,观察最终余额,而不能只测试第一次点击后数字增加。

监护人信息被误覆盖。 编辑学生资料时,关联信息如何合并、哪些字段允许更新,都需要明确。一个表单保存成功,并不意味着其他页面的数据仍然正确。修复后要回到关联记录核对,尤其不能用空值或无关修改悄悄覆盖已有联系信息。

这些问题在当时都进行了修复。它们也改变了我的验收方式:沿着一件事的开始、修改、撤销和再次执行去检查,比按菜单逐页看一遍更容易发现真正的缺口。

导出文件也是产品的一部分

班主任的工作经常在应用之外继续:表格要汇总,记录要打印,座位图要展示。因此,我把导入、导出和备份放进第一版交付范围。

学生名单支持 Excel、CSV 导入导出,成绩可以导出为 Excel;个人报告及请假、谈话、工作记录提供中文 Word;统计和座位内容能够导出图片。这里的重点是验证生成结果,而不只是看浏览器是否弹出了下载。

当时的验证会重新读取 Excel 和 CSV,解包 Word 检查内容,核对图片尺寸,再检查备份结构。备份恢复还专门使用错误数据测试事务回滚,确认失败不会留下恢复了一半的数据库。

如果再做类似工具,我仍会尽早完成“录入一条记录—关闭重开—导出—重新读取”这条链路。它能及时暴露数据关联、编码和持久化问题,也能让后面的页面建立在可靠的数据基础上。

第一版交付到哪里

8 月 11 日最后一轮验收使用了包含 10 名演示学生、3 场考试的数据。桌面应用完成冷启动,读取了持久化 SQLite;API 回归、类型检查、数据库检查、Web 与桌面构建,以及导出回读都通过了当时的检查。

界面也在 375×812 的窄屏下检查过:导航收进抽屉,宽表格在自己的区域滚动,页面没有整体横向溢出。这个结果验证的是响应式布局,并不代表已经交付手机应用。

交付边界同样需要记住:当时完成的是 macOS Apple Silicon 的自用桌面版本,使用 ad-hoc 签名。它还没有完成公开分发所需的 Apple Developer ID 签名与公证。头像文件选择器的浏览器自动化验收也遇到过超时,写入和持久化由 API 回归补充验证,不能把两者当作完全相同的证据。

做完这一版,我对“本地优先”的理解具体了许多:数据在哪里、关闭后是否还在、导出的文件能否使用、恢复失败会留下什么,都是产品体验。下一次增加功能,我会先沿着老师的一天找到需要衔接的地方,再决定多加一个页面,还是把现有流程做得更顺手。