diff --git a/electron/main/ipc.ts b/electron/main/ipc.ts
index c9a793e..44d9d68 100644
--- a/electron/main/ipc.ts
+++ b/electron/main/ipc.ts
@@ -43,8 +43,31 @@ function getDb() {
ai_score REAL,
teacher_score REAL,
confidence REAL,
- created_at DATETIME DEFAULT CURRENT_TIMESTAMP
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
+ question_title TEXT DEFAULT '',
+ max_score REAL DEFAULT 100,
+ reference_answer TEXT DEFAULT '',
+ rubric TEXT DEFAULT '',
+ deductions TEXT DEFAULT '',
+ comment TEXT DEFAULT '',
+ result_json TEXT DEFAULT '',
+ image_data TEXT DEFAULT ''
)`).run()
+ // migrate: add columns for existing DBs
+ const migrateCols: { name: string; type: string }[] = [
+ { name: 'question_title', type: 'TEXT DEFAULT \'\'' },
+ { name: 'max_score', type: 'REAL DEFAULT 100' },
+ { name: 'reference_answer', type: 'TEXT DEFAULT \'\'' },
+ { name: 'rubric', type: 'TEXT DEFAULT \'\'' },
+ { name: 'deductions', type: 'TEXT DEFAULT \'\'' },
+ { name: 'comment', type: 'TEXT DEFAULT \'\'' },
+ { name: 'result_json', type: 'TEXT DEFAULT \'\'' },
+ { name: 'image_data', type: 'TEXT DEFAULT \'\'' },
+ { name: 'reference_answer_image', type: 'TEXT DEFAULT \'\'' }
+ ]
+ for (const col of migrateCols) {
+ try { db.prepare(`ALTER TABLE history ADD COLUMN ${col.name} ${col.type}`).run() } catch (_) {}
+ }
db.prepare(`CREATE TABLE IF NOT EXISTS exam (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT,
@@ -180,6 +203,15 @@ export function setupIpc(win: BrowserWindow): void {
}
})
+ ipcMain.handle('history:getById', (_event, id: number) => {
+ try {
+ const record = getDb().prepare('SELECT * FROM history WHERE id = ?').get(id) as any
+ return record || null
+ } catch {
+ return null
+ }
+ })
+
ipcMain.handle('grading:submit', (_event, data: {
questionId: number
imagePath: string
@@ -187,22 +219,40 @@ export function setupIpc(win: BrowserWindow): void {
teacherScore: number
confidence: number
studentAnswer?: string
+ questionTitle?: string
+ maxScore?: number
+ referenceAnswer?: string
+ rubric?: string
+ deductions?: string[]
+ comment?: string
+ resultJson?: string
+ imageData?: string
+ referenceAnswerImage?: string
}) => {
- try {
- getDb().prepare(`INSERT INTO history (question_id, image_path, student_answer, ai_score, teacher_score, confidence)
- VALUES (?, ?, ?, ?, ?, ?)`).run(
- data.questionId || 0,
- data.imagePath || '',
- data.studentAnswer || '',
- data.aiScore,
- data.teacherScore,
- data.confidence
- )
- return true
- } catch (err) {
- log.error('grading:submit error:', err)
- return false
- }
+ log.info('grading:submit called', JSON.stringify({ ...data, imageData: data.imageData ? `len=${data.imageData.length}` : 'empty', referenceAnswerImage: data.referenceAnswerImage ? `len=${data.referenceAnswerImage.length}` : 'empty' }))
+ const deductionsStr = JSON.stringify(data.deductions || [])
+ getDb().prepare(`INSERT INTO history
+ (question_id, image_path, student_answer, ai_score, teacher_score, confidence,
+ question_title, max_score, reference_answer, rubric, deductions, comment, result_json, image_data,
+ reference_answer_image)
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(
+ data.questionId || 0,
+ data.imagePath || '',
+ data.studentAnswer || '',
+ data.aiScore,
+ data.teacherScore,
+ data.confidence,
+ data.questionTitle || '',
+ data.maxScore ?? 100,
+ data.referenceAnswer || '',
+ data.rubric || '',
+ deductionsStr,
+ data.comment || '',
+ data.resultJson || '',
+ data.imageData || '',
+ data.referenceAnswerImage || ''
+ )
+ return true
})
ipcMain.handle('template:list', () => {
diff --git a/electron/preload/preload.ts b/electron/preload/preload.ts
index 1911387..1265a7f 100644
--- a/electron/preload/preload.ts
+++ b/electron/preload/preload.ts
@@ -33,7 +33,8 @@ contextBridge.exposeInMainWorld('electronAPI', {
history: {
list: () => ipcRenderer.invoke('history:list'),
- delete: (id: number) => ipcRenderer.invoke('history:delete', id)
+ delete: (id: number) => ipcRenderer.invoke('history:delete', id),
+ getById: (id: number) => ipcRenderer.invoke('history:getById', id)
},
grading: {
diff --git a/src/components/FloatingToolbar.vue b/src/components/FloatingToolbar.vue
index 3245411..fef017f 100644
--- a/src/components/FloatingToolbar.vue
+++ b/src/components/FloatingToolbar.vue
@@ -76,8 +76,12 @@ onMounted(() => {
if (window.electronAPI) {
cleanupScreenshotListener = window.electronAPI.screenshot.onCompleted(async (base64: string) => {
if (!appStore.isGrading) {
- gradingStore.setImage(await addWatermark(base64, '学生答案'))
- startGrading()
+ try {
+ gradingStore.setImage(await addWatermark(base64, '学生答案'))
+ startGrading()
+ } catch (err) {
+ ElMessage.error('水印处理失败:' + (err as Error).message)
+ }
}
})
}
@@ -95,7 +99,12 @@ async function selectImage() {
if (!window.electronAPI) return
const data = await window.electronAPI.dialog.openImage()
if (data) {
- gradingStore.setImage(await addWatermark(data.base64, '学生答案'))
+ try {
+ gradingStore.setImage(await addWatermark(data.base64, '学生答案'))
+ } catch (err) {
+ ElMessage.error('水印处理失败:' + (err as Error).message)
+ return
+ }
startGrading()
}
}
diff --git a/src/components/ResultDrawer.vue b/src/components/ResultDrawer.vue
index fc2ae8c..694942f 100644
--- a/src/components/ResultDrawer.vue
+++ b/src/components/ResultDrawer.vue
@@ -6,8 +6,8 @@