「准备——开始!」教师统一发令,学生同步开赛;每一次击键都有反馈,每一段进步都有记录。
KeySprint(键跃)是一套可自托管的中文输入课堂工具。教师选择范文、创建限时竞赛并统一发令,学生通过比赛编号进入赛场,系统实时统计速度、正确率和完成进度,赛后生成个人与班级分析。
长文章输入时,页面会在当前行接近屏幕边缘时自动滚动,退格和返回前文修改也会跟随光标,并为输入法候选框预留空间。
成绩口径保持一致:正确率为“正确字数 ÷ 已输入字数”,速度为“正确字数 ÷ 实际用时(分钟)”。范文总篇幅只用于显示完成进度,不参与正确率计算。
| 学生赛场 | 教师工作台 | 系统底座 |
|---|---|---|
| 比赛编号快速加入 | 范文上传、编辑与共享 | Go 单进程 + SQLite WAL |
| 名单选人或手动填写身份 | 多场竞赛并行控制、AI 生成范文 | WebSocket 实时发令 |
| 逐字拼音提示、按词分组,可按场开关 | 在线名单与自动停赛 | 刷新恢复与成绩择优保存 |
| 中文输入法组合输入与纠错 | 个人/班级趋势与成绩导出 | ClassOrbit 班级同步 |
flowchart LR
T[教师选择范文] --> C[创建竞赛 · 分享编号]
C --> S[学生进入赛场]
S --> R[统一发令 · 实时输入]
R --> A[成绩排行 · 趋势分析]
创建竞赛时可点「文本选项」按场多选,不启用则保持原有体验:
| 选项 | 学生的感受 |
|---|---|
| 拼音提示 | 汉字上方显示拼音,帮助认读 |
| 去除符号 | 标点隐藏,只练文字 |
| 符号统一 | 全角/半角标点视为同一答案 |
| 去除换行 | 段落合并,文章连续显示 |
| 分词输入 | 词与词之间留出空隙,正在输入的词下方有蓝色下划线,顶部提示「当前词:清晨」,帮助学生以词为单位输入 |
后台「系统配置」还可调「界面字号」(75–150%,预设 100%):整个界面按百分比缩放,适配不同机房的屏幕比例;手机窄屏(≤760px)自动按 100% 显示,避免横向滚动。
分词由后端 Go 分词库(go-ego/gse,纯 Go、jieba 词库)在服务端完成:学生页面先按文本选项变换文章,再向 POST /api/segment 请求当前文本的词边界;接口要求有效比赛编号、单次不超过 8000 字,相同文本会命中内存缓存(首次加载词典约 300ms,之后约 2ms)。分词只是显示提示,不改变要输入的文字,也不影响计分口径。
服务器只需要 Docker 与 Compose 插件,不需要 Go、Node.js 或项目源码。
GHCR 镜像已经公开,服务器无需登录即可直接拉取。
mkdir -p /opt/keysprint
cd /opt/keysprint
curl -fsSLO https://raw.githubusercontent.com/Alumos/KeySprint/main/compose.deploy.yaml
curl -fsSL https://raw.githubusercontent.com/Alumos/KeySprint/main/.env.example -o .env编辑 .env,至少将 JWT_SECRET 换成长随机字符串,可使用 openssl rand -hex 32 生成。随后直接拉取成品镜像:
docker compose -f compose.deploy.yaml pull
docker compose -f compose.deploy.yaml up -d访问 http://服务器地址:8080,首次打开会进入管理员初始化页面。
更新与查看日志:
docker compose -f compose.deploy.yaml pull
docker compose -f compose.deploy.yaml up -d
docker compose -f compose.deploy.yaml logs -f keysprint默认镜像为 ghcr.io/alumos/keysprint:latest,架构为 linux/amd64(Windows 免 Docker 部署见下一节)。生产环境建议在 .env 中固定完整版本,例如 KEYSPRINT_TAG=2.1.1。数据保存在独立卷 keysprint_data 的 /data/keysprint.db,更新容器不会删除数据。
ClassOrbit 已在同一台 VPS 的宿主机 8080 端口运行时,直接使用仓库中的 compose.vps.yaml:
mkdir -p /opt/keysprint
cd /opt/keysprint
curl -fsSLO https://raw.githubusercontent.com/Alumos/KeySprint/main/compose.vps.yaml
curl -fsSL https://raw.githubusercontent.com/Alumos/KeySprint/main/.env.vps.example -o .env编辑 .env,替换两项密钥:
JWT_SECRET=使用-openssl-rand-hex-32-生成
CLASS_SYSTEM_TOKEN=与-ClassOrbit-完全相同的共享密钥确认 ClassOrbit 自己的部署配置包含相同密钥并监听宿主机 8080:
APP_PORT=8080
CLASS_SYSTEM_TOKEN=与-KeySprint-完全相同的共享密钥然后启动 KeySprint:
docker compose -f compose.vps.yaml pull
docker compose -f compose.vps.yaml up -d
docker compose -f compose.vps.yaml ps访问 http://VPS_IP:8081。VPS 配置默认通过 ghcr.milu.moe 加速拉取 GHCR 镜像,并加入 Linux Docker 所需的 host-gateway 映射。KeySprint 容器会通过 http://host.docker.internal:8080 访问 ClassOrbit;不要填写 http://127.0.0.1:8080,容器内的回环地址指向 KeySprint 自己。
机房/教室没有云服务器、也不允许安装 Docker 时,用发布页的 Windows 便携包(keysprint-<版本>-windows-x64.zip,amd64)把教师机变成课堂服务器:
- 从 Releases 下载并解压到固定目录(例如
D:\KeySprint);zip 是扁平的,解压一次就能看到keysprint.exe; - 右键
allow-firewall.bat→ 以管理员身份运行,放行 8080 端口; - 双击
start.bat启动(首次自动生成config.env与数据库),本机打开http://127.0.0.1:8080完成管理员初始化; - 用
ipconfig查出本机 IPv4,学生浏览器访问http://<教师机IP>:8080,输入比赛编号即可; - 可选:以管理员身份运行
install-autostart.bat,开机自动启动,无需登录桌面。
整套服务运行时不需要外网(前端资源全部打包,没有 CDN、在线字体或第三方请求),因此适合只能访问国内网络的教学专网。内网访问无需备案号,后台「系统配置」里留空即可。备份 = 停止服务后复制 data 目录;升级 = 替换 keysprint.exe 与 web,保留 data 与 config.env。完整步骤、常见问题与多教师共用方案见 docs/LAN-DEPLOY.md。
GitHub Actions 会执行:
- 运行 Go 后端测试;
- 安装锁定的前端依赖,运行输入逻辑回归测试并执行 TypeScript/Vite 生产构建;
- 构建
linux/amd64极简镜像并发布到ghcr.io/alumos/keysprint; - 为镜像附加 SBOM 与 provenance;
- 在原生 amd64 的
windows-latest环境构建 Windows 便携包(免 Docker,功能与容器版一致); - 正式 Tag 构建完成后自动创建 GitHub Release,并附上 Windows 便携包。
推送 main 会生成 latest、main 和 sha-xxxxxxx;推送 v1.2.3 标签还会生成 1.2.3、1.2 与 1。Pull Request 只测试和构建,不发布镜像。每次构建的 Windows 包也会作为 Actions artifact(keysprint-windows-x64)保留 30 天,无需打 Tag 也能取用。
运行镜像以 scratch 为底,只包含静态 Go 二进制、前端资源与 HTTPS 根证书;没有 shell、包管理器或多余系统工具。容器使用非 root 用户、只读根文件系统、应用内健康检查并移除全部 Linux capabilities。
当前稳定版本为 v2.1.1。KeySprint 遵循 Semantic Versioning:
PATCH:向后兼容的修复与安全更新;MINOR:向后兼容的新功能;MAJOR:不兼容的 API、配置或数据行为变化;-rc.N:正式发布前的候选版本。
根目录 VERSION 是唯一版本源,并与前端包版本、Changelog 和 Git Tag 自动校验。完整规则与发布步骤见 RELEASING.md,版本变化见 CHANGELOG.md。已发布 Tag 永不移动或覆盖。
make version
./scripts/check-version.sh| 变量 | 默认值 | 说明 |
|---|---|---|
KEYSPRINT_IMAGE |
ghcr.io/alumos/keysprint |
成品镜像地址 |
KEYSPRINT_TAG |
latest |
镜像标签,生产环境可固定版本 |
DATA_VOLUME_NAME |
keysprint_data |
SQLite 数据卷名称 |
PORT |
8080 |
对外端口 |
TZ |
Asia/Shanghai |
服务时区 |
JWT_SECRET |
无 | 必须设置的登录签名密钥 |
CLASS_SOURCE |
manual |
名单主要来源:manual 或 classorbit |
CLASS_SYSTEM_URL |
空 | ClassOrbit 服务地址 |
CLASS_SYSTEM_PATH |
/api/integration/classes |
班级同步接口 |
CLASS_SYSTEM_TOKEN |
空 | 与 ClassOrbit 完全一致的共享 Bearer 密钥 |
CLASS_SYSTEM_TIMEOUT |
8s |
外部请求超时 |
ALLOWED_ORIGINS |
空 | WebSocket 允许的来源,逗号分隔;CDN 回源 Host 与页面域名不一致时填写 |
AI_BASE_URL |
空 | OpenAI 兼容接口地址(/v1),建议在后台配置 |
AI_API_KEY |
空 | AI 接口密钥,建议在后台配置(只存数据库) |
AI_MODEL |
gpt-6-luna |
默认生成模型 |
AI_REASONING_EFFORT |
medium |
思考强度:low / medium / high |
后台「系统配置 → AI 文章生成」可对接任意 OpenAI 兼容接口(/v1 地址 + API Key),支持探测上游模型列表、设置默认模型与思考强度(low / medium / high)。配置保存后,文章管理的「AI 生成」按主题、体裁与字数范围生成范文,直接写入文章库并标记来源为「AI 生成」。
- 默认模型
gpt-6-luna、思考强度medium;接口地址与密钥只保存在本机数据库,页面上只回显末 4 位,留空保存不会覆盖已有密钥。 - 上游不认识
reasoning_effort时会自动降级重试一次,兼容更多第三方网关。 - 生成文章与手动文章同等管理(预览、编辑、删除、选用),来源记录在
articles.source。 - 环境变量
AI_BASE_URL/AI_API_KEY/AI_MODEL/AI_REASONING_EFFORT可作为初始默认值;后台保存后以数据库为准。 - 需要访问所选 AI 接口;纯内网(教育专网只能连国内 IP)环境请确认网关可达,否则 AI 功能不可用,其余功能不受影响。
KeySprint 的班级名单支持两种来源:
Excel 手工导入:默认模式,教师上传.xlsx/.xls名单;ClassOrbit 接口:教师在班级管理中点击同步,从 ClassOrbit 获取自己管理的班级和学生。
Excel 导入始终保留为课堂兜底。每个班级都会标记实际来源,ClassOrbit 同步只更新或停用接口班级,不会清空手工班级,也不会删除已有比赛成绩。
管理员登录 KeySprint 后,进入 名单来源配置,填写:
| 后台字段 | 同机 VPS 配置值 |
|---|---|
| 主要来源 | ClassOrbit 接口 |
| ClassOrbit 服务地址 | http://host.docker.internal:8080 |
| 班级接口路径 | /api/integration/classes |
| 共享 Bearer 密钥 | 与 ClassOrbit 的 CLASS_SYSTEM_TOKEN 完全一致 |
| 请求超时 | 8s |
点击“保存并测试连接”后,配置会立即持久化到 KeySprint 数据库,并用当前管理员用户名只读检查 ClassOrbit 名单;此后数据库中的可视化配置优先于容器环境变量。接口同步是教师主动触发,不是定时任务。
同步只携带教师用户名与独立 Bearer 密钥,不会转发教师密码或 KeySprint 登录令牌。KeySprint 教师的登录用户名必须与 ClassOrbit 教师用户名一致,否则页面会直接显示 ClassOrbit 的具体错误。双方使用稳定班级 ID 保持改名后的历史关联,并通过 ETag 跳过没有变化的重复写入;远端删除会将对应接口班级停用,已有成绩仍保持正确关联。
需要 Go 1.24+ 与 Node.js 22+。
cd frontend
npm ci
npm run dev另开终端:
cd backend
ADDR=:8080 DB_PATH=./data/keysprint.db PUBLIC_DIR=../frontend/dist go run .完整验证:
make test架构、数据模型、文本选项语义与 Windows 本地开发(不装 Docker)的完整说明见 docs/PROJECT-GUIDE.md。
如果需要从源码构建本地镜像:
cp .env.example .env
docker compose up -d --buildSQLite 使用 WAL 模式。停止服务后复制数据库可获得一致备份:
docker compose -f compose.deploy.yaml stop keysprint
docker compose -f compose.deploy.yaml cp keysprint:/data/keysprint.db ./keysprint-backup.db
docker compose -f compose.deploy.yaml start keysprint生产环境请在 KeySprint 前配置 HTTPS 反向代理,并妥善保管 .env、数据卷与备份。