feat: 完成分龄页开发

This commit is contained in:
R524809
2026-05-06 17:28:51 +08:00
parent 50394154f7
commit 9bdf850f20
54 changed files with 3499 additions and 1021 deletions
+557
View File
@@ -0,0 +1,557 @@
import type { AgeBandKey } from '../../core/data/difficulty';
export type AbilityItem = {
icon: string;
title: string;
desc: string;
};
/** 每周练习项:与云 / page-config 中 worksheet 字段对齐,便于跳转 */
export type WeekExercise = {
/** 与云数据库 worksheets._id、page-config category.items[].id 一致 */
_id: string;
title: string;
subtitle: string;
/** 小程序内路径,可含 query,如 /mathPages/mathDraw/mathDraw?id=xxx */
path: string;
};
export type WeekPlan = {
week: number;
theme: string;
exercises: WeekExercise[];
};
export const AGE_TAB_SUB: Record<AgeBandKey, string> = {
'3-4': '启蒙认知',
'4-5': '基础练习',
'5-6': '能力提升',
'6-7': '幼小衔接',
'7-8': '知识拓展',
};
/** 各年龄段能力目标(初版,可由 AI Skill 更新) */
export const AGE_ABILITIES: Record<AgeBandKey, AbilityItem[]> = {
'3-4': [
{ icon: '🔢', title: '数感', desc: '认读 1-5、点数对应' },
{ icon: '✏️', title: '书写', desc: '涂鸦线条、简单描红' },
{ icon: '🧩', title: '思维', desc: '找相同、简单配对' },
],
'4-5': [
{ icon: '🔢', title: '数感', desc: '10 以内数数、比大小' },
{ icon: '✏️', title: '书写', desc: '笔画模仿、图形描边' },
{ icon: '🧩', title: '思维', desc: '规律排序、图形分类' },
],
'5-6': [
{ icon: '🔢', title: '数感', desc: '10以内加减法、凑十法' },
{ icon: '✏️', title: '书写', desc: '练字帖、拼音入门' },
{ icon: '🧩', title: '思维', desc: '方格推理、格子仿画 5×5' },
],
'6-7': [
{ icon: '🔢', title: '数感', desc: '20 以内运算、应用题启蒙' },
{ icon: '✏️', title: '书写', desc: '常用字书写、词语积累' },
{ icon: '🧩', title: '思维', desc: '逻辑填空、空间想象' },
],
'7-8': [
{ icon: '🔢', title: '数感', desc: '乘除启蒙、巧算练习' },
{ icon: '✏️', title: '书写', desc: '段落抄写、古诗诵读' },
{ icon: '🧩', title: '思维', desc: '数独入门、综合推理' },
],
};
/**
* 4 周路线(初版):每项含 _id / subtitle / path,与线上 worksheet 或本地分类兜底一致。
* AI Skill 生成时应从 .cache/page-config.json 的 category.items[] 复制 id→_id、title、subtitle、path。
*/
export const AGE_WEEK_PLANS: Record<AgeBandKey, WeekPlan[]> = {
'3-4': [
{
week: 1,
theme: '数感启蒙',
exercises: [
{
_id: 'number-find',
title: '找数字,涂一涂',
subtitle: '在数字方阵中找出目标数字并涂色',
path: '/mathPages/mathDraw/mathDraw?id=number-find',
},
{
_id: 'addition-5',
title: '5以内加法',
subtitle: '图形化展示 5 以内加法',
path: '/mathPages/mathDraw/mathDraw?id=addition-5',
},
{
_id: 'counting-matching',
title: '数一数,连一连',
subtitle: '连线配对数字和对应数量图形',
path: '/mathPages/mathDraw/mathDraw?id=counting-matching',
},
],
},
{
week: 2,
theme: '形状与连线',
exercises: [
{
_id: 'shape-recognition',
title: '识别形状',
subtitle: '识别形状,涂一涂',
path: '/focusPages/focusDraw/focusDraw?id=shape-recognition',
},
{
_id: 'line-recognition',
title: '线条识别',
subtitle: '认识不同线条,画出颜色对应的线条',
path: '/focusPages/focusDraw/focusDraw?id=line-recognition',
},
{
_id: 'dot-connect',
title: '数字点连线',
subtitle: '按数字顺序连点成图',
path: '/focusPages/focusDraw/focusDraw?id=dot-connect',
},
],
},
{
week: 3,
theme: '趣味专注',
exercises: [
{
_id: 'color-pattern',
title: '颜色找规律',
subtitle: '观察颜色规律,在空白图形中涂色',
path: '/focusPages/focusDraw/focusDraw?id=color-pattern',
},
{
_id: 'grid-drawing-3x3',
title: '格子仿画 3×3',
subtitle: '简单有趣,培养专注力',
path: '/focusPages/focusDraw/focusDraw?id=grid-drawing-3x3',
},
{
_id: 'match-connect',
title: '连连看',
subtitle: '根据物品连一连',
path: '/focusPages/focusDraw/focusDraw?id=match-connect',
},
],
},
{
week: 4,
theme: '综合练习',
exercises: [
{
_id: 'addition-10',
title: '10以内加法',
subtitle: '图形化展示 10 以内加法',
path: '/mathPages/mathDraw/mathDraw?id=addition-10',
},
{
_id: 'word-recognition',
title: '识字卡',
subtitle: '输入或选字生成涂色识字卡',
path: '/pages/index/index',
},
{
_id: 'number-coloring',
title: '按数字,涂颜色',
subtitle: '按指定数字给对应圆圈涂色',
path: '/mathPages/mathDraw/mathDraw?id=number-coloring',
},
],
},
],
'4-5': [
{
week: 1,
theme: '数数与比较',
exercises: [
{
_id: 'counting-fill',
title: '数一数,填一填',
subtitle: '数出物品数量,填写数字',
path: '/mathPages/mathDraw/mathDraw?id=counting-fill',
},
{
_id: 'compare',
title: '数一数,比大小',
subtitle: '比较数量,填入 ><=',
path: '/mathPages/mathDraw/mathDraw?id=compare',
},
{
_id: 'number-object-match',
title: '数物连线',
subtitle: '连线相同数量的物品和数字',
path: '/mathPages/mathDraw/mathDraw?id=number-object-match',
},
],
},
{
week: 2,
theme: '线条与形状',
exercises: [
{
_id: 'number-write',
title: '看数字,写一写',
subtitle: '按笔画顺序练习书写数字',
path: '/mathPages/mathDraw/mathDraw?id=number-write',
},
{
_id: 'shape-symbol',
title: '图形符号配对',
subtitle: '根据图形画对应符号',
path: '/focusPages/focusDraw/focusDraw?id=shape-symbol',
},
{
_id: 'counting-matching',
title: '数一数,连一连',
subtitle: '连线配对数字和对应数量图形',
path: '/mathPages/mathDraw/mathDraw?id=counting-matching',
},
],
},
{
week: 3,
theme: '规律与分类',
exercises: [
{
_id: 'color-pattern',
title: '颜色找规律',
subtitle: '观察颜色规律,在空白图形中涂色',
path: '/focusPages/focusDraw/focusDraw?id=color-pattern',
},
{
_id: 'number-sort',
title: '数字排序',
subtitle: '写出正确的数字顺序',
path: '/mathPages/mathDraw/mathDraw?id=number-sort',
},
{
_id: 'color-shape-match',
title: '根据颜色画图形',
subtitle: '根据颜色画出对应图形',
path: '/focusPages/focusDraw/focusDraw?id=color-shape-match',
},
],
},
{
week: 4,
theme: '综合提升',
exercises: [
{
_id: 'code-connect',
title: '译码连线',
subtitle: '按数字顺序将数字对应颜色连线',
path: '/focusPages/focusDraw/focusDraw?id=code-connect',
},
{
_id: 'match-connect',
title: '连连看',
subtitle: '根据物品连一连',
path: '/focusPages/focusDraw/focusDraw?id=match-connect',
},
{
_id: 'addition-10',
title: '10以内加法',
subtitle: '图形化展示 10 以内加法',
path: '/mathPages/mathDraw/mathDraw?id=addition-10',
},
],
},
],
'5-6': [
{
week: 1,
theme: '加减入门',
exercises: [
{
_id: 'addition-5',
title: '5以内加法',
subtitle: '图形化展示 5 以内加法',
path: '/mathPages/mathDraw/mathDraw?id=addition-5',
},
{
_id: 'addition-10',
title: '10以内加法',
subtitle: '图形化展示 10 以内加法',
path: '/mathPages/mathDraw/mathDraw?id=addition-10',
},
{
_id: 'subtraction-10',
title: '10以内减法',
subtitle: '图形化展示 10 以内减法',
path: '/mathPages/mathDraw/mathDraw?id=subtraction-10',
},
],
},
{
week: 2,
theme: '凑十与分解',
exercises: [
{
_id: 'make-ten',
title: '凑十法练习',
subtitle: '20 以内进位加法',
path: '/mathPages/mathDraw/mathDraw?id=make-ten',
},
{
_id: 'number-decompose',
title: '10以内数的分与合',
subtitle: '把数字分一分,合一合',
path: '/mathPages/mathDraw/mathDraw?id=number-decompose',
},
{
_id: 'one-digit-addition',
title: '一位数加法',
subtitle: '通过圆点学习一位数加法运算',
path: '/mathPages/mathDraw/mathDraw?id=one-digit-addition',
},
],
},
{
week: 3,
theme: '逻辑与推理',
exercises: [
{
_id: 'grid-reasoning',
title: '方格推理',
subtitle: '推理出合并方格并连线',
path: '/focusPages/focusDraw/focusDraw?id=grid-reasoning',
},
{
_id: 'grid-drawing-5x5',
title: '格子仿画 5×5',
subtitle: '创意挑战,提升观察力',
path: '/focusPages/focusDraw/focusDraw?id=grid-drawing-5x5',
},
{
_id: 'missing-number',
title: '填上缺少的数字',
subtitle: '在数列中找出并填写缺失数字',
path: '/mathPages/mathDraw/mathDraw?id=missing-number',
},
],
},
{
week: 4,
theme: '综合应用',
exercises: [
{
_id: 'addition-subtraction-10',
title: '10以内加减法',
subtitle: '加减法混合运算',
path: '/mathPages/mathDraw/mathDraw?id=addition-subtraction-10',
},
{
_id: 'practice-addition',
title: '加法运算',
subtitle: '10/20/50/100 以内加法',
path: '/mathPages/mathDraw/mathDraw?id=practice-addition',
},
{
_id: 'copybook',
title: '练字帖',
subtitle: '选字生成田字格笔顺练字帖',
path: '/pages/copyBook/copyBook',
},
],
},
],
'6-7': [
{
week: 1,
theme: '20 以内运算',
exercises: [
{
_id: 'practice-addition',
title: '加法运算',
subtitle: '10/20/50/100 以内加法',
path: '/mathPages/mathDraw/mathDraw?id=practice-addition',
},
{
_id: 'practice-subtraction',
title: '减法运算',
subtitle: '10/20/50/100 以内减法',
path: '/mathPages/mathDraw/mathDraw?id=practice-subtraction',
},
{
_id: 'practice-mixed',
title: '混合运算',
subtitle: '10/20/50/100 以内加减法混合',
path: '/mathPages/mathDraw/mathDraw?id=practice-mixed',
},
],
},
{
week: 2,
theme: '识字与词语',
exercises: [
{
_id: 'copybook',
title: '练字帖',
subtitle: '选字生成田字格笔顺练字帖',
path: '/pages/copyBook/copyBook',
},
{
_id: 'match-connect',
title: '连连看',
subtitle: '根据物品连一连',
path: '/focusPages/focusDraw/focusDraw?id=match-connect',
},
{
_id: 'word-recognition',
title: '识字卡',
subtitle: '输入或选字生成涂色识字卡',
path: '/pages/index/index',
},
],
},
{
week: 3,
theme: '逻辑与空间',
exercises: [
{
_id: 'grid-reasoning',
title: '方格推理',
subtitle: '推理出合并方格并连线',
path: '/focusPages/focusDraw/focusDraw?id=grid-reasoning',
},
{
_id: 'position-coloring',
title: '方位涂涂乐',
subtitle: '观察位置,在方格中涂色',
path: '/focusPages/focusDraw/focusDraw?id=position-coloring',
},
{
_id: 'code-connect',
title: '译码连线',
subtitle: '按数字顺序将数字对应颜色连线',
path: '/focusPages/focusDraw/focusDraw?id=code-connect',
},
],
},
{
week: 4,
theme: '综合提升',
exercises: [
{
_id: 'break-ten',
title: '破十法练习',
subtitle: '20 以内退位减法',
path: '/mathPages/mathDraw/mathDraw?id=break-ten',
},
{
_id: 'flat-ten',
title: '平十法练习',
subtitle: '20 以内退位减法',
path: '/mathPages/mathDraw/mathDraw?id=flat-ten',
},
{
_id: 'number-decompose-20',
title: '20以内数的分与合',
subtitle: '把数字分一分,合一合',
path: '/mathPages/mathDraw/mathDraw?id=number-decompose-20',
},
],
},
],
'7-8': [
{
week: 1,
theme: '乘除启蒙',
exercises: [
{
_id: 'multiplication-table',
title: '九九乘法表',
subtitle: '学习九九乘法口诀',
path: '/mathPages/mathDraw/mathDraw?id=multiplication-table',
},
{
_id: 'practice-addition',
title: '加法运算',
subtitle: '10/20/50/100 以内加法',
path: '/mathPages/mathDraw/mathDraw?id=practice-addition',
},
{
_id: 'practice-subtraction',
title: '减法运算',
subtitle: '10/20/50/100 以内减法',
path: '/mathPages/mathDraw/mathDraw?id=practice-subtraction',
},
],
},
{
week: 2,
theme: '巧算与策略',
exercises: [
{
_id: 'make-ten',
title: '凑十法练习',
subtitle: '20 以内进位加法',
path: '/mathPages/mathDraw/mathDraw?id=make-ten',
},
{
_id: 'borrow-ten',
title: '借十法练习',
subtitle: '20 以上退位减法',
path: '/mathPages/mathDraw/mathDraw?id=borrow-ten',
},
{
_id: 'practice-mixed',
title: '混合运算',
subtitle: '10/20/50/100 以内加减法混合',
path: '/mathPages/mathDraw/mathDraw?id=practice-mixed',
},
],
},
{
week: 3,
theme: '综合推理',
exercises: [
{
_id: 'grid-reasoning',
title: '方格推理',
subtitle: '推理出合并方格并连线',
path: '/focusPages/focusDraw/focusDraw?id=grid-reasoning',
},
{
_id: 'code-connect',
title: '译码连线',
subtitle: '按数字顺序将数字对应颜色连线',
path: '/focusPages/focusDraw/focusDraw?id=code-connect',
},
{
_id: 'dot-connect',
title: '数字点连线',
subtitle: '按数字顺序连点成图',
path: '/focusPages/focusDraw/focusDraw?id=dot-connect',
},
],
},
{
week: 4,
theme: '能力拓展',
exercises: [
{
_id: 'letter-tracing-two-column',
title: '两列练习',
subtitle: '左 A-M、右 N-Z,大小写配对描红',
path: '/englishPages/letterTracing/letterTracing?id=letter-tracing-two-column',
},
{
_id: 'word-recognition',
title: '识字卡',
subtitle: '输入或选字生成涂色识字卡',
path: '/pages/index/index',
},
{
_id: 'practice-mixed',
title: '混合运算',
subtitle: '10/20/50/100 以内加减法混合',
path: '/mathPages/mathDraw/mathDraw?id=practice-mixed',
},
],
},
],
};
+2 -1
View File
@@ -5,6 +5,7 @@
"backgroundColor": "#FEF6E7",
"enablePullDownRefresh": false,
"usingComponents": {
"nav-bar": "../../components3.0/nav-bar/nav-bar"
"nav-bar": "../../components3.0/nav-bar/nav-bar",
"worksheet-card": "../../components3.0/worksheet-card/worksheet-card"
}
}
+48 -25
View File
@@ -11,7 +11,7 @@
.age-page {
min-height: 100vh;
background: @bg-page;
padding-bottom: calc(48rpx + env(safe-area-inset-bottom));
padding-bottom: calc(10rpx + env(safe-area-inset-bottom));
box-sizing: border-box;
}
@@ -289,14 +289,27 @@
border-bottom: none;
}
.age-week-row__title {
.age-week-row__meta {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
gap: 8rpx;
}
.age-week-row__title {
font-size: 28rpx;
font-weight: 700;
color: @text-title;
}
.age-week-row__subtitle {
font-size: 22rpx;
font-weight: 500;
color: @text-gray;
line-height: 1.35;
}
.age-week-row__btn {
flex-shrink: 0;
display: flex;
@@ -324,6 +337,39 @@
box-sizing: border-box;
}
.age-rec-loading {
margin-top: @section-gap-lg;
padding: 48rpx @page-padding-x @section-gap-xs;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
box-sizing: border-box;
}
.age-rec-loading__icon {
margin-right: 12rpx;
font-size: 30rpx;
color: @text-secondary;
animation: age-rec-loading-spin 0.8s linear infinite;
}
.age-rec-loading__text {
font-size: 26rpx;
font-weight: 700;
color: @text-secondary;
}
@keyframes age-rec-loading-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.age-rec__head {
display: flex;
flex-direction: row;
@@ -356,28 +402,5 @@
.age-rec__card {
width: calc(50% - 16rpx);
background: @bg-white;
border-radius: @radius-lg;
overflow: hidden;
border: 1rpx solid rgba(50, 46, 37, 0.08);
box-shadow: @shadow;
box-sizing: border-box;
}
.age-rec__img {
width: 100%;
height: 200rpx;
display: block;
background: fade(@brand, 15%);
}
.age-rec__body {
padding: 20rpx 20rpx 24rpx;
}
.age-rec__card-title {
font-size: 26rpx;
font-weight: 700;
color: @text-title;
line-height: 1.35;
}
+118 -189
View File
@@ -1,187 +1,101 @@
import { AGE_BANDS, AgeBandKey } from '../../core/data/difficulty';
import { parseMiniProgramUrl } from '../../utils/index';
import {
AGE_ABILITIES,
AGE_TAB_SUB,
AGE_WEEK_PLANS,
type AbilityItem,
type WeekPlan,
} from './age.config';
type AbilityItem = {
icon: string;
const DEFAULT_AGE: AgeBandKey = '3-4';
const TAB_BAR_PATHS = new Set([
'/pages/home/home',
'/pages/category/category',
'/pages/age/age',
'/pages/favorites/favorites',
'/pages/profile/profile',
]);
function navigateByPath(path?: string, fallbackTitle?: string) {
const p = String(path || '').trim();
if (!p) {
wx.showToast({
title: fallbackTitle ? `${fallbackTitle} 即将上线` : '即将上线',
icon: 'none',
});
return;
}
const { path: basePath, query } = parseMiniProgramUrl(p);
if (TAB_BAR_PATHS.has(basePath)) {
if (Object.keys(query).length > 0) {
console.warn(
'[age navigateByPath] tabBar 不支持携带参数,已忽略 query:',
basePath,
query,
);
}
wx.switchTab({ url: basePath });
return;
}
wx.navigateTo({ url: p }).catch((err) => {
console.error('navigateByPath error:', err);
});
}
type RecommendedItemView = {
title: string;
desc: string;
image: string;
subtitle: string;
ageBand: string;
difficulty: string;
path: string;
worksheetId?: string;
};
const RECOMMENDED_FALLBACK: RecommendedItemView[] = [];
const DIFFICULTY_LABELS: Record<string, string> = {
1: '入门',
2: '基础',
3: '进阶',
4: '挑战',
};
type WeekExercise = {
title: string;
};
function toDifficultyLabel(value: unknown) {
const text = String(value || '').trim();
return DIFFICULTY_LABELS[text] || text;
}
type WeekPlan = {
week: number;
theme: string;
exercises: WeekExercise[];
};
const AGE_TAB_SUB: Record<AgeBandKey, string> = {
'3-4': '启蒙认知',
'4-5': '基础练习',
'5-6': '能力提升',
'6-7': '幼小衔接',
'7-8': '知识拓展',
};
/** Stitch「为你推荐」占位图(需在小程序后台配置 download 合法域名含 lh3.googleusercontent.com */
const RECOMMENDED_FROM_STITCH: { title: string; image: string }[] = [
{
title: '10以内加减法',
image: 'https://lh3.googleusercontent.com/aida-public/AB6AXuD-3lADhclTGODN9WtNh5v8bQPLysbllbKNkH40bAmVyE5d54PwfTBOiX9nER1hpE4rzHAfsmM_JhVnsE4EbdA914rYIb3S3e4r9QKFjUqYmj2XpE4MlYr_vLkG4oeMnvnHOqGC96nLGrPSOq-fpIddV7RSlYLDeNccBs0G2oUOy-6jIMujzTuEGk4nnxme5rpxs7rYjwcvVsqM5dlkpJthY42e4B3lSPH7ezx187WRSk--m4ZiWmAI52mMOiygzTSWoNormlvfvdM',
},
{
title: '拼音描红',
image: 'https://lh3.googleusercontent.com/aida-public/AB6AXuBYS4O7PyflR5q8M6oXKwj_8QHzex3OL3YvdHBncutm7a_bjlZj83-8UBpGUQvJO20V0BnAdU3iKEoLlUqwpS60CiPhVyxYaHEAqv52P5YUhJdjf0hpLir1Li4rdI_-eqGkPTasYl-5kD2r8-RjUokKg_HiW5_TF72UbxFXHQh4BefYJZfl0Oc9-aTQvkbFL0C3tagi9Qv1jRsgQldMFU4M7cHt8KkxhO1QDF7-R85ZFORJM0RiqV2l-jn0c-UscKtuWtroiX6UUKk',
},
{
title: '趣味找不同',
image: 'https://lh3.googleusercontent.com/aida-public/AB6AXuBSafbTyucs8JLpTgibRWwAJsHukrklTAuEnaAzax_Kr1RNCwHjqpQjta0Q-h47ClufzEmaHPgCIOlm_a2lL4gNlgBDyraCwzRU7aWCf_Fj_dM1cLGzROJmtqrdHKjQzTbCp0_Da8BvXi4a4H2X4RAYVPnLbZVmbgPXrTvpKgEI605kIMmr3n0--WojJQRsF4B_xCho80gABbIaMTHJHrs9xdEY6fZKg8ArQx7lRbJ6_EsLLB_C5a5crZ_begwruXKr3pmdU6KneC8',
},
{
title: '走迷宫大挑战',
image: 'https://lh3.googleusercontent.com/aida-public/AB6AXuAOZHI1Dz6ax4iFUb3QYL-EWp2euA_3kyUeCcu6V57BBCzarMwKnFzcpJxJn4X4woklWFB08Ii1w6zsk0H5eDaPdgUYmsvY0NFqvAhKN_IbZGZjZnclZlBHkLRcX64Nl767L2pg01FQu9Tp6nq2p3lAuYeEQ2fiIdXh4j-QHyikbmx4_aDlx5X5fC0fqMMxWykhwLNkDzl2Rs3ucXj7zYnUP-dNNY-aj_JvqkY4pqoXQDt9ZJcfSeL0dWes7nvD5U2C_JFhrk1bVkw',
},
{
title: '数字点连线',
image: 'https://lh3.googleusercontent.com/aida-public/AB6AXuD-3lADhclTGODN9WtNh5v8bQPLysbllbKNkH40bAmVyE5d54PwfTBOiX9nER1hpE4rzHAfsmM_JhVnsE4EbdA914rYIb3S3e4r9QKFjUqYmj2XpE4MlYr_vLkG4oeMnvnHOqGC96nLGrPSOq-fpIddV7RSlYLDeNccBs0G2oUOy-6jIMujzTuEGk4nnxme5rpxs7rYjwcvVsqM5dlkpJthY42e4B3lSPH7ezx187WRSk--m4ZiWmAI52mMOiygzTSWoNormlvfvdM',
},
{
title: '方格推理高手',
image: 'https://lh3.googleusercontent.com/aida-public/AB6AXuBYS4O7PyflR5q8M6oXKwj_8QHzex3OL3YvdHBncutm7a_bjlZj83-8UBpGUQvJO20V0BnAdU3iKEoLlUqwpS60CiPhVyxYaHEAqv52P5YUhJdjf0hpLir1Li4rdI_-eqGkPTasYl-5kD2r8-RjUokKg_HiW5_TF72UbxFXHQh4BefYJZfl0Oc9-aTQvkbFL0C3tagi9Qv1jRsgQldMFU4M7cHt8KkxhO1QDF7-R85ZFORJM0RiqV2l-jn0c-UscKtuWtroiX6UUKk',
},
];
/** 各年龄段能力目标(Mock) */
const MOCK_ABILITY: Record<AgeBandKey, AbilityItem[]> = {
'3-4': [
{
icon: '🔢',
title: '数感',
desc: '认读 1-5、点数对应',
},
{
icon: '✏️',
title: '书写',
desc: '涂鸦线条、简单描红',
},
{
icon: '🧩',
title: '思维',
desc: '找相同、简单配对',
},
],
'4-5': [
{
icon: '🔢',
title: '数感',
desc: '10 以内数数、比大小',
},
{
icon: '✏️',
title: '书写',
desc: '笔画模仿、图形描边',
},
{
icon: '🧩',
title: '思维',
desc: '规律排序、图形分类',
},
],
'5-6': [
{
icon: '🔢',
title: '数感',
desc: '10以内加减法、凑十法',
},
{
icon: '✏️',
title: '书写',
desc: '练字帖、拼音入门',
},
{
icon: '🧩',
title: '思维',
desc: '方格推理、格子仿画 5×5',
},
],
'6-7': [
{
icon: '🔢',
title: '数感',
desc: '20 以内运算、应用题启蒙',
},
{
icon: '✏️',
title: '书写',
desc: '常用字书写、词语积累',
},
{
icon: '🧩',
title: '思维',
desc: '逻辑填空、空间想象',
},
],
'7-8': [
{
icon: '🔢',
title: '数感',
desc: '乘除启蒙、巧算练习',
},
{
icon: '✏️',
title: '书写',
desc: '段落抄写、古诗诵读',
},
{
icon: '🧩',
title: '思维',
desc: '数独入门、综合推理',
},
],
};
/** 4 周路线(各年龄段共用结构,内容 Mock) */
const MOCK_WEEKS: WeekPlan[] = [
{
week: 1,
theme: '数感启蒙',
exercises: [
{ title: '找数字涂一涂' },
{ title: '5 以内加法' },
{ title: '数数连一连' },
],
},
{
week: 2,
theme: '形状与连线',
exercises: [
{ title: '识别形状' },
{ title: '线条识别' },
{ title: '数字点连线' },
],
},
{
week: 3,
theme: '趣味专注',
exercises: [
{ title: '颜色找规律' },
{ title: '方格推理' },
{ title: '格子仿画' },
],
},
{
week: 4,
theme: '综合练习',
exercises: [
{ title: '10以内加减法' },
{ title: '识字卡' },
{ title: '连连看' },
],
},
];
const DEFAULT_AGE: AgeBandKey = '5-6';
async function fetchAgeRecommended(
ageKey: AgeBandKey,
): Promise<RecommendedItemView[]> {
try {
const res = await wx.cloud.callFunction({
name: 'ageRecommendedQuery',
data: { ageKey },
});
const payload = (res && (res.result as any)) || null;
if (!payload?.success) return [];
const items = (payload.data?.items || []) as any[];
return items
.map((it) => ({
title: String(it.title || ''),
image: String(it.previewImg || ''),
subtitle: String(it.subtitle || ''),
ageBand: String(it.ageBand || it.ageRange || ''),
difficulty: toDifficultyLabel(
it.difficultyLabel || it.difficulty || '',
),
path: String(it.path || ''),
worksheetId: String(it.worksheetId || ''),
}))
.filter((it) => it.title);
} catch (e) {
console.warn('[age] fetchAgeRecommended failed:', e);
return [];
}
}
Page({
data: {
@@ -190,24 +104,34 @@ Page({
rangeText: b.label.replace(/\s*岁\s*$/, ''),
subLabel: AGE_TAB_SUB[b.key],
})),
activeAgeKey: DEFAULT_AGE,
activeAgeKey: DEFAULT_AGE as AgeBandKey,
goalTitle: '',
abilityItems: [] as AbilityItem[],
weekPlans: MOCK_WEEKS,
recommendedItems: RECOMMENDED_FROM_STITCH,
weekPlans: [] as WeekPlan[],
recommendedItems: RECOMMENDED_FALLBACK,
recommendedLoading: false,
},
onLoad() {
this.applyAge(DEFAULT_AGE);
},
applyAge(key: AgeBandKey) {
async applyAge(key: AgeBandKey) {
const band = AGE_BANDS.find((b) => b.key === key);
const goalTitle = band ? `${band.label}能力目标` : '能力目标';
this.setData({
activeAgeKey: key,
goalTitle,
abilityItems: MOCK_ABILITY[key],
abilityItems: AGE_ABILITIES[key] || [],
weekPlans: AGE_WEEK_PLANS[key] || [],
recommendedLoading: true,
});
const recommended = await fetchAgeRecommended(key);
this.setData({
recommendedItems:
recommended.length > 0 ? recommended : RECOMMENDED_FALLBACK,
recommendedLoading: false,
});
},
@@ -218,18 +142,23 @@ Page({
},
onPracticeTap(e: WechatMiniprogram.TouchEvent) {
const path = e.currentTarget.dataset.path as string | undefined;
const title = e.currentTarget.dataset.title as string | undefined;
if (!title) return;
wx.showToast({ title: `即将前往:${title}`, icon: 'none' });
navigateByPath(path, title);
},
onRecommendMore() {
wx.switchTab({ url: '/pages/home/home' });
},
onRecommendTap(e: WechatMiniprogram.TouchEvent) {
const title = e.currentTarget.dataset.title as string | undefined;
if (!title) return;
wx.showToast({ title: `去看看:${title}`, icon: 'none' });
onTapCard(e: WechatMiniprogram.CustomEvent) {
const detail = (e.detail || {}) as { title?: string; path?: string };
const path =
detail.path ||
(e.currentTarget.dataset.path as string | undefined);
const title =
detail.title ||
(e.currentTarget.dataset.title as string | undefined);
navigateByPath(path, title);
},
});
+31 -13
View File
@@ -59,12 +59,22 @@
<view
wx:for="{{item.exercises}}"
wx:for-item="ex"
wx:key="title"
wx:key="_id"
class="age-week-row">
<text class="age-week-row__title">{{ex.title}}</text>
<view class="age-week-row__meta">
<text class="age-week-row__title"
>{{ex.title}}</text
>
<text
wx:if="{{ex.subtitle}}"
class="age-week-row__subtitle"
>{{ex.subtitle}}</text
>
</view>
<view
class="age-week-row__btn"
data-title="{{ex.title}}"
data-path="{{ex.path}}"
catchtap="onPracticeTap">
<text>去练习</text>
<text
@@ -78,7 +88,14 @@
</view>
</view>
<view class="age-rec">
<view wx:if="{{recommendedLoading}}" class="age-rec-loading">
<text
class="toy-icon toy-icon-loading age-rec-loading__icon"
aria-hidden="true"></text>
<text class="age-rec-loading__text">推荐加载中...</text>
</view>
<view wx:else class="age-rec">
<view class="age-rec__head">
<text class="age-rec__title">为你推荐</text>
<text class="age-rec__more" bindtap="onRecommendMore"
@@ -86,20 +103,21 @@
>
</view>
<view class="age-rec__grid">
<view
<worksheet-card
wx:for="{{recommendedItems}}"
wx:key="title"
class="age-rec__card"
variant="track"
title="{{item.title}}"
preview-img="{{item.image}}"
subtitle="{{item.subtitle}}"
age-band="{{item.ageBand}}"
difficulty="{{item.difficulty}}"
path="{{item.path}}"
data-title="{{item.title}}"
bindtap="onRecommendTap">
<image
class="age-rec__img"
src="{{item.image}}"
mode="aspectFill" />
<view class="age-rec__body">
<text class="age-rec__card-title">{{item.title}}</text>
</view>
</view>
data-path="{{item.path}}"
bindtap="onTapCard"
/>
</view>
</view>
</view>