存储
SQLite
数据库默认路径:
data/exams.sqlite
可用环境变量覆盖:
EXAMS_DB_FILE=D:/data/exams.sqlite
相对路径基于程序目录(开发模式为项目根目录,打包后为 exe 所在目录)。
exams 表
| 字段 | 类型 | 说明 |
|---|---|---|
id |
INTEGER | 主键,自增 |
exam |
TEXT | 试卷名,唯一索引 |
json |
TEXT | 完整试卷 JSON,不包含试卷名 |
CREATE TABLE exams (
id INTEGER PRIMARY KEY AUTOINCREMENT,
exam TEXT NOT NULL,
json TEXT NOT NULL
);
CREATE UNIQUE INDEX exams_exam_name_unique ON exams (exam);
新创建的试卷 json 为 {};内容通过 PUT /api/v1/exams/{id} 替换。
试卷 JSON 不经过数据库 JSON 插件约束,结构由接口层的 Zod schema 校验。
旧版本带 json_valid / json_extract CHECK 的表会在启动时自动迁移为当前三列结构。
files 表
| 字段 | 类型 | 说明 |
|---|---|---|
files_id |
INTEGER | 文件 id,主键 |
hash |
TEXT | SHA-256,唯一索引 |
u_time |
INTEGER | Unix 秒级时间戳 |
CREATE TABLE files (
files_id INTEGER PRIMARY KEY AUTOINCREMENT,
hash TEXT NOT NULL,
u_time INTEGER NOT NULL
);
CREATE UNIQUE INDEX files_hash_unique ON files (hash);
HashFileStorage
src/utils/hashFileStorage.js 只负责磁盘文件,不操作 SQLite。
目录规则:
<FILES_DIRECTORY>/
└─ ab/
└─ cd/
└─ abcdef... # 完整 hash,无扩展名
主要方法:
saveFiles([{hash, blob}])getFiles([hash])deleteFiles([hash])getFilePath(hash)
默认根目录:
data/files
可用环境变量覆盖:
FILES_DIRECTORY=D:/data/files
上传接口 POST /api/v1/files 先计算文件 SHA-256,再写入 hash 路径,最后登记 files 表。
同一 hash 重复上传会返回已有 fileId,不会重复入库。