feat: improve student practice experience

This commit is contained in:
Codex
2026-06-29 15:12:35 +08:00
parent 134f7830dd
commit b96897b2be
12 changed files with 443 additions and 63 deletions

View File

@@ -1065,6 +1065,20 @@ async function testCatalogAndLearning() {
});
assert.equal(answer.item?.isCorrect, false, 'wrong answer should be judged false');
const selfJudgedObjective = await request('/api/learning/answers', {
userId: false,
headers: { authorization: `Bearer ${freeLogin.session.token}` },
method: 'POST',
body: {
questionId: ids.question,
selectedOptions: ['0'],
selfJudgedCorrect: true,
practiceSessionId: freeSession.item.id,
},
expectStatus: 400,
});
assert.equal(selfJudgedObjective.code, 'SELF_JUDGMENT_NOT_ALLOWED', 'objective questions must not accept self judgment');
const staffSequentialSession = await request('/api/learning/practice-sessions', {
userId: TENANT_ADMIN_USER_ID,
method: 'POST',
@@ -1128,6 +1142,19 @@ async function testCatalogAndLearning() {
practiceSessionId: mockSession.item.id,
},
});
const subjectiveAnswer = await request('/api/learning/answers', {
userId: TENANT_ADMIN_USER_ID,
method: 'POST',
body: {
userId: TENANT_ADMIN_USER_ID,
questionId: ids.questionThree,
answerText: '已经对照参考答案完成自评',
selfJudgedCorrect: true,
practiceSessionId: mockSession.item.id,
},
});
assert.equal(subjectiveAnswer.item?.isCorrect, true, 'subjective self judgment should be persisted by backend');
assert.equal(subjectiveAnswer.item?.selfJudged, true, 'subjective answer response should mark self judgment');
const mockReport = await request('/api/learning/practice-sessions/submit', {
userId: TENANT_ADMIN_USER_ID,
@@ -1139,14 +1166,18 @@ async function testCatalogAndLearning() {
});
assert.equal(mockReport.item?.practiceSessionId, mockSession.item.id, 'mock submit should create a report for the session');
assert.equal(mockReport.item?.totalQuestions, 3, 'mock report should count session snapshot questions');
assert.equal(mockReport.item?.answeredCount, 2, 'mock report should count latest submitted answers');
assert.equal(mockReport.item?.correctCount, 1, 'mock report should count correct answers');
assert.equal(mockReport.item?.answeredCount, 3, 'mock report should count latest submitted answers');
assert.equal(mockReport.item?.correctCount, 2, 'mock report should count correct answers');
assert.equal(mockReport.item?.wrongCount, 1, 'mock report should count wrong answers');
assert.equal(mockReport.item?.unansweredCount, 1, 'mock report should count unanswered questions');
assert.equal(mockReport.item?.score, 2, 'mock report should use backend scoring only');
assert.equal(mockReport.item?.unansweredCount, 0, 'mock report should count unanswered questions');
assert.equal(mockReport.item?.score, 4, 'mock report should use backend scoring only');
assert.equal(mockReport.item?.totalScore, 100, 'mock report should keep configured paper total score');
assert.ok(mockReport.item?.wrongQuestionIds?.includes(ids.questionTwo), 'mock report should include wrong question ids');
assert.ok(mockReport.item?.questionResults?.some(item => item.questionId === ids.question && item.isCorrect === true), 'mock report should include per-question result');
assert.ok(
mockReport.item?.questionResults?.some(item => item.questionId === ids.questionThree && item.isCorrect === true && item.answerText === '已经对照参考答案完成自评'),
'mock report should include backend-persisted subjective self judgment',
);
const idempotentReport = await request('/api/learning/practice-sessions/submit', {
userId: TENANT_ADMIN_USER_ID,