feat(后台): 编程题出题页重做——左边写,右边是学生看到的样子;例子和测试数据的输出都由标准答案跑出来,改老题能直接看、改测试数据
- 例子就是测试数据里勾了「当例子」的几组,不再手抄输出;老题的例子不在测试数据里的补到最后 - 改了答案,输出变了的那组标黄、写清原来存的是什么;答案在某组上报错就挡住保存 - 没存标准答案的老题输出手写;太大的测试数据(>100 组或单文件 >32KB)只能导入 / 下载 zip - 预制代码只写学生看得到的那段,前后藏起来的代码收进折叠;语法要求先拿标准答案自测 - 流程图两个互斥开关改成三选一;时间 / 内存限制能改了;草稿只给新建页 - 后端:读回测试点原文、语法要求自测、AI 想测试输入三个接口 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
033a245abb
commit
ba5b9ada0e
15 files changed
+3043
-1068
No files matched your search
@@ -1,5 +1,5 @@
|
||||
import { createHash } from "node:crypto"
|
||||
import { mkdir, chmod, readdir, readFile, writeFile } from "node:fs/promises"
|
||||
import { mkdir, chmod, readdir, readFile, stat, writeFile } from "node:fs/promises"
|
||||
import { resolve } from "node:path"
|
||||
|
||||
import { unzipSync, zipSync } from "fflate"
|
||||
@@ -250,6 +250,43 @@ export async function readSqlScripts(testCaseId: string) {
|
||||
return scripts
|
||||
}
|
||||
|
||||
/**
|
||||
* 读回编程题测试点的原文(出题页回显、就地改)。超过 `limits` 的只报数量和大小,不读内容。
|
||||
* 目录不存在时抛 TestCaseError。
|
||||
*/
|
||||
export async function readTestCaseFiles(
|
||||
testCaseId: string,
|
||||
limits: { maxCases: number; maxFileBytes: number },
|
||||
): Promise<
|
||||
| { editable: true; cases: { input: string; output: string }[] }
|
||||
| { editable: false; count: number; totalBytes: number }
|
||||
> {
|
||||
const directory = resolve(config.testCaseDirectory, testCaseId)
|
||||
let entries: string[]
|
||||
try {
|
||||
entries = await readdir(directory)
|
||||
} catch {
|
||||
throw new TestCaseError("Test case does not exist")
|
||||
}
|
||||
const pairs = collectPairs(new Set(entries))
|
||||
let totalBytes = 0
|
||||
let tooLarge = pairs.length > limits.maxCases
|
||||
for (const name of pairs.flat()) {
|
||||
const size = (await stat(resolve(directory, name))).size
|
||||
totalBytes += size
|
||||
if (size > limits.maxFileBytes) tooLarge = true
|
||||
}
|
||||
if (tooLarge) return { editable: false, count: pairs.length, totalBytes }
|
||||
const cases: { input: string; output: string }[] = []
|
||||
for (const [input, output] of pairs) {
|
||||
cases.push({
|
||||
input: await readFile(resolve(directory, input), "utf8"),
|
||||
output: await readFile(resolve(directory, output), "utf8"),
|
||||
})
|
||||
}
|
||||
return { editable: true, cases }
|
||||
}
|
||||
|
||||
function randomId() {
|
||||
const alphabet = "abcdefghijklmnopqrstuvwxyz0123456789"
|
||||
const bytes = new Uint8Array(32)
|
||||
|
||||
Reference in new issue
Block a user