feat: 首页增加每日练习模块

This commit is contained in:
R524809
2026-05-22 11:29:08 +08:00
parent bcece55238
commit 143395dbfd
12 changed files with 866 additions and 983 deletions
+539 -1
View File
File diff suppressed because one or more lines are too long
@@ -1,9 +1,7 @@
import type { DebugPublishMeta } from '../../utils/debugPublish'; import type { DebugPublishMeta } from '../../utils/debugPublish';
import { inferGradeFromAge } from '../../utils/debugPublish'; import { inferGradeFromAge } from '../../utils/debugPublish';
export type HandwritingSheetMode = export type HandwritingSheetMode = 'hanzi-sheet' | 'hanzi-daily-checkin';
| 'handwriting-sheet'
| 'handwriting-daily-checkin';
interface HandwritingSheetWorksheetDefinition { interface HandwritingSheetWorksheetDefinition {
id: HandwritingSheetMode; id: HandwritingSheetMode;
@@ -20,7 +18,7 @@ interface HandwritingSheetWorksheetDefinition {
export const HANDWRITING_SHEET_WORKSHEET_DEFINITIONS: HandwritingSheetWorksheetDefinition[] = export const HANDWRITING_SHEET_WORKSHEET_DEFINITIONS: HandwritingSheetWorksheetDefinition[] =
[ [
{ {
id: 'handwriting-sheet', id: 'hanzi-sheet',
icon: 'draw-o', icon: 'draw-o',
title: '自定义练字帖', title: '自定义练字帖',
subtitle: '自定义田字格练字帖', subtitle: '自定义田字格练字帖',
@@ -31,7 +29,7 @@ export const HANDWRITING_SHEET_WORKSHEET_DEFINITIONS: HandwritingSheetWorksheetD
sortOrder: 35, sortOrder: 35,
}, },
{ {
id: 'handwriting-daily-checkin', id: 'hanzi-daily-checkin',
icon: 'task-o', icon: 'task-o',
title: '汉字每日打卡', title: '汉字每日打卡',
subtitle: '每日 8 字带拼音笔顺打卡', subtitle: '每日 8 字带拼音笔顺打卡',
@@ -74,7 +72,7 @@ export function getPublishMetaByMode(id: string): DebugPublishMeta | null {
title: item.title, title: item.title,
subtitle: item.subtitle, subtitle: item.subtitle,
category: 'chinese', category: 'chinese',
subcategory: 'handwriting-sheet', subcategory: 'hanzi-sheet',
path: `/chinesePages/handwritingSheet/handwritingSheet?id=${item.id}`, path: `/chinesePages/handwritingSheet/handwritingSheet?id=${item.id}`,
ageMin: item.ageMin, ageMin: item.ageMin,
ageMax: item.ageMax, ageMax: item.ageMax,
@@ -33,6 +33,8 @@ const CUSTOM_MAX_WORDS = 11;
const CHECKIN_MAX_WORDS = 8; const CHECKIN_MAX_WORDS = 8;
const RANDOM_WORD_COUNT = 8; const RANDOM_WORD_COUNT = 8;
const CUSTOM_DEFAULT_WORDS = '东西南北日月山河风雨'; const CUSTOM_DEFAULT_WORDS = '东西南北日月山河风雨';
/** 汉字每日打卡默认文案(8 字,与 CHECKIN_MAX_WORDS 一致) */
const CHECKIN_DEFAULT_WORDS = '日拱一卒不期而至';
const CUSTOM_CATEGORY_TAGS = WORDS.slice(0, 3).map((cat) => ({ const CUSTOM_CATEGORY_TAGS = WORDS.slice(0, 3).map((cat) => ({
categoryId: cat.categoryId, categoryId: cat.categoryId,
icon: cat.icon, icon: cat.icon,
@@ -65,8 +67,7 @@ createPage(
data: { data: {
pageTitle: HANDWRITING_SHEET_WORKSHEET_DEFINITIONS[0].title, pageTitle: HANDWRITING_SHEET_WORKSHEET_DEFINITIONS[0].title,
functionId: HANDWRITING_SHEET_WORKSHEET_ID, functionId: HANDWRITING_SHEET_WORKSHEET_ID,
currentMode: currentMode: HANDWRITING_SHEET_WORKSHEET_ID as HandwritingSheetMode,
HANDWRITING_SHEET_WORKSHEET_ID as HandwritingSheetMode,
modeOptions: HANDWRITING_SHEET_MODE_OPTIONS, modeOptions: HANDWRITING_SHEET_MODE_OPTIONS,
hasContent: false, hasContent: false,
words: [] as string[], words: [] as string[],
@@ -155,7 +156,7 @@ createPage(
async prepareCanvasForCurrentMode() { async prepareCanvasForCurrentMode() {
if (!this.canvas) return; if (!this.canvas) return;
if (this.data.currentMode === 'handwriting-sheet') { if (this.data.currentMode === 'hanzi-sheet') {
if (!this.wordDrawService) return; if (!this.wordDrawService) return;
await this.wordDrawService.drawLayout(); await this.wordDrawService.drawLayout();
const { maxRow, maxCol } = const { maxRow, maxCol } =
@@ -167,11 +168,8 @@ createPage(
} }
}, },
applyMode( applyMode(mode: HandwritingSheetMode, options?: { redraw?: boolean }) {
mode: HandwritingSheetMode, const isCheckin = mode === 'hanzi-daily-checkin';
options?: { redraw?: boolean },
) {
const isCheckin = mode === 'handwriting-daily-checkin';
const max = isCheckin ? CHECKIN_MAX_WORDS : CUSTOM_MAX_WORDS; const max = isCheckin ? CHECKIN_MAX_WORDS : CUSTOM_MAX_WORDS;
this.setData( this.setData(
@@ -253,7 +251,7 @@ createPage(
}, },
getMaxWordsForMode(): number { getMaxWordsForMode(): number {
return this.data.currentMode === 'handwriting-daily-checkin' return this.data.currentMode === 'hanzi-daily-checkin'
? CHECKIN_MAX_WORDS ? CHECKIN_MAX_WORDS
: CUSTOM_MAX_WORDS; : CUSTOM_MAX_WORDS;
}, },
@@ -375,8 +373,25 @@ createPage(
}, },
initDefaultWords() { initDefaultWords() {
if (this.data.currentMode === 'handwriting-daily-checkin') { if (this.data.currentMode === 'hanzi-daily-checkin') {
this.refreshWords(); const defaults = this.getSupportedWords(
this.splitToSingleChars(CHECKIN_DEFAULT_WORDS),
).slice(0, CHECKIN_MAX_WORDS);
if (defaults.length === 0) {
this.refreshWords();
return;
}
this.setData(
{
words: defaults,
inputWords: defaults,
selectedWords: [],
inputValue: defaults.join(''),
},
() => this.renderPracticeContent().catch(console.error),
);
return; return;
} }
@@ -401,8 +416,7 @@ createPage(
}, },
refreshWords() { refreshWords() {
const isCheckin = const isCheckin = this.data.currentMode === 'hanzi-daily-checkin';
this.data.currentMode === 'handwriting-daily-checkin';
const candidates = isCheckin const candidates = isCheckin
? collectFirstGradeWords() ? collectFirstGradeWords()
: WORDS.slice(0, 3).reduce( : WORDS.slice(0, 3).reduce(
@@ -446,7 +460,7 @@ createPage(
const words = this.data.words as string[]; const words = this.data.words as string[];
if (this.data.currentMode === 'handwriting-daily-checkin') { if (this.data.currentMode === 'hanzi-daily-checkin') {
await this.renderCheckinContent(words); await this.renderCheckinContent(words);
return; return;
} }
+6 -6
View File
@@ -38,12 +38,12 @@ export const CATEGORY_LIST: CategoryType[] = [
icon: '🔤', icon: '🔤',
path: '/pages/category/category?id=english', path: '/pages/category/category?id=english',
}, },
{ // {
id: 'craft', // id: 'craft',
name: '创意手工', // name: '创意手工',
icon: '🌈', // icon: '🌈',
path: '/pages/category/category?id=craft', // path: '/pages/category/category?id=craft',
}, // },
]; ];
export const CATEGORY_LIST_WITH_ALL: CategoryType[] = [ export const CATEGORY_LIST_WITH_ALL: CategoryType[] = [
@@ -87,8 +87,8 @@ export const LETTER_TRACING_WORKSHEET_DEFINITIONS = [
icon: 'task-o', icon: 'task-o',
title: '字母每日打卡', title: '字母每日打卡',
subtitle: '四宫格每日字母打卡练习', subtitle: '四宫格每日字母打卡练习',
ageMin: 6, ageMin: 5,
ageMax: 8, ageMax: 7,
difficulty: 2, difficulty: 2,
tags: ['字母', '描红', '每日打卡'], tags: ['字母', '描红', '每日打卡'],
sortOrder: 48, sortOrder: 48,
+8 -8
View File
@@ -148,10 +148,10 @@ export const AGE_WEEK_PLANS: Record<AgeBandKey, WeekPlan[]> = {
path: '/mathPages/mathDraw/mathDraw?id=number-sort', path: '/mathPages/mathDraw/mathDraw?id=number-sort',
}, },
{ {
_id: 'handwriting-sheet', _id: 'hanzi-sheet',
title: '自定义练字帖', title: '自定义练字帖',
subtitle: '自定义田字格练字帖', subtitle: '自定义田字格练字帖',
path: '/chinesePages/handwritingSheet/handwritingSheet?id=handwriting-sheet', path: '/chinesePages/handwritingSheet/handwritingSheet?id=hanzi-sheet',
}, },
{ {
_id: 'letter-tracing-single', _id: 'letter-tracing-single',
@@ -252,10 +252,10 @@ export const AGE_WEEK_PLANS: Record<AgeBandKey, WeekPlan[]> = {
path: '/englishPages/letterTracing/letterTracing?id=letter-tracing-single', path: '/englishPages/letterTracing/letterTracing?id=letter-tracing-single',
}, },
{ {
_id: 'handwriting-sheet', _id: 'hanzi-sheet',
title: '自定义练字帖', title: '自定义练字帖',
subtitle: '自定义田字格练字帖', subtitle: '自定义田字格练字帖',
path: '/chinesePages/handwritingSheet/handwritingSheet?id=handwriting-sheet', path: '/chinesePages/handwritingSheet/handwritingSheet?id=hanzi-sheet',
}, },
], ],
}, },
@@ -400,10 +400,10 @@ export const AGE_WEEK_PLANS: Record<AgeBandKey, WeekPlan[]> = {
path: '/pinyinPages/pinyinDictation/pinyinDictation?id=pinyin-dictation', path: '/pinyinPages/pinyinDictation/pinyinDictation?id=pinyin-dictation',
}, },
{ {
_id: 'handwriting-sheet', _id: 'hanzi-sheet',
title: '自定义练字帖', title: '自定义练字帖',
subtitle: '自定义田字格练字帖', subtitle: '自定义田字格练字帖',
path: '/chinesePages/handwritingSheet/handwritingSheet?id=handwriting-sheet', path: '/chinesePages/handwritingSheet/handwritingSheet?id=hanzi-sheet',
}, },
], ],
}, },
@@ -546,10 +546,10 @@ export const AGE_WEEK_PLANS: Record<AgeBandKey, WeekPlan[]> = {
path: '/englishPages/letterTracing/letterTracing?id=letter-tracing-daily-checkin', path: '/englishPages/letterTracing/letterTracing?id=letter-tracing-daily-checkin',
}, },
{ {
_id: 'handwriting-sheet', _id: 'hanzi-sheet',
title: '自定义练字帖', title: '自定义练字帖',
subtitle: '自定义田字格练字帖', subtitle: '自定义田字格练字帖',
path: '/chinesePages/handwritingSheet/handwritingSheet?id=handwriting-sheet', path: '/chinesePages/handwritingSheet/handwritingSheet?id=hanzi-sheet',
}, },
], ],
}, },
+63 -791
View File
@@ -48,796 +48,68 @@ export type HomeDisplayDataset = {
const HOME_CATEGORY_TABS: HomeDisplayDataset['categoryTabs'] = const HOME_CATEGORY_TABS: HomeDisplayDataset['categoryTabs'] =
CATEGORY_LIST_WITH_ALL.map(({ id, name }) => ({ id, name })); CATEGORY_LIST_WITH_ALL.map(({ id, name }) => ({ id, name }));
const HOME_AGE_BANDS = AGE_BANDS.map((item, index) => ({ const HOME_AGE_BANDS: HomeDisplayDataset['ageBands'] = AGE_BANDS.map(
key: item.key, (item, index) => ({
label: item.label, key: item.key,
desc: ['启蒙认知', '基础练习', '能力提升', '幼小衔接', '知识拓展'][index], label: item.label,
path: '/pages/age/age', desc: ['启蒙认知', '基础练习', '能力提升', '幼小衔接', '知识拓展'][
})); index
],
path: '/pages/age/age',
}),
);
export const HOME_PRODUCT_TARGET_DATA: HomeDisplayDataset = { /** 首页固定:每日打卡练习(不随云端配置变化) */
searchPlaceholder: '搜索你喜欢的练习册...', export const HOME_DAILY_CHECKIN_ITEMS: HomeDisplayItem[] = [
categoryTabs: [...HOME_CATEGORY_TABS], {
ageBands: HOME_AGE_BANDS, id: 'hanzi-daily-checkin',
featured: [ title: '汉字每日打卡',
{ subtitle: '每日 8 字带拼音笔顺打卡',
id: 'target-featured-1', category: 'chinese',
title: '圣诞主题涂色卡', ageBand: '5-8岁',
subtitle: '节日限定创意内容', difficulty: '基础',
description: '首页推荐位示例,强调季节热点与真实打印效果。', icon: '📝',
category: 'craft', previewImg:
ageBand: '3-8岁', 'cloud://cloud1-9gifs7a2756e2c87.636c-cloud1-9gifs7a2756e2c87-1351593184/assets/previews/chinese/hanzi-daily-checkin.jpg',
difficulty: '入门', path: '/chinesePages/handwritingSheet/handwritingSheet?id=hanzi-daily-checkin',
icon: '🎄', available: true,
badge: 'NEW', },
path: '', {
available: false, id: 'pinyin-daily',
source: '产品设计文档 5.1 今日推荐', title: '拼音每日打卡',
}, subtitle: '四宫格每日打卡练习',
{ category: 'pinyin',
id: 'target-featured-2', ageBand: '6-8岁',
title: '走迷宫大挑战', difficulty: '基础',
subtitle: '热门趣味训练', icon: '🔤',
description: '产品规划中的高趣味内容,用于首页焦点推荐。', previewImg:
category: 'puzzle', 'cloud://cloud1-9gifs7a2756e2c87.636c-cloud1-9gifs7a2756e2c87-1351593184/assets/previews/pinyin/pinyin-daily.jpg',
ageBand: '4-7岁', path: '/pinyinPages/pinyinDictation/pinyinDictation?id=pinyin-daily',
difficulty: '进阶', available: true,
icon: '🌀', },
badge: 'HOT', {
path: '', id: 'letter-tracing-daily-checkin',
available: false, title: '字母每日打卡',
source: '产品设计文档 P2-22', subtitle: '四宫格每日字母打卡练习',
}, category: 'english',
{ ageBand: '6-8岁',
id: 'target-featured-3', difficulty: '基础',
title: '拼音描红', icon: '🔠',
subtitle: '幼小衔接高频内容', previewImg:
description: '语文模块重点新增内容,适合推荐位曝光。', 'cloud://cloud1-9gifs7a2756e2c87.636c-cloud1-9gifs7a2756e2c87-1351593184/assets/previews/english/letter-tracing-daily-checkin.jpg',
category: 'chinese', path: '/englishPages/letterTracing/letterTracing?id=letter-tracing-daily-checkin',
ageBand: '5-7岁', available: true,
difficulty: '基础', },
icon: '🔤', ];
badge: '推荐',
path: '',
available: false,
source: '产品设计文档 P1-12',
},
],
hot: [
{
id: 'target-hot-1',
title: '迷宫',
subtitle: '高趣味路径探索',
category: 'puzzle',
ageBand: '4-7岁',
difficulty: '进阶',
icon: '🧭',
badge: '热门',
path: '',
available: false,
source: '产品设计文档 5.1 热门下载',
},
{
id: 'target-hot-2',
title: '涂色卡',
subtitle: '动物与节日主题',
category: 'craft',
ageBand: '3-6岁',
difficulty: '入门',
icon: '🎨',
badge: '热门',
path: '',
available: false,
source: '产品设计文档 P3-29',
},
{
id: 'target-hot-3',
title: '加减法',
subtitle: '家长高频打印内容',
category: 'math',
ageBand: '5-7岁',
difficulty: '基础',
icon: '',
badge: '热门',
previewImg: '/assets/entrancePicture/math/addition-5.png',
path: '/mathPages/mathDraw/mathDraw?id=addition',
available: true,
source: '现有加减法页面可承接',
},
],
sections: [
{
id: 'math',
title: '数学启蒙',
subtitle: '数字认知、计数练习、加减运算、时钟与形状',
morePath: '/pages/category/category?id=math',
items: [
{
id: 'target-math-1',
title: '数字认知',
subtitle: '认识数字 1-10',
category: 'math',
ageBand: '3-4岁',
difficulty: '入门',
icon: '🔢',
previewImg: '/assets/entrancePicture/math/number-find.png',
path: '/mathPages/mathDraw/mathDraw?id=number-find',
available: true,
source: '现有 找数字/写数字 能力',
},
{
id: 'target-math-2',
title: '计数练习',
subtitle: '数一数、连一连、选一选',
category: 'math',
ageBand: '4-5岁',
difficulty: '基础',
icon: '🧮',
previewImg: '/assets/entrancePicture/math/count-match.png',
path: '/mathPages/mathDraw/mathDraw?id=counting-matching',
available: true,
source: '现有 countMatch/countingSelect',
},
{
id: 'target-math-3',
title: '加减运算',
subtitle: '从 5 以内到 100 以内',
category: 'math',
ageBand: '5-7岁',
difficulty: '基础',
icon: '',
previewImg: '/assets/entrancePicture/math/addition-5.png',
path: '/mathPages/mathDraw/mathDraw?id=addition',
available: true,
source: '现有 addition/calculationPractice',
},
{
id: 'target-math-4',
title: '时钟练习',
subtitle: '认识钟表与时间',
category: 'math',
ageBand: '5-7岁',
difficulty: '进阶',
icon: '🕒',
path: '',
available: false,
source: '产品设计文档 P1-7',
},
{
id: 'target-math-5',
title: '形状认知',
subtitle: '图形分类与空间感',
category: 'math',
ageBand: '3-5岁',
difficulty: '入门',
icon: '📐',
path: '',
available: false,
source: '产品设计文档 3.1 信息架构',
},
],
},
{
id: 'chinese',
title: '语文启蒙',
subtitle: '识字、练字、拼音、表达训练',
morePath: '/pages/category/category?id=chinese',
items: [
{
id: 'target-chinese-1',
title: '识字卡',
subtitle: '自定义汉字卡片',
category: 'chinese',
ageBand: '3-6岁',
difficulty: '入门',
icon: '📖',
path: '/pages/index/index',
available: true,
source: '现有识字页',
},
{
id: 'target-chinese-2',
title: '练字帖',
subtitle: '田字格笔顺练习',
category: 'chinese',
ageBand: '4-7岁',
difficulty: '基础',
icon: '✏️',
path: '/pages/copyBook/copyBook',
available: true,
source: '现有练字页',
},
{
id: 'target-chinese-3',
title: '拼音练习',
subtitle: '声母韵母描红',
category: 'chinese',
ageBand: '5-7岁',
difficulty: '基础',
icon: '🔤',
path: '',
available: false,
source: '产品设计文档 P1-12',
},
{
id: 'target-chinese-4',
title: '看图说话',
subtitle: '图片引导表达',
category: 'chinese',
ageBand: '5-7岁',
difficulty: '进阶',
icon: '🗣️',
path: '',
available: false,
source: '产品设计文档 P1-15',
},
],
},
{
id: 'english',
title: '英语启蒙',
subtitle: '字母学习、闪卡、描红与自然拼读',
morePath: '/pages/category/category?id=english',
items: [
{
id: 'target-english-1',
title: '字母描红',
subtitle: 'A-Z 大小写练习',
category: 'english',
ageBand: '4-6岁',
difficulty: '入门',
icon: '🔠',
path: '/englishPages/letterTracing/letterTracing?id=letter-tracing-single',
available: true,
source: 'letter-tracing-single',
},
{
id: 'target-english-2',
title: '字母闪卡',
subtitle: '字母与单词联想',
category: 'english',
ageBand: '3-6岁',
difficulty: '入门',
icon: '🪪',
path: '',
available: false,
source: '产品设计文档 P1-18',
},
{
id: 'target-english-3',
title: '自然拼读练习纸',
subtitle: 'CVC 单词启蒙',
category: 'english',
ageBand: '5-7岁',
difficulty: '进阶',
icon: '🔡',
path: '',
available: false,
source: '产品设计文档 P1-21',
},
],
},
{
id: 'puzzle',
title: '益智游戏',
subtitle: '迷宫、找不同、连线、数独与控笔',
morePath: '/pages/category/category?id=puzzle',
items: [
{
id: 'target-puzzle-1',
title: '迷宫',
subtitle: '不同难度路径挑战',
category: 'puzzle',
ageBand: '4-7岁',
difficulty: '进阶',
icon: '🌀',
path: '',
available: false,
source: '产品设计文档 P2-22',
},
{
id: 'target-puzzle-2',
title: '找不同',
subtitle: '观察力与专注力训练',
category: 'puzzle',
ageBand: '4-7岁',
difficulty: '进阶',
icon: '🔍',
path: '',
available: false,
source: '产品设计文档 P2-23',
},
{
id: 'target-puzzle-3',
title: '连线题',
subtitle: '数字点连线与物品连线',
category: 'puzzle',
ageBand: '4-6岁',
difficulty: '基础',
icon: '🧵',
previewImg: '/assets/entrancePicture/focus/dot-connect.png',
path: '/focusPages/focusDraw/focusDraw?id=dot-connect',
available: true,
source: '现有 dotConnect/matchConnect',
},
{
id: 'target-puzzle-4',
title: '数独入门',
subtitle: '4x4 / 6x6 逻辑启蒙',
category: 'puzzle',
ageBand: '6-8岁',
difficulty: '挑战',
icon: '🧠',
path: '',
available: false,
source: '产品设计文档 P2-24',
},
],
},
{
id: 'craft',
title: '创意手工',
subtitle: '涂色卡、折纸、贴纸和主题手工',
items: [
{
id: 'target-craft-1',
title: '涂色卡',
subtitle: '动物、交通、节日主题',
category: 'craft',
ageBand: '3-6岁',
difficulty: '入门',
icon: '🎨',
path: '',
available: false,
source: '产品设计文档 P3-29',
},
{
id: 'target-craft-2',
title: '折纸模板',
subtitle: '打印后即可折叠',
category: 'craft',
ageBand: '4-7岁',
difficulty: '基础',
icon: '🪭',
path: '',
available: false,
source: '产品设计文档 P3-30',
},
{
id: 'target-craft-3',
title: '贴纸打印',
subtitle: '奖励贴纸与装饰贴纸',
category: 'craft',
ageBand: '3-8岁',
difficulty: '入门',
icon: '⭐',
path: '',
available: false,
source: '产品设计文档 P3-33',
},
],
},
],
};
export const HOME_CURRENT_CAPABILITY_DATA: HomeDisplayDataset = { /** 云端配置不可用时的空首页结构(仅保留 Tab / 分龄导航骨架) */
searchPlaceholder: '搜索你喜欢的练习册...', export function createEmptyHomeDataset(): HomeDisplayDataset {
categoryTabs: [...HOME_CATEGORY_TABS], return {
ageBands: HOME_AGE_BANDS, searchPlaceholder: '搜索你喜欢的练习册...',
featured: [ categoryTabs: [...HOME_CATEGORY_TABS],
{ ageBands: [...HOME_AGE_BANDS],
id: 'current-featured-1', featured: [],
title: '10以内加减法', hot: [],
subtitle: '最适合首页推荐的高频内容', sections: [],
description: '现有数学能力中最接近产品文档“热门下载”的内容。', };
category: 'math', }
ageBand: '5-6岁',
difficulty: '基础',
icon: '',
badge: 'HOT',
previewImg: '/assets/entrancePicture/math/addition-5.png',
path: '/mathPages/mathDraw/mathDraw?id=addition',
available: true,
source: '现有功能清单 addition',
},
{
id: 'current-featured-2',
title: '涂色识字卡',
subtitle: '兼顾识字与趣味涂色',
description: '当前最接近创意内容的主包能力,可承接语文与创意入口。',
category: 'chinese',
ageBand: '3-6岁',
difficulty: '入门',
icon: '📚',
badge: '推荐',
path: '/pages/index/index',
available: true,
source: '现有识字页',
},
{
id: 'current-featured-3',
title: '数字点连线',
subtitle: '用连点成图提升专注力',
description: '能承担产品文档中“益智游戏”内容氛围。',
category: 'puzzle',
ageBand: '4-6岁',
difficulty: '基础',
icon: '🔗',
badge: '热门',
previewImg: '/assets/entrancePicture/focus/dot-connect.png',
path: '/focusPages/focusDraw/focusDraw?id=dot-connect',
available: true,
source: '现有功能清单 dot-connect',
},
],
hot: [
{
id: 'current-hot-1',
title: '找数字,涂一涂',
subtitle: '低龄启蒙高频内容',
category: 'math',
ageBand: '3-4岁',
difficulty: '入门',
icon: '🔢',
badge: '热门',
previewImg: '/assets/entrancePicture/math/number-find.png',
path: '/mathPages/mathDraw/mathDraw?id=number-find',
available: true,
source: 'number-find',
},
{
id: 'current-hot-2',
title: '数一数,连一连',
subtitle: '点数和数字对应',
category: 'math',
ageBand: '4-5岁',
difficulty: '基础',
icon: '🧮',
badge: '热门',
previewImg: '/assets/entrancePicture/math/count-match.png',
path: '/mathPages/mathDraw/mathDraw?id=counting-matching',
available: true,
source: 'counting-matching',
},
{
id: 'current-hot-3',
title: '格子仿画 5×5',
subtitle: '图形观察与耐心训练',
category: 'puzzle',
ageBand: '5-7岁',
difficulty: '进阶',
icon: '🟨',
badge: '热门',
previewImg: '/assets/entrancePicture/focus/grid-drawing-5x5.png',
path: '/focusPages/focusDraw/focusDraw?id=grid-drawing',
available: true,
source: 'grid-drawing-5x5',
},
],
sections: [
{
id: 'math',
title: '数感启蒙',
subtitle: '优先展示现有高价值、高覆盖的数感与运算内容',
morePath: '/pages/category/category?id=math',
items: [
{
id: 'current-math-1',
title: '数字认知',
subtitle: '找数字、写数字',
category: 'math',
ageBand: '3-4岁',
difficulty: '入门',
icon: '🔢',
previewImg: '/assets/entrancePicture/math/number-find.png',
path: '/mathPages/mathDraw/mathDraw?id=number-find',
available: true,
source: 'number-find / number-write',
},
{
id: 'current-math-2',
title: '计数练习',
subtitle: '数一数、连一连、选一选',
category: 'math',
ageBand: '4-5岁',
difficulty: '基础',
icon: '🧮',
previewImg: '/assets/entrancePicture/math/count-match.png',
path: '/mathPages/mathDraw/mathDraw?id=counting-matching',
available: true,
source: 'countMatch / countingSelect',
},
{
id: 'current-math-3',
title: '数字序列',
subtitle: '数字排序与缺失填空',
category: 'math',
ageBand: '4-5岁',
difficulty: '基础',
icon: '📈',
previewImg: '/assets/entrancePicture/math/number-sort.png',
path: '/mathPages/mathDraw/mathDraw?id=number-sort',
available: true,
source: 'numberSort / missingNumber',
},
{
id: 'current-math-4',
title: '加减运算',
subtitle: '5以内到100以内逐步进阶',
category: 'math',
ageBand: '5-7岁',
difficulty: '基础',
icon: '',
previewImg: '/assets/entrancePicture/math/addition-5.png',
path: '/mathPages/mathDraw/mathDraw?id=addition',
available: true,
source: 'addition / calculationPractice',
},
{
id: 'current-math-5',
title: '乘法口诀',
subtitle: '九九乘法表启蒙',
category: 'math',
ageBand: '7-8岁',
difficulty: '挑战',
icon: '✖️',
previewImg:
'/assets/entrancePicture/math/multiplication-table.png',
path: '/mathPages/mathDraw/mathDraw?id=multiplication-table',
available: true,
source: 'multiplicationTable',
},
],
},
{
id: 'chinese',
title: '识字练字',
subtitle: '用现有识字与练字能力先覆盖核心语文场景',
morePath: '/pages/category/category?id=chinese',
items: [
{
id: 'current-chinese-1',
title: '识字卡',
subtitle: '最多 6 个汉字,自定义颜色',
category: 'chinese',
ageBand: '3-6岁',
difficulty: '入门',
icon: '📖',
path: '/pages/index/index',
available: true,
source: 'pages/index/index',
},
{
id: 'current-chinese-2',
title: '找一找识字',
subtitle: '识字 find 模板,更接近游戏化练习',
category: 'chinese',
ageBand: '4-6岁',
difficulty: '基础',
icon: '🔍',
path: '/pages/index/index',
available: true,
source: '识字页 find 模板',
},
{
id: 'current-chinese-3',
title: '笔顺练字帖',
subtitle: '田字格与笔顺描红',
category: 'chinese',
ageBand: '4-7岁',
difficulty: '基础',
icon: '✏️',
path: '/pages/copyBook/copyBook',
available: true,
source: 'pages/copyBook/copyBook',
},
],
},
{
id: 'puzzle',
title: '益智游戏',
subtitle: '从现有专注力模块中抽取最符合产品重设计的内容',
morePath: '/pages/category/category?id=puzzle',
items: [
{
id: 'current-puzzle-1',
title: '数字点连线',
subtitle: '按顺序连点成图',
category: 'puzzle',
ageBand: '4-6岁',
difficulty: '基础',
icon: '🔗',
previewImg: '/assets/entrancePicture/focus/dot-connect.png',
path: '/focusPages/focusDraw/focusDraw?id=dot-connect',
available: true,
source: 'dot-connect',
},
{
id: 'current-puzzle-2',
title: '连连看',
subtitle: '物品配对与关系匹配',
category: 'puzzle',
ageBand: '4-6岁',
difficulty: '基础',
icon: '🧵',
previewImg:
'/assets/entrancePicture/focus/match-connect.png',
path: '/focusPages/focusDraw/focusDraw?id=match-connect',
available: true,
source: 'match-connect',
},
{
id: 'current-puzzle-3',
title: '颜色找规律',
subtitle: '模式识别与推理',
category: 'puzzle',
ageBand: '4-6岁',
difficulty: '基础',
icon: '🌈',
previewImg:
'/assets/entrancePicture/focus/color-pattern.png',
path: '/focusPages/focusDraw/focusDraw?id=color-pattern',
available: true,
source: 'color-pattern',
},
{
id: 'current-puzzle-4',
title: '方格推理',
subtitle: '逻辑关系与观察力',
category: 'puzzle',
ageBand: '5-7岁',
difficulty: '进阶',
icon: '🧠',
previewImg:
'/assets/entrancePicture/focus/grid-reasoning.png',
path: '/focusPages/focusDraw/focusDraw?id=grid-reasoning',
available: true,
source: 'grid-reasoning',
},
{
id: 'current-puzzle-5',
title: '格子仿画',
subtitle: '3、5、7 逐级挑战',
category: 'puzzle',
ageBand: '4-7岁',
difficulty: '进阶',
icon: '🟨',
previewImg:
'/assets/entrancePicture/focus/grid-drawing-5x5.png',
path: '/focusPages/focusDraw/focusDraw?id=grid-drawing',
available: true,
source: 'grid-drawing',
},
],
},
{
id: 'english',
title: '英语启蒙',
subtitle: '多种描红版式,认读与书写循序渐进',
morePath: '/pages/category/category?id=english',
items: [
{
id: 'current-english-1',
title: '默认字帖',
subtitle: '配图例句,逐字描红',
category: 'english',
ageBand: '4-7岁',
difficulty: '入门',
icon: '',
previewImg:
'/assets/entrancePicture/english/letter-tracing-single.jpg',
path: '/englishPages/letterTracing/letterTracing?id=letter-tracing-single',
available: true,
source: 'letter-tracing-single',
},
{
id: 'current-english-2',
title: '基础描红',
subtitle: '26 字母大小写速览',
category: 'english',
ageBand: '4-7岁',
difficulty: '入门',
icon: '',
previewImg:
'/assets/entrancePicture/english/letter-tracing-upper-lower.jpg',
path: '/englishPages/letterTracing/letterTracing?id=letter-tracing-upper-lower',
available: true,
source: 'letter-tracing-upper-lower',
},
{
id: 'current-english-3',
title: '大小写对照',
subtitle: '左大右小,逐行对照',
category: 'english',
ageBand: '4-7岁',
difficulty: '入门',
icon: '',
previewImg:
'/assets/entrancePicture/english/letter-tracing-case-pairing.jpg',
path: '/englishPages/letterTracing/letterTracing?id=letter-tracing-case-pairing',
available: true,
source: 'letter-tracing-case-pairing',
},
{
id: 'current-english-4',
title: '两列描红',
subtitle: 'Aa 配对,左右分列',
category: 'english',
ageBand: '4-7岁',
difficulty: '入门',
icon: '',
previewImg:
'/assets/entrancePicture/english/letter-tracing-two-column.jpg',
path: '/englishPages/letterTracing/letterTracing?id=letter-tracing-two-column',
available: true,
source: 'letter-tracing-two-column',
},
{
id: 'current-english-5',
title: '13字母半表',
subtitle: '每行一字,逐字专练',
category: 'english',
ageBand: '4-7岁',
difficulty: '入门',
icon: '',
previewImg:
'/assets/entrancePicture/english/letter-tracing-half.jpg',
path: '/englishPages/letterTracing/letterTracing?id=letter-tracing-half',
available: true,
source: 'letter-tracing-half',
},
{
id: 'current-english-6',
title: '三字母精练',
subtitle: '每页三字,深度书写',
category: 'english',
ageBand: '4-7岁',
difficulty: '入门',
icon: '',
previewImg:
'/assets/entrancePicture/english/letter-tracing-three.jpg',
path: '/englishPages/letterTracing/letterTracing?id=letter-tracing-three',
available: true,
source: 'letter-tracing-three',
},
],
},
{
id: 'craft',
title: '创意手工',
subtitle: '暂用最接近创意表达的现有能力承接展示位',
morePath: '/pages/category/category?id=craft',
items: [
{
id: 'current-craft-1',
title: '涂色识字卡',
subtitle: '在识字场景里提供涂色表达',
category: 'craft',
ageBand: '3-6岁',
difficulty: '入门',
icon: '🎨',
path: '/pages/index/index',
available: true,
source: '现有识字卡着色能力',
},
{
id: 'current-craft-2',
title: '字帖打印',
subtitle: '打印后可反复练习',
category: 'craft',
ageBand: '4-7岁',
difficulty: '基础',
icon: '🖌️',
path: '/pages/copyBook/copyBook',
available: true,
source: '练字页打印能力',
},
],
},
],
};
export const HOME_DISPLAY_DATA = {
productTarget: HOME_PRODUCT_TARGET_DATA,
currentCapability: HOME_CURRENT_CAPABILITY_DATA,
} as const;
+20 -7
View File
@@ -4,7 +4,8 @@ import {
stashPendingCategoryTabId, stashPendingCategoryTabId,
} from '../../utils/index'; } from '../../utils/index';
import { import {
HOME_CURRENT_CAPABILITY_DATA, HOME_DAILY_CHECKIN_ITEMS,
createEmptyHomeDataset,
type HomeDisplayItem, type HomeDisplayItem,
type HomeDisplaySection, type HomeDisplaySection,
type HomeDisplayDataset, type HomeDisplayDataset,
@@ -133,11 +134,22 @@ let _homeData: HomeDisplayDataset | null = null;
function applyHomeData(data: HomeDisplayDataset) { function applyHomeData(data: HomeDisplayDataset) {
_homeData = data; _homeData = data;
const tabs: HomeTab[] = data.categoryTabs.map((item) => ({
id: item.id, const sectionsWithItems = data.sections.filter(
name: item.name, (section) => section.items.length > 0,
})); );
const sections = sortSectionsByTabs(tabs, data.sections); const sectionIdsWithItems = new Set(
sectionsWithItems.map((section) => section.id),
);
const tabs: HomeTab[] = data.categoryTabs
.filter((tab) => tab.id === 'all' || sectionIdsWithItems.has(tab.id))
.map((tab) => ({
id: tab.id,
name: tab.name,
}));
const sections = sortSectionsByTabs(tabs, sectionsWithItems);
const ageBands: HomeAgeBandView[] = data.ageBands.map((item, idx) => ({ const ageBands: HomeAgeBandView[] = data.ageBands.map((item, idx) => ({
...item, ...item,
icon: AGE_BAND_ICONS[idx] || '🌟', icon: AGE_BAND_ICONS[idx] || '🌟',
@@ -156,6 +168,7 @@ Page({
heroSwiperCurrent: 0, heroSwiperCurrent: 0,
featuredItems: SKELETON_FEATURED, featuredItems: SKELETON_FEATURED,
hotRecommends: SKELETON_HOT, hotRecommends: SKELETON_HOT,
dailyCheckinItems: HOME_DAILY_CHECKIN_ITEMS.map(toItemView),
sections: [] as HomeDisplaySectionView[], sections: [] as HomeDisplaySectionView[],
loading: true, loading: true,
}, },
@@ -185,7 +198,7 @@ Page({
sections: (raw.sections || []) as HomeDisplaySection[], sections: (raw.sections || []) as HomeDisplaySection[],
}; };
} else { } else {
homeData = HOME_CURRENT_CAPABILITY_DATA; homeData = createEmptyHomeDataset();
} }
const { tabs, sections, ageBands } = applyHomeData(homeData); const { tabs, sections, ageBands } = applyHomeData(homeData);
+48
View File
@@ -164,6 +164,54 @@
</view> </view>
</view> </view>
<view class="home-section-panel home-section-panel--hot">
<view class="home-section-head">
<text class="home-section-head__title">每日练习</text>
</view>
<view class="home-hot-list">
<view
wx:for="{{dailyCheckinItems}}"
wx:key="id"
class="home-hot-card"
data-title="{{item.title}}"
data-path="{{item.path}}"
bindtap="onTapHotRecommend">
<view class="home-hot-card__thumb">
<image
wx:if="{{item.previewImg}}"
class="home-hot-card__thumb-img"
src="{{item.previewImg}}"
mode="aspectFill" />
<text
wx:if="{{!item.previewImg}}"
class="home-hot-card__thumb-emoji"
>{{item.icon}}</text
>
</view>
<view class="home-hot-card__content">
<text class="home-hot-card__title">{{item.title}}</text>
<text class="home-hot-card__desc"
>{{item.subtitle}}</text
>
<view class="home-hot-card__meta">
<text class="home-hot-card__tag"
>{{item.ageBand}}</text
>
<text class="home-hot-card__score"
>{{item.difficulty}}</text
>
</view>
</view>
<view class="home-hot-card__action">
<toy-icon
name="arrow-right"
size="36rpx"
color="#2b2b2b" />
</view>
</view>
</view>
</view>
<view <view
wx:for="{{sections}}" wx:for="{{sections}}"
wx:key="id" wx:key="id"
@@ -71,8 +71,8 @@ export const PINYIN_DICTATION_WORKSHEET_DEFINITIONS: PinyinDictationWorksheetDef
icon: 'task-o', icon: 'task-o',
title: '拼音每日打卡', title: '拼音每日打卡',
subtitle: '四宫格每日打卡练习', subtitle: '四宫格每日打卡练习',
ageMin: 6, ageMin: 5,
ageMax: 8, ageMax: 7,
difficulty: 2, difficulty: 2,
tags: ['拼音', '每日练习', '打卡'], tags: ['拼音', '每日练习', '打卡'],
sortOrder: 54, sortOrder: 54,
@@ -10,7 +10,7 @@ export const MOCK_SEED_COUNTS: Record<
downloads: 0, downloads: 0,
likes: 0, likes: 0,
}, },
'handwriting-sheet': { 'hanzi-sheet': {
downloads: 0, downloads: 0,
likes: 0, likes: 0,
}, },
+145 -145
View File
@@ -1,148 +1,148 @@
{ {
"description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html", "description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html",
"projectname": "doodle-mini", "projectname": "doodle-mini",
"setting": { "setting": {
"compileHotReLoad": true, "compileHotReLoad": true,
"urlCheck": true, "urlCheck": true,
"coverView": false, "coverView": false,
"lazyloadPlaceholderEnable": false, "lazyloadPlaceholderEnable": false,
"skylineRenderEnable": true, "skylineRenderEnable": true,
"preloadBackgroundData": false, "preloadBackgroundData": false,
"autoAudits": false, "autoAudits": false,
"useApiHook": true, "useApiHook": true,
"useApiHostProcess": true, "useApiHostProcess": true,
"showShadowRootInWxmlPanel": false, "showShadowRootInWxmlPanel": false,
"useStaticServer": false, "useStaticServer": false,
"useLanDebug": false, "useLanDebug": false,
"showES6CompileOption": false, "showES6CompileOption": false,
"checkInvalidKey": true, "checkInvalidKey": true,
"ignoreDevUnusedFiles": true, "ignoreDevUnusedFiles": true,
"bigPackageSizeSupport": false "bigPackageSizeSupport": false
}, },
"libVersion": "3.7.12", "libVersion": "3.7.12",
"condition": { "condition": {
"miniprogram": { "miniprogram": {
"list": [ "list": [
{ {
"name": "chinesePages/handwritingSheet/handwritingSheet", "name": "chinesePages/handwritingSheet/handwritingSheet",
"pathName": "chinesePages/handwritingSheet/handwritingSheet", "pathName": "chinesePages/handwritingSheet/handwritingSheet",
"query": "id=handwriting-sheet", "query": "id=hanzi-sheet",
"scene": null, "scene": null,
"launchMode": "default" "launchMode": "default"
}, },
{ {
"name": "chinesePages/handwritingSheet/handwritingSheet", "name": "chinesePages/handwritingSheet/handwritingSheet",
"pathName": "chinesePages/handwritingSheet/handwritingSheet", "pathName": "chinesePages/handwritingSheet/handwritingSheet",
"query": "id=handwriting-sheet", "query": "id=hanzi-sheet",
"launchMode": "default", "launchMode": "default",
"scene": null "scene": null
}, },
{ {
"name": "pinyinPages/pinyinDictation/pinyinDictation", "name": "pinyinPages/pinyinDictation/pinyinDictation",
"pathName": "pinyinPages/pinyinDictation/pinyinDictation", "pathName": "pinyinPages/pinyinDictation/pinyinDictation",
"query": "", "query": "",
"launchMode": "default", "launchMode": "default",
"scene": null "scene": null
}, },
{ {
"name": "chinesePages/handwritingSheet/handwritingSheet", "name": "chinesePages/handwritingSheet/handwritingSheet",
"pathName": "chinesePages/handwritingSheet/handwritingSheet", "pathName": "chinesePages/handwritingSheet/handwritingSheet",
"query": "", "query": "",
"launchMode": "default", "launchMode": "default",
"scene": null "scene": null
}, },
{ {
"name": "chinesePages/wordColoring/wordColoring", "name": "chinesePages/wordColoring/wordColoring",
"pathName": "chinesePages/wordColoring/wordColoring", "pathName": "chinesePages/wordColoring/wordColoring",
"query": "", "query": "",
"launchMode": "default", "launchMode": "default",
"scene": null "scene": null
}, },
{ {
"name": "pages/profile/profile", "name": "pages/profile/profile",
"pathName": "pages/profile/profile", "pathName": "pages/profile/profile",
"query": "", "query": "",
"launchMode": "default", "launchMode": "default",
"scene": null "scene": null
}, },
{ {
"name": "pages/age/age", "name": "pages/age/age",
"pathName": "pages/age/age", "pathName": "pages/age/age",
"query": "", "query": "",
"launchMode": "default", "launchMode": "default",
"scene": null "scene": null
}, },
{ {
"name": "supportPages/debug/debug", "name": "supportPages/debug/debug",
"pathName": "supportPages/debug/debug", "pathName": "supportPages/debug/debug",
"query": "", "query": "",
"launchMode": "default", "launchMode": "default",
"scene": null "scene": null
}, },
{ {
"name": "englishPages/letterTracing/letterTracing", "name": "englishPages/letterTracing/letterTracing",
"pathName": "englishPages/letterTracing/letterTracing", "pathName": "englishPages/letterTracing/letterTracing",
"query": "", "query": "",
"launchMode": "default", "launchMode": "default",
"scene": null "scene": null
}, },
{ {
"name": "supportPages/debug/debug", "name": "supportPages/debug/debug",
"pathName": "supportPages/debug/debug", "pathName": "supportPages/debug/debug",
"query": "", "query": "",
"launchMode": "default", "launchMode": "default",
"scene": null "scene": null
}, },
{ {
"name": "pages/category/category", "name": "pages/category/category",
"pathName": "pages/category/category", "pathName": "pages/category/category",
"query": "", "query": "",
"launchMode": "default", "launchMode": "default",
"scene": null "scene": null
}, },
{ {
"name": "mathIndex", "name": "mathIndex",
"pathName": "mathPages/mathDraw/mathDraw", "pathName": "mathPages/mathDraw/mathDraw",
"query": "", "query": "",
"launchMode": "default", "launchMode": "default",
"scene": null "scene": null
}, },
{ {
"name": "focusDraw", "name": "focusDraw",
"pathName": "focusPages/focusDraw/focusDraw", "pathName": "focusPages/focusDraw/focusDraw",
"query": "", "query": "",
"launchMode": "default", "launchMode": "default",
"scene": null "scene": null
}, },
{ {
"name": "oldFocusIndex", "name": "oldFocusIndex",
"pathName": "supportPages/focusIndex/focusIndex", "pathName": "supportPages/focusIndex/focusIndex",
"query": "", "query": "",
"launchMode": "default", "launchMode": "default",
"scene": null "scene": null
}, },
{ {
"name": "oldMathIndex", "name": "oldMathIndex",
"pathName": "supportPages/mathIndex/mathIndex", "pathName": "supportPages/mathIndex/mathIndex",
"query": "", "query": "",
"launchMode": "default", "launchMode": "default",
"scene": null "scene": null
}, },
{ {
"name": "pages/index/index", "name": "pages/index/index",
"pathName": "pages/index/index", "pathName": "pages/index/index",
"query": "", "query": "",
"launchMode": "default", "launchMode": "default",
"scene": null "scene": null
}, },
{ {
"name": "englishPages/letterTracing/letterTracing", "name": "englishPages/letterTracing/letterTracing",
"pathName": "englishPages/letterTracing/letterTracing", "pathName": "englishPages/letterTracing/letterTracing",
"query": "id=letter-tracing-single", "query": "id=letter-tracing-single",
"launchMode": "default", "launchMode": "default",
"scene": null "scene": null
}
]
} }
]
} }
} }
}