From 31c435c4101a5bccee1d58bbf7f1c0b55db9ba84 Mon Sep 17 00:00:00 2001 From: brianling Date: Thu, 16 Jul 2026 05:44:44 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A4=9A=E9=A2=98=E7=9B=AE=E8=AF=84?= =?UTF-8?q?=E5=88=86=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/FloatingToolbar.vue | 68 +++++++------ src/components/ResultDrawer.vue | 150 ++++++++++++++++++++--------- src/components/RubricEditor.vue | 146 ++++++++++++++++++---------- src/stores/grading.ts | 11 ++- src/types/index.ts | 7 ++ 5 files changed, 257 insertions(+), 125 deletions(-) diff --git a/src/components/FloatingToolbar.vue b/src/components/FloatingToolbar.vue index 5c74039..f1cda4b 100644 --- a/src/components/FloatingToolbar.vue +++ b/src/components/FloatingToolbar.vue @@ -80,6 +80,28 @@ async function selectImage() { } } +async function gradeQuestion(questionIdx: number) { + const questions = gradingStore.questions + if (!questions.length) { + ElMessage.warning('请先在评分标准中添加题目') + return null + } + const q = questions[Math.min(questionIdx, questions.length - 1)] + const result = await window.electronAPI.ai.grade({ + imageBase64: gradingStore.currentImage, + rubric: q.rubric || `请根据答案内容评分,满分${q.maxScore}分`, + maxScore: q.maxScore, + referenceAnswer: q.referenceAnswer, + questionTitle: q.questionTitle, + apiConfig: { + apiKey: settingsStore.settings.apiKey, + baseUrl: settingsStore.settings.baseUrl, + model: settingsStore.settings.model + } + }) + return result +} + async function startGrading() { if (!gradingStore.currentImage) { ElMessage.info('请先截图或选择图片') @@ -91,44 +113,28 @@ async function startGrading() { return } + // load rubric data + const rubricData = await window.electronAPI?.rubric.getData() + const questions = rubricData?.questions?.length + ? JSON.parse(JSON.stringify(rubricData.questions)) + : [{ questionTitle: '', maxScore: 100, referenceAnswer: '', rubric: '' }] + gradingStore.setQuestions(questions) + gradingStore.setCurrentQuestionIndex(0) + appStore.isGrading = true try { - // load latest rubric data from main process (may have been updated by rubric dialog) - const rubricData = await window.electronAPI?.rubric.getData() - if (rubricData) { - if (rubricData.rubric) gradingStore.setRubric(rubricData.rubric) - if (rubricData.questionTitle) gradingStore.setQuestionTitle(rubricData.questionTitle) - if (rubricData.maxScore) gradingStore.setMaxScore(rubricData.maxScore) - if (rubricData.referenceAnswer) gradingStore.setReferenceAnswer(rubricData.referenceAnswer) - } - const result = await window.electronAPI.ai.grade({ - imageBase64: gradingStore.currentImage, - rubric: gradingStore.rubric || `请根据答案内容评分,满分${gradingStore.maxScore}分`, - maxScore: gradingStore.maxScore, - referenceAnswer: gradingStore.referenceAnswer, - questionTitle: gradingStore.questionTitle, - apiConfig: { - apiKey: settingsStore.settings.apiKey, - baseUrl: settingsStore.settings.baseUrl, - model: settingsStore.settings.model - } - }) + const q = questions[0] + const result = await gradeQuestion(0) + if (!result) return + gradingStore.setResult(result) if (window.electronAPI) { + // store grading data for result window await window.electronAPI.grading.storeData({ result, image: gradingStore.currentImage, - rubric: gradingStore.rubric, - questionTitle: gradingStore.questionTitle, - maxScore: gradingStore.maxScore, - referenceAnswer: gradingStore.referenceAnswer - }) - // also update rubric bridge - await window.electronAPI.rubric.storeData({ - questionTitle: gradingStore.questionTitle, - maxScore: gradingStore.maxScore, - referenceAnswer: gradingStore.referenceAnswer, - rubric: gradingStore.rubric + questions, + currentQuestionIndex: 0 }) await window.electronAPI.dialog.open('result') } diff --git a/src/components/ResultDrawer.vue b/src/components/ResultDrawer.vue index e1ce977..0bf2ed9 100644 --- a/src/components/ResultDrawer.vue +++ b/src/components/ResultDrawer.vue @@ -7,6 +7,19 @@
+
+ 上一题 + {{ currentIdx + 1 }} / {{ questions.length }} + {{ currentIdx === questions.length - 1 ? '回到首题' : '下一题' }} +
+ +
+ {{ currentQuestion.questionTitle }} +
+
+ 满分:{{ currentQuestion.maxScore }} +
+
{{ gradingStore.currentResult.score }}
建议分数
@@ -34,29 +47,18 @@
教师评分(可修改)
- +
教师评语
- +
@@ -65,23 +67,30 @@ + + \ No newline at end of file diff --git a/src/stores/grading.ts b/src/stores/grading.ts index 0a6c2c7..a653952 100644 --- a/src/stores/grading.ts +++ b/src/stores/grading.ts @@ -1,10 +1,12 @@ import { defineStore } from 'pinia' import { ref } from 'vue' -import type { GradeResult } from '@/types' +import type { GradeResult, QuestionItem } from '@/types' export const useGradingStore = defineStore('grading', () => { const currentImage = ref(null) const currentResult = ref(null) + const questions = ref([]) + const currentQuestionIndex = ref(0) const rubric = ref('') const questionTitle = ref('') const maxScore = ref(100) @@ -28,6 +30,9 @@ export const useGradingStore = defineStore('grading', () => { function setMaxScore(val: number) { maxScore.value = val } function setReferenceAnswer(val: string) { referenceAnswer.value = val } + function setQuestions(list: QuestionItem[]) { questions.value = list } + function setCurrentQuestionIndex(idx: number) { currentQuestionIndex.value = idx } + function reset() { currentImage.value = null currentResult.value = null @@ -38,6 +43,8 @@ export const useGradingStore = defineStore('grading', () => { return { currentImage, currentResult, + questions, + currentQuestionIndex, rubric, questionTitle, maxScore, @@ -50,6 +57,8 @@ export const useGradingStore = defineStore('grading', () => { setQuestionTitle, setMaxScore, setReferenceAnswer, + setQuestions, + setCurrentQuestionIndex, reset } }) diff --git a/src/types/index.ts b/src/types/index.ts index 49e83a3..93ad479 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,3 +1,10 @@ +export interface QuestionItem { + questionTitle: string + maxScore: number + referenceAnswer: string + rubric: string +} + export interface GradeResult { score: number confidence: number