diff --git a/src/admin/api.ts b/src/admin/api.ts index 0ff61c0..2d8f7c8 100644 --- a/src/admin/api.ts +++ b/src/admin/api.ts @@ -163,6 +163,14 @@ export function getSQLTestcaseScripts(problemId: number) { ) } +// AI 根据标准答案生成一个 SQL 测试点初始化脚本 +export function generateSQLTestcase(data: { + ref_sql: string + mode: "query" | "modify" +}) { + return http.post<{ sql: string }>("admin/sql_test_case_ai_gen", data) +} + export function createProblem(problem: BlankProblem) { return http.post("admin/problem", problem) } diff --git a/src/admin/problem/components/SQLTestcaseEditor.vue b/src/admin/problem/components/SQLTestcaseEditor.vue index 68c7996..f5dddbb 100644 --- a/src/admin/problem/components/SQLTestcaseEditor.vue +++ b/src/admin/problem/components/SQLTestcaseEditor.vue @@ -3,6 +3,7 @@ import { downloadZip } from "client-zip" import type { LANGUAGE, SQLDisplay, Testcase } from "utils/types" import SQLDataTable from "oj/problem/components/SQLDataTable.vue" import { + generateSQLTestcase, getSQLTestcaseScripts, previewSQLTestcase, uploadTestcases, @@ -35,7 +36,7 @@ function blankEntry(): ScriptEntry { return { id: nextId++, sql: "", display: null, error: "", stale: false } } -const scripts = ref([blankEntry(), blankEntry()]) +const scripts = ref([blankEntry(), blankEntry(), blankEntry()]) const refSQL = computed( () => @@ -45,8 +46,10 @@ const refSQL = computed( const isPreviewing = ref(false) const isUploading = ref(false) +const isGenerating = ref(false) const hasAnyScript = computed(() => scripts.value.some((s) => s.sql.trim())) +const hasBlankScript = computed(() => scripts.value.some((s) => !s.sql.trim())) const canUpload = computed(() => { const filled = scripts.value.filter((s) => s.sql.trim()) @@ -83,7 +86,7 @@ function remove(index: number) { } function reset() { - scripts.value = [blankEntry(), blankEntry()] + scripts.value = [blankEntry(), blankEntry(), blankEntry()] } function expectedQuery(d: SQLDisplay) { @@ -94,6 +97,28 @@ function changedTables(d: SQLDisplay) { return "changed_tables" in d.expected ? d.expected.changed_tables : [] } +async function generate() { + const blanks = scripts.value.filter((s) => !s.sql.trim()) + if (!blanks.length) return + isGenerating.value = true + await Promise.all( + blanks.map(async (s) => { + try { + const res = await generateSQLTestcase({ + ref_sql: refSQL.value, + mode: props.mode, + }) + s.sql = res.data.sql + } catch (err) { + const data = (err as { data?: unknown })?.data + message.error(typeof data === "string" ? data : "AI 生成失败") + } + }), + ) + isGenerating.value = false + await preview() +} + async function preview() { // 丢弃空脚本 scripts.value = scripts.value.filter((s) => s.sql.trim()) @@ -168,15 +193,33 @@ async function upload() { 还没有填写 SQL 标准答案,请先在上方"本题参考答案"中填写,再来编写测试点 - 清空 - +1 + + 清空 + + + +1 + + + + {{ !refSQL ? "请先填写 SQL 标准答案" : "所有脚本都写好了,无需生成" }} + - + 提交