Files
d1kt/server/utils/vocabularyAuditFilters.ts
2026-06-13 10:58:53 +08:00

53 lines
1.5 KiB
TypeScript

const escapeRegex = (value: string): string => value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
const parseOptionalPositiveInt = (value: unknown, fieldName: string) => {
const raw = String(value ?? '').trim();
if (!raw) return { value: undefined as number | undefined };
if (!/^\d+$/.test(raw)) {
return { error: `${fieldName}必须是正整数` };
}
const parsed = Number(raw);
if (!Number.isFinite(parsed) || parsed <= 0) {
return { error: `${fieldName}必须大于0` };
}
return { value: parsed };
};
export const buildVocabularySummaryFilters = (query: Record<string, any>) => {
const studentNo = String(query.studentNo || '').trim();
const rawMinUniqueWords = query.minUniqueWords ?? query.minCorrectWords ?? query.minWords;
const wordCountResult = parseOptionalPositiveInt(rawMinUniqueWords, '去重单词数量');
if ('error' in wordCountResult) return { error: wordCountResult.error };
const minUniqueWords = wordCountResult.value;
const userMatchStages = studentNo
? [{
$match: {
'user.username': {
$regex: escapeRegex(studentNo),
$options: 'i'
}
}
}]
: [];
const baseMatch: Record<string, any> = {};
return {
minUniqueWords,
userMatchStages,
baseMatch
};
};
export const applyVocabularySummaryItemFilters = <T extends { uniqueWords?: number }>(
items: T[],
minUniqueWords?: number
): T[] => {
if (typeof minUniqueWords !== 'number') return items;
return items.filter(item => Number(item.uniqueWords || 0) >= minUniqueWords);
};