Files
doodle-mini/docs/页面内容管理方案.md
T
2026-04-29 17:47:14 +08:00

17 KiB
Raw Blame History

页面内容管理方案

版本:v1.0  |  最后更新:2026-04-29 配套文档:Worksheet 发布方案  |  小程序云开发方案


一、背景与目标

worksheet 已可通过 Debug 发布进入云数据库,但三个展示页仍使用本地静态数据:

页面 当前数据来源 问题
首页 pages/home/home.data.ts featured、hot、分区靠代码手动维护
分类页 pages/category/category.data.ts 新 worksheet 发布后不会自动出现
分龄页 pages/age/age.ts 内 Mock 推荐内容和周路线无法运营配置

目标: 通过 Debug 管理页配置三个页面的内容,生成统一 JSON 上传云存储,小程序启动时通过数据预拉取获取并渲染。


二、整体架构

2.1 数据流

┌──────────────────────────────────────────────────────────────────┐
│  Debug 内容管理页(三个独立 tab)                                    │
│                                                                    │
│  ┌─────────┐   ┌─────────┐   ┌─────────┐                         │
│  │ 首页管理  │   │ 分类页管理 │   │ 分龄页管理 │                      │
│  └────┬────┘   └────┬────┘   └────┬────┘                         │
│       │             │             │                                │
│       └──────┬──────┘──────┬──────┘                               │
│              ▼             ▼                                       │
│     点击「更新」按钮 → 调用云函数 pageContentUpdate                   │
│              │                                                     │
│              ▼                                                     │
│     更新云存储 content/page-config.json 中对应页面的配置              │
└──────────────────────────────────────────────────────────────────┘

                              ▼

┌──────────────────────────────────────────────────────────────────┐
│  小程序启动                                                        │
│                                                                    │
│  app.onLaunch                                                      │
│    └─ 数据预拉取 → 获取 content/page-config.json                    │
│                                                                    │
│  页面 onLoad                                                       │
│    ├─ 1. 使用本地 *.data.ts / age.config.ts 渲染兜底首屏             │
│    ├─ 2. 读取预拉取结果中对应页面的配置                                │
│    └─ 3. 成功则 setData 更新页面                                     │
└──────────────────────────────────────────────────────────────────┘

2.2 统一 JSON 格式

云存储路径:content/page-config.json

// content/page-config.json 结构
type PageConfig = {
    home: HomePageData;       // 首页配置
    category: CategoryPageData; // 分类页配置
    age: AgePageData;         // 分龄页配置
    version: number;          // 版本号,每次更新递增
    updatedAt: string;        // 最后更新时间
};

每个管理页更新时,只修改 JSON 中自己负责的字段,通过云函数读取当前 JSON → 合并更新 → 写回云存储。

2.3 页面加载策略

三个页面统一采用数据预拉取 + 本地兜底的加载策略:

