feat: 新增控笔练习,增加首页公告

This commit is contained in:
R524809
2026-05-29 10:21:39 +08:00
parent 2f0c4ab591
commit a6e8f4df02
28 changed files with 1045 additions and 672 deletions
@@ -1,8 +1,13 @@
import { MOCK_SEED_COUNTS } from './mockLikes';
import { MATH_WORKSHEET_DEFINITIONS } from '../../mathPages/mathDraw/mathDraw.config';
import { FOCUS_WORKSHEET_DEFINITIONS } from '../../focusPages/focusDraw/focusDraw.config';
import { LETTER_TRACING_WORKSHEET_DEFINITIONS } from '../../englishPages/letterTracing/letterTracing.config';
import { PINYIN_DICTATION_MODE_OPTIONS } from '../../pinyinPages/pinyinDictation/pinyinDictation.config';
import {
MATH_WORKSHEET_DEFINITIONS,
FOCUS_WORKSHEET_DEFINITIONS,
LETTER_TRACING_WORKSHEET_DEFINITIONS,
PINYIN_DICTATION_WORKSHEET_DEFINITIONS,
PEN_CONTROL_WORKSHEET_DEFINITIONS,
WORD_COLORING_WORKSHEET_DEFINITIONS,
type WorksheetDefinition,
} from '../../config/worksheets';
type CloudFunctionResult<T> = {
success?: boolean;
@@ -25,13 +30,6 @@ async function callCloudFunction<T>(
return response.result || {};
}
type LocalDef = {
id: string;
ageMin: number;
ageMax: number;
tags: readonly string[];
};
function inferGradeFromAge(ageMin: number, ageMax: number): number {
const centerAge = Math.round((ageMin + ageMax) / 2);
const ageGradeMap: Record<number, number> = {
@@ -53,30 +51,38 @@ function inferGradeFromAge(ageMin: number, ageMax: number): number {
type ConfigSource = {
label: string;
data: readonly LocalDef[];
data: ReadonlyArray<WorksheetDefinition>;
};
const CONFIG_SOURCES: ConfigSource[] = [
{
label: 'math',
data: MATH_WORKSHEET_DEFINITIONS as unknown as LocalDef[],
data: MATH_WORKSHEET_DEFINITIONS,
},
{
label: 'focus',
data: FOCUS_WORKSHEET_DEFINITIONS as unknown as LocalDef[],
data: FOCUS_WORKSHEET_DEFINITIONS,
},
{
label: 'letterTracing',
data: LETTER_TRACING_WORKSHEET_DEFINITIONS as unknown as LocalDef[],
data: LETTER_TRACING_WORKSHEET_DEFINITIONS,
},
{
label: 'pinyin',
data: PINYIN_DICTATION_MODE_OPTIONS as unknown as LocalDef[],
data: PINYIN_DICTATION_WORKSHEET_DEFINITIONS,
},
{
label: 'penControl',
data: PEN_CONTROL_WORKSHEET_DEFINITIONS,
},
{
label: 'wordColoring',
data: WORD_COLORING_WORKSHEET_DEFINITIONS,
},
];
function isLocalDef(value: unknown): value is LocalDef {
const row = value as Partial<LocalDef>;
function isWorksheetDefinition(value: unknown): value is WorksheetDefinition {
const row = value as Partial<WorksheetDefinition>;
return (
!!row &&
typeof row.id === 'string' &&
@@ -86,22 +92,24 @@ function isLocalDef(value: unknown): value is LocalDef {
);
}
async function loadConfigSource(source: ConfigSource): Promise<LocalDef[]> {
async function loadConfigSource(
source: ConfigSource,
): Promise<WorksheetDefinition[]> {
const rows = source.data;
if (!Array.isArray(rows) || !rows.every(isLocalDef)) {
if (!Array.isArray(rows) || !rows.every(isWorksheetDefinition)) {
throw new Error(`${source.label} 配置格式不正确`);
}
return [...rows];
}
async function collectAll(): Promise<LocalDef[]> {
async function collectAll(): Promise<WorksheetDefinition[]> {
const groups = await Promise.all(CONFIG_SOURCES.map(loadConfigSource));
return groups.flat();
}
function assertUniqueIds(rows: LocalDef[]) {
function assertUniqueIds(rows: WorksheetDefinition[]) {
const set = new Set<string>();
for (const r of rows) {
if (set.has(r.id)) {