53 lines
1.5 KiB
TypeScript
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);
|
|
};
|