页面 onLoad
  │
  ├─ Step 1: 使用本地静态数据渲染首屏(零延迟)
  │           首页 → home.data.ts
  │           分类页 → category.data.ts
  │           分龄页 → age.config.ts
  │
  ├─ Step 2: 读取数据预拉取结果
  │           wx.getBackgroundFetchData('pre') 获取 page-config.json
  │           取出当前页面对应的配置(home / category / age
  │
  └─ Step 3: 成功 → setData 更新页面内容
             失败 → 保持本地兜底数据,用户无感知

数据预拉取app.json 中配置 fetchDataUrl,小程序冷启动时由微信客户端自动发起,不占用页面加载时间。预拉取的数据指向云存储中的 content/page-config.json

2.4 云函数设计

新增一个统一云函数 pageContentUpdate

// cloudfunctions/pageContentUpdate/index.js
type PageContentUpdatePayload = {
    page: 'home' | 'category' | 'age';  // 要更新的页面
    data: HomePageData | CategoryPageData | AgePageData; // 该页面的完整配置
};

执行逻辑:

接收参数 { page, data }
  → 从云存储读取当前 content/page-config.json
  → 合并:config[page] = data
  → config.version++
  → config.updatedAt = new Date()
  → 写回云存储 content/page-config.json
  → 返回 { success, version }

三、首页内容管理

3.1 管理 UI

首页管理 tab 分为四个区块:

区块 对应字段 管理方式
分类 tab categoryTabs 跟随 CATEGORY_LIST_WITH_ALL,一般不单独管理
年龄入口 ageBands 跟随 AGE_BANDS,可管理描述文案
今日推荐 featured 手动选择 3-5 个 active worksheet
热门推荐 hot 手动选择或按 downloads 自动生成
分类分区 sections 每个分类选择若干 active worksheet,支持排序

交互流程:

首页 tab 展示当前配置
  → 每个位置点击「选择内容」
  → 弹出 worksheet 选择器(筛选 active 内容)
  → 保存配置
  → 点击「更新首页数据」
  → 调用 pageContentUpdate({ page: 'home', data: ... })

3.2 数据结构

type HomePageData = {
    searchPlaceholder: string;
    categoryTabs: Array<{ id: string; name: string; path?: string }>;
    ageBands: Array<{ key: string; label: string; desc: string; path: string }>;
    featured: HomeDisplayItem[];
    hot: HomeDisplayItem[];
    sections: HomeDisplaySection[];
};

自动生成规则:

模块 默认规则
categoryTabs CATEGORY_LIST_WITH_ALL 生成
ageBands AGE_BANDS 生成
featured 优先使用手动选择,不足时补 isNew == true
hot 优先使用手动选择,不足时补 isHot == true 或 downloads 高的内容
sections 使用配置中的 worksheetIds,不足时从该分类 active 内容补齐

四、分类页内容管理

4.1 管理 UI

分类页管理 tab 顶部展示分类选择器(来源 CATEGORY_LIST),默认选中 math

分类头部统计:

指标 查询规则
总数 worksheets.category == 当前分类
草稿 status == draft
线上 status == active
已隐藏 status == hidden

列表展示当前分类下所有 worksheet(按 statussortOrderupdatedAt 排序),每项显示预览图、标题、ID、年龄/难度/标签、状态、排序权重。

操作按钮:

当前状态 可执行操作
draft 激活上线
active 下架为 hidden
hidden 恢复为 draft 或直接激活
任意 调整排序、预览跳转、刷新

4.2 数据结构

type CategoryPageData = {
    searchPlaceholder: string;
    categories: Array<{
        id: string;
        name: string;
        icon: string;
        items: CategoryItem[];
    }>;
};

生成时从 worksheets 集合查询 status == active 的内容,按分类分组、按 sortOrder 排序,转换为 CategoryItem

4.3 更新流程

分类页管理 tab → 管理 worksheet 状态和排序
  → 点击「更新分类数据」
  → 查询所有 active worksheets,按 category 分组
  → 调用 pageContentUpdate({ page: 'category', data: ... })
  → 云函数更新 page-config.json 中的 category 字段

五、分龄页内容管理

5.1 新增 age.config.ts

miniprogram/pages/age/ 下新增 age.config.ts,将年龄段划分、能力目标、默认 worksheet 写死在配置中,作为兜底数据和管理页的基础结构。

// miniprogram/pages/age/age.config.ts

import { AGE_BANDS, type AgeBandKey } from '../../core/data/difficulty';

export type AbilityItem = {
    icon: string;
    title: string;
    desc: string;
};

export type WeekPlan = {
    week: number;
    theme: string;
    worksheetIds: string[];   // worksheet 业务 ID
    worksheetTitles: string[]; // 兜底展示标题
};

export type AgeBandConfig = {
    key: AgeBandKey;
    label: string;
    subLabel: string;
    abilities: AbilityItem[];
    weeks: WeekPlan[];
};

export const AGE_CONFIG: AgeBandConfig[] = [
    {
        key: '3-4',
        label: '3-4 岁',
        subLabel: '启蒙认知',
        abilities: [
            { icon: '🔢', title: '数感', desc: '认读 1-5、点数对应' },
            { icon: '✏️', title: '书写', desc: '涂鸦线条、简单描红' },
            { icon: '🧩', title: '思维', desc: '找相同、简单配对' },
        ],
        weeks: [
            { week: 1, theme: '数感启蒙',
              worksheetIds: [], worksheetTitles: ['找数字涂一涂', '5以内加法', '数数连一连'] },
            { week: 2, theme: '形状与连线',
              worksheetIds: [], worksheetTitles: ['识别形状', '线条识别', '数字点连线'] },
            { week: 3, theme: '趣味专注',
              worksheetIds: [], worksheetTitles: ['颜色找规律', '方格推理', '格子仿画'] },
            { week: 4, theme: '综合练习',
              worksheetIds: [], worksheetTitles: ['10以内加减法', '识字卡', '连连看'] },
        ],
    },
    {
        key: '4-5',
        label: '4-5 岁',
        subLabel: '基础练习',
        abilities: [
            { icon: '🔢', title: '数感', desc: '10 以内数数、比大小' },
            { icon: '✏️', title: '书写', desc: '笔画模仿、图形描边' },
            { icon: '🧩', title: '思维', desc: '规律排序、图形分类' },
        ],
        weeks: [
            { week: 1, theme: '数感启蒙',
              worksheetIds: [], worksheetTitles: ['找数字涂一涂', '5以内加法', '数数连一连'] },
            { week: 2, theme: '形状与连线',
              worksheetIds: [], worksheetTitles: ['识别形状', '线条识别', '数字点连线'] },
            { week: 3, theme: '趣味专注',
              worksheetIds: [], worksheetTitles: ['颜色找规律', '方格推理', '格子仿画'] },
            { week: 4, theme: '综合练习',
              worksheetIds: [], worksheetTitles: ['10以内加减法', '识字卡', '连连看'] },
        ],
    },
    // 5-6、6-7、7-8 结构相同,abilities 和 weeks 内容不同
    // ... 完整配置见 age.config.ts 文件
];

worksheetIds 初始为空数组,由分龄管理页选择后填入。worksheetTitles 作为兜底展示。

5.2 管理 UI

分龄管理 tab 按年龄段切换:3-4 岁 | 4-5 岁 | 5-6 岁 | 6-7 岁 | 7-8 岁

每个年龄段下的管理内容:

模块 操作 说明
能力目标 只读展示 来自 age.config.ts,不需要在管理页修改
四周路线 选择 worksheet 每周选择 4 个 worksheet,主题来自 config
推荐内容 选择 worksheet 动态数据,展示 likes 数量最高的 6 个worksheet

worksheet 选择器默认筛选条件:

status == active
ageMin <= 当前年龄段 maxAge
ageMax >= 当前年龄段 minAge

核心简化: 分龄管理页不需要配置能力目标和周主题(这些写死在 age.config.ts 中),只需要为不同年龄段、不同周选择对应的 worksheet。

5.3 数据结构

type AgePageData = {
    ageTabs: Array<{
        key: AgeBandKey;
        rangeText: string;
        subLabel: string;
    }>;
    bands: Record<AgeBandKey, {
        goalTitle: string;
        abilityItems: AbilityItem[];
        weekPlans: Array<{
            week: number;
            theme: string;
            exercises: Array<{
                id: string;
                title: string;
                path: string;
                previewImg?: string;
            }>;
        }>;
        recommendedItems: Array<{
            id: string;
            title: string;
            image?: string;
            path: string;
        }>;
    }>;
};

5.4 更新流程

分龄管理 tab → 选择年龄段
  → 为每周选择 worksheet
  → 选择推荐内容
  → 点击「更新分龄数据」
  → 合并 age.config.ts 的能力目标 + 管理页选择的 worksheet 详情
  → 调用 pageContentUpdate({ page: 'age', data: ... })
  → 云函数更新 page-config.json 中的 age 字段

六、Debug 页入口结构

supportPages/debug/debug
  ├─ 分类基础数据管理      (已有:同步 CATEGORY_LIST → categories
  ├─ Worksheet 内容池      (已有:状态、分类、上下架、预览)
  └─ 页面内容管理           (新增)
       ├─ Tab: 首页管理     → 编排 featured / hot / sections
       ├─ Tab: 分类页管理   → 管理 worksheet 状态和排序
       └─ Tab: 分龄页管理   → 按年龄段选择周 worksheet

七、实施计划

Phase 1:基础设施

  1. 配置 app.json 数据预拉取,指向 content/page-config.json
  2. 实现 pageContentUpdate 云函数
  3. 上传初始 page-config.json(从现有 *.data.ts 转换)
  4. 三个页面统一接入预拉取加载逻辑

Phase 2:分类页管理

  1. 实现分类页管理 tab(worksheet 列表、状态管理、排序)
  2. 实现「更新分类数据」→ 生成 category 配置 → 调用云函数更新

Phase 3:首页管理

  1. 实现首页管理 tabfeatured / hot / sections 编排)
  2. 实现 worksheet 选择器弹窗
  3. 实现「更新首页数据」→ 生成 home 配置 → 调用云函数更新

Phase 4:分龄页管理

  1. 新增 age.config.ts 配置文件
  2. 实现分龄管理 tab(年龄段切换、周 worksheet 选择)
  3. 实现「更新分龄数据」→ 合并 config + worksheet 详情 → 调用云函数更新

八、风险与约束

风险 处理方式
预拉取失败 本地 *.data.ts / age.config.ts 兜底,用户无感知
JSON 生成失败 云函数返回错误,管理页提示重试,线上数据不受影响
首页配置引用了 hidden 内容 生成时只允许 active 内容,不足时返回警告
分龄内容不适龄 选择器按年龄段默认过滤
并发更新冲突 云函数使用 version 乐观锁,冲突时提示重新加载后重试

九、关键文件索引

文件 / 模块 职责
supportPages/contentManage/ 三 tab 内容管理页
cloudfunctions/pageContentUpdate/ 更新 page-config.json 中指定页面的配置
pages/age/age.config.ts 分龄页兜底配置(年龄段、能力目标、默认 worksheet)
pages/home/home.data.ts 首页兜底数据
pages/category/category.data.ts 分类页兜底数据
content/page-config.json(云存储) 三个页面的统一配置 JSON