diff --git a/electron/main/ipc.ts b/electron/main/ipc.ts index b72bcc7..654d0f1 100644 --- a/electron/main/ipc.ts +++ b/electron/main/ipc.ts @@ -283,6 +283,37 @@ export function setupIpc(win: BrowserWindow): void { return null }) + ipcMain.handle('rubric:exportJson', async () => { + const d = getDb() + const rows: any[] = d.prepare('SELECT * FROM rubric ORDER BY sort_order').all() + if (!rows.length) throw new Error('暂无评分标准可导出') + const questions = rows.map(r => ({ + questionTitle: r.question_title, + maxScore: r.max_score, + referenceAnswer: r.reference_answer, + rubric: r.rubric + })) + const result = await dialogBox.showSaveDialog({ + defaultPath: '评分标准.json', + filters: [{ name: 'JSON', extensions: ['json'] }] + }) + if (result.canceled || !result.filePath) return false + fs.writeFileSync(result.filePath, JSON.stringify(questions, null, 2), 'utf-8') + return true + }) + + ipcMain.handle('rubric:importJson', async () => { + const result = await dialogBox.showOpenDialog({ + properties: ['openFile'], + filters: [{ name: 'JSON', extensions: ['json'] }] + }) + if (result.canceled || result.filePaths.length === 0) return null + const content = fs.readFileSync(result.filePaths[0], 'utf-8') + const questions = JSON.parse(content) + if (!Array.isArray(questions)) throw new Error('JSON 格式错误:应为数组') + return { questions, currentIndex: 0 } + }) + // --- Grading data bridge (toolbar → result window) --- ipcMain.handle('grading:storeData', (_event, data: any) => { gradingPayload = data diff --git a/electron/preload/preload.ts b/electron/preload/preload.ts index 68a0db5..cb1e781 100644 --- a/electron/preload/preload.ts +++ b/electron/preload/preload.ts @@ -50,7 +50,9 @@ contextBridge.exposeInMainWorld('electronAPI', { rubric: { storeData: (data: any) => ipcRenderer.invoke('rubric:storeData', data), - getData: () => ipcRenderer.invoke('rubric:getData') + getData: () => ipcRenderer.invoke('rubric:getData'), + exportJson: () => ipcRenderer.invoke('rubric:exportJson'), + importJson: () => ipcRenderer.invoke('rubric:importJson') }, template: { diff --git a/src/components/RubricEditor.vue b/src/components/RubricEditor.vue index c44431a..004d494 100644 --- a/src/components/RubricEditor.vue +++ b/src/components/RubricEditor.vue @@ -34,8 +34,14 @@ @@ -96,12 +102,39 @@ async function handleSave() { } } +async function handleExport() { + try { + await window.electronAPI?.rubric.exportJson() + ElMessage.success('导出成功') + } catch (err) { + ElMessage.error('导出失败:' + (err as Error).message) + } +} + +async function handleImport() { + try { + const data = await window.electronAPI?.rubric.importJson() + if (data?.questions?.length) { + questions.value = JSON.parse(JSON.stringify(data.questions)) + activeIndex.value = 0 + ElMessage.success(`已导入 ${data.questions.length} 题`) + } + } catch (err) { + ElMessage.error('导入失败:' + (err as Error).message) + } +} + function handleClose() { window.electronAPI?.dialog.close() } \ No newline at end of file diff --git a/src/types/index.ts b/src/types/index.ts index 93ad479..8aa3019 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -81,6 +81,8 @@ export interface ElectronAPI { rubric: { storeData: (data: any) => Promise getData: () => Promise + exportJson: () => Promise + importJson: () => Promise<{ questions: QuestionItem[]; currentIndex: number } | null> } template: { list: () => Promise