Files
2026-08-25 15:40:38 +08:00

743 lines
26 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { CATEGORY_LIST } from '../../core/data/categories';
export type CategoryItem = {
id: string;
title: string;
subtitle: string;
icon?: string;
/** 无图时在列表中用 icon 占位 */
previewImg?: string;
ageBand: string;
ageMin?: number;
ageMax?: number;
difficulty: 1 | 2 | 3 | 4;
difficultyLabel: string;
path: string;
available: boolean;
likes: number;
downloads: number;
/** 列表底部展示的日期(静态数据用 id 派生稳定值) */
date: string;
/** 最后更新时间(云端数据用于排序) */
updatedAt?: string;
};
export type CategoryGroup = {
id: string;
name: string;
icon: string;
items: CategoryItem[];
};
export type CategoryDataset = {
searchPlaceholder: string;
categories: CategoryGroup[];
};
const DIFFICULTY_LABELS: Record<CategoryItem['difficulty'], string> = {
1: '入门',
2: '基础',
3: '进阶',
4: '挑战',
};
function age(min: number, max: number): string {
return `${min}-${max}岁`;
}
/** 基于 id 生成稳定的伪随机统计数 */
function statsFromId(id: string): { likes: number; downloads: number } {
let h = 0;
for (let i = 0; i < id.length; i++) h = (h * 31 + id.charCodeAt(i)) | 0;
const likes = 100 + Math.abs(h % 900);
const downloads = 20 + Math.abs((h >>> 4) % 200);
return { likes, downloads };
}
function dateFromId(id: string): string {
let h = 0;
for (let i = 0; i < id.length; i++) h = (h * 31 + id.charCodeAt(i)) | 0;
const days = Math.abs(h % 500);
const d = new Date('2024-01-01');
d.setDate(d.getDate() + days);
return d.toISOString().slice(0, 10);
}
type ItemInput = Omit<
CategoryItem,
'likes' | 'downloads' | 'date' | 'difficultyLabel'
>;
function item(input: ItemInput): CategoryItem {
const { likes, downloads } = statsFromId(input.id);
return {
...input,
likes,
downloads,
date: dateFromId(input.id),
difficultyLabel: DIFFICULTY_LABELS[input.difficulty],
};
}
/** 目前只作为兜底数据 */
const CATEGORY_ITEMS_BY_ID: Record<string, CategoryItem[]> = {
math: [
item({
id: 'number-find',
title: '找数字,涂一涂',
subtitle: '在数字方阵中找出目标数字并涂色',
icon: '🔍',
previewImg: '/assets/entrancePicture/math/number-find.png',
ageBand: age(3, 5),
difficulty: 1,
path: '/mathPages/mathDraw/mathDraw?id=number-find',
available: true,
}),
item({
id: 'number-write',
title: '看数字,写一写',
subtitle: '按笔画顺序练习书写数字',
icon: '✏️',
previewImg: '/assets/entrancePicture/math/number-write.png',
ageBand: age(3, 5),
difficulty: 1,
path: '/mathPages/mathDraw/mathDraw?id=number-write',
available: true,
}),
item({
id: 'number-coloring',
title: '按数字,涂颜色',
subtitle: '按指定数字给对应圆圈涂色',
icon: '🎨',
previewImg: '/assets/entrancePicture/math/number-coloring.png',
ageBand: age(3, 5),
difficulty: 1,
path: '/mathPages/mathDraw/mathDraw?id=number-coloring',
available: true,
}),
item({
id: 'counting-matching',
title: '数一数,连一连',
subtitle: '连线配对数字和对应数量图形',
icon: '🔗',
previewImg: '/assets/entrancePicture/math/count-match.png',
ageBand: age(3, 5),
difficulty: 1,
path: '/mathPages/mathDraw/mathDraw?id=counting-matching',
available: true,
}),
item({
id: 'number-object-match',
title: '数物连线',
subtitle: '连线相同数量的物品和数字',
icon: '🔗',
previewImg: '/assets/entrancePicture/math/number-object-match.png',
ageBand: age(3, 5),
difficulty: 1,
path: '/mathPages/mathDraw/mathDraw?id=number-object-match',
available: true,
}),
item({
id: 'number-object-fill',
title: '数物填写',
subtitle: '数物品数量,填写对应数字',
icon: '✏️',
previewImg: '/assets/entrancePicture/math/number-object-fill.png',
ageBand: age(3, 5),
difficulty: 1,
path: '/mathPages/mathDraw/mathDraw?id=number-object-fill',
available: true,
}),
item({
id: 'counting-select',
title: '数一数,选一选',
subtitle: '数出物品数量,圈出正确答案',
icon: '✓',
previewImg: '/assets/entrancePicture/math/counting-select.png',
ageBand: age(3, 5),
difficulty: 1,
path: '/mathPages/mathDraw/mathDraw?id=counting-select',
available: true,
}),
item({
id: 'counting-fill',
title: '数一数,填一填',
subtitle: '数出物品数量,填写数字',
icon: '✏️',
previewImg: '/assets/entrancePicture/math/counting-fill.png',
ageBand: age(3, 5),
difficulty: 1,
path: '/mathPages/mathDraw/mathDraw?id=counting-fill',
available: true,
}),
item({
id: 'compare',
title: '数一数,比大小',
subtitle: '比较数量,填入 ><=',
icon: '⚖️',
previewImg: '/assets/entrancePicture/math/compare.png',
ageBand: age(4, 6),
difficulty: 2,
path: '/mathPages/mathDraw/mathDraw?id=compare',
available: true,
}),
item({
id: 'number-sort',
title: '数字排序',
subtitle: '写出正确的数字顺序',
icon: '🔢',
previewImg: '/assets/entrancePicture/math/number-sort.png',
ageBand: age(4, 6),
difficulty: 2,
path: '/mathPages/mathDraw/mathDraw?id=number-sort',
available: true,
}),
item({
id: 'missing-number',
title: '填上缺少的数字',
subtitle: '在数列中找出并填写缺失数字',
icon: '❓',
previewImg: '/assets/entrancePicture/math/missing-number.png',
ageBand: age(4, 6),
difficulty: 2,
path: '/mathPages/mathDraw/mathDraw?id=missing-number',
available: true,
}),
item({
id: 'number-decompose',
title: '10以内数的分与合',
subtitle: '把数字分一分,合一合',
icon: '🔢',
previewImg: '/assets/entrancePicture/math/number-decompose.png',
ageBand: age(4, 6),
difficulty: 1,
path: '/mathPages/mathDraw/mathDraw?id=number-decompose',
available: true,
}),
item({
id: 'number-decompose-20',
title: '20以内数的分与合',
subtitle: '把数字分一分,合一合',
icon: '🔢',
previewImg: '/assets/entrancePicture/math/number-decompose-20.png',
ageBand: age(5, 7),
difficulty: 2,
path: '/mathPages/mathDraw/mathDraw?id=number-decompose-20',
available: true,
}),
item({
id: 'one-digit-addition',
title: '一位数加法',
subtitle: '通过圆点学习一位数加法运算',
icon: '',
previewImg: '/assets/entrancePicture/math/one-digit-addition.png',
ageBand: age(4, 6),
difficulty: 2,
path: '/mathPages/mathDraw/mathDraw?id=one-digit-addition',
available: true,
}),
item({
id: 'addition-5',
title: '5以内加法',
subtitle: '图形化展示 5 以内加法',
icon: '',
previewImg: '/assets/entrancePicture/math/addition-5.png',
ageBand: age(3, 5),
difficulty: 1,
path: '/mathPages/mathDraw/mathDraw?id=addition-5',
available: true,
}),
item({
id: 'addition-10',
title: '10以内加法',
subtitle: '图形化展示 10 以内加法',
icon: '',
previewImg: '/assets/entrancePicture/math/addition-10.png',
ageBand: age(4, 6),
difficulty: 2,
path: '/mathPages/mathDraw/mathDraw?id=addition-10',
available: true,
}),
item({
id: 'subtraction-10',
title: '10以内减法',
subtitle: '图形化展示 10 以内减法',
icon: '',
previewImg: '/assets/entrancePicture/math/subtraction-10.png',
ageBand: age(4, 6),
difficulty: 2,
path: '/mathPages/mathDraw/mathDraw?id=subtraction-10',
available: true,
}),
item({
id: 'addition-subtraction-10',
title: '10以内加减法',
subtitle: '加减法混合运算',
icon: '±',
previewImg:
'/assets/entrancePicture/math/addition-subtraction-10.png',
ageBand: age(5, 7),
difficulty: 2,
path: '/mathPages/mathDraw/mathDraw?id=addition-subtraction-10',
available: true,
}),
item({
id: 'make-ten',
title: '凑十法练习',
subtitle: '20 以内进位加法',
icon: '',
previewImg: '/assets/entrancePicture/math/make-ten.png',
ageBand: age(5, 7),
difficulty: 3,
path: '/mathPages/mathDraw/mathDraw?id=make-ten',
available: true,
}),
item({
id: 'break-ten',
title: '破十法练习',
subtitle: '20 以内退位减法',
icon: '',
previewImg: '/assets/entrancePicture/math/break-ten.png',
ageBand: age(5, 7),
difficulty: 3,
path: '/mathPages/mathDraw/mathDraw?id=break-ten',
available: true,
}),
item({
id: 'flat-ten',
title: '平十法练习',
subtitle: '20 以内退位减法',
icon: '',
previewImg: '/assets/entrancePicture/math/flat-ten.png',
ageBand: age(5, 7),
difficulty: 3,
path: '/mathPages/mathDraw/mathDraw?id=flat-ten',
available: true,
}),
item({
id: 'borrow-ten',
title: '借十法练习',
subtitle: '20 以上退位减法',
icon: '',
previewImg: '/assets/entrancePicture/math/borrow-ten.png',
ageBand: age(6, 8),
difficulty: 4,
path: '/mathPages/mathDraw/mathDraw?id=borrow-ten',
available: true,
}),
item({
id: 'practice-addition',
title: '加法运算',
subtitle: '10/20/50/100 以内加法',
icon: '',
previewImg: '/assets/entrancePicture/math/practice-addition.png',
ageBand: age(5, 8),
difficulty: 3,
path: '/mathPages/mathDraw/mathDraw?id=practice-addition',
available: true,
}),
item({
id: 'practice-subtraction',
title: '减法运算',
subtitle: '10/20/50/100 以内减法',
icon: '',
previewImg: '/assets/entrancePicture/math/practice-subtraction.png',
ageBand: age(5, 8),
difficulty: 3,
path: '/mathPages/mathDraw/mathDraw?id=practice-subtraction',
available: true,
}),
item({
id: 'practice-mixed',
title: '混合运算',
subtitle: '10/20/50/100 以内加减法混合',
icon: '±',
previewImg: '/assets/entrancePicture/math/practice-mixed.png',
ageBand: age(5, 8),
difficulty: 3,
path: '/mathPages/mathDraw/mathDraw?id=practice-mixed',
available: true,
}),
item({
id: 'multiplication-table',
title: '九九乘法表',
subtitle: '学习九九乘法口诀',
icon: '✖️',
previewImg: '/assets/entrancePicture/math/multiplication-table.png',
ageBand: age(6, 8),
difficulty: 3,
path: '/mathPages/mathDraw/mathDraw?id=multiplication-table',
available: true,
}),
item({
id: 'clock-reading',
title: '认识钟表',
subtitle: '看钟读时间,填写数字时刻',
icon: '🕐',
ageBand: age(4, 7),
difficulty: 1,
path: '/mathPages/clockReading/clockReading?id=clock-reading',
available: true,
}),
],
pinyin: [
item({
id: 'pinyin-initials',
title: '声母描红',
subtitle: '23个声母认读与书写练习',
icon: '🔤',
ageBand: age(5, 7),
difficulty: 2,
path: '',
available: false,
}),
item({
id: 'pinyin-finals',
title: '韵母描红',
subtitle: '24个韵母认读与书写练习',
icon: '🔤',
ageBand: age(5, 7),
difficulty: 2,
path: '',
available: false,
}),
item({
id: 'pinyin-overall',
title: '整体认读音节',
subtitle: '16个整体认读音节练习',
icon: '🔤',
ageBand: age(5, 7),
difficulty: 3,
path: '',
available: false,
}),
],
puzzle: [
item({
id: 'color-shape-match',
title: '根据颜色画图形',
subtitle: '根据颜色画出对应图形',
icon: '🎯',
previewImg: '/assets/entrancePicture/focus/color-shape-match.png',
ageBand: age(4, 6),
difficulty: 2,
path: '/focusPages/focusDraw/focusDraw?id=color-shape-match',
available: true,
}),
item({
id: 'shape-symbol',
title: '图形符号配对',
subtitle: '根据图形画对应符号',
icon: '🔗',
previewImg: '/assets/entrancePicture/focus/shape-symbol.png',
ageBand: age(4, 6),
difficulty: 2,
path: '/focusPages/focusDraw/focusDraw?id=shape-symbol',
available: true,
}),
item({
id: 'shape-recognition',
title: '识别形状',
subtitle: '识别形状,涂一涂',
icon: '🔍',
previewImg: '/assets/entrancePicture/focus/shape-recognition.png',
ageBand: age(3, 5),
difficulty: 1,
path: '/focusPages/focusDraw/focusDraw?id=shape-recognition',
available: true,
}),
item({
id: 'position-coloring',
title: '方位涂涂乐',
subtitle: '观察位置,在方格中涂色',
icon: '📍',
previewImg: '/assets/entrancePicture/focus/position-coloring.png',
ageBand: age(4, 6),
difficulty: 2,
path: '/focusPages/focusDraw/focusDraw?id=position-coloring',
available: true,
}),
item({
id: 'color-pattern',
title: '颜色找规律',
subtitle: '观察颜色规律,在空白图形中涂色',
icon: '🎨',
previewImg: '/assets/entrancePicture/focus/color-pattern.png',
ageBand: age(4, 6),
difficulty: 2,
path: '/focusPages/focusDraw/focusDraw?id=color-pattern',
available: true,
}),
item({
id: 'match-connect',
title: '连连看',
subtitle: '根据物品连一连',
icon: '🔗',
previewImg: '/assets/entrancePicture/focus/match-connect.png',
ageBand: age(3, 6),
difficulty: 1,
path: '/focusPages/focusDraw/focusDraw?id=match-connect',
available: true,
}),
item({
id: 'line-recognition',
title: '线条识别',
subtitle: '认识不同线条,画出颜色对应的线条',
icon: '📏',
previewImg: '/assets/entrancePicture/focus/line-recognition.png',
ageBand: age(3, 5),
difficulty: 1,
path: '/focusPages/focusDraw/focusDraw?id=line-recognition',
available: true,
}),
item({
id: 'grid-reasoning',
title: '方格推理',
subtitle: '推理出合并方格并连线',
icon: '🧩',
previewImg: '/assets/entrancePicture/focus/grid-reasoning.png',
ageBand: age(5, 7),
difficulty: 3,
path: '/focusPages/focusDraw/focusDraw?id=grid-reasoning',
available: true,
}),
item({
id: 'code-connect',
title: '译码连线',
subtitle: '按数字顺序将数字对应颜色连线',
icon: '🔢',
previewImg: '/assets/entrancePicture/focus/code-connect.png',
ageBand: age(5, 7),
difficulty: 3,
path: '/focusPages/focusDraw/focusDraw?id=code-connect',
available: true,
}),
item({
id: 'dot-connect',
title: '数字点连线',
subtitle: '按数字顺序连点成图',
icon: '🔗',
previewImg: '/assets/entrancePicture/focus/dot-connect.png',
ageBand: age(3, 6),
difficulty: 1,
path: '/focusPages/focusDraw/focusDraw?id=dot-connect',
available: true,
}),
item({
id: 'grid-drawing-3x3',
title: '格子仿画 3×3',
subtitle: '简单有趣,培养专注力',
icon: '🎨',
previewImg: '/assets/entrancePicture/focus/grid-drawing-3x3.png',
ageBand: age(3, 5),
difficulty: 1,
path: '/focusPages/focusDraw/focusDraw?id=grid-drawing-3x3',
available: true,
}),
item({
id: 'grid-drawing-5x5',
title: '格子仿画 5×5',
subtitle: '创意挑战,提升观察力',
icon: '🎨',
previewImg: '/assets/entrancePicture/focus/grid-drawing-5x5.png',
ageBand: age(4, 6),
difficulty: 2,
path: '/focusPages/focusDraw/focusDraw?id=grid-drawing-5x5',
available: true,
}),
item({
id: 'grid-drawing-7x7',
title: '格子仿画 7×7',
subtitle: '大师挑战,锻炼耐心',
icon: '🎨',
previewImg: '/assets/entrancePicture/focus/grid-drawing-7x7.png',
ageBand: age(5, 8),
difficulty: 3,
path: '/focusPages/focusDraw/focusDraw?id=grid-drawing-7x7',
available: true,
}),
],
chinese: [
item({
id: 'word-recognition',
title: '识字卡',
subtitle: '输入或选字生成涂色识字卡',
icon: '📖',
ageBand: age(3, 6),
difficulty: 1,
path: '/pages/index/index',
available: true,
}),
item({
id: 'copybook',
title: '练字帖',
subtitle: '选字生成田字格笔顺练字帖',
icon: '✏️',
ageBand: age(4, 7),
difficulty: 2,
path: '/pages/copyBook/copyBook',
available: true,
}),
item({
id: 'pen-control-mix',
title: '控笔组合练习',
subtitle: '3–6 种图形,每种占两行田字格',
icon: '✍️',
ageBand: age(3, 6),
difficulty: 1,
path: '/chinesePages/penControlSheet/penControlSheet?id=pen-control-mix',
available: true,
}),
],
english: [
item({
id: 'letter-tracing-single',
title: '看图描红',
subtitle: '单字母配图、例句与六行四线三格描红',
icon: '🔠',
previewImg:
'/assets/entrancePicture/english/letter-tracing-single.jpg',
ageBand: age(4, 7),
difficulty: 1,
path: '/englishPages/letterTracing/letterTracing?id=letter-tracing-single',
available: true,
}),
item({
id: 'letter-tracing-single2',
title: '看图描红',
subtitle: '单字母配图、例句与六行四线三格描红',
icon: '🔠',
previewImg:
'/assets/entrancePicture/english/letter-tracing-single2.jpg',
ageBand: age(4, 7),
difficulty: 1,
path: '/englishPages/letterTracing/letterTracing?id=letter-tracing-single',
available: true,
}),
item({
id: 'letter-tracing-upper-lower',
title: '字母总览',
subtitle: 'Uppercase / Lowercase 分区总览',
icon: '🔡',
previewImg:
'/assets/entrancePicture/english/letter-tracing-upper-lower.jpg',
ageBand: age(4, 7),
difficulty: 1,
path: '/englishPages/letterTracing/letterTracing?id=letter-tracing-upper-lower',
available: true,
}),
item({
id: 'letter-tracing-case-pairing',
title: '大小写练习',
subtitle: '半组字母左大写右小写,逐行对照描红',
icon: '✏️',
previewImg:
'/assets/entrancePicture/english/letter-tracing-case-pairing.jpg',
ageBand: age(4, 7),
difficulty: 1,
path: '/englishPages/letterTracing/letterTracing?id=letter-tracing-case-pairing',
available: true,
}),
item({
id: 'letter-tracing-two-column',
title: '两列练习',
subtitle: '左 A-M、右 N-Z,大小写配对描红',
icon: '🔤',
previewImg:
'/assets/entrancePicture/english/letter-tracing-two-column.jpg',
ageBand: age(4, 7),
difficulty: 1,
path: '/englishPages/letterTracing/letterTracing?id=letter-tracing-two-column',
available: true,
}),
item({
id: 'letter-tracing-half',
title: '单字母逐行',
subtitle: '13 字母半表逐字练习',
icon: '📝',
previewImg:
'/assets/entrancePicture/english/letter-tracing-half.jpg',
ageBand: age(4, 7),
difficulty: 2,
path: '/englishPages/letterTracing/letterTracing?id=letter-tracing-half',
available: true,
}),
item({
id: 'letter-tracing-three',
title: '三字母精练',
subtitle: '每页 3 个字母,大写 + 小写深度书写',
icon: '🔤',
previewImg:
'/assets/entrancePicture/english/letter-tracing-three.jpg',
ageBand: age(4, 7),
difficulty: 2,
path: '/englishPages/letterTracing/letterTracing?id=letter-tracing-three',
available: true,
}),
item({
id: 'letter-tracing-daily-checkin',
title: '每日打卡',
subtitle: '四宫格每日字母打卡练习',
icon: '🔤',
previewImg:
'/assets/entrancePicture/english/letter-tracing-daily-checkin.jpg',
ageBand: age(4, 7),
difficulty: 2,
path: '/englishPages/letterTracing/letterTracing?id=letter-tracing-daily-checkin',
available: true,
}),
],
papers: [
item({
id: 'paper-sheet',
title: '作业纸',
subtitle: '田字格 / 方格 / 信纸等多种作业纸一键打印',
icon: '📄',
ageBand: age(3, 12),
difficulty: 1,
path: '/papersPages/paperSheet/paperSheet?id=paper-sheet',
available: true,
}),
],
craft: [
item({
id: 'craft-coloring',
title: '涂色卡',
subtitle: '动物、交通、节日主题涂色',
icon: '🎨',
ageBand: age(3, 6),
difficulty: 1,
path: '',
available: false,
}),
item({
id: 'craft-origami',
title: '折纸模板',
subtitle: '打印后即可折叠的趣味模板',
icon: '🪭',
ageBand: age(4, 7),
difficulty: 2,
path: '',
available: false,
}),
item({
id: 'craft-stickers',
title: '贴纸打印',
subtitle: '奖励贴纸与装饰贴纸',
icon: '⭐',
ageBand: age(3, 8),
difficulty: 1,
path: '',
available: false,
}),
],
};
export const CATEGORY_DATA: CategoryDataset = {
searchPlaceholder: '搜索练习纸...',
categories: CATEGORY_LIST.map((category) => ({
...category,
items: CATEGORY_ITEMS_BY_ID[category.id] ?? [],
})),
};