diff --git a/miniprogram/assets/tabBar/2.0/icon-age-active.png b/backup/tabbar/2.0/icon-age-active.png similarity index 100% rename from miniprogram/assets/tabBar/2.0/icon-age-active.png rename to backup/tabbar/2.0/icon-age-active.png diff --git a/miniprogram/assets/tabBar/2.0/icon-age.png b/backup/tabbar/2.0/icon-age.png similarity index 100% rename from miniprogram/assets/tabBar/2.0/icon-age.png rename to backup/tabbar/2.0/icon-age.png diff --git a/miniprogram/assets/tabBar/2.0/icon-edit-active.png b/backup/tabbar/2.0/icon-edit-active.png similarity index 100% rename from miniprogram/assets/tabBar/2.0/icon-edit-active.png rename to backup/tabbar/2.0/icon-edit-active.png diff --git a/miniprogram/assets/tabBar/2.0/icon-edit.png b/backup/tabbar/2.0/icon-edit.png similarity index 100% rename from miniprogram/assets/tabBar/2.0/icon-edit.png rename to backup/tabbar/2.0/icon-edit.png diff --git a/miniprogram/assets/tabBar/2.0/icon-fav-active.png b/backup/tabbar/2.0/icon-fav-active.png similarity index 100% rename from miniprogram/assets/tabBar/2.0/icon-fav-active.png rename to backup/tabbar/2.0/icon-fav-active.png diff --git a/miniprogram/assets/tabBar/2.0/icon-fav.png b/backup/tabbar/2.0/icon-fav.png similarity index 100% rename from miniprogram/assets/tabBar/2.0/icon-fav.png rename to backup/tabbar/2.0/icon-fav.png diff --git a/miniprogram/assets/tabBar/2.0/icon-home-active.png b/backup/tabbar/2.0/icon-home-active.png similarity index 100% rename from miniprogram/assets/tabBar/2.0/icon-home-active.png rename to backup/tabbar/2.0/icon-home-active.png diff --git a/miniprogram/assets/tabBar/2.0/icon-home.png b/backup/tabbar/2.0/icon-home.png similarity index 100% rename from miniprogram/assets/tabBar/2.0/icon-home.png rename to backup/tabbar/2.0/icon-home.png diff --git a/miniprogram/assets/tabBar/2.0/icon-math-active.png b/backup/tabbar/2.0/icon-math-active.png similarity index 100% rename from miniprogram/assets/tabBar/2.0/icon-math-active.png rename to backup/tabbar/2.0/icon-math-active.png diff --git a/miniprogram/assets/tabBar/2.0/icon-math.png b/backup/tabbar/2.0/icon-math.png similarity index 100% rename from miniprogram/assets/tabBar/2.0/icon-math.png rename to backup/tabbar/2.0/icon-math.png diff --git a/miniprogram/assets/tabBar/2.0/icon-profile-active.png b/backup/tabbar/2.0/icon-profile-active.png similarity index 100% rename from miniprogram/assets/tabBar/2.0/icon-profile-active.png rename to backup/tabbar/2.0/icon-profile-active.png diff --git a/miniprogram/assets/tabBar/2.0/icon-profile.png b/backup/tabbar/2.0/icon-profile.png similarity index 100% rename from miniprogram/assets/tabBar/2.0/icon-profile.png rename to backup/tabbar/2.0/icon-profile.png diff --git a/miniprogram/assets/tabBar/2.0/icon-word-active.png b/backup/tabbar/2.0/icon-word-active.png similarity index 100% rename from miniprogram/assets/tabBar/2.0/icon-word-active.png rename to backup/tabbar/2.0/icon-word-active.png diff --git a/miniprogram/assets/tabBar/2.0/icon-word.png b/backup/tabbar/2.0/icon-word.png similarity index 100% rename from miniprogram/assets/tabBar/2.0/icon-word.png rename to backup/tabbar/2.0/icon-word.png diff --git a/miniprogram/assets/tabBar/old/icon-shape-active.png b/backup/tabbar/old/icon-shape-active.png similarity index 100% rename from miniprogram/assets/tabBar/old/icon-shape-active.png rename to backup/tabbar/old/icon-shape-active.png diff --git a/miniprogram/assets/tabBar/old/icon-shape-active2.png b/backup/tabbar/old/icon-shape-active2.png similarity index 100% rename from miniprogram/assets/tabBar/old/icon-shape-active2.png rename to backup/tabbar/old/icon-shape-active2.png diff --git a/miniprogram/assets/tabBar/old/icon-shape.png b/backup/tabbar/old/icon-shape.png similarity index 100% rename from miniprogram/assets/tabBar/old/icon-shape.png rename to backup/tabbar/old/icon-shape.png diff --git a/miniprogram/assets/tabBar/old/icon-word-active.png b/backup/tabbar/old/icon-word-active.png similarity index 100% rename from miniprogram/assets/tabBar/old/icon-word-active.png rename to backup/tabbar/old/icon-word-active.png diff --git a/miniprogram/assets/tabBar/old/icon-word-active2.png b/backup/tabbar/old/icon-word-active2.png similarity index 100% rename from miniprogram/assets/tabBar/old/icon-word-active2.png rename to backup/tabbar/old/icon-word-active2.png diff --git a/miniprogram/assets/tabBar/old/icon-word.png b/backup/tabbar/old/icon-word.png similarity index 100% rename from miniprogram/assets/tabBar/old/icon-word.png rename to backup/tabbar/old/icon-word.png diff --git a/miniprogram/app.json b/miniprogram/app.json index e20c63d..b797416 100644 --- a/miniprogram/app.json +++ b/miniprogram/app.json @@ -1,6 +1,7 @@ { "pages": [ "pages/home/home", + "pages/category/category", "pages/age/age", "pages/favorites/favorites", "pages/profile/profile" @@ -79,6 +80,12 @@ "selectedIconPath": "assets/tabBar/home-active.png", "text": "发现" }, + { + "pagePath": "pages/category/category", + "iconPath": "assets/tabBar/category.png", + "selectedIconPath": "assets/tabBar/category-active.png", + "text": "分类" + }, { "pagePath": "pages/age/age", "iconPath": "assets/tabBar/age.png", diff --git a/miniprogram/assets/tabBar/2.0/icon-shape-active.png b/miniprogram/assets/tabBar/2.0/icon-shape-active.png deleted file mode 100644 index fb56cf8..0000000 Binary files a/miniprogram/assets/tabBar/2.0/icon-shape-active.png and /dev/null differ diff --git a/miniprogram/assets/tabBar/2.0/icon-shape.png b/miniprogram/assets/tabBar/2.0/icon-shape.png deleted file mode 100644 index 0c5336e..0000000 Binary files a/miniprogram/assets/tabBar/2.0/icon-shape.png and /dev/null differ diff --git a/miniprogram/assets/tabBar/category-active.png b/miniprogram/assets/tabBar/category-active.png new file mode 100644 index 0000000..ae94df3 Binary files /dev/null and b/miniprogram/assets/tabBar/category-active.png differ diff --git a/miniprogram/assets/tabBar/category.png b/miniprogram/assets/tabBar/category.png new file mode 100644 index 0000000..d5e2a8a Binary files /dev/null and b/miniprogram/assets/tabBar/category.png differ diff --git a/miniprogram/components3.0/nav-bar/nav-bar.less b/miniprogram/components3.0/nav-bar/nav-bar.less index 9cc91f4..4adce12 100644 --- a/miniprogram/components3.0/nav-bar/nav-bar.less +++ b/miniprogram/components3.0/nav-bar/nav-bar.less @@ -19,10 +19,34 @@ flex-direction: row; align-items: center; justify-content: flex-start; + gap: 10px; padding: 0 @page-padding-x; box-sizing: border-box; } +.nav-bar__brand { + display: flex; + flex-direction: row; + align-items: center; + gap: 10px; + flex-shrink: 0; +} + +.nav-bar__logo { + width: 32px; + height: 32px; + border-radius: 16px; + flex-shrink: 0; +} + +.nav-bar__brand-name { + font-size: @fs-nav-title; + font-weight: @fw-nav-title; + color: @color-nav-title; + letter-spacing: @ls-nav-title; + line-height: 1; +} + .nav-bar__back { width: 64rpx; height: 64rpx; diff --git a/miniprogram/components3.0/nav-bar/nav-bar.ts b/miniprogram/components3.0/nav-bar/nav-bar.ts index 8b84793..e5736be 100644 --- a/miniprogram/components3.0/nav-bar/nav-bar.ts +++ b/miniprogram/components3.0/nav-bar/nav-bar.ts @@ -1,8 +1,11 @@ import { NAV_INNER_PX } from '../../utils/navMetrics'; const HOME_TAB_URL = '/pages/home/home'; +const HOME_ROUTE = 'pages/home/home'; + const TAB_BAR_ROUTES = new Set([ - 'pages/home/home', + HOME_ROUTE, + 'pages/category/category', 'pages/age/age', 'pages/favorites/favorites', 'pages/profile/profile', @@ -17,7 +20,9 @@ Component({ data: { statusBarHeight: 0, navBlockHeight: 0, - leftActionType: 'none', + leftActionType: 'none' as 'none' | 'back' | 'home' | 'brand', + /** 仅首页(Tab 根页)在 logo 旁展示「涂鸦丫」;其余主 Tab 只展示 logo */ + showBrandName: false, }, lifetimes: { attached() { @@ -40,15 +45,19 @@ Component({ const currentRoute = pages[pages.length - 1]?.route || ''; const isTabBarPage = TAB_BAR_ROUTES.has(currentRoute); - let leftActionType: 'none' | 'back' | 'home' = 'none'; + let leftActionType: 'none' | 'back' | 'home' | 'brand' = 'none'; + const showBrandName = currentRoute === HOME_ROUTE; if (pages.length > 1) { leftActionType = 'back'; } else if (!isTabBarPage) { leftActionType = 'home'; + } else { + // 五个主 Tab 根页:仅展示品牌区(左 logo;首页另见 showBrandName) + leftActionType = 'brand'; } - this.setData({ leftActionType }); + this.setData({ leftActionType, showBrandName }); }, handleLeftAction() { diff --git a/miniprogram/components3.0/nav-bar/nav-bar.wxml b/miniprogram/components3.0/nav-bar/nav-bar.wxml index 6ca2a87..f33fe86 100644 --- a/miniprogram/components3.0/nav-bar/nav-bar.wxml +++ b/miniprogram/components3.0/nav-bar/nav-bar.wxml @@ -2,7 +2,17 @@ class="nav-bar" style="padding-top: {{statusBarHeight}}px; {{background ? 'background:' + background + ';' : ''}}"> + + + 涂鸦丫 + - {{title}} diff --git a/miniprogram/pages/category/category.data.ts b/miniprogram/pages/category/category.data.ts new file mode 100644 index 0000000..a065861 --- /dev/null +++ b/miniprogram/pages/category/category.data.ts @@ -0,0 +1,149 @@ +export type CategoryItem = { + id: string; + title: string; + subtitle: string; + icon: string; + img?: string; + ageBand: string; + difficulty: string; + path: string; + available: boolean; + likes: number; + downloads: number; + date: string; +}; + +export type CategoryGroup = { + id: string; + name: string; + icon: string; + items: CategoryItem[]; +}; + +export type CategoryDataset = { + searchPlaceholder: string; + categories: CategoryGroup[]; +}; + +const DIFFICULTY_MAP: Record = { + beginner: '入门', + basic: '基础', + intermediate: '进阶', + advanced: '挑战', +}; + +function d(key: string): string { + return DIFFICULTY_MAP[key] ?? key; +} + +function age(min: number, max: number): string { + return `${min}-${max}岁`; +} + +const TODAY = '2026-4-22'; + +/** 基于 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 }; +} + +type ItemInput = Omit; + +function item(input: ItemInput): CategoryItem { + const { likes, downloads } = statsFromId(input.id); + return { ...input, likes, downloads, date: TODAY }; +} + +// prettier-ignore +export const CATEGORY_DATA: CategoryDataset = { + searchPlaceholder: '搜索练习纸...', + categories: [ + { + id: 'math', name: '数感启蒙', icon: '📐', + items: [ + item({ id: 'number-find', title: '找数字,涂一涂', subtitle: '在数字方阵中找出目标数字并涂色', icon: '🔍', img: '/assets/entrancePicture/math/number-find.png', ageBand: age(3, 5), difficulty: d('beginner'), path: '/mathPages/mathDraw/mathDraw?id=number-find', available: true }), + item({ id: 'number-write', title: '看数字,写一写', subtitle: '按笔画顺序练习书写数字', icon: '✏️', img: '/assets/entrancePicture/math/number-write.png', ageBand: age(3, 5), difficulty: d('beginner'), path: '/mathPages/mathDraw/mathDraw?id=number-write', available: true }), + item({ id: 'number-coloring', title: '按数字,涂颜色', subtitle: '按指定数字给对应圆圈涂色', icon: '🎨', img: '/assets/entrancePicture/math/number-coloring.png', ageBand: age(3, 5), difficulty: d('beginner'), path: '/mathPages/mathDraw/mathDraw?id=number-coloring', available: true }), + item({ id: 'counting-matching', title: '数一数,连一连', subtitle: '连线配对数字和对应数量图形', icon: '🔗', img: '/assets/entrancePicture/math/count-match.png', ageBand: age(3, 5), difficulty: d('beginner'), path: '/mathPages/mathDraw/mathDraw?id=counting-matching', available: true }), + item({ id: 'number-object-match', title: '数物连线', subtitle: '连线相同数量的物品和数字', icon: '🔗', img: '/assets/entrancePicture/math/number-object-match.png', ageBand: age(3, 5), difficulty: d('beginner'), path: '/mathPages/mathDraw/mathDraw?id=number-object-match', available: true }), + item({ id: 'number-object-fill', title: '数物填写', subtitle: '数物品数量,填写对应数字', icon: '✏️', img: '/assets/entrancePicture/math/number-object-fill.png', ageBand: age(3, 5), difficulty: d('beginner'), path: '/mathPages/mathDraw/mathDraw?id=number-object-fill', available: true }), + item({ id: 'counting-select', title: '数一数,选一选', subtitle: '数出物品数量,圈出正确答案', icon: '✓', img: '/assets/entrancePicture/math/counting-select.png', ageBand: age(3, 5), difficulty: d('beginner'), path: '/mathPages/mathDraw/mathDraw?id=counting-select', available: true }), + item({ id: 'counting-fill', title: '数一数,填一填', subtitle: '数出物品数量,填写数字', icon: '✏️', img: '/assets/entrancePicture/math/counting-fill.png', ageBand: age(3, 5), difficulty: d('beginner'), path: '/mathPages/mathDraw/mathDraw?id=counting-fill', available: true }), + item({ id: 'compare', title: '数一数,比大小', subtitle: '比较数量,填入 ><=', icon: '⚖️', img: '/assets/entrancePicture/math/compare.png', ageBand: age(4, 6), difficulty: d('basic'), path: '/mathPages/mathDraw/mathDraw?id=compare', available: true }), + item({ id: 'number-sort', title: '数字排序', subtitle: '写出正确的数字顺序', icon: '🔢', img: '/assets/entrancePicture/math/number-sort.png', ageBand: age(4, 6), difficulty: d('basic'), path: '/mathPages/mathDraw/mathDraw?id=number-sort', available: true }), + item({ id: 'missing-number', title: '填上缺少的数字', subtitle: '在数列中找出并填写缺失数字', icon: '❓', img: '/assets/entrancePicture/math/missing-number.png', ageBand: age(4, 6), difficulty: d('basic'), path: '/mathPages/mathDraw/mathDraw?id=missing-number', available: true }), + item({ id: 'number-decompose', title: '10以内数的分与合', subtitle: '把数字分一分,合一合', icon: '🔢', img: '/assets/entrancePicture/math/number-decompose.png', ageBand: age(4, 6), difficulty: d('beginner'), path: '/mathPages/mathDraw/mathDraw?id=number-decompose', available: true }), + item({ id: 'number-decompose-20', title: '20以内数的分与合', subtitle: '把数字分一分,合一合', icon: '🔢', img: '/assets/entrancePicture/math/number-decompose-20.png', ageBand: age(5, 7), difficulty: d('basic'), path: '/mathPages/mathDraw/mathDraw?id=number-decompose-20', available: true }), + item({ id: 'one-digit-addition', title: '一位数加法', subtitle: '通过圆点学习一位数加法运算', icon: '➕', img: '/assets/entrancePicture/math/one-digit-addition.png', ageBand: age(4, 6), difficulty: d('basic'), path: '/mathPages/mathDraw/mathDraw?id=one-digit-addition', available: true }), + item({ id: 'addition-5', title: '5以内加法', subtitle: '图形化展示 5 以内加法', icon: '➕', img: '/assets/entrancePicture/math/addition-5.png', ageBand: age(3, 5), difficulty: d('beginner'), path: '/mathPages/mathDraw/mathDraw?id=addition-5', available: true }), + item({ id: 'addition-10', title: '10以内加法', subtitle: '图形化展示 10 以内加法', icon: '➕', img: '/assets/entrancePicture/math/addition-10.png', ageBand: age(4, 6), difficulty: d('basic'), path: '/mathPages/mathDraw/mathDraw?id=addition-10', available: true }), + item({ id: 'subtraction-10', title: '10以内减法', subtitle: '图形化展示 10 以内减法', icon: '➖', img: '/assets/entrancePicture/math/subtraction-10.png', ageBand: age(4, 6), difficulty: d('basic'), path: '/mathPages/mathDraw/mathDraw?id=subtraction-10', available: true }), + item({ id: 'addition-subtraction-10', title: '10以内加减法', subtitle: '加减法混合运算', icon: '±', img: '/assets/entrancePicture/math/addition-subtraction-10.png', ageBand: age(5, 7), difficulty: d('basic'), path: '/mathPages/mathDraw/mathDraw?id=addition-subtraction-10', available: true }), + item({ id: 'make-ten', title: '凑十法练习', subtitle: '20 以内进位加法', icon: '➕', img: '/assets/entrancePicture/math/make-ten.png', ageBand: age(5, 7), difficulty: d('intermediate'), path: '/mathPages/mathDraw/mathDraw?id=make-ten', available: true }), + item({ id: 'break-ten', title: '破十法练习', subtitle: '20 以内退位减法', icon: '➖', img: '/assets/entrancePicture/math/break-ten.png', ageBand: age(5, 7), difficulty: d('intermediate'), path: '/mathPages/mathDraw/mathDraw?id=break-ten', available: true }), + item({ id: 'flat-ten', title: '平十法练习', subtitle: '20 以内退位减法', icon: '➖', img: '/assets/entrancePicture/math/flat-ten.png', ageBand: age(5, 7), difficulty: d('intermediate'), path: '/mathPages/mathDraw/mathDraw?id=flat-ten', available: true }), + item({ id: 'borrow-ten', title: '借十法练习', subtitle: '20 以上退位减法', icon: '➖', img: '/assets/entrancePicture/math/borrow-ten.png', ageBand: age(6, 8), difficulty: d('advanced'), path: '/mathPages/mathDraw/mathDraw?id=borrow-ten', available: true }), + item({ id: 'practice-addition', title: '加法运算', subtitle: '10/20/50/100 以内加法', icon: '➕', img: '/assets/entrancePicture/math/practice-addition.png', ageBand: age(5, 8), difficulty: d('intermediate'), path: '/mathPages/mathDraw/mathDraw?id=practice-addition', available: true }), + item({ id: 'practice-subtraction', title: '减法运算', subtitle: '10/20/50/100 以内减法', icon: '➖', img: '/assets/entrancePicture/math/practice-subtraction.png', ageBand: age(5, 8), difficulty: d('intermediate'), path: '/mathPages/mathDraw/mathDraw?id=practice-subtraction', available: true }), + item({ id: 'practice-mixed', title: '混合运算', subtitle: '10/20/50/100 以内加减法混合', icon: '±', img: '/assets/entrancePicture/math/practice-mixed.png', ageBand: age(5, 8), difficulty: d('intermediate'), path: '/mathPages/mathDraw/mathDraw?id=practice-mixed', available: true }), + item({ id: 'multiplication-table', title: '九九乘法表', subtitle: '学习九九乘法口诀', icon: '✖️', img: '/assets/entrancePicture/math/multiplication-table.png', ageBand: age(6, 8), difficulty: d('intermediate'), path: '/mathPages/mathDraw/mathDraw?id=multiplication-table', available: true }), + ], + }, + { + id: 'pinyin', name: '汉语拼音', icon: '🔤', + items: [ + item({ id: 'pinyin-initials', title: '声母描红', subtitle: '23个声母认读与书写练习', icon: '🔤', ageBand: age(5, 7), difficulty: d('basic'), path: '', available: false }), + item({ id: 'pinyin-finals', title: '韵母描红', subtitle: '24个韵母认读与书写练习', icon: '🔤', ageBand: age(5, 7), difficulty: d('basic'), path: '', available: false }), + item({ id: 'pinyin-overall', title: '整体认读音节', subtitle: '16个整体认读音节练习', icon: '🔤', ageBand: age(5, 7), difficulty: d('intermediate'), path: '', available: false }), + ], + }, + { + id: 'puzzle', name: '益智游戏', icon: '🧩', + items: [ + item({ id: 'color-shape-match', title: '根据颜色画图形', subtitle: '根据颜色画出对应图形', icon: '🎯', img: '/assets/entrancePicture/focus/color-shape-match.png', ageBand: age(4, 6), difficulty: d('basic'), path: '/focusPages/focusDraw/focusDraw?id=color-shape-match', available: true }), + item({ id: 'shape-symbol', title: '图形符号配对', subtitle: '根据图形画对应符号', icon: '🔗', img: '/assets/entrancePicture/focus/shape-symbol.png', ageBand: age(4, 6), difficulty: d('basic'), path: '/focusPages/focusDraw/focusDraw?id=shape-symbol', available: true }), + item({ id: 'shape-recognition', title: '识别形状', subtitle: '识别形状,涂一涂', icon: '🔍', img: '/assets/entrancePicture/focus/shape-recognition.png', ageBand: age(3, 5), difficulty: d('beginner'), path: '/focusPages/focusDraw/focusDraw?id=shape-recognition', available: true }), + item({ id: 'position-coloring', title: '方位涂涂乐', subtitle: '观察位置,在方格中涂色', icon: '📍', img: '/assets/entrancePicture/focus/position-coloring.png', ageBand: age(4, 6), difficulty: d('basic'), path: '/focusPages/focusDraw/focusDraw?id=position-coloring', available: true }), + item({ id: 'color-pattern', title: '颜色找规律', subtitle: '观察颜色规律,在空白图形中涂色', icon: '🎨', img: '/assets/entrancePicture/focus/color-pattern.png', ageBand: age(4, 6), difficulty: d('basic'), path: '/focusPages/focusDraw/focusDraw?id=color-pattern', available: true }), + item({ id: 'match-connect', title: '连连看', subtitle: '根据物品连一连', icon: '🔗', img: '/assets/entrancePicture/focus/match-connect.png', ageBand: age(3, 6), difficulty: d('beginner'), path: '/focusPages/focusDraw/focusDraw?id=match-connect', available: true }), + item({ id: 'line-recognition', title: '线条识别', subtitle: '认识不同线条,画出颜色对应的线条', icon: '📏', img: '/assets/entrancePicture/focus/line-recognition.png', ageBand: age(3, 5), difficulty: d('beginner'), path: '/focusPages/focusDraw/focusDraw?id=line-recognition', available: true }), + item({ id: 'grid-reasoning', title: '方格推理', subtitle: '推理出合并方格并连线', icon: '🧩', img: '/assets/entrancePicture/focus/grid-reasoning.png', ageBand: age(5, 7), difficulty: d('intermediate'), path: '/focusPages/focusDraw/focusDraw?id=grid-reasoning', available: true }), + item({ id: 'code-connect', title: '译码连线', subtitle: '按数字顺序将数字对应颜色连线', icon: '🔢', img: '/assets/entrancePicture/focus/code-connect.png', ageBand: age(5, 7), difficulty: d('intermediate'), path: '/focusPages/focusDraw/focusDraw?id=code-connect', available: true }), + item({ id: 'dot-connect', title: '数字点连线', subtitle: '按数字顺序连点成图', icon: '🔗', img: '/assets/entrancePicture/focus/dot-connect.png', ageBand: age(3, 6), difficulty: d('beginner'), path: '/focusPages/focusDraw/focusDraw?id=dot-connect', available: true }), + item({ id: 'grid-drawing-3x3', title: '格子仿画 3×3', subtitle: '简单有趣,培养专注力', icon: '🎨', img: '/assets/entrancePicture/focus/grid-drawing-3x3.png', ageBand: age(3, 5), difficulty: d('beginner'), path: '/focusPages/focusDraw/focusDraw?id=grid-drawing-3x3', available: true }), + item({ id: 'grid-drawing-5x5', title: '格子仿画 5×5', subtitle: '创意挑战,提升观察力', icon: '🎨', img: '/assets/entrancePicture/focus/grid-drawing-5x5.png', ageBand: age(4, 6), difficulty: d('basic'), path: '/focusPages/focusDraw/focusDraw?id=grid-drawing-5x5', available: true }), + item({ id: 'grid-drawing-7x7', title: '格子仿画 7×7', subtitle: '大师挑战,锻炼耐心', icon: '🎨', img: '/assets/entrancePicture/focus/grid-drawing-7x7.png', ageBand: age(5, 8), difficulty: d('intermediate'), path: '/focusPages/focusDraw/focusDraw?id=grid-drawing-7x7', available: true }), + ], + }, + { + id: 'chinese', name: '趣味识字', icon: '✏️', + items: [ + item({ id: 'word-recognition', title: '识字卡', subtitle: '输入或选字生成涂色识字卡', icon: '📖', ageBand: age(3, 6), difficulty: d('beginner'), path: '/pages/index/index', available: true }), + item({ id: 'copybook', title: '练字帖', subtitle: '选字生成田字格笔顺练字帖', icon: '✏️', ageBand: age(4, 7), difficulty: d('basic'), path: '/pages/copyBook/copyBook', available: true }), + ], + }, + { + id: 'english', name: '英语启蒙', icon: '🔤', + items: [ + item({ id: 'letter-tracing-single', title: '看图描红', subtitle: '单字母配图、例句与六行四线三格描红', icon: '🔠', img: '/assets/entrancePicture/english/letter-tracing-single.jpg', ageBand: age(4, 7), difficulty: d('beginner'), path: '/englishPages/letterTracing/letterTracing?id=letter-tracing-single', available: true }), + item({ id: 'letter-tracing-upper-lower', title: '字母总览', subtitle: 'Uppercase / Lowercase 分区总览', icon: '🔡', img: '/assets/entrancePicture/english/letter-tracing-upper-lower.jpg', ageBand: age(4, 7), difficulty: d('beginner'), path: '/englishPages/letterTracing/letterTracing?id=letter-tracing-upper-lower', available: true }), + item({ id: 'letter-tracing-case-pairing', title: '大小写练习', subtitle: '半组字母左大写右小写,逐行对照描红', icon: '✏️', img: '/assets/entrancePicture/english/letter-tracing-case-pairing.jpg', ageBand: age(4, 7), difficulty: d('beginner'), path: '/englishPages/letterTracing/letterTracing?id=letter-tracing-case-pairing', available: true }), + item({ id: 'letter-tracing-two-column', title: '两列练习', subtitle: '左 A–M、右 N–Z,大小写配对描红', icon: '🔤', img: '/assets/entrancePicture/english/letter-tracing-two-column.jpg', ageBand: age(4, 7), difficulty: d('beginner'), path: '/englishPages/letterTracing/letterTracing?id=letter-tracing-two-column', available: true }), + item({ id: 'letter-tracing-half', title: '单字母逐行', subtitle: '13 字母半表逐字练习', icon: '📝', img: '/assets/entrancePicture/english/letter-tracing-half.jpg', ageBand: age(4, 7), difficulty: d('basic'), path: '/englishPages/letterTracing/letterTracing?id=letter-tracing-half', available: true }), + item({ id: 'letter-tracing-three', title: '三字母精练', subtitle: '每页 3 个字母,大写 + 小写深度书写', icon: '🔤', img: '/assets/entrancePicture/english/letter-tracing-three.jpg', ageBand: age(4, 7), difficulty: d('basic'), path: '/englishPages/letterTracing/letterTracing?id=letter-tracing-three', available: true }), + ], + }, + { + id: 'craft', name: '创意手工', icon: '🌈', + items: [ + item({ id: 'craft-coloring', title: '涂色卡', subtitle: '动物、交通、节日主题涂色', icon: '🎨', ageBand: age(3, 6), difficulty: d('beginner'), path: '', available: false }), + item({ id: 'craft-origami', title: '折纸模板', subtitle: '打印后即可折叠的趣味模板', icon: '🪭', ageBand: age(4, 7), difficulty: d('basic'), path: '', available: false }), + item({ id: 'craft-stickers', title: '贴纸打印', subtitle: '奖励贴纸与装饰贴纸', icon: '⭐', ageBand: age(3, 8), difficulty: d('beginner'), path: '', available: false }), + ], + }, + ], +}; diff --git a/miniprogram/pages/category/category.json b/miniprogram/pages/category/category.json new file mode 100644 index 0000000..6e50618 --- /dev/null +++ b/miniprogram/pages/category/category.json @@ -0,0 +1,13 @@ +{ + "navigationStyle": "custom", + "navigationBarTitleText": "分类", + "navigationBarTextStyle": "black", + "navigationBarBackgroundColor": "#FEF6E7", + "backgroundColor": "#FEF6E7", + "enablePullDownRefresh": false, + "usingComponents": { + "nav-bar": "../../components3.0/nav-bar/nav-bar", + "van-icon": "@vant/weapp/icon/index", + "toy-icon": "/toy/icon/icon" + } +} diff --git a/miniprogram/pages/category/category.less b/miniprogram/pages/category/category.less new file mode 100644 index 0000000..332ba48 --- /dev/null +++ b/miniprogram/pages/category/category.less @@ -0,0 +1,263 @@ +@import '../../style/theme.less'; +@import '../../style/tags.less'; + +.cat-page { + height: 100vh; + background: @bg-page; + display: flex; + flex-direction: column; + overflow: hidden; + color: @text-secondary; +} + +.cat-body { + flex: 1; + display: flex; + flex-direction: column; + overflow: hidden; +} + +.cat-search-wrap { + padding: @section-gap-xs @page-padding-x 0; + flex-shrink: 0; +} + +.cat-search { + display: flex; + flex-direction: row; + align-items: center; + gap: 16rpx; + background: #e5dcc9; + border-radius: 999rpx; + padding: 20rpx 32rpx; + box-sizing: border-box; +} + +.cat-search__icon { + flex-shrink: 0; + line-height: 1; +} + +.cat-search__input { + flex: 1; + font-size: 28rpx; + color: @text-title; + min-height: 40rpx; + line-height: 40rpx; +} + +.cat-search__placeholder { + font-size: 28rpx; + color: rgba(50, 46, 37, 0.45); +} + +.cat-main { + flex: 1; + display: flex; + flex-direction: row; + overflow: hidden; + margin-top: @section-gap-xs; +} + +.cat-sidebar { + width: 180rpx; + flex-shrink: 0; + background: @bg-header; + border-top-right-radius: @radius-lg; + padding: 16rpx 0; + box-sizing: border-box; +} + +.cat-sidebar__item { + display: flex; + flex-direction: column; + align-items: center; + gap: 6rpx; + padding: 24rpx 12rpx; + margin: 4rpx 12rpx; + border-radius: 999rpx; + transition: all 0.25s ease; +} + +.cat-sidebar__item--active { + background: @brand; + transform: scale(1.05); + box-shadow: 0 4rpx 16rpx rgba(255, 215, 9, 0.35); +} + +.cat-sidebar__icon { + font-size: 36rpx; + line-height: 1; +} + +.cat-sidebar__name { + font-size: 24rpx; + font-weight: 500; + color: @text-secondary; + white-space: nowrap; + text-align: center; +} + +.cat-sidebar__item--active .cat-sidebar__name { + color: @text-selected-btn; + font-weight: 700; +} + +.cat-content { + flex: 1; + background: @bg-page; + padding: 0; + box-sizing: border-box; +} + +.cat-content__inner { + padding: 8rpx 16rpx; + display: flex; + flex-direction: column; + gap: 16rpx; +} + +.cat-content__footer { + height: 48rpx; +} + +.cat-card { + background: @bg-white; + border-radius: 24rpx; + padding: 16rpx; + display: flex; + flex-direction: row; + gap: 20rpx; + box-shadow: 0 4rpx 20rpx rgba(50, 46, 37, 0.06); + transition: box-shadow 0.2s ease; + overflow: hidden; +} + +.cat-card__thumb { + width: 160rpx; + height: 180rpx; + flex-shrink: 0; + border-radius: 10rpx; + display: flex; + align-items: center; + justify-content: center; + overflow: hidden; + border: 1rpx solid #bbb; +} + +.cat-card__thumb-img { + width: 100%; + height: 100%; + display: block; +} + +.cat-card__thumb-icon { + font-size: 56rpx; + line-height: 1; +} + +.cat-card__body { + flex: 1; + width: 0; + display: flex; + flex-direction: column; + justify-content: space-between; + overflow: hidden; + gap: 8rpx; + padding: 4rpx 0; +} + +.cat-card__header { + display: flex; + flex-direction: row; + align-items: center; + gap: 12rpx; +} + +.cat-card__title { + font-size: 30rpx; + font-weight: 700; + color: @text-title; + line-height: 1.35; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + flex: 1; + min-width: 0; +} + +.cat-card__coming { + flex-shrink: 0; + padding: 4rpx 14rpx; + border-radius: 999rpx; + background: rgba(50, 46, 37, 0.08); + font-size: 20rpx; + color: @text-gray; + font-weight: 500; +} + +.cat-card__subtitle { + font-size: 24rpx; + color: @text-gray; + line-height: 1.4; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + +.cat-card__tags { + display: flex; + flex-direction: row; + gap: 12rpx; + margin-top: 4rpx; +} + +.cat-card__footer { + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + margin-top: 4rpx; +} + +.cat-card__stats { + display: flex; + flex-direction: row; + align-items: center; + gap: 16rpx; +} + +.cat-card__stat { + display: flex; + flex-direction: row; + align-items: center; + gap: 4rpx; + font-size: 20rpx; + color: #7c766a; + line-height: 20rpx; +} + +.cat-card__date { + font-size: 20rpx; + color: #7c766a; + line-height: 20rpx; +} + +.cat-empty { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 120rpx 0; + gap: 24rpx; +} + +.cat-empty__icon { + font-size: 80rpx; + line-height: 1; +} + +.cat-empty__text { + font-size: 28rpx; + color: @text-gray; +} \ No newline at end of file diff --git a/miniprogram/pages/category/category.ts b/miniprogram/pages/category/category.ts new file mode 100644 index 0000000..9da57f5 --- /dev/null +++ b/miniprogram/pages/category/category.ts @@ -0,0 +1,151 @@ +import { CATEGORY_DATA, type CategoryItem } from './category.data'; + +type CategoryTab = { + id: string; + name: string; + icon: string; +}; + +type DisplayItem = CategoryItem & { + thumbBg: string; +}; + +const CATEGORY_BG: Record = { + math: '#fff3c4', + pinyin: '#d8f0d0', + puzzle: '#f5e6dc', + chinese: '#d8f0d0', + english: '#e8f4ff', + craft: '#fce4ec', +}; + +const ALL_TAB: CategoryTab = { id: 'all', name: '全部', icon: '📋' }; + +const SIDEBAR_TABS: CategoryTab[] = [ + ALL_TAB, + ...CATEGORY_DATA.categories.map((c) => ({ + id: c.id, + name: c.name, + icon: c.icon, + })), +]; + +function buildAllItems(): DisplayItem[] { + const items: DisplayItem[] = []; + for (const group of CATEGORY_DATA.categories) { + for (const item of group.items) { + items.push({ + ...item, + thumbBg: CATEGORY_BG[group.id] ?? '#f0e7d6', + }); + } + } + return items; +} + +function getItemsByCategory(categoryId: string): DisplayItem[] { + if (categoryId === 'all') return buildAllItems(); + const group = CATEGORY_DATA.categories.find((c) => c.id === categoryId); + if (!group) return []; + return group.items.map((item) => ({ + ...item, + thumbBg: CATEGORY_BG[group.id] ?? '#f0e7d6', + })); +} + +function filterByKeyword(items: DisplayItem[], keyword: string): DisplayItem[] { + if (!keyword) return items; + const kw = keyword.toLowerCase(); + return items.filter( + (item) => + item.title.toLowerCase().includes(kw) || + item.subtitle.toLowerCase().includes(kw), + ); +} + +const TAB_BAR_PATHS = new Set([ + '/pages/home/home', + '/pages/category/category', + '/pages/age/age', + '/pages/favorites/favorites', + '/pages/profile/profile', +]); + +Page({ + data: { + searchPlaceholder: CATEGORY_DATA.searchPlaceholder, + searchKeyword: '', + sidebarTabs: SIDEBAR_TABS, + activeCategoryId: 'all', + displayItems: buildAllItems() as DisplayItem[], + scrollIntoViewId: '', + }, + + onTapCategory(e: WechatMiniprogram.TouchEvent) { + const id = e.currentTarget.dataset.id as string; + if (!id || id === this.data.activeCategoryId) return; + + const items = getItemsByCategory(id); + const filtered = filterByKeyword(items, this.data.searchKeyword); + + this.setData({ + activeCategoryId: id, + displayItems: filtered, + scrollIntoViewId: '', + }); + }, + + onSearchInput(e: WechatMiniprogram.Input) { + const keyword = (e.detail.value ?? '').trim(); + const items = getItemsByCategory(this.data.activeCategoryId); + const filtered = filterByKeyword(items, keyword); + + this.setData({ + searchKeyword: keyword, + displayItems: filtered, + }); + }, + + onClearSearch() { + const items = getItemsByCategory(this.data.activeCategoryId); + this.setData({ + searchKeyword: '', + displayItems: items, + }); + }, + + onTapItem(e: WechatMiniprogram.TouchEvent) { + const path = e.currentTarget.dataset.path as string; + const title = e.currentTarget.dataset.title as string; + const available = e.currentTarget.dataset.available; + + if (!available || !path) { + wx.showToast({ + title: title ? `${title} 即将上线` : '即将上线', + icon: 'none', + }); + return; + } + + if (TAB_BAR_PATHS.has(path)) { + wx.switchTab({ url: path }); + return; + } + + wx.navigateTo({ url: path }); + }, + + onShareAppMessage() { + return { + title: '涂鸦丫 - 全部练习分类', + path: '/pages/category/category', + }; + }, + + onShareTimeline() { + return { + title: '涂鸦丫 - 全部练习分类', + query: '', + }; + }, +}); diff --git a/miniprogram/pages/category/category.wxml b/miniprogram/pages/category/category.wxml new file mode 100644 index 0000000..f0da4f2 --- /dev/null +++ b/miniprogram/pages/category/category.wxml @@ -0,0 +1,125 @@ + + + + + + + + + + + + + + + + + {{item.name}} + + + + + + + + + {{item.icon}} + + + + {{item.title}} + + {{item.subtitle}} + + {{item.ageBand}} + {{item.difficulty}} + + + + + + {{item.likes}} + + + + {{item.downloads}} + + + {{item.date}} + + + + + + 🔍 + 没有找到匹配的内容 + + + + + + + + diff --git a/miniprogram/pages/home/home.data.ts b/miniprogram/pages/home/home.data.ts index ca7660f..f2a61ae 100644 --- a/miniprogram/pages/home/home.data.ts +++ b/miniprogram/pages/home/home.data.ts @@ -46,6 +46,7 @@ export type HomeDisplayDataset = { const HOME_CATEGORY_TABS = [ { id: 'all', name: '全部' }, { id: 'math', name: '数感启蒙' }, + { id: 'pinyin', name: '汉语拼音' }, { id: 'puzzle', name: '益智游戏' }, { id: 'chinese', name: '趣味识字' }, { id: 'english', name: '英语启蒙' }, diff --git a/miniprogram/pages/home/home.json b/miniprogram/pages/home/home.json index fe829fc..b8a6143 100644 --- a/miniprogram/pages/home/home.json +++ b/miniprogram/pages/home/home.json @@ -6,6 +6,7 @@ "backgroundColor": "#FEF6E7", "enablePullDownRefresh": false, "usingComponents": { + "nav-bar": "/components3.0/nav-bar/nav-bar", "category-tabs": "/components3.0/category-tabs/category-tabs", "van-icon": "@vant/weapp/icon/index" } diff --git a/miniprogram/pages/home/home.less b/miniprogram/pages/home/home.less index 9f711b5..bca9abe 100644 --- a/miniprogram/pages/home/home.less +++ b/miniprogram/pages/home/home.less @@ -11,43 +11,6 @@ color: @text-secondary; } -.home-nav { - position: fixed; - top: 0; - left: 0; - right: 0; - z-index: 100; - background: fade(@bg-header, 85%); - backdrop-filter: blur(40rpx); - -webkit-backdrop-filter: blur(40rpx); - box-shadow: 0 2rpx 12rpx rgba(50, 46, 37, 0.05); - box-sizing: content-box; -} - -.home-nav__inner { - height: @nav-inner-height; - display: flex; - flex-direction: row; - align-items: center; - padding: 0 16px; - gap: 10px; -} - -.home-nav__logo { - width: 32px; - height: 32px; - flex-shrink: 0; - border-radius: 16px; -} - -.home-nav__name { - font-size: @fs-nav-title; - font-weight: @fw-nav-title; - color: @color-nav-title; - letter-spacing: @ls-nav-title; - line-height: 1; -} - .home-body { width: 100%; box-sizing: border-box; diff --git a/miniprogram/pages/home/home.ts b/miniprogram/pages/home/home.ts index f626fa1..06e7b12 100644 --- a/miniprogram/pages/home/home.ts +++ b/miniprogram/pages/home/home.ts @@ -106,8 +106,6 @@ console.log('HOME_SECTIONS', HOME_SECTIONS); Page({ data: { - statusBarHeight: win.statusBarHeight, - navBlockHeight: win.statusBarHeight + NAV_INNER_PX, searchPlaceholder: HOME_DATA.searchPlaceholder, tabs: HOME_TABS, activeTab: 'all', diff --git a/miniprogram/pages/home/home.wxml b/miniprogram/pages/home/home.wxml index b86066d..90be3ed 100644 --- a/miniprogram/pages/home/home.wxml +++ b/miniprogram/pages/home/home.wxml @@ -1,15 +1,7 @@ - - - - 涂鸦丫 - - + - + + + + + +分类 - Doodle Mini + + + + + + + + + +
+
+
+search + +
+
+
+ +
+ + + +
+
+ +
+
+Colorful counting beads on a wooden frame, bright sunny lighting, educational +
+
+
+

认识基础图形

+

通过趣味拼贴,让孩子初步感知圆形、方形与三角形的美妙世界。

+
+3-6岁 +入门 +
+
+
+
+favorite 456 +download 89 +
+2024-05-20 +
+
+
+ +
+
+Hand drawn numbers on colorful paper cutouts, messy desk, creative warm light +
+
+
+

数字连连看

+

跟随小兔子走迷宫,在游戏中掌握1-10的数字顺序。

+
+4-5岁 +进阶 +
+
+
+
+favorite 230 +download 45 +
+2024-05-18 +
+
+
+ +
+
+Wooden abacus with colorful beads on a bright yellow desk, soft shadows +
+
+
+

加法启蒙

+

结合生动插画,帮助孩子轻松记忆基础加法运算。

+
+5-7岁 +挑战 +
+
+
+
+favorite 890 +download 156 +
+2024-05-15 +
+
+
+ +
+
+Comic style colorful abstract shapes on white paper, playful child drawing +
+
+
+

找规律

+

简单的剪贴纸工艺,培养孩子的动手能力与色彩感知。

+
+4-6岁 +逻辑 +
+
+
+
+favorite 512 +download 110 +
+2024-05-10 +
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/stitch-ui/category/screen.png b/stitch-ui/category/screen.png new file mode 100644 index 0000000..18422a0 Binary files /dev/null and b/stitch-ui/category/screen.png differ