feat: 历史记录增强+IPC响应式Proxy修复+水印异常处理

This commit is contained in:
2026-07-16 12:55:44 +08:00
parent 08a831b806
commit cc0f80d020
7 changed files with 391 additions and 44 deletions
+66 -16
View File
@@ -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', () => {
+2 -1
View File
@@ -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: {