# 页面内容管理方案 > 版本:v1.0  |  最后更新:2026-04-29 > 配套文档:[Worksheet 发布方案](./Worksheet发布方案.md)  |  [小程序云开发方案](./小程序云开发方案.md) --- ## 一、背景与目标 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` ```ts // 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`: ```ts // 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 数据结构 ```ts 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(按 `status` → `sortOrder` → `updatedAt` 排序),每项显示预览图、标题、ID、年龄/难度/标签、状态、排序权重。 操作按钮: | 当前状态 | 可执行操作 | | -------- | --------------- | | `draft` | 激活上线 | | `active` | 下架为 hidden | | `hidden` | 恢复为 draft 或直接激活 | | 任意 | 调整排序、预览跳转、刷新 | ### 4.2 数据结构 ```ts 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 写死在配置中,作为兜底数据和管理页的基础结构。 ```ts // 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 数据结构 ```ts type AgePageData = { ageTabs: Array<{ key: AgeBandKey; rangeText: string; subLabel: string; }>; bands: Record; }>; 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. 实现首页管理 tab(featured / 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 |