add more info of AdminVocabularyAudit

This commit is contained in:
2026-05-27 08:29:50 +08:00
parent 0ec12aa0ca
commit 37e4837e3f
4 changed files with 1006 additions and 34 deletions

View File

@@ -102,10 +102,16 @@ export interface VocabularyPassSummaryItem {
passedWords: number;
uniqueWords: number;
testRecords: number;
totalRecords?: number;
validRecords?: number;
invalidatedRecords?: number;
wordSets: number;
testTypes: string[];
riskFlags?: string[];
firstPassedAt: string;
lastPassedAt: string;
firstRecordAt?: string;
lastRecordAt?: string;
}
export interface VocabularyPassSummaryResponse {
@@ -113,6 +119,8 @@ export interface VocabularyPassSummaryResponse {
end: string;
totalStudents: number;
totalPassedWords: number;
totalRecords?: number;
invalidatedRecords?: number;
items: VocabularyPassSummaryItem[];
}
@@ -127,6 +135,124 @@ export interface ClearVocabularyPassSummaryResponse {
rebuiltWords: number;
}
export interface VocabularyAuditWordBrief {
_id: string;
word?: string;
translation?: string;
pronunciation?: string;
example?: string;
}
export interface VocabularyAuditUserBrief {
_id?: string;
userId?: string;
username?: string;
fullname?: string;
email?: string;
}
export interface VocabularyAuditInteractionSummary {
keyCount: number;
inputCount: number;
pasteCount: number;
focusCount: number;
blurCount: number;
pointerCount: number;
firstEventOffset: number;
lastEventOffset: number;
}
export interface VocabularyAuditResultDetail {
index: number;
wordId: string;
word: VocabularyAuditWordBrief | null;
userAnswer: string;
correctAnswer: string;
isCorrect: boolean;
}
export interface VocabularyAuditAnswerDetail extends VocabularyAuditResultDetail {
questionToken: string;
submittedAt?: string;
duration?: number;
riskFlags: string[];
interactionSummary?: VocabularyAuditInteractionSummary | null;
}
export interface VocabularyAuditAttemptDetail {
attemptId: string;
status: string;
testType: string;
wordSetId: string;
issuedAt?: string;
expiresAt?: string;
submittedAt?: string;
riskFlags: string[];
reviewDecision?: string;
reviewedAt?: string;
reviewedBy?: VocabularyAuditUserBrief | null;
reviewNote?: string;
questionWordIds: string[];
questionTokens: string[];
optionTokens: string[][];
optionTexts: string[][];
answeredQuestionTokens: string[];
answerDurations: number[];
answers: VocabularyAuditAnswerDetail[];
}
export interface VocabularyAuditRecordDetail {
recordId: string;
attemptId: string;
wordSet: {
_id: string;
name?: string;
description?: string;
} | null;
testType: string;
stats: {
totalWords: number;
correctWords: number;
accuracy: number;
startTime: string;
endTime: string;
duration: number;
};
invalidated: boolean;
riskFlags: string[];
reviewDecision?: string;
reviewedAt?: string;
reviewedBy?: VocabularyAuditUserBrief | null;
reviewNote?: string;
createdAt: string;
results: VocabularyAuditResultDetail[];
attempt: VocabularyAuditAttemptDetail | null;
}
export interface VocabularyPassSummaryDetailsResponse {
start: string;
end: string;
user: VocabularyAuditUserBrief;
totalRecords: number;
totalPassedWords: number;
invalidatedRecords: number;
approvedRecords: number;
records: VocabularyAuditRecordDetail[];
}
export interface ApproveVocabularyTestRecordResponse {
message: string;
recordId: string;
attemptId?: string;
totalWords?: number;
correctWords?: number;
accuracy?: number;
riskFlags?: string[];
affectedWords?: number;
rebuiltWords?: number;
alreadyEffective?: boolean;
}
export const adminApi = {
getUsers: async (): Promise<User[]> => {
return api.get<User[]>('/admin/users');
@@ -217,4 +343,13 @@ export const adminApi = {
clearVocabularyPassSummary: async (data: { userId: string; start: string; end: string }): Promise<ClearVocabularyPassSummaryResponse> => {
return api.post<ClearVocabularyPassSummaryResponse>('/admin/vocabulary/test-pass-summary/clear', data);
},
getVocabularyPassSummaryDetails: async (params: { userId: string; start: string; end: string }): Promise<VocabularyPassSummaryDetailsResponse> => {
const { userId, ...query } = params;
return api.get<VocabularyPassSummaryDetailsResponse>(`/admin/vocabulary/test-pass-summary/${userId}/details`, { params: query });
},
approveVocabularyTestRecord: async (recordId: string, data: { note?: string } = {}): Promise<ApproveVocabularyTestRecordResponse> => {
return api.post<ApproveVocabularyTestRecordResponse>(`/admin/vocabulary/test-records/${recordId}/approve`, data);
},
};