diff --git a/docs/PC-Web端技术预案.md b/docs/PC-Web端技术预案.md new file mode 100644 index 0000000..f39630f --- /dev/null +++ b/docs/PC-Web端技术预案.md @@ -0,0 +1,147 @@ +# Doodle / 涂鸦丫 - PC Web 端技术预案 + +> 状态:**远期规划**(当前聚焦小程序,暂不启动 Web 开发) +> 最后更新:2026-03-24 +> 配套文档:[技术架构设计文档](./技术架构设计文档.md) | [产品设计文档](./产品设计文档.md) + +--- + +## 一、启动时机判断 + +### 1.1 当前不急于开发 PC Web 的原因 + +- 小程序用户群与目标用户(家长)高度重合,微信即触达 +- PC Web 需要额外解决支付、登录、SEO 等问题 +- 先把小程序做好,积累内容和用户 + +### 1.2 何时启动 PC Web + +满足以下条件中的 **2 项以上** 时考虑启动: + +- 小程序 DAU 稳定 > 1000 +- 用户反馈中"想在电脑上用"的需求频繁出现 +- 内容积累到 100+ 种题型 +- 模板引擎已稳定运行,core/ 层与 wx.* 完全解耦 + +--- + +## 二、技术选型 + +``` +PC Web 技术栈: +┌────────────────────────────────────┐ +│ 框架:Next.js (App Router) │ +│ UI:Tailwind CSS + Radix UI │ +│ Canvas:HTML5 Canvas 2D │ +│ PDF:jsPDF + html2canvas │ +│ 状态:Zustand │ +│ 部署:Vercel │ +│ │ +│ 核心复用: │ +│ @doodle/core (共享核心层) │ +│ └── 模板引擎、生成器、数据模型 │ +│ → 直接 import 使用 │ +│ │ +│ 需新建: │ +│ • Web UI 组件 │ +│ • 平台适配层 (Web 实现) │ +│ • 用户登录(微信扫码/手机号) │ +│ • SEO 优化(SSR/SSG 题型页) │ +└────────────────────────────────────┘ +``` + +--- + +## 三、后端 API 层方案 + +PC Web 需要一个 API 层来访问小程序云开发的数据。三种方案对比: + +| 方案 | 说明 | 成本 | 推荐度 | +|------|------|------|--------| +| **A: 云开发 HTTP API** | 微信云开发提供的 HTTP 触发器,Web 直接调用 | 零额外成本 | ⭐⭐⭐⭐⭐ | +| **B: Cloudflare Workers** | 轻量 Serverless 代理层,转发请求到云开发 | 极低(免费额度充裕) | ⭐⭐⭐⭐ | +| **C: Vercel Serverless** | Next.js API Routes 做代理 | 低(Vercel 免费额度) | ⭐⭐⭐ | +| **D: 独立 Node.js 服务** | 自建 Express/Fastify 服务,独立数据库 | 较高(¥50-100/月+) | ⭐⭐ | + +**推荐路径**:先用方案 A(零成本),若遇到限制再升级到方案 B。 + +--- + +## 四、代码共享策略 + +### 4.1 Monorepo 结构(未来演进) + +``` +doodle/ +├── packages/ +│ └── core/ ← 共享核心(npm 包) +│ ├── src/ +│ │ ├── draw/ ← 模板引擎 + 渲染器 +│ │ ├── generators/ ← 题目生成器 +│ │ ├── models/ ← 数据模型 +│ │ └── utils/ ← 工具函数 +│ ├── package.json +│ └── tsconfig.json +├── apps/ +│ ├── mini/ ← 微信小程序 +│ │ ├── miniprogram/ +│ │ ├── cloudfunctions/ +│ │ └── project.config.json +│ └── web/ ← PC Web +│ ├── src/ +│ │ ├── app/ ← Next.js App Router +│ │ ├── components/ ← Web UI 组件 +│ │ ├── platform/ ← Web 平台适配层 +│ │ └── services/ ← Web 业务服务 +│ ├── package.json +│ └── next.config.js +├── pnpm-workspace.yaml +└── package.json +``` + +### 4.2 当前阶段的准备 + +当前不需要搭建 Monorepo,只需在小程序项目中做好分层即可: + +1. 将 `core/` 作为独立目录组织代码 +2. 确保 `core/` 内**不 import 任何 wx.* API** +3. 模板引擎、生成器、数据模型全部放在 `core/` 中 +4. 未来迁移时,将 `core/` 提取为独立 npm 包即可 + +### 4.3 平台适配层映射 + +| 适配器 | 小程序实现 | Web 实现 | +|--------|-----------|---------| +| CanvasAdapter | `wx.createSelectorQuery` + Canvas 2D | `document.getElementById` + Canvas 2D | +| ImageAdapter | `canvas.createImage()` | `new Image()` | +| StorageAdapter | `wx.setStorageSync` / `wx.getStorageSync` | `localStorage` | +| CloudAdapter | `wx.cloud.callFunction` | HTTP fetch 到云开发 API | +| ShareAdapter | `onShareAppMessage` / `onShareTimeline` | Web Share API / 复制链接 | +| ExportAdapter | `canvasToTempFilePath` → `saveImageToPhotosAlbum` | `canvas.toBlob()` → 下载 / jsPDF | + +--- + +## 五、Web 端特有功能 + +| 功能 | 说明 | +|------|------| +| **直接下载 PDF** | jsPDF 前端生成,无需保存到相册 | +| **批量下载** | 一次生成多张 → 打包 ZIP 下载 | +| **打印预览** | 浏览器原生 `window.print()` + CSS @media print | +| **SEO** | SSR/SSG 生成题型介绍页,搜索引擎可抓取 | +| **用户登录** | 微信扫码登录 / 手机号 + 验证码 | +| **分享** | 生成题型页面 URL,可直接分享链接 | + +--- + +## 六、开发估算 + +| 阶段 | 内容 | 预估人时 | +|------|------|---------| +| 环境搭建 | Monorepo + Next.js 项目 + core 包提取 | ~16h | +| 平台适配层 | 5 个适配器的 Web 实现 | ~16h | +| UI 开发 | 首页 + 分类页 + 生成页 + 我的 | ~40h | +| 用户登录 | 微信扫码 + 手机号登录 | ~16h | +| SEO 优化 | SSG 题型页 + sitemap + meta | ~8h | +| 测试与上线 | 联调 + 部署 Vercel | ~8h | +| **总计** | | **~104h(约 3-4 周全职)** | diff --git a/docs/产品设计文档.md b/docs/产品设计文档.md index f114455..894ba91 100644 --- a/docs/产品设计文档.md +++ b/docs/产品设计文档.md @@ -1,7 +1,11 @@ -# Doodle Mini 小程序 - 产品设计文档 v2.0 +# 涂鸦丫 小程序 - 产品设计文档 v3.0 > 定位:3-8 岁早教 A4 纸打印资料小程序 -> 版本:v2.0 产品重设计方案 +> 品牌名称:**涂鸦丫**(谐音双关:涂鸦 = doodle + 丫 ≈ 鸭,呼应小鸭子 IP 形象) +> 品牌 Slogan:**"涂鸦丫,跟小鸭丫一起画!"** +> 品牌 IP:小鸭丫(一只爱涂鸦的小黄鸭) +> 主题色:**#f7ee47**(明黄色,呼应小鸭子形象) +> 版本:v3.0 产品重设计方案 > 最后更新:2026-03-24 --- @@ -10,33 +14,33 @@ ### 1.1 内容层面 -| 问题 | 现状 | 影响 | -|------|------|------| -| 品类单一 | 仅有数学计算、专注力训练、识字、练字四类 | 缺少英语启蒙、科学认知、艺术创造、生活常识等早教核心板块 | -| 题型趋同 | 数学 26 种题型多为数字计算变体,缺少生活化数学 | 用户容易审美疲劳,低龄段(3-5岁)可用内容少 | -| 缺乏体系 | 题型平铺排列,无年龄分级/难度递进 | 家长无法按孩子年龄/水平选择合适内容 | -| 无趣味化 | 缺少迷宫、涂色卡、手工折纸等高趣味性内容 | 与竞品(kiddoworksheets)差距大 | -| 内容静态 | 所有内容均为代码写死,无法动态扩展 | 新增题型需要发版,运营效率低 | +| 问题 | 现状 | 影响 | +| -------- | ---------------------------------------------- | -------------------------------------------------------- | +| 品类单一 | 仅有数学计算、专注力训练、识字、练字四类 | 缺少英语启蒙、科学认知、艺术创造、生活常识等早教核心板块 | +| 题型趋同 | 数学 26 种题型多为数字计算变体,缺少生活化数学 | 用户容易审美疲劳,低龄段(3-5岁)可用内容少 | +| 缺乏体系 | 题型平铺排列,无年龄分级/难度递进 | 家长无法按孩子年龄/水平选择合适内容 | +| 无趣味化 | 缺少迷宫、涂色卡、手工折纸等高趣味性内容 | 与竞品(kiddoworksheets)差距大 | +| 内容静态 | 所有内容均为代码写死,每种题型需独立编写绘制代码 | 新增题型需要发版(1-2 周),无法快速响应热点/节日内容 | ### 1.2 用户体验层面 -| 问题 | 现状 | 影响 | -|------|------|------| -| 首页缺吸引力 | 入口卡片列表式排布,无分类筛选 | 题型多时找不到内容,新用户不知从何开始 | -| 无用户体系 | 无登录/收藏/历史记录 | 用户无法追踪使用情况,留存差 | -| 缺少预览图 | 进入题型前看不到最终效果 | 试错成本高 | -| 无批量打印 | 每次只能生成一张 → 保存 → 打印 | 需要多张时操作繁琐 | -| 无打印指引 | 保存到相册后缺少从相册打印的引导 | 用户可能不知道如何打印 | +| 问题 | 现状 | 影响 | +| ------------ | -------------------------------- | -------------------------------------- | +| 首页缺吸引力 | 入口卡片列表式排布,无分类筛选 | 题型多时找不到内容,新用户不知从何开始 | +| 无用户体系 | 无登录/收藏/历史记录 | 用户无法追踪使用情况,留存差 | +| 缺少预览图 | 进入题型前看不到最终效果 | 试错成本高 | +| 无批量打印 | 每次只能生成一张 → 保存 → 打印 | 需要多张时操作繁琐 | +| 无打印指引 | 保存到相册后缺少从相册打印的引导 | 用户可能不知道如何打印 | ### 1.3 技术层面 -| 问题 | 现状 | 影响 | -|------|------|------| -| 云函数名不一致 | 代码调用 `robotaxi`,目录名 `doodle` | 可能存在线上风险 | -| 无效代码引用 | `index.js` 引用不存在的 `station/area` 等模块 | 部署可能失败 | -| debug 页有死链 | 指向不存在的 `demoPages/shapePrint` | 功能残缺 | -| 无 PDF 导出 | `createPDF` 云函数仅实验性代码 | 缺少直接生成 PDF 的能力 | -| 渲染方案限制 | 全部 Canvas 渲染,交互受限 | 难以实现复杂交互(如拖拽、填写) | +| 问题 | 现状 | 影响 | +| -------------- | --------------------------------------------- | ---------------------------------------------------------------------- | +| 云函数名不一致 | 代码调用 `robotaxi`,目录名 `doodle` | 可能存在线上风险 | +| 无效代码引用 | `index.js` 引用不存在的 `station/area` 等模块 | 部署可能失败 | +| debug 页有死链 | 指向不存在的 `demoPages/shapePrint` | 功能残缺 | +| 无 PDF 导出 | `createPDF` 云函数仅实验性代码 | 非核心问题,PNG 保存到相册更符合手机端用户习惯,PDF 可作为远期增值功能 | +| 渲染方案限制 | 全部 Canvas 渲染,交互受限 | 难以实现复杂交互(如拖拽、填写) | --- @@ -44,15 +48,15 @@ 参考 [kiddoworksheets.com](https://www.kiddoworksheets.com/),对比如下: -| 维度 | kiddoworksheets | Doodle Mini 现状 | 差距 | -|------|----------------|------------------|------| -| 内容品类 | 30+ 大类(字母、拼写、涂色、迷宫、折纸、找不同、时钟...) | 4 大类 | 严重不足 | -| 年龄覆盖 | 学前 - 5 年级 | 3-8 岁(但内容未分级) | 缺少分级体系 | -| 题目数量 | 每个品类数十到数百张 | 每种题型动态生成(无限但变化有限) | 模板多样性不够 | -| 下载方式 | 直接 PDF 下载 | 保存 PNG 到相册 | 体验略差 | -| 视觉风格 | 彩色卡通插画 | 简约线条风格 | 视觉吸引力弱 | -| 内容更新 | 持续更新 | 代码写死 | 运营效率差距大 | -| SEO/分享 | 独立网页,搜索引擎友好 | 小程序,依赖微信生态 | 获客渠道不同 | +| 维度 | kiddoworksheets | 涂鸦丫 现状 | 差距 | +| -------- | --------------------------------------------------------- | ---------------------------------- | -------------------------------------------------------- | +| 内容品类 | 30+ 大类(字母、拼写、涂色、迷宫、折纸、找不同、时钟...) | 4 大类 | 严重不足 | +| 年龄覆盖 | 学前 - 5 年级 | 3-8 岁(但内容未分级) | 缺少分级体系 | +| 题目数量 | 每个品类数十到数百张 | 每种题型动态生成(无限但变化有限) | 模板多样性不够 | +| 下载方式 | 直接 PDF 下载 | 保存 PNG 到相册 | PNG 更适合手机端用户(相册易找、可直接分享打印),非劣势 | +| 视觉风格 | 彩色卡通插画 | 简约线条风格 | 视觉吸引力弱 | +| 内容更新 | 持续更新 | 代码写死 | 运营效率差距大 | +| SEO/分享 | 独立网页,搜索引擎友好 | 小程序,依赖微信生态 | 获客渠道不同 | --- @@ -80,12 +84,12 @@ ### 3.2 新 TabBar 设计 -| Tab | 名称 | 说明 | -|-----|------|------| -| 1 | 发现 | 首页,分类浏览所有可打印资料,含推荐/热门/最新 | -| 2 | 分龄 | 按年龄(3-4/4-5/5-6/6-7/7-8)筛选适合的内容 | -| 3 | 收藏 | 收藏的题型、已下载的历史记录 | -| 4 | 我的 | 用户中心、打印指南、设置、意见反馈 | +| Tab | 名称 | 说明 | +| --- | ---- | ---------------------------------------------- | +| 1 | 发现 | 首页,分类浏览所有可打印资料,含推荐/热门/最新 | +| 2 | 分龄 | 按年龄(3-4/4-5/5-6/6-7/7-8)筛选适合的内容 | +| 3 | 收藏 | 收藏的题型、已下载的历史记录 | +| 4 | 我的 | 用户中心、打印指南、设置、意见反馈 | --- @@ -95,14 +99,14 @@ > 低开发成本、高用户价值,优先推进 -| # | 功能 | 描述 | 开发难度 | 用户价值 | -|---|------|------|---------|---------| -| 1 | **年龄分级体系** | 为所有题型标注适合年龄段(3-4/4-5/5-6/6-7/7-8),首页增加年龄筛选 | ⭐⭐ | ⭐⭐⭐⭐⭐ | -| 2 | **难度标签** | 每个题型标注难度(入门/基础/进阶/挑战),方便家长选择 | ⭐ | ⭐⭐⭐⭐ | -| 3 | **效果预览图** | 入口卡片展示真实的打印效果缩略图,非 icon 风格 | ⭐⭐ | ⭐⭐⭐⭐ | -| 4 | **首页重设计** | 增加分类导航(横向滚动标签)+ 搜索 + 推荐区域 | ⭐⭐ | ⭐⭐⭐⭐⭐ | -| 5 | **打印指南页** | 新增「如何打印」图文引导页(从保存→打印→装订的完整教程) | ⭐ | ⭐⭐⭐⭐ | -| 6 | **修复技术问题** | 清理云函数无效引用、统一函数名、移除死链 | ⭐ | ⭐⭐⭐ | +| # | 功能 | 描述 | 开发难度 | 用户价值 | +| --- | ---------------- | ----------------------------------------------------------------- | -------- | ---------- | +| 1 | **年龄分级体系** | 为所有题型标注适合年龄段(3-4/4-5/5-6/6-7/7-8),首页增加年龄筛选 | ⭐⭐ | ⭐⭐⭐⭐⭐ | +| 2 | **难度标签** | 每个题型标注难度(入门/基础/进阶/挑战),方便家长选择 | ⭐ | ⭐⭐⭐⭐ | +| 3 | **效果预览图** | 入口卡片展示真实的打印效果缩略图,非 icon 风格 | ⭐⭐ | ⭐⭐⭐⭐ | +| 4 | **首页重设计** | 增加分类导航(横向滚动标签)+ 搜索 + 推荐区域 | ⭐⭐ | ⭐⭐⭐⭐⭐ | +| 5 | **打印指南页** | 新增「如何打印」图文引导页(从保存→打印→装订的完整教程) | ⭐ | ⭐⭐⭐⭐ | +| 6 | **修复技术问题** | 清理云函数无效引用、统一函数名、移除死链 | ⭐ | ⭐⭐⭐ | ### P1 - 内容扩充(2-4 周) @@ -110,76 +114,76 @@ #### 4.1 数学新增题型 -| # | 功能 | 描述 | 开发难度 | -|---|------|------|---------| -| 7 | **时钟练习** | 认识钟表、读时间、画时针分针 | ⭐⭐⭐ | -| 8 | **形状分类** | 按形状/大小/颜色分类,圈出不同类 | ⭐⭐ | -| 9 | **规律填空** | 数字/图形规律,找出下一个 | ⭐⭐ | -| 10 | **货币认知** | 认识人民币面值,简单找零练习 | ⭐⭐⭐ | -| 11 | **测量启蒙** | 用尺子量长度、比较长短 | ⭐⭐ | +| # | 功能 | 描述 | 开发难度 | +| --- | ------------ | -------------------------------- | -------- | +| 7 | **时钟练习** | 认识钟表、读时间、画时针分针 | ⭐⭐⭐ | +| 8 | **形状分类** | 按形状/大小/颜色分类,圈出不同类 | ⭐⭐ | +| 9 | **规律填空** | 数字/图形规律,找出下一个 | ⭐⭐ | +| 10 | **货币认知** | 认识人民币面值,简单找零练习 | ⭐⭐⭐ | +| 11 | **测量启蒙** | 用尺子量长度、比较长短 | ⭐⭐ | #### 4.2 语文新增题型 -| # | 功能 | 描述 | 开发难度 | -|---|------|------|---------| -| 12 | **拼音练习** | 声母/韵母/整体认读音节描红、拼音组合 | ⭐⭐⭐ | -| 13 | **笔画练习** | 基本笔画(横竖撇捺等)描红练习 | ⭐⭐ | -| 14 | **偏旁部首** | 偏旁部首认知、组字练习 | ⭐⭐ | -| 15 | **看图说话** | 提供图片场景,引导孩子看图说话/写话 | ⭐⭐⭐ | -| 16 | **成语/古诗填空** | 常见成语、古诗的填空练习 | ⭐⭐ | +| # | 功能 | 描述 | 开发难度 | +| --- | ----------------- | ------------------------------------ | -------- | +| 12 | **拼音练习** | 声母/韵母/整体认读音节描红、拼音组合 | ⭐⭐⭐ | +| 13 | **笔画练习** | 基本笔画(横竖撇捺等)描红练习 | ⭐⭐ | +| 14 | **偏旁部首** | 偏旁部首认知、组字练习 | ⭐⭐ | +| 15 | **看图说话** | 提供图片场景,引导孩子看图说话/写话 | ⭐⭐⭐ | +| 16 | **成语/古诗填空** | 常见成语、古诗的填空练习 | ⭐⭐ | #### 4.3 英语启蒙(全新模块) -| # | 功能 | 描述 | 开发难度 | -|---|------|------|---------| -| 17 | **字母描红** | A-Z 大小写字母描红练习 | ⭐⭐ | -| 18 | **字母闪卡** | 字母+对应单词+插图的闪卡 | ⭐⭐ | -| 19 | **字母找一找** | 在字母方阵中找出目标字母 | ⭐(复用 numberFind) | -| 20 | **单词描红** | 常见英语单词描红(颜色/动物/数字/水果) | ⭐⭐⭐ | -| 21 | **自然拼读练习纸** | CVC 单词拼读、元音辅音分类 | ⭐⭐⭐ | +| # | 功能 | 描述 | 开发难度 | +| --- | ------------------ | --------------------------------------- | --------------------- | +| 17 | **字母描红** | A-Z 大小写字母描红练习 | ⭐⭐ | +| 18 | **字母闪卡** | 字母+对应单词+插图的闪卡 | ⭐⭐ | +| 19 | **字母找一找** | 在字母方阵中找出目标字母 | ⭐(复用 numberFind) | +| 20 | **单词描红** | 常见英语单词描红(颜色/动物/数字/水果) | ⭐⭐⭐ | +| 21 | **自然拼读练习纸** | CVC 单词拼读、元音辅音分类 | ⭐⭐⭐ | ### P2 - 益智游戏(4-6 周) > 高趣味性内容,显著提升差异化 -| # | 功能 | 描述 | 开发难度 | -|---|------|------|---------| -| 22 | **走迷宫** | 不同难度的迷宫(简单路径/多分支/主题迷宫) | ⭐⭐⭐⭐ | -| 23 | **找不同** | 两张相似图片找出差异点 | ⭐⭐⭐⭐ | -| 24 | **数独入门** | 4×4 / 6×6 简易数独 | ⭐⭐⭐ | -| 25 | **控笔练习** | 虚线描画(直线/曲线/锯齿/螺旋) | ⭐⭐ | -| 26 | **连线画图** | 按数字/字母顺序连点成画(Dot-to-Dot) | ⭐⭐⭐ | -| 27 | **图形拼图** | 七巧板/图形拼合练习 | ⭐⭐⭐ | -| 28 | **记忆力翻翻卡** | 可打印的配对翻翻卡(打印→剪切→玩) | ⭐⭐ | +| # | 功能 | 描述 | 开发难度 | +| --- | ---------------- | ------------------------------------------ | -------- | +| 22 | **走迷宫** | 不同难度的迷宫(简单路径/多分支/主题迷宫) | ⭐⭐⭐⭐ | +| 23 | **找不同** | 两张相似图片找出差异点 | ⭐⭐⭐⭐ | +| 24 | **数独入门** | 4×4 / 6×6 简易数独 | ⭐⭐⭐ | +| 25 | **控笔练习** | 虚线描画(直线/曲线/锯齿/螺旋) | ⭐⭐ | +| 26 | **连线画图** | 按数字/字母顺序连点成画(Dot-to-Dot) | ⭐⭐⭐ | +| 27 | **图形拼图** | 七巧板/图形拼合练习 | ⭐⭐⭐ | +| 28 | **记忆力翻翻卡** | 可打印的配对翻翻卡(打印→剪切→玩) | ⭐⭐ | ### P3 - 创意手工(6-8 周) > 拓展品类边界,吸引更多用户群 -| # | 功能 | 描述 | 开发难度 | -|---|------|------|---------| -| 29 | **涂色卡** | 卡通主题线稿涂色(动物/交通/节日/恐龙等) | ⭐⭐⭐ | -| 30 | **折纸模板** | 可打印的折纸展开图+步骤说明 | ⭐⭐(主要是素材制作) | -| 31 | **字母/数字手工** | 打印→剪切→粘贴的立体字母/数字 | ⭐⭐ | -| 32 | **主题手工** | 节日手工(春节/中秋/圣诞等)、季节手工 | ⭐⭐⭐ | -| 33 | **贴纸打印** | 可打印的奖励贴纸、装饰贴纸 | ⭐⭐ | -| 34 | **自制绘本** | 打印→装订的简易绘本模板 | ⭐⭐⭐ | +| # | 功能 | 描述 | 开发难度 | +| --- | ----------------- | ----------------------------------------- | ---------------------- | +| 29 | **涂色卡** | 卡通主题线稿涂色(动物/交通/节日/恐龙等) | ⭐⭐⭐ | +| 30 | **折纸模板** | 可打印的折纸展开图+步骤说明 | ⭐⭐(主要是素材制作) | +| 31 | **字母/数字手工** | 打印→剪切→粘贴的立体字母/数字 | ⭐⭐ | +| 32 | **主题手工** | 节日手工(春节/中秋/圣诞等)、季节手工 | ⭐⭐⭐ | +| 33 | **贴纸打印** | 可打印的奖励贴纸、装饰贴纸 | ⭐⭐ | +| 34 | **自制绘本** | 打印→装订的简易绘本模板 | ⭐⭐⭐ | ### P4 - 体验升级(持续迭代) > 提升产品专业度和用户粘性 -| # | 功能 | 描述 | 开发难度 | -|---|------|------|---------| -| 35 | **用户体系** | 微信授权登录 + 用户信息 | ⭐⭐ | -| 36 | **收藏功能** | 收藏喜欢的题型,快速访问 | ⭐⭐ | -| 37 | **下载历史** | 记录每次下载的内容和时间 | ⭐⭐ | -| 38 | **批量生成** | 一次生成多张不同题目的练习纸 | ⭐⭐⭐ | -| 39 | **PDF 导出** | 支持直接生成多页 PDF(需云函数) | ⭐⭐⭐⭐ | -| 40 | **自定义纸张** | 支持 A4/B5/Letter 等纸张尺寸切换 | ⭐⭐ | -| 41 | **打印套餐** | 按周/月推荐「每日一练」打印计划 | ⭐⭐⭐ | -| 42 | **社区分享** | 用户分享打印效果、使用心得 | ⭐⭐⭐⭐ | -| 43 | **数据统计** | 记录孩子使用数据,生成学习报告 | ⭐⭐⭐⭐ | +| # | 功能 | 描述 | 开发难度 | +| --- | ------------------------ | ----------------------------------------------------------- | -------- | +| 35 | **用户体系** | 微信授权登录 + 用户信息 | ⭐⭐ | +| 36 | **收藏功能** | 收藏喜欢的题型,快速访问 | ⭐⭐ | +| 37 | **下载历史** | 记录每次下载的内容和时间 | ⭐⭐ | +| 38 | **批量生成** | 一次生成多张不同题目的练习纸 | ⭐⭐⭐ | +| 39 | **PDF 导出(增值服务)** | 会员专属功能,支持多页 PDF 合并导出(需云函数),非核心路径 | ⭐⭐⭐⭐ | +| 40 | **自定义纸张** | 支持 A4/B5/Letter 等纸张尺寸切换 | ⭐⭐ | +| 41 | **打印套餐** | 按周/月推荐「每日一练」打印计划 | ⭐⭐⭐ | +| 42 | **社区分享** | 用户分享打印效果、使用心得 | ⭐⭐⭐⭐ | +| 43 | **数据统计** | 记录孩子使用数据,生成学习报告 | ⭐⭐⭐⭐ | --- @@ -287,11 +291,11 @@ │ └────────────────────────────┘ │ │ │ │ ┌──────────┐ ┌──────────────┐ │ -│ │ 🔄 换一批 │ │ 📥 保存并打印 │ │ +│ │ 🔄 换一批 │ │ 📥 保存到相册 │ │ │ └──────────┘ └──────────────┘ │ │ │ │ ┌──────────┐ ┌──────────────┐ │ -│ │ 📄 存PDF │ │ 📤 分享好友 │ │ +│ │ 📤 分享 │ │ 📄 存PDF(会员)│ │ │ └──────────┘ └──────────────┘ │ │ │ └─────────────────────────────────────┘ @@ -331,28 +335,60 @@ - 入口卡片仅为简单的文字+icon,缺少视觉吸引力 - 配色单一,整体观感不够「儿童友好」 -- 缺少品牌感(Logo、IP形象等) +- 小鸭子 IP 形象已有但未贯穿全应用,品牌感不够强 -### 6.2 改进方向 +### 6.2 品牌体系 -| 维度 | 建议 | -|------|------| -| 主色调 | 采用温暖明亮的渐变色系(橙黄 → 粉紫),传达活力与童趣 | -| 品牌 IP | 设计一个可爱的 IP 形象(如小恐龙/小兔子),贯穿全应用 | -| 卡片风格 | 入口卡片使用真实打印效果预览图 + 圆角卡片 + 柔和阴影 | -| 字体 | 标题使用圆体/手写风格字体,正文保持清晰易读 | -| 图标 | 使用统一的手绘风格图标替代 emoji | -| 动效 | 适度加入微动效(卡片进场、按钮反馈、生成加载) | -| 空状态 | IP 形象配合趣味文案(如「还没有收藏哦,去发现好玩的练习纸吧~」) | +#### 品牌命名释义 -### 6.3 打印页面风格 +「**涂鸦丫**」是一个谐音双关的品牌名: -| 维度 | 建议 | -|------|------| -| 页眉 | 统一品牌 Logo + 小程序码 + 日期 + 孩子姓名(可选) | -| 页脚 | 鼓励语/小贴士(如「做得真棒!」「今天又进步了!」) | -| 装饰 | 页面边角增加可爱装饰元素(星星、花朵、小动物) | -| 排版 | 优化题目间距,确保打印后字体大小适合儿童辨认(≥14pt) | +- **涂鸦** = doodle,精准描述产品核心功能(儿童涂鸦 / 练习纸打印) +- **丫** = 可爱语气词,暗示小朋友 / 小丫头;同时谐音「**鸭**」,呼应 IP 形象 +- 品牌故事:_涂鸦丫是一只最爱涂鸦的小鸭丫,它相信每个孩子都是天生的小画家。_ + +#### 品牌色彩 + +| 色彩 | 色值 | 用途 | +| ------------------ | ------- | -------------------------- | +| 品牌主色(鸭丫黄) | #f7ee47 | 主按钮、品牌标识、强调元素 | +| 主色加深(暖金) | #e6d520 | 按钮按压态、边框强调 | +| 辅助色(暖白) | #fffef0 | 页面背景、卡片底色 | +| 辅助色(浅灰) | #f5f5f5 | 次级背景 | +| 文字主色 | #333333 | 标题、正文 | +| 文字次色 | #999999 | 辅助说明文字 | + +#### IP 形象规范 + +现有 IP「**小鸭丫**」已用于小程序图标,需进一步延伸: + +| 场景 | IP 应用 | +| ----------- | ------------------------------------------------------------------------------ | +| 小程序图标 | 小鸭丫正面头像(已有) | +| 启动页/闪屏 | 小鸭丫拿着画笔,配 Slogan | +| 空状态 | 小鸭丫的不同姿态 + 趣味文案(如「鸭丫还没找到收藏呢,去发现好玩的练习纸吧~」) | +| 加载动画 | 小鸭丫走路 / 画画的微动效 | +| 打印页装饰 | 页眉角落小鸭丫 logo,页脚鸭丫鼓励语 | +| 错误页面 | 小鸭丫摊手/挠头,配友好提示文案 | + +### 6.3 视觉改进方向 + +| 维度 | 建议 | +| -------- | ---------------------------------------------------------------------- | +| 主色调 | 以品牌黄 #f7ee47 为核心,搭配暖白 #fffef0 背景,营造温暖明快的儿童氛围 | +| 卡片风格 | 入口卡片使用真实打印效果预览图 + 圆角卡片 + 柔和阴影 | +| 字体 | 标题使用圆体/手写风格字体,正文保持清晰易读 | +| 图标 | 使用统一的手绘风格图标替代 emoji,风格与小鸭丫 IP 一致 | +| 动效 | 适度加入微动效(卡片进场、按钮反馈、小鸭丫加载动画) | + +### 6.4 打印页面风格 + +| 维度 | 建议 | +| ---- | ------------------------------------------------------------------- | +| 页眉 | 小鸭丫 Logo + 「涂鸦丫」品牌字 + 小程序码 + 日期 + 孩子姓名(可选) | +| 页脚 | 小鸭丫鼓励语(如「鸭丫说:做得真棒!」「小鸭丫为你点赞!」) | +| 装饰 | 页面边角增加小鸭丫元素(小脚印、鸭丫剪影、星星等) | +| 排版 | 优化题目间距,确保打印后字体大小适合儿童辨认(≥14pt) | --- @@ -360,15 +396,80 @@ ### 7.1 架构优化 -| 改造项 | 现状 | 目标 | 优先级 | -|--------|------|------|--------| -| 内容配置化 | 题型硬编码 | JSON 配置 + 云端下发,新增题型无需发版 | P0 | -| 模板引擎 | 各题型独立 Draw Service | 抽象通用模板引擎,减少重复代码 | P1 | -| 云端渲染 | 本地 Canvas 导出 PNG | 云函数生成 PDF,支持多页/高清 | P2 | -| 素材管理 | 素材随代码打包 | CDN + 按需下载,减少包体积 | P1 | -| 数据埋点 | 基础 tracker | 完善用户行为分析(使用频率、下载量、题型偏好) | P1 | +| 改造项 | 现状 | 目标 | 优先级 | +| ---------------- | ----------------------- | ---------------------------------------------- | ------ | +| 内容配置化 | 题型硬编码 | JSON 配置 + 云端下发,新增题型无需发版 | P0 | +| **模板引擎** | 各题型独立 Draw Service | **抽象通用模板引擎,80% 新内容通过配置上线** | **P0** | +| 客户端渲染优化 | 本地 Canvas 导出 PNG | 优化渲染性能,支持批量生成多张图片保存到相册 | P1 | +| 素材管理 | 素材随代码打包 | CDN + 按需下载,减少包体积 | P1 | +| 数据埋点 | 基础 tracker | 完善用户行为分析(使用频率、下载量、题型偏好) | P1 | +| PDF 导出(增值) | createPDF 实验性代码 | 会员增值功能,云函数合并多页 PNG 为 PDF | P4 | -### 7.2 分包优化 +### 7.2 模板引擎(产品视角) + +> 详细技术设计见 [技术架构设计文档](./技术架构设计文档.md) 第五章 + +#### 为什么需要模板引擎? + +**现状痛点**:目前每新增一种可打印资料(如一种新题型、一张涂色卡),都需要开发者编写新的前端页面和绘制代码,然后提交微信审核发版。这意味着: + +- 新增一种题型需要 1-3 天开发 + 1-3 天审核 = 最快一周上线 +- 要达到 150+ 种内容的产品目标,需要写 150+ 套绘制代码,**不可持续** +- 无法快速响应节日/热点内容(如六一儿童节涂色卡、春节手工等) + +#### 模板引擎解决什么? + +核心思路:**所有可打印资料的排版模式是有限的**,虽然题型有上百种,但归纳后只有 6-8 种排版模式。 + +``` +排版模式 覆盖的题型(举例) +──────────────── ────────────────────────────────── +网格计算型 加减法、乘法、凑十/破十、比大小、填空... +配对连线型 数物连线、连连看、译码连线、点连线... +网格涂色型 找数字涂色、方位涂色、格子仿画... +卡片排列型 涂色卡、闪卡、识字卡、字母卡、贴纸... +描红书写型 练字、拼音描红、字母描红、数字描红... +全幅素材型 整页涂色卡、折纸模板、手工模板... +序列排序型 数字排序、缺失数字、颜色规律... +特殊图形型 时钟练习、形状分类、货币认知... +``` + +**有了模板引擎后:** + +| 场景 | 之前 | 之后 | +|------|------|------| +| 新增「50以内减法」 | 写代码 → 发版 | JSON 配置一条记录 → **即时上线** | +| 新增「恐龙涂色卡」 | 写绘制代码 → 发版 | 上传 SVG 素材 + JSON 配置 → **即时上线** | +| 新增「字母描红」 | 写代码 → 发版 | JSON 配置 + 字母数据 → **即时上线** | +| 新增「迷宫」 | 写迷宫算法 → 发版 | 需写新生成器 → **仍需发版** | +| 六一主题涂色卡 | 来不及开发 | 上传素材 + 配置 → **当天上线** | + +#### 对产品运营的影响 + +模板引擎上线后,产品运营模式从「开发驱动」转变为「运营驱动」: + +``` +之前:产品经理提需求 → 开发排期 → 编码 → 测试 → 审核 → 上线(1-2周) + +之后: + 场景 A(已有模板覆盖的新题型/素材): + 运营/产品 → 编写 JSON 配置 + 上传素材 → 云端生效 → 即时上线(<1小时) + + 场景 B(需要新排版模式的题型): + 产品提需求 → 开发新 TemplateRenderer → 发版(1-2周) + 之后该模式下的新题型走场景 A +``` + +#### 内容运营节奏建议 + +| 运营方式 | 频率 | 说明 | +|---------|------|------| +| 常规上新 | 每周 2-3 种 | 通过 JSON 配置新增题型变体或素材型内容 | +| 主题上新 | 每月 1 次 | 节日/季节主题内容包(涂色卡、手工模板等) | +| 热点响应 | 随时 | 追节日/热点快速上线应景内容 | +| 版本迭代 | 每 2-4 周 | 新排版模板、新生成算法、UI 改进等需发版内容 | + +### 7.3 分包优化 ``` 当前分包结构: 建议优化后: @@ -384,28 +485,40 @@ └── craftPages (创意手工) ``` -### 7.3 数据模型扩展 +### 7.4 数据模型扩展 ```typescript -interface WorksheetType { +interface WorksheetConfig { id: string; - page: string; title: string; desc: string; - // 新增字段 + // ─── 分类与筛选 ─── category: 'math' | 'chinese' | 'english' | 'puzzle' | 'craft'; subcategory: string; - ageRange: [number, number]; // [minAge, maxAge] - difficulty: 1 | 2 | 3 | 4; // 入门/基础/进阶/挑战 - previewImage: string; // 真实效果预览图 - downloadCount: number; // 下载次数(可云端维护) - tags: string[]; // 搜索标签 - isNew: boolean; // 新上线标记 - sortOrder: number; // 排序权重 + ageRange: [number, number]; + difficulty: 1 | 2 | 3 | 4; + previewImage: string; + tags: string[]; + isNew: boolean; + sortOrder: number; + downloadCount: number; + status: 'active' | 'draft' | 'hidden'; + + // ─── 模板引擎配置(核心新增)─── + template: TemplateType; // 使用哪个排版模板 + generator: GeneratorType; // 使用哪个数据生成器 + generatorConfig: Record;// 生成器参数 + layoutConfig: LayoutConfig; // 排版参数 + userConfigurable?: UserConfigField[];// 用户可调整的参数(渲染到设置面板) + + // ─── 兼容旧架构 ─── + legacyPage?: string; // 旧页面路径(迁移过渡期使用) } ``` +> 完整的类型定义和 JSON 配置示例见 [技术架构设计文档](./技术架构设计文档.md) 第五章 + --- ## 八、实施路线图 @@ -414,100 +527,107 @@ interface WorksheetType { Phase 1(第 1-2 周) ← 夯实基础 ├── 修复技术问题(云函数/死链) ├── 增加年龄分级和难度标签 -├── 首页重设计(分类导航 + 搜索) +├── 效果预览图优化 ├── 新增打印指南页 -└── 效果预览图优化 +└── 代码分层重构(建立 core/ 和 platform/ 目录) -Phase 2(第 3-4 周) ← 内容扩充 -├── 新增:控笔练习 -├── 新增:时钟练习 -├── 新增:拼音练习 -├── 新增:字母描红 -├── 新增:字母闪卡 -└── 新增:笔画练习 +Phase 2(第 3-5 周) ← 🔑 模板引擎 + 首页重构 +├── 【核心】开发模板引擎 +│ ├── 实现 3 种高优先级模板渲染器 +│ │ ├── grid-exercise(网格计算型) +│ │ ├── full-page-asset(全幅素材型) +│ │ └── tracing-writing(描红书写型) +│ ├── 实现通用 worksheet 页面 +│ └── 试点迁移 2-3 种现有题型验证 +├── 首页重设计(分类导航 + 搜索) +├── 内容配置化(JSON + 云端下发) +└── 云数据库建表(含模板引擎字段) -Phase 3(第 5-6 周) ← 趣味内容 -├── 新增:走迷宫 -├── 新增:涂色卡(引入线稿素材) -├── 新增:折纸模板 -├── 新增:找不同 -├── 新增:控笔练习升级版 -└── 新增:记忆力翻翻卡 +Phase 3(第 6-8 周) ← 内容爆发(模板引擎红利期) +├── 补全剩余 5 种模板渲染器 +├── 存量 40+ 题型批量迁移到模板引擎 +├── 通过 JSON 配置快速上线新题型: +│ ├── 数学:时钟练习、形状分类 +│ ├── 语文:拼音练习、笔画练习 +│ ├── 英语:字母描红、字母闪卡(JSON 配置即可) +│ ├── 益智:控笔练习 +│ └── 创意:涂色卡、折纸(上传素材即可) +└── 需新生成器的题型:走迷宫、找不同 -Phase 4(第 7-8 周) ← 体验升级 +Phase 4(第 9-10 周) ← 体验升级 ├── 用户体系(登录/收藏/历史) -├── PDF 导出功能 -├── 批量生成 +├── 批量生成图片(多张保存到相册) ├── 每日打印计划 └── 数据统计与学习报告 -Phase 5(持续迭代) ← 生态建设 -├── 更多主题手工内容 -├── 节日/季节限定内容 +Phase 5(持续运营迭代) ← 运营驱动增长 +├── 每周通过 JSON 配置上新 2-3 种内容(无需发版) +├── 节日/季节主题内容包(涂色卡、手工模板等) +├── PDF 导出(会员增值功能) ├── 社区分享 ├── 内容创作者入驻 -└── 会员体系(免费内容 + 高级内容) +└── 会员体系(免费 + 高级内容) ``` --- ## 九、商业化思路 -| 模式 | 说明 | -|------|------| -| **免费 + 广告** | 基础内容免费,展示原生广告(现有模式) | -| **会员订阅** | 月/年会员,解锁高级内容、去广告、批量导出 PDF | -| **内容付费** | 特定高级内容包(如「幼升小全套」「暑假特训」)单独购买 | -| **打印服务** | 接入云打印平台,用户一键下单,直接邮寄打印成品 | +| 模式 | 说明 | +| --------------- | ------------------------------------------------------- | +| **免费 + 广告** | 基础内容免费,展示原生广告(现有模式) | +| **会员订阅** | 月/年会员,解锁高级内容、去广告、PDF 多页导出、批量生成 | +| **内容付费** | 特定高级内容包(如「幼升小全套」「暑假特训」)单独购买 | +| **打印服务** | 接入云打印平台,用户一键下单,直接邮寄打印成品 | --- ## 十、关键指标(KPI) -| 指标 | 当前预估 | Phase 2 目标 | 长期目标 | -|------|---------|-------------|---------| -| 内容品类 | 4 类 | 8 类 | 15+ 类 | -| 可打印题型 | 41 种 | 60+ 种 | 150+ 种 | -| 日均使用 UV | - | 500 | 5,000 | -| 人均停留时长 | - | 3 min | 8 min | -| 日均下载量 | - | 1,000 张 | 10,000 张 | -| 用户次日留存 | - | 25% | 40% | -| 分享率 | - | 10% | 20% | +| 指标 | 当前预估 | Phase 2 目标 | 长期目标 | +| ------------ | -------- | ------------ | --------- | +| 内容品类 | 4 类 | 8 类 | 15+ 类 | +| 可打印题型 | 41 种 | 60+ 种 | 150+ 种 | +| 日均使用 UV | - | 500 | 5,000 | +| 人均停留时长 | - | 3 min | 8 min | +| 日均下载量 | - | 1,000 张 | 10,000 张 | +| 用户次日留存 | - | 25% | 40% | +| 分享率 | - | 10% | 20% | --- ## 附录 A:竞品功能对照表 -| 功能 | kiddoworksheets | Doodle Mini 现有 | Doodle Mini v2.0 规划 | -|------|----------------|-----------------|---------------------| -| 字母描红 | ✅ | ❌ | ✅ P1 | -| 草书练习 | ✅ | ❌ | ❌(非目标用户需求) | -| 缺失字母 | ✅ | ❌ | ✅ P1(字母找一找) | -| 数字描红 | ✅ | ✅ 看数字写一写 | ✅ | -| 缺失数字 | ✅ | ✅ 填上缺少的数字 | ✅ | -| 闪卡 | ✅ | ❌ | ✅ P1 | -| 形状练习 | ✅ | ✅ 识别形状 | ✅ | -| 规律练习 | ✅ | ✅ 颜色找规律 | ✅ 扩展数字/图形规律 | -| 涂色页 | ✅ | ❌ | ✅ P2 | -| 画画教程 | ✅ | ❌ | ❌(优先级低) | -| 点连线 | ✅ | ✅ 数字点连线 | ✅ 扩展字母连线 | -| 加法 | ✅ | ✅ 多种加法题型 | ✅ | -| 减法 | ✅ | ✅ 多种减法题型 | ✅ | -| 乘法 | ✅ | ✅ 九九乘法表 | ✅ | -| 计数 | ✅ | ✅ 多种计数题型 | ✅ | -| 英语练习 | ✅ | ❌ | ✅ P1 | -| 高频词 | ✅ | ❌ | ✅ P2 | -| 词汇拼写 | ✅ | ❌ | ✅ P2 | -| 字谜 | ✅ | ❌ | ✅ P3 | -| 填字游戏 | ✅ | ❌ | ✅ P3 | -| 常识问答 | ✅ | ❌ | ❌(优先级低) | -| 描线练习 | ✅ | ✅ 线条识别 | ✅ 控笔练习 | -| 配对连线 | ✅ | ✅ 连连看/连线 | ✅ | -| 找相同 | ✅ | ❌ | ✅ P2 | -| 人体部位 | ✅ | ❌ | ❌(优先级低) | -| 时钟 | ✅ | ❌ | ✅ P1 | -| 贴纸 | ✅ | ❌ | ✅ P3 | -| 滑动拼图 | ✅(在线游戏) | ❌ | ❌(非打印类) | -| 找不同 | ✅ | ❌ | ✅ P2 | -| 折纸 | ✅ | ❌ | ✅ P2 | -| 迷宫 | ✅ | ❌ | ✅ P2 | +| 功能 | kiddoworksheets | 涂鸦丫 现有 | 涂鸦丫 v3.0 规划 | +| -------- | --------------- | ----------------- | -------------------- | +| 字母描红 | ✅ | ❌ | ✅ P1 | +| 草书练习 | ✅ | ❌ | ❌(非目标用户需求) | +| 缺失字母 | ✅ | ❌ | ✅ P1(字母找一找) | +| 数字描红 | ✅ | ✅ 看数字写一写 | ✅ | +| 缺失数字 | ✅ | ✅ 填上缺少的数字 | ✅ | +| 闪卡 | ✅ | ❌ | ✅ P1 | +| 形状练习 | ✅ | ✅ 识别形状 | ✅ | +| 规律练习 | ✅ | ✅ 颜色找规律 | ✅ 扩展数字/图形规律 | +| 涂色页 | ✅ | ❌ | ✅ P2 | +| 画画教程 | ✅ | ❌ | ❌(优先级低) | +| 点连线 | ✅ | ✅ 数字点连线 | ✅ 扩展字母连线 | +| 加法 | ✅ | ✅ 多种加法题型 | ✅ | +| 减法 | ✅ | ✅ 多种减法题型 | ✅ | +| 乘法 | ✅ | ✅ 九九乘法表 | ✅ | +| 计数 | ✅ | ✅ 多种计数题型 | ✅ | +| 英语练习 | ✅ | ❌ | ✅ P1 | +| 高频词 | ✅ | ❌ | ✅ P2 | +| 词汇拼写 | ✅ | ❌ | ✅ P2 | +| 字谜 | ✅ | ❌ | ✅ P3 | +| 填字游戏 | ✅ | ❌ | ✅ P3 | +| 常识问答 | ✅ | ❌ | ❌(优先级低) | +| 描线练习 | ✅ | ✅ 线条识别 | ✅ 控笔练习 | +| 配对连线 | ✅ | ✅ 连连看/连线 | ✅ | +| 找相同 | ✅ | ❌ | ✅ P2 | +| 人体部位 | ✅ | ❌ | ❌(优先级低) | +| 时钟 | ✅ | ❌ | ✅ P1 | +| 贴纸 | ✅ | ❌ | ✅ P3 | +| 滑动拼图 | ✅(在线游戏) | ❌ | ❌(非打印类) | +| 找不同 | ✅ | ❌ | ✅ P2 | +| 折纸 | ✅ | ❌ | ✅ P2 | +| 迷宫 | ✅ | ❌ | ✅ P2 | diff --git a/docs/技术架构设计文档.md b/docs/技术架构设计文档.md index 9814d2a..45c5dcc 100644 --- a/docs/技术架构设计文档.md +++ b/docs/技术架构设计文档.md @@ -1,8 +1,8 @@ # Doodle Mini - 技术架构设计文档 -> 版本:v2.0 +> 版本:v3.0 > 最后更新:2026-03-24 -> 配套文档:[现有功能清单](./现有功能清单.md) | [产品设计文档](./产品设计文档.md) +> 配套文档:[现有功能清单](./现有功能清单.md) | [产品设计文档](./产品设计文档.md) | [PC-Web端技术预案](./PC-Web端技术预案.md) --- @@ -10,12 +10,12 @@ ### 1.1 核心原则 -| 原则 | 说明 | -|------|------| -| **成本优先** | 优先使用微信云开发,避免自建服务器的运维和费用 | -| **渐进增强** | 先小程序跑通,后续再扩展 PC Web,不为未来过度设计 | -| **前端为主** | Canvas 渲染、随机生成等核心逻辑保持前端执行,后端仅做必要的数据存储和服务 | -| **可迁移** | 核心绘制逻辑与平台 API 解耦,为将来迁移 Web 做准备 | +| 原则 | 说明 | +| ------------ | ------------------------------------------------------------------------------------------------- | +| **成本优先** | 优先使用微信云开发,避免自建服务器的运维和费用 | +| **渐进增强** | 先小程序跑通,后续再扩展 PC Web,不为未来过度设计 | +| **前端为主** | Canvas 渲染、随机生成、PNG 导出等核心逻辑保持前端执行,零服务器成本;后端仅做必要的数据存储和服务 | +| **可迁移** | 核心绘制逻辑与平台 API 解耦,为将来迁移 Web 做准备 | ### 1.2 后端方案决策 @@ -41,22 +41,22 @@ │ 📦 静态素材存储与 CDN 分发(涂色卡线稿、折纸模板等) │ │ 📦 用户数据同步(收藏、历史记录跨设备) │ │ 📦 下载统计 / 热度排名 │ -│ 📦 PDF 多页合并导出 │ +│ 📦 PDF 多页合并导出(远期增值功能,非核心路径) │ │ 📦 未来 PC Web 端的 API 服务 │ └─────────────────────────────────────────────────────────┘ ``` #### 方案对比与选择 -| 维度 | 微信云开发 | 自建云服务器 | 决策 | -|------|-----------|-------------|------| -| 接入成本 | ⭐ 极低(已有基础) | ⭐⭐⭐ 需搭建部署 | 云开发 ✅ | -| 运维成本 | ⭐ 免运维 | ⭐⭐⭐ 需监控/维护 | 云开发 ✅ | -| 费用 | 免费额度足够早期(数据库 2GB/存储 5GB/云函数 10万次/月) | 最低约 ¥50-100/月 | 云开发 ✅ | -| 小程序集成 | ⭐ 原生集成,鉴权零成本 | ⭐⭐ 需对接登录/鉴权 | 云开发 ✅ | -| PC Web 支持 | ⭐⭐ 需通过 HTTP API 桥接 | ⭐ 天然支持 | 自建 ✅ | -| 灵活性 | ⭐⭐ 受限于云开发 SDK | ⭐ 完全自由 | 自建 ✅ | -| 数据迁移 | ⭐⭐ 可导出但不方便 | ⭐ 标准数据库 | 自建 ✅ | +| 维度 | 微信云开发 | 自建云服务器 | 决策 | +| ----------- | -------------------------------------------------------- | -------------------- | --------- | +| 接入成本 | ⭐ 极低(已有基础) | ⭐⭐⭐ 需搭建部署 | 云开发 ✅ | +| 运维成本 | ⭐ 免运维 | ⭐⭐⭐ 需监控/维护 | 云开发 ✅ | +| 费用 | 免费额度足够早期(数据库 2GB/存储 5GB/云函数 10万次/月) | 最低约 ¥50-100/月 | 云开发 ✅ | +| 小程序集成 | ⭐ 原生集成,鉴权零成本 | ⭐⭐ 需对接登录/鉴权 | 云开发 ✅ | +| PC Web 支持 | ⭐⭐ 需通过 HTTP API 桥接 | ⭐ 天然支持 | 自建 ✅ | +| 灵活性 | ⭐⭐ 受限于云开发 SDK | ⭐ 完全自由 | 自建 ✅ | +| 数据迁移 | ⭐⭐ 可导出但不方便 | ⭐ 标准数据库 | 自建 ✅ | **最终决策:近期使用微信云开发,远期按需引入轻量后端** @@ -64,10 +64,8 @@ Phase 1-3(当前~8周):100% 微信云开发 └── 云数据库 + 云存储 + 云函数,零服务器成本 -Phase 4+(需要 PC Web 时):引入轻量后端 - └── 方案 A(推荐):云开发 HTTP API + PC Web 直接调用 - └── 方案 B:Cloudflare Workers / Vercel Serverless 做 API 代理层 - └── 方案 C:轻量 Node.js 服务(仅在流量大时考虑) +远期(需要 PC Web 时):按需引入轻量后端 + └── 详见 PC-Web端技术预案.md ``` --- @@ -75,74 +73,60 @@ Phase 4+(需要 PC Web 时):引入轻量后端 ## 二、系统架构总图 ``` -┌─────────────────────────────────────────────────────────────────────┐ -│ 用户端 │ -│ │ -│ ┌──────────────────────┐ ┌──────────────────────┐ │ -│ │ 微信小程序 (当前) │ │ PC Web (未来) │ │ -│ │ │ │ │ │ -│ │ ┌────────────────┐ │ │ ┌────────────────┐ │ │ -│ │ │ UI 层 (WXML) │ │ │ │ UI 层 (React) │ │ │ -│ │ │ Skyline 渲染 │ │ │ │ Tailwind CSS │ │ │ -│ │ └───────┬────────┘ │ │ └───────┬────────┘ │ │ -│ │ │ │ │ │ │ │ -│ │ ┌───────▼────────┐ │ │ ┌───────▼────────┐ │ │ -│ │ │ 业务逻辑层 (TS) │ │ │ │ 业务逻辑层 (TS) │ │ │ -│ │ │ Page + Mixin │ │ │ │ Hooks + Store │ │ │ -│ │ └───────┬────────┘ │ │ └───────┬────────┘ │ │ -│ │ │ │ │ │ │ │ -│ │ ┌───────▼────────┐ │ │ ┌───────▼────────┐ │ │ -│ │ │ 共享核心层 │◄─┼─────────┼──► 共享核心层 │ │ │ -│ │ │ @doodle/core │ │ │ │ @doodle/core │ │ │ -│ │ │ ┌─────────────┐ │ │ │ │ (同一套代码) │ │ │ -│ │ │ │ DrawService │ │ │ │ └───────┬────────┘ │ │ -│ │ │ │ DataModels │ │ │ │ │ │ │ -│ │ │ │ Generators │ │ │ │ │ │ │ -│ │ │ │ Utils │ │ │ │ │ │ │ -│ │ │ └─────────────┘ │ │ │ │ │ │ -│ │ └───────┬────────┘ │ │ │ │ │ -│ │ │ │ │ │ │ │ -│ │ ┌───────▼────────┐ │ │ ┌───────▼────────┐ │ │ -│ │ │ 平台适配层 │ │ │ │ 平台适配层 │ │ │ -│ │ │ wx.* API │ │ │ │ Web API │ │ │ -│ │ │ wx.cloud.* │ │ │ │ HTTP Client │ │ │ -│ │ │ Canvas 2D │ │ │ │ Canvas 2D │ │ │ -│ │ └───────┬────────┘ │ │ └───────┬────────┘ │ │ -│ └──────────┼──────────┘ └──────────┼──────────┘ │ -└──────────────┼───────────────────────────────┼──────────────────┘ - │ │ - ▼ ▼ -┌─────────────────────────────────────────────────────────────────────┐ -│ 后端服务层 │ -│ │ -│ ┌─────────────────────────────────────────────────┐ │ -│ │ 微信云开发 (Phase 1-3) │ │ -│ │ │ │ -│ │ ┌─────────────┐ ┌──────────┐ ┌────────────┐ │ │ -│ │ │ 云数据库 │ │ 云存储 │ │ 云函数 │ │ │ -│ │ │ (MongoDB) │ │ (COS) │ │ (Node.js) │ │ │ -│ │ │ │ │ │ │ │ │ │ -│ │ │ • 用户数据 │ │ • 涂色卡 │ │ • getOpenId│ │ │ -│ │ │ • 收藏记录 │ │ • 折纸图 │ │ • genPDF │ │ │ -│ │ │ • 下载统计 │ │ • 手工图 │ │ • syncData │ │ │ -│ │ │ • 内容配置 │ │ • 预览图 │ │ • stats │ │ │ -│ │ │ • 反馈数据 │ │ • 字体 │ │ │ │ │ -│ │ └─────────────┘ └──────────┘ └────────────┘ │ │ -│ └─────────────────────────────────────────────────┘ │ -│ │ -│ ┌─────────────────────────────────────────────────┐ │ -│ │ 轻量 API 层 (Phase 4+, 仅 PC Web) │ │ -│ │ │ │ -│ │ 方案 A: 云开发 HTTP API (推荐,零额外成本) │ │ -│ │ 方案 B: Cloudflare Workers (极低成本) │ │ -│ │ 方案 C: Vercel Serverless Functions │ │ -│ └─────────────────────────────────────────────────┘ │ -│ │ -│ ┌─────────────────────────────────────────────────┐ │ -│ │ CDN (腾讯云) │ │ -│ │ 素材图片 / 字体文件 / 预览图 / 分享图 │ │ -│ └─────────────────────────────────────────────────┘ │ -└─────────────────────────────────────────────────────────────────────┘ +┌────────────────────────────────────────────────────────────────┐ +│ 微信小程序(当前重心) │ +│ │ +│ ┌──────────────────────────────────────────────────────┐ │ +│ │ UI 层 (WXML + WXSS) │ │ +│ │ pages/ + components/ — Skyline 渲染 │ │ +│ └────────────────────────┬─────────────────────────────┘ │ +│ │ │ +│ ┌────────────────────────▼─────────────────────────────┐ │ +│ │ 业务服务层 (services/ + store/) │ │ +│ │ worksheet-service / print-service / user-service │ │ +│ └────────────────────────┬─────────────────────────────┘ │ +│ │ │ +│ ┌────────────────────────▼─────────────────────────────┐ │ +│ │ 平台适配层 (platform/) │ │ +│ │ canvas-adapter / storage-adapter / cloud-adapter │ │ +│ └────────────────────────┬─────────────────────────────┘ │ +│ │ │ +│ ┌────────────────────────▼─────────────────────────────┐ │ +│ │ 共享核心层 (core/) — 纯 TypeScript,零平台依赖 │ │ +│ │ ┌─────────────┐ ┌────────────┐ ┌────────────────┐ │ │ +│ │ │ 模板引擎 │ │ 生成器 │ │ 数据模型/工具 │ │ │ +│ │ │ 8种渲染器 │ │ 15种生成器 │ │ WorksheetConfig│ │ │ +│ │ └─────────────┘ └────────────┘ └────────────────┘ │ │ +│ │ 🔑 此层可直接在未来 PC Web 项目中 import 复用 │ │ +│ └──────────────────────────────────────────────────────┘ │ +└───────────────────────────┬────────────────────────────────────┘ + │ + ▼ +┌────────────────────────────────────────────────────────────────┐ +│ 后端服务层 │ +│ │ +│ ┌──────────────────────────────────────────────────────┐ │ +│ │ 微信云开发(零服务器成本) │ │ +│ │ │ │ +│ │ ┌────────────┐ ┌──────────┐ ┌─────────────┐ │ │ +│ │ │ 云数据库 │ │ 云存储 │ │ 云函数 │ │ │ +│ │ │ (MongoDB) │ │ (COS) │ │ (Node.js) │ │ │ +│ │ │ │ │ │ │ │ │ │ +│ │ │ • 题型配置 │ │ • 涂色卡 │ │ • getOpenId │ │ │ +│ │ │ • 用户数据 │ │ • 折纸图 │ │ • syncData │ │ │ +│ │ │ • 收藏记录 │ │ • 手工图 │ │ • stats │ │ │ +│ │ │ • 下载统计 │ │ • 预览图 │ │ • genPDF │ │ │ +│ │ │ • 反馈数据 │ │ • 字体 │ │ (增值) │ │ │ +│ │ └────────────┘ └──────────┘ └─────────────┘ │ │ +│ └──────────────────────────────────────────────────────┘ │ +│ │ +│ ┌──────────────────────────────────────────────────────┐ │ +│ │ CDN (腾讯云) │ │ +│ │ 素材图片 / 字体文件 / 预览图 / 分享图 │ │ +│ └──────────────────────────────────────────────────────┘ │ +│ │ +│ PC Web 远期方案见 → PC-Web端技术预案.md │ +└────────────────────────────────────────────────────────────────┘ ``` --- @@ -168,14 +152,14 @@ miniprogram/ **问题分析:** -| 问题 | 详情 | -|------|------| -| Mixin 模式笨重 | `pageMixin` 通过对象展开合并,无类型安全,难以追踪数据流 | -| Draw 服务分散 | 每个分包下各有 `shared/service/`,大量重复的绘制工具方法 | -| 平台耦合严重 | Draw 服务直接使用 `wx.createImage`、`canvas.createImage` 等 API | -| 模板重复 | `mathPages` 和 `focusPages` 的 `canvas-page-template.wxml` 内容相同 | -| 无共享核心 | 数据模型、生成算法与 UI 逻辑混在一起,无法跨平台复用 | -| 状态管理原始 | 纯 `setData`,无统一的状态管理方案 | +| 问题 | 详情 | +| -------------- | ------------------------------------------------------------------- | +| Mixin 模式笨重 | `pageMixin` 通过对象展开合并,无类型安全,难以追踪数据流 | +| Draw 服务分散 | 每个分包下各有 `shared/service/`,大量重复的绘制工具方法 | +| 平台耦合严重 | Draw 服务直接使用 `wx.createImage`、`canvas.createImage` 等 API | +| 模板重复 | `mathPages` 和 `focusPages` 的 `canvas-page-template.wxml` 内容相同 | +| 无共享核心 | 数据模型、生成算法与 UI 逻辑混在一起,无法跨平台复用 | +| 状态管理原始 | 纯 `setData`,无统一的状态管理方案 | ### 3.2 目标架构 @@ -198,11 +182,22 @@ miniprogram/ │ │ └── english/ ← 英语题目生成器 │ ├── draw/ ← 绘制服务(Canvas 2D API,平台无关) │ │ ├── base-draw.ts ← 基础绘制(纸面、页眉、网格等) -│ │ ├── math-draw/ ← 数学绘制服务 -│ │ ├── focus-draw/ ← 专注力绘制服务 -│ │ ├── chinese-draw/ ← 语文绘制服务 -│ │ ├── english-draw/ ← 英语绘制服务 -│ │ └── craft-draw/ ← 手工/涂色绘制服务 +│ │ ├── template-engine.ts ← 🆕 模板引擎入口 +│ │ ├── renderer-registry.ts ← 🆕 渲染器注册表 +│ │ ├── base-template-renderer.ts ← 🆕 渲染器基类 +│ │ ├── renderers/ ← 🆕 各排版模板渲染器(6-8 种) +│ │ │ ├── grid-exercise.ts +│ │ │ ├── match-connect.ts +│ │ │ ├── grid-coloring.ts +│ │ │ ├── card-layout.ts +│ │ │ ├── tracing-writing.ts +│ │ │ ├── full-page-asset.ts +│ │ │ ├── sequence-pattern.ts +│ │ │ └── special-graphic.ts +│ │ ├── legacy/ ← 存量专用绘制服务(渐进迁移后移除) +│ │ │ ├── math-draw/ +│ │ │ ├── focus-draw/ +│ │ │ └── chinese-draw/ │ ├── data/ ← 内容配置数据 │ │ ├── worksheets.ts ← 所有题型定义(本地兜底) │ │ ├── categories.ts ← 分类定义 @@ -308,12 +303,12 @@ miniprogram/ * 但图片加载、字体加载等需要适配 */ interface ICanvasAdapter { - getContext(): CanvasRenderingContext2D; - setSize(width: number, height: number): void; - loadImage(src: string): Promise; - toDataURL(type?: string, quality?: number): Promise; - toBlob(): Promise; // Web 专用 - toTempFilePath(): Promise; // 小程序专用 + getContext(): CanvasRenderingContext2D; + setSize(width: number, height: number): void; + loadImage(src: string): Promise; + toDataURL(type?: string, quality?: number): Promise; + toBlob(): Promise; // Web 专用 + toTempFilePath(): Promise; // 小程序专用 } ``` @@ -321,18 +316,39 @@ interface ICanvasAdapter { ```typescript abstract class BaseDrawService { - protected ctx: CanvasRenderingContext2D; - protected paperWidth: number; - protected paperHeight: number; + protected ctx: CanvasRenderingContext2D; + protected paperWidth: number; + protected paperHeight: number; - // 这些方法仅使用标准 Canvas 2D API,不依赖任何平台 - protected drawGrid(rows: number, cols: number): void { /* ... */ } - protected drawText(text: string, x: number, y: number, options: TextOptions): void { /* ... */ } - protected drawLine(x1: number, y1: number, x2: number, y2: number): void { /* ... */ } - protected drawHeader(config: PrintConfig): void { /* ... */ } - protected drawRoundedRect(x: number, y: number, w: number, h: number, r: number): void { /* ... */ } + // 这些方法仅使用标准 Canvas 2D API,不依赖任何平台 + protected drawGrid(rows: number, cols: number): void { + /* ... */ + } + protected drawText( + text: string, + x: number, + y: number, + options: TextOptions, + ): void { + /* ... */ + } + protected drawLine(x1: number, y1: number, x2: number, y2: number): void { + /* ... */ + } + protected drawHeader(config: PrintConfig): void { + /* ... */ + } + protected drawRoundedRect( + x: number, + y: number, + w: number, + h: number, + r: number, + ): void { + /* ... */ + } - abstract draw(params: DrawParams): Promise; + abstract draw(params: DrawParams): Promise; } ``` @@ -345,29 +361,575 @@ abstract class BaseDrawService { * 绘制服务消费这些数据来渲染 Canvas */ interface IWorksheetGenerator { - generate(config: TConfig): TData; - getDefaultConfig(): TConfig; + generate(config: TConfig): TData; + getDefaultConfig(): TConfig; } // 示例:加法题生成器 -class AdditionGenerator implements IWorksheetGenerator { - generate(config: AdditionConfig): AdditionData { - const questions = []; - for (let i = 0; i < config.count; i++) { - const a = randomInt(0, config.maxNumber); - const b = randomInt(0, config.maxNumber - a); - questions.push({ a, b, answer: a + b }); +class AdditionGenerator + implements IWorksheetGenerator +{ + generate(config: AdditionConfig): AdditionData { + const questions = []; + for (let i = 0; i < config.count; i++) { + const a = randomInt(0, config.maxNumber); + const b = randomInt(0, config.maxNumber - a); + questions.push({ a, b, answer: a + b }); + } + return { questions, config }; } - return { questions, config }; - } } ``` --- -## 五、后端(云开发)详细设计 +## 五、模板引擎架构(核心设计) -### 5.1 云数据库集合设计 +> 本章解决一个根本性问题:**每新增一种可打印资料,都需要新写前端页面和绘制代码,如何实现内容的动态扩展?** + +### 5.1 问题分析 + +现有模式下,新增一种题型的完整链路是: + +``` +新增「时钟练习」题型: + ① 新建 clockPractice/ 页面目录(.ts + .wxml + .wxss + .json) + ② 新写 ClockPracticeDraw 绘制服务(~200-400 行 TS) + ③ 新写 ClockGenerator 生成器 + ④ 在 constants 注册题型元数据 + ⑤ 提交代码 → 审核 → 发版 + ───────────────────────── + 成本:~1-3 天开发 + 1-3 天审核 +``` + +如果要达到产品目标的 150+ 种可打印资料,按这种模式需要写 150+ 个页面和绘制服务,**不可持续**。 + +### 5.2 核心洞察:排版模式是收敛的 + +虽然题型看起来有几十上百种,但**排版模式(Layout Pattern)只有有限的几种**: + +``` +┌──────────────────────────────────────────────────────────────────┐ +│ │ +│ 模式 A:网格计算型 │ +│ ┌────────────────────────┐ │ +│ │ 3 + 5 = ___ │ 适用:加减法、混合运算、凑十/破十、 │ +│ │ 7 - 2 = ___ │ 乘法口诀、数字填空、比大小等 │ +│ │ 9 + 1 = ___ │ │ +│ │ ... │ 变化点:题目数据、运算符、行列数、 │ +│ └────────────────────────┘ 是否带图示辅助 │ +│ │ +│ 模式 B:配对连线型 │ +│ ┌────────────────────────┐ │ +│ │ 3 ╌╌╌╌ 🍎🍎🍎 │ 适用:数物连线、连连看、数字点连线、│ +│ │ 5 ╌╌╌╌ 🍎🍎 │ 译码连线、配对连线等 │ +│ │ 2 ╌╌╌╌ 🍎🍎🍎🍎 │ │ +│ └────────────────────────┘ 变化点:左右两列内容、连线方式 │ +│ │ +│ 模式 C:网格涂色型 │ +│ ┌────────────────────────┐ │ +│ │ ┌─┬─┬─┬─┬─┐ │ 适用:找数字涂色、按数涂色、方位涂 │ +│ │ │3│7│3│5│3│ │ 色、格子仿画、图形符号配对等 │ +│ │ ├─┼─┼─┼─┼─┤ │ │ +│ │ │2│3│8│3│1│ │ 变化点:网格大小、单元格内容/颜色、 │ +│ └────────────────────────┘ 涂色规则说明 │ +│ │ +│ 模式 D:卡片排列型 │ +│ ┌────────────────────────┐ │ +│ │ [图片] [图片] │ 适用:涂色卡、闪卡、识字卡、字母卡、│ +│ │ 苹果 香蕉 │ 贴纸、翻翻卡等 │ +│ │ [图片] [图片] │ │ +│ └────────────────────────┘ 变化点:图片源、文字、布局方式 │ +│ │ +│ 模式 E:描红书写型 │ +│ ┌────────────────────────┐ │ +│ │ ┌田┐┌田┐┌田┐ │ 适用:练字、笔画练习、字母描红、 │ +│ │ │大││大││ │ │ 数字描红、拼音描红等 │ +│ │ └──┘└──┘└──┘ │ │ +│ └────────────────────────┘ 变化点:字符数据、格子类型、淡化规则│ +│ │ +│ 模式 F:全幅素材型 │ +│ ┌────────────────────────┐ │ +│ │ │ 适用:涂色卡(整页)、折纸展开图、 │ +│ │ [整页图片/SVG] │ 手工模板、迷宫底图等 │ +│ │ │ │ +│ └────────────────────────┘ 变化点:素材文件本身 │ +│ │ +│ 模式 G:序列/排序型 │ +│ ┌────────────────────────┐ │ +│ │ 2 → __ → 4 → __ → 6 │ 适用:数字排序、缺失数字、颜色找 │ +│ │ │ 规律、图形规律等 │ +│ └────────────────────────┘ 变化点:序列数据、空位位置 │ +│ │ +│ 模式 H:时钟/特殊图形型 │ +│ ┌────────────────────────┐ │ +│ │ 🕐 → 3:00 │ 适用:时钟练习、形状分类、货币认知 │ +│ │ 🕑 → ___ │ 等需要特殊图形绘制的题型 │ +│ └────────────────────────┘ │ +│ │ +└──────────────────────────────────────────────────────────────────┘ +``` + +**结论:只需要实现 6-8 种 TemplateRenderer,就能覆盖绝大多数题型。** + +### 5.3 模板引擎架构 + +``` +┌──────────────────────────────────────────────────────────────┐ +│ 模板引擎工作流 │ +│ │ +│ ┌─────────────┐ │ +│ │ 题型 JSON │ ← 本地内置 / 云端下发 │ +│ │ 配置数据 │ │ +│ └──────┬──────┘ │ +│ │ │ +│ ┌────────────┼────────────┐ │ +│ ▼ ▼ ▼ │ +│ ┌────────────┐ ┌───────────┐ ┌──────────┐ │ +│ │ template │ │ generator │ │ layout │ │ +│ │ 选择渲染器 │ │ 选择生成器│ │ 排版参数 │ │ +│ └─────┬──────┘ └─────┬─────┘ └────┬─────┘ │ +│ │ │ │ │ +│ ▼ ▼ │ │ +│ ┌───────────┐ ┌──────────┐ │ │ +│ │ Template │ │Generator │ │ │ +│ │ Renderer │ │ 生成数据 │ │ │ +│ │ (6-8种) │ │ │ │ │ +│ └─────┬─────┘ └────┬─────┘ │ │ +│ │ │ │ │ +│ ▼ ▼ ▼ │ +│ ┌────────────────────────────────────┐ │ +│ │ Canvas 2D 渲染 │ │ +│ │ TemplateRenderer.render(data, layout) │ +│ └───────────────────┬────────────────┘ │ +│ │ │ +│ ▼ │ +│ ┌─────────────┐ │ +│ │ A4 打印图片 │ │ +│ └─────────────┘ │ +└──────────────────────────────────────────────────────────────┘ +``` + +### 5.4 JSON 配置 Schema + +每个题型由一条 JSON 配置定义,包含三个核心部分:「用哪个模板渲染」「用哪个生成器产出数据」「排版参数」。 + +```typescript +/** + * 题型配置(可云端下发,可前端内置) + */ +interface WorksheetConfig { + // ─── 元数据(展示用)─── + id: string; + title: string; + desc: string; + category: 'math' | 'chinese' | 'english' | 'puzzle' | 'craft'; + subcategory: string; + ageRange: [number, number]; + difficulty: 1 | 2 | 3 | 4; + previewImage: string; + tags: string[]; + isNew: boolean; + sortOrder: number; + status: 'active' | 'draft' | 'hidden'; + + // ─── 模板引擎配置(渲染用)─── + template: TemplateType; // 使用哪个排版模板 + generator: GeneratorType; // 使用哪个数据生成器 + generatorConfig: Record; // 生成器参数(不同生成器不同) + layoutConfig: LayoutConfig; // 排版参数 + userConfigurable?: UserConfigField[]; // 用户可调整的参数定义 +} + +/** + * 排版模板枚举(前端代码实现,新增需发版) + */ +type TemplateType = + | 'grid-exercise' // 模式 A:网格计算型 + | 'match-connect' // 模式 B:配对连线型 + | 'grid-coloring' // 模式 C:网格涂色型 + | 'card-layout' // 模式 D:卡片排列型 + | 'tracing-writing' // 模式 E:描红书写型 + | 'full-page-asset' // 模式 F:全幅素材型 + | 'sequence-pattern' // 模式 G:序列/排序型 + | 'special-graphic'; // 模式 H:时钟/特殊图形型 + +/** + * 数据生成器枚举(前端代码实现,新增需发版) + */ +type GeneratorType = + | 'arithmetic' // 加减乘除运算题 + | 'number-sequence' // 数列/排序 + | 'number-decompose' // 数的分与合 + | 'counting' // 数数类 + | 'comparison' // 比大小 + | 'shape-grid' // 图形网格 + | 'color-pattern' // 颜色规律 + | 'character-tracing' // 汉字描红(需 SVG 笔画数据) + | 'letter-tracing' // 字母描红 + | 'pinyin-tracing' // 拼音描红 + | 'static-asset' // 静态素材(不生成,直接用素材) + | 'maze' // 迷宫算法 + | 'dot-connect' // 点连线 + | 'clock' // 时钟 + | 'custom'; // 自定义(需指定 customGeneratorId) + +/** + * 排版配置 + */ +interface LayoutConfig { + columns?: number; // 列数 + rows?: number; // 行数 + fontSize?: number; // 字号 + showBorder?: boolean; // 是否显示边框 + showTitle?: boolean; // 是否显示标题 + padding?: number; // 内边距 + itemSpacing?: number; // 元素间距 + showInstruction?: boolean; // 是否显示题目说明文字 + instructionText?: string; // 说明文字内容 +} + +/** + * 用户可配置的参数定义(渲染到参数设置面板) + */ +interface UserConfigField { + key: string; // 对应 generatorConfig 中的 key + label: string; // 显示名称 + type: 'select' | 'slider' | 'switch'; + options?: { label: string; value: any }[]; // select 类型的选项 + min?: number; // slider 最小值 + max?: number; // slider 最大值 + defaultValue: any; +} +``` + +### 5.5 配置示例 + +**示例 1:算法生成型 — 10 以内加法** + +```json +{ + "id": "addition-10", + "title": "10以内加法", + "desc": "练习10以内的加法运算,图形化展示", + "category": "math", + "subcategory": "basic-arithmetic", + "ageRange": [4, 6], + "difficulty": 2, + + "template": "grid-exercise", + "generator": "arithmetic", + "generatorConfig": { + "operators": ["+"], + "maxNumber": 10, + "count": 20, + "showDots": true, + "showAnswer": false + }, + "layoutConfig": { + "columns": 2, + "showBorder": true, + "fontSize": 18, + "showInstruction": true, + "instructionText": "算一算,填上答案" + }, + "userConfigurable": [ + { + "key": "count", + "label": "题目数量", + "type": "select", + "options": [ + { "label": "10 题", "value": 10 }, + { "label": "20 题", "value": 20 }, + { "label": "30 题", "value": 30 } + ], + "defaultValue": 20 + }, + { + "key": "showDots", + "label": "显示圆点辅助", + "type": "switch", + "defaultValue": true + } + ] +} +``` + +**示例 2:素材型 — 恐龙涂色卡** + +```json +{ + "id": "coloring-dinosaur-01", + "title": "恐龙涂色卡", + "desc": "可爱恐龙线稿,涂出你喜欢的颜色", + "category": "craft", + "subcategory": "coloring", + "ageRange": [3, 6], + "difficulty": 1, + + "template": "full-page-asset", + "generator": "static-asset", + "generatorConfig": { + "assetUrl": "cloud://doodle-xxx/assets/coloring/dinosaur-01.svg", + "assetType": "svg" + }, + "layoutConfig": { + "padding": 20, + "showTitle": true + }, + "userConfigurable": [] +} +``` + +**示例 3:混合型 — 字母描红** + +```json +{ + "id": "letter-tracing-uppercase", + "title": "大写字母描红", + "desc": "A-Z 大写字母描红练习", + "category": "english", + "subcategory": "letter-tracing", + "ageRange": [4, 7], + "difficulty": 1, + + "template": "tracing-writing", + "generator": "letter-tracing", + "generatorConfig": { + "letters": "ABCDEFGHIJKLMNOPQRSTUVWXYZ", + "case": "upper", + "lettersPerPage": 4, + "repetitions": 6, + "gridType": "four-line" + }, + "layoutConfig": { + "showInstruction": true, + "instructionText": "沿虚线描写字母,注意笔画顺序" + }, + "userConfigurable": [ + { + "key": "lettersPerPage", + "label": "每页字母数", + "type": "select", + "options": [ + { "label": "2 个", "value": 2 }, + { "label": "4 个", "value": 4 }, + { "label": "6 个", "value": 6 } + ], + "defaultValue": 4 + } + ] +} +``` + +### 5.6 TemplateRenderer 实现结构 + +```typescript +/** + * 所有模板渲染器的基类 + */ +abstract class BaseTemplateRenderer { + protected ctx: CanvasRenderingContext2D; + protected paper: PaperConfig; + + constructor(ctx: CanvasRenderingContext2D, paper: PaperConfig) { + this.ctx = ctx; + this.paper = paper; + } + + async render(data: any, layout: LayoutConfig, printConfig: PrintConfig): Promise { + this.drawBackground(); + this.drawHeader(printConfig); + if (layout.showInstruction) { + this.drawInstruction(layout.instructionText!); + } + await this.drawContent(data, layout); + this.drawFooter(printConfig); + } + + protected abstract drawContent(data: any, layout: LayoutConfig): Promise; +} + +/** + * 模式 A:网格计算型渲染器 + * 可渲染所有「一行一题」或「多列排布」的练习题 + */ +class GridExerciseRenderer extends BaseTemplateRenderer { + protected async drawContent(data: ArithmeticData, layout: LayoutConfig) { + const { columns = 2, fontSize = 16, showBorder = true } = layout; + const { questions } = data; + // 按 columns 分列排布,每题绘制:操作数 + 运算符 + 等号 + 空位 + // 如果 showDots,绘制圆点图示辅助 + } +} + +/** + * 模式 F:全幅素材型渲染器 + * 加载图片/SVG → 居中适配到 A4 页面 + */ +class FullPageAssetRenderer extends BaseTemplateRenderer { + protected async drawContent(data: AssetData, layout: LayoutConfig) { + const image = await this.loadImage(data.assetUrl); + // 计算等比缩放,居中绘制到 A4 内容区 + } +} +``` + +``` +core/draw/ +├── base-template-renderer.ts ← 渲染器基类 +├── renderers/ +│ ├── grid-exercise.ts ← 模式 A:网格计算型 +│ ├── match-connect.ts ← 模式 B:配对连线型 +│ ├── grid-coloring.ts ← 模式 C:网格涂色型 +│ ├── card-layout.ts ← 模式 D:卡片排列型 +│ ├── tracing-writing.ts ← 模式 E:描红书写型 +│ ├── full-page-asset.ts ← 模式 F:全幅素材型 +│ ├── sequence-pattern.ts ← 模式 G:序列/排序型 +│ └── special-graphic.ts ← 模式 H:时钟/特殊图形型 +├── renderer-registry.ts ← 渲染器注册表 +└── template-engine.ts ← 模板引擎入口 +``` + +### 5.7 模板引擎入口 + +```typescript +/** + * 模板引擎:根据 JSON 配置,选择渲染器和生成器,完成绘制 + * 这是通用 worksheet 页面的核心调用逻辑 + */ +class TemplateEngine { + private rendererRegistry: Map; + private generatorRegistry: Map; + + async render( + worksheetConfig: WorksheetConfig, + userParams: Record, // 用户在 UI 上调整的参数 + ctx: CanvasRenderingContext2D, + printConfig: PrintConfig, + ): Promise { + // 1. 合并用户参数到 generatorConfig + const mergedConfig = { ...worksheetConfig.generatorConfig, ...userParams }; + + // 2. 选择生成器,生成题目数据 + const generator = this.generatorRegistry.get(worksheetConfig.generator); + const data = generator.generate(mergedConfig); + + // 3. 选择渲染器,绘制到 Canvas + const renderer = this.rendererRegistry.get(worksheetConfig.template); + await renderer.render(data, worksheetConfig.layoutConfig, printConfig); + } +} +``` + +### 5.8 通用 Worksheet 页面 + +有了模板引擎后,**不再需要为每种题型创建独立页面**。只需一个通用页面: + +``` +pages/worksheet/worksheet ← 通用题型生成页 +``` + +```typescript +// pages/worksheet/worksheet.ts(伪代码) +createPage({ + onLoad(options) { + const worksheetId = options.id; + // 从本地缓存或云端获取该题型的 JSON 配置 + const config = WorksheetService.getConfig(worksheetId); + this.setData({ + title: config.title, + userFields: config.userConfigurable, // 动态渲染参数面板 + userParams: getDefaultParams(config), + }); + }, + onCanvasReady() { + this.drawCanvas(); + }, + async drawCanvas() { + await TemplateEngine.render( + this.config, + this.data.userParams, + this.ctx, + getApp().globalData.printConfig, + ); + }, + onParamChange(e) { + // 用户调整参数 → 重新绘制 + this.setData({ userParams: { ...this.data.userParams, ...e.detail } }); + this.drawCanvas(); + }, + onRefresh() { + // 换一批 → 重新生成+绘制 + this.drawCanvas(); + }, +}); +``` + +### 5.9 什么能动态更新 vs 什么需要发版 + +``` +┌────────────────────────────────────────────────────────────────┐ +│ │ +│ ✅ 可动态更新(修改 JSON 配置 / 上传素材,无需发版) │ +│ ────────────────────────────────────────────────── │ +│ • 已有模板+已有生成器 组合出的新题型 │ +│ (例:用 grid-exercise + arithmetic 配出「50以内减法」) │ +│ • 修改题型参数(数量范围、难度、显示选项等) │ +│ • 上下架/排序/分类调整/标签修改 │ +│ • 新增素材型内容(涂色卡、折纸模板、闪卡图片等) │ +│ • 修改页眉/页脚样式配置 │ +│ • 新增分类/子分类 │ +│ │ +│ ❌ 需要发版(新增前端代码) │ +│ ────────────────────────────────────────────────── │ +│ • 全新的排版模板(TemplateRenderer) │ +│ • 全新的生成算法(Generator) │ +│ • 新的用户交互模式 │ +│ • 新的 UI 组件 │ +│ │ +│ 📊 预估覆盖率 │ +│ ────────────────────────────────────────────────── │ +│ • 实现 8 种模板 + 15 种生成器后 │ +│ • 约 80% 的新题型可通过 JSON 配置动态上线 │ +│ • 剩余 20% 需要新模板/生成器,但复用已有基础代码 │ +│ │ +└────────────────────────────────────────────────────────────────┘ +``` + +### 5.10 存量题型迁移策略 + +现有 40+ 种题型已经稳定运行,**不建议一次性全部推翻重写**。推荐渐进式迁移: + +``` +阶段 1(与模板引擎同步开发): +├── 新题型全部走模板引擎 +└── 旧题型保持原有专用 DrawService,正常运行 + +阶段 2(按模板类型逐批迁移): +├── 批次 1:所有 grid-exercise 类 +│ └── addition, subtraction, calculationPractice, +│ missingNumber, compare, makeTen, breakTen... (~15 种) +├── 批次 2:所有 match-connect 类 +│ └── countMatch, numberObjectMatch, matchConnect, +│ codeConnect, dotConnect... (~6 种) +├── 批次 3:所有 grid-coloring 类 +│ └── numberFind, positionColoring, gridDrawing, +│ shapeSymbol, colorPattern... (~8 种) +├── 批次 4:tracing-writing 类 +│ └── copyBook, numberWrite... (~2 种) +└── 批次 5:其余类型 + +路由兼容: + 旧页面路径不变,内部逻辑替换为 TemplateEngine.render() + 或:旧路径 redirect 到通用 worksheet 页面 +``` + +--- + +## 六、后端(云开发)详细设计 + +### 6.1 云数据库集合设计 ``` 云数据库 Collections: @@ -383,13 +945,21 @@ class AdditionGenerator implements IWorksheetGenerator { - img.onload = () => resolve(img); - img.onerror = reject; - img.src = src; - }); - } -} - -// Web 实现(未来) -class WebImageAdapter implements IImageAdapter { - async loadImage(_canvas: HTMLCanvasElement, src: string) { - const img = new Image(); - img.crossOrigin = 'anonymous'; - return new Promise((resolve, reject) => { - img.onload = () => resolve(img); - img.onerror = reject; - img.src = src; - }); - } + async loadImage(canvas: WechatMiniprogram.Canvas, src: string) { + const img = canvas.createImage(); + return new Promise((resolve, reject) => { + img.onload = () => resolve(img); + img.onerror = reject; + img.src = src; + }); + } } +// Web 端适配见 PC-Web端技术预案.md ``` -### 6.3 PDF 导出方案(Phase 4) +### 7.3 导出方案 ``` -方案对比: +核心路径:客户端 Canvas 渲染 → PNG 图片 → 保存到相册 -A. 云函数生成 PDF(推荐) - 云函数接收绘制参数 JSON → 服务端用 pdfkit 生成 → 上传云存储 → 返回下载链接 - 优点:不受客户端限制,可生成多页 - 缺点:云函数有执行时间限制(60s),复杂图形渲染较慢 +┌─────────────────────────────────────────────────────┐ +│ 为什么选择 PNG 保存到相册作为主路径: │ +│ │ +│ 1. 用户认知成本最低 │ +│ 相册是手机用户最熟悉的文件存储位置 │ +│ PDF 保存后,大量用户找不到文件在哪里 │ +│ │ +│ 2. 打印路径最短 │ +│ 相册 → 手机连打印机 → 直接打印 │ +│ 无需额外 App 打开 PDF │ +│ │ +│ 3. 分享最便捷 │ +│ 微信聊天直接发图片,接收方零门槛查看 │ +│ │ +│ 4. 零服务器成本 │ +│ Canvas 本地渲染,不消耗云函数算力和存储 │ +│ 用户量增长不会带来额外成本 │ +│ │ +│ 5. 技术架构成熟 │ +│ 现有 Canvas → PNG 链路已完善且稳定 │ +└─────────────────────────────────────────────────────┘ -B. 客户端多页 Canvas 拼接 - 前端生成多张 PNG → 云函数用 pdfkit 合并为 PDF - 优点:渲染在客户端,云函数只做拼接 - 缺点:需上传多张图片到云存储,流量开销大 +批量生成方案(P4): + → 一次渲染多张不同题目 → 批量保存到相册 + → 用户打印时多选图片即可 -C. Web 端直接使用 jsPDF - 仅适用于 PC Web 版本 - 优点:零服务器成本 - 缺点:小程序不可用 - -推荐路径: - 小程序:方案 B(客户端渲染 + 云端拼接) - PC Web:方案 C(jsPDF 纯前端) +PDF 导出方案(远期增值功能,会员专属): + 小程序:客户端渲染多张 PNG → 上传云存储 → 云函数用 pdfkit 合并为 PDF + 定位:会员订阅的差异化权益,非核心路径 ``` -### 6.4 涂色卡/迷宫等素材型内容方案 +### 7.4 涂色卡/迷宫等素材型内容方案 ``` ┌──────────────────────────────────────────────────────┐ @@ -668,80 +1235,15 @@ C. Web 端直接使用 jsPDF --- -## 七、PC Web 端技术预案 +## 八、PC Web 端技术预案(远期) -### 7.1 时机判断 - -**当前不急于开发 PC Web 的原因:** -- 小程序用户群与目标用户(家长)高度重合,微信即触达 -- PC Web 需要额外解决支付、登录、SEO 等问题 -- 先把小程序做好,积累内容和用户 - -**何时启动 PC Web:** -- 小程序 DAU 稳定 > 1000 -- 用户反馈中"想在电脑上用"的需求频繁出现 -- 内容积累到 100+ 种题型 - -### 7.2 技术选型预案 - -``` -PC Web 技术栈(未来): -┌────────────────────────────────────┐ -│ 框架:Next.js (App Router) │ -│ UI:Tailwind CSS + Radix UI │ -│ Canvas:HTML5 Canvas 2D │ -│ PDF:jsPDF + html2canvas │ -│ 状态:Zustand │ -│ 部署:Vercel │ -│ │ -│ 核心复用: │ -│ @doodle/core (共享核心层) │ -│ └── 绘制服务、生成器、数据模型 │ -│ → 直接 import 使用 │ -│ │ -│ 需新建: │ -│ • Web UI 组件 │ -│ • 平台适配层 (Web 实现) │ -│ • 用户登录(微信扫码/手机号) │ -│ • SEO 优化(SSR/SSG 题型页) │ -└────────────────────────────────────┘ -``` - -### 7.3 代码共享策略 - -``` -仓库结构(Monorepo,未来演进): -doodle/ -├── packages/ -│ └── core/ ← 共享核心(npm 包) -│ ├── src/ -│ │ ├── draw/ -│ │ ├── generators/ -│ │ ├── models/ -│ │ └── utils/ -│ ├── package.json -│ └── tsconfig.json -├── apps/ -│ ├── mini/ ← 微信小程序 -│ │ ├── miniprogram/ -│ │ ├── cloudfunctions/ -│ │ └── project.config.json -│ └── web/ ← PC Web(未来) -│ ├── src/ -│ ├── package.json -│ └── next.config.js -├── pnpm-workspace.yaml -└── package.json - -当前阶段不需要 Monorepo,只需在小程序项目中: -1. 将 core/ 作为目录组织代码 -2. 确保 core/ 内不 import 任何 wx.* API -3. 未来迁移时,将 core/ 提取为独立 npm 包即可 -``` +> PC Web 端属于远期规划,详细方案见独立文档:[PC-Web端技术预案](./PC-Web端技术预案.md) +> +> **当前阶段的准备**:只需确保 `core/` 层内不 import 任何 `wx.*` API,未来迁移时提取为独立 npm 包即可。 --- -## 八、前端重构路线图 +## 九、前端重构路线图 ### Phase 1:基础重构(第 1-2 周) @@ -771,53 +1273,76 @@ doodle/ └── 合并 mathPages 和 focusPages 的重复 canvas-page-template ``` -### Phase 2:首页重构 + 内容配置化(第 3-4 周) +### Phase 2:模板引擎 + 首页重构 + 配置化(第 3-5 周) ``` -优先级:🟡 重要 +优先级:🟡 重要(模板引擎是后续扩展的基础) -1. 数据模型升级 - ├── WorksheetType 增加 category/ageRange/difficulty/tags 等字段 +1. 模板引擎核心开发 + ├── 实现 BaseTemplateRenderer 基类 + ├── 实现 TemplateEngine 入口(配置解析 + 渲染器/生成器调度) + ├── 实现 RendererRegistry / GeneratorRegistry + ├── 开发通用 worksheet 页面(pages/worksheet/worksheet) + │ └── 根据 JSON 配置动态渲染参数面板 + Canvas 预览 + ├── 优先实现 3 种高复用模板渲染器: + │ ├── grid-exercise(网格计算型,覆盖 ~15 种现有数学题) + │ ├── full-page-asset(全幅素材型,覆盖涂色卡/折纸等新内容) + │ └── tracing-writing(描红书写型,覆盖练字/字母/拼音) + └── 将 2-3 种现有题型试点迁移到模板引擎(验证可行性) + +2. 数据模型升级 + ├── WorksheetConfig 增加 template/generator/layoutConfig 等字段 ├── 定义 Category 模型 - └── 重构 MATH_FUNCTION_TYPES / FOCUS_FUNCTION_TYPES 为统一格式 + ├── 重构 MATH_FUNCTION_TYPES / FOCUS_FUNCTION_TYPES 为统一 JSON 格式 + └── 编写存量题型的 JSON 配置映射 -2. 首页重构 +3. 首页重构 ├── 新建 pages/home/ 替代原四个 Tab 入口页 ├── 实现分类标签栏 + 搜索 + 推荐区 ├── 实现年龄筛选、难度筛选 └── 使用新的 worksheet-card 组件(带预览图) -3. TabBar 重构 +4. TabBar 重构 └── 发现 | 分龄 | 收藏 | 我的 -4. 云数据库初始化 - ├── 建表:worksheets、categories - ├── 编写数据初始化脚本 +5. 云数据库初始化 + ├── 建表:worksheets(含模板引擎字段)、categories + ├── 编写数据初始化脚本(存量题型 JSON 导入) └── 实现前端数据加载(缓存优先 + 云端更新) ``` -### Phase 3:新内容接入(第 5-6 周) +### Phase 3:模板扩展 + 新内容接入(第 6-8 周) ``` 优先级:🟡 重要 -1. 开发通用素材渲染器 - └── 通用的「加载图片 + A4 排版 + 导出」流程 +1. 补全剩余模板渲染器 + ├── match-connect(配对连线型) + ├── grid-coloring(网格涂色型) + ├── card-layout(卡片排列型) + ├── sequence-pattern(序列/排序型) + └── special-graphic(时钟/特殊图形型) -2. 新增题型开发 - ├── 数学:时钟练习、形状分类 - ├── 语文:拼音练习、笔画练习 - ├── 英语:字母描红(复用 numberFind 逻辑) - ├── 益智:控笔练习 - └── 创意:涂色卡(素材型) +2. 新增题型(通过 JSON 配置 + 素材上传,大部分无需写新代码) + ├── 数学:时钟练习(需 special-graphic 渲染器) + ├── 语文:拼音练习(复用 tracing-writing) + ├── 英语:字母描红(复用 tracing-writing + letter-tracing 生成器) + ├── 英语:字母闪卡(复用 card-layout + static-asset) + ├── 益智:控笔练习(复用 tracing-writing) + └── 创意:涂色卡(复用 full-page-asset,仅需上传素材) -3. 完善新分包 +3. 存量题型批量迁移 + ├── 批次 1:grid-exercise 类 (~15 种) + ├── 批次 2:match-connect 类 (~6 种) + └── 批次 3:grid-coloring 类 (~8 种) + +4. 完善新分包 ├── english/ 分包 ├── puzzle/ 分包 └── craft/ 分包 ``` -### Phase 4:体验与功能升级(第 7-8 周) +### Phase 4:体验与功能升级(第 9-10 周) ``` 优先级:🟢 增强 @@ -829,18 +1354,21 @@ doodle/ 2. 打印体验 ├── 打印指南页面 - ├── 批量生成(多题一页/多页) - └── PDF 导出(云函数) + ├── 批量生成图片(多张保存到相册) + └── 客户端渲染性能优化 3. 运营能力 ├── 数据埋点完善 ├── 下载统计展示(热门排行) └── 用户反馈入口 + +4. 远期增值功能 + └── PDF 导出(会员专属,云函数合并 PNG 为 PDF) ``` --- -## 九、成本预估 +## 十、成本预估 ### 9.1 微信云开发费用 @@ -869,60 +1397,62 @@ doodle/ ``` 开发投入估算: -┌──────────────────────────────┐ -│ Phase 1: ~20 人时 │ -│ Phase 2: ~40 人时 │ -│ Phase 3: ~40 人时 │ -│ Phase 4: ~30 人时 │ -│ ────────────────────── │ -│ 总计: ~130 人时 │ -│ (1 人兼职 ~8 周可完成) │ -└──────────────────────────────┘ +┌──────────────────────────────────────────────────┐ +│ Phase 1: ~20 人时(基础重构 + 修复技术债) │ +│ Phase 2: ~60 人时(模板引擎 + 首页重构 + 配置化) │ +│ Phase 3: ~40 人时(模板扩展 + 新内容 + 存量迁移) │ +│ Phase 4: ~30 人时(用户体系 + 体验升级) │ +│ ────────────────────── │ +│ 总计: ~150 人时 │ +│ (1 人兼职 ~10 周可完成) │ +│ │ +│ 注:模板引擎上线后,新增内容仅需 JSON 配置 │ +│ + 素材上传,边际成本趋近于零 │ +└──────────────────────────────────────────────────┘ ``` --- -## 十、技术风险与应对 +## 十一、技术风险与应对 -| 风险 | 影响 | 应对方案 | -|------|------|---------| -| 云开发免费额度不够 | 功能受限 | ① 优化查询减少调用 ② 本地缓存减少读取 ③ 升级付费版(19.9元/月起) | -| Canvas 兼容性 | 低端机渲染异常 | ① 使用 Canvas 2D(已采用)② 控制单次绘制复杂度 ③ 降级方案 | -| 小程序包体积 | 超 2MB 限制 | ① 素材用 CDN / 云存储 ② 合理分包 ③ 图片压缩 | -| 素材制作瓶颈 | 涂色卡等需设计资源 | ① 使用开源 SVG 素材 ② AI 生成线稿 ③ 社区投稿 | -| 跨平台迁移成本 | Web 端重复开发 | ① core/ 层保持平台无关 ② 适配器模式隔离差异 | -| 云开发 HTTP API 限制 | PC Web 调用不便 | ① 使用云开发 HTTP API 触发器 ② 必要时引入轻量后端 | +| 风险 | 影响 | 应对方案 | +| -------------------- | ------------------ | ----------------------------------------------------------------- | +| 云开发免费额度不够 | 功能受限 | ① 优化查询减少调用 ② 本地缓存减少读取 ③ 升级付费版(19.9元/月起) | +| Canvas 兼容性 | 低端机渲染异常 | ① 使用 Canvas 2D(已采用)② 控制单次绘制复杂度 ③ 降级方案 | +| 小程序包体积 | 超 2MB 限制 | ① 素材用 CDN / 云存储 ② 合理分包 ③ 图片压缩 | +| 素材制作瓶颈 | 涂色卡等需设计资源 | ① 使用开源 SVG 素材 ② AI 生成线稿 ③ 社区投稿 | +| 跨平台迁移成本 | Web 端重复开发 | ① core/ 层保持平台无关 ② 适配器模式隔离差异(详见 [PC-Web端技术预案](./PC-Web端技术预案.md)) | --- ## 附录 A:现有代码与目标架构映射 -| 现有文件 | 目标位置 | 迁移动作 | -|---------|---------|---------| -| `constants/mathFunctions.ts` | `core/data/worksheets.ts` | 合并,增加字段 | -| `constants/focusFunctions.ts` | `core/data/worksheets.ts` | 合并,增加字段 | -| `constants/words.ts` | `core/data/words.ts` | 移动 | -| `constants/colors.ts` | `core/data/colors.ts` | 移动 | -| `constants/shapes.ts` | `core/data/shapes.ts` | 移动 | -| `service/baseDraw.ts` | `core/draw/base-draw.ts` | 重构,去除 wx.* 依赖 | -| `service/wordDrawService.ts` | `core/draw/chinese-draw/word-draw.ts` | 移动,去除 wx.* | -| `service/drawServiceFactory.ts` | `core/draw/draw-factory.ts` | 扩展 | -| `mathPages/shared/service/*.ts` | `core/draw/math-draw/*.ts` | 移动,去除 wx.* | -| `focusPages/shared/service/*.ts` | `core/draw/focus-draw/*.ts` | 移动,去除 wx.* | -| `base/pageMixin.ts` | `services/print-service.ts` + 页面代码 | 拆分职责 | -| `base/callCloud.ts` | `platform/cloud-adapter.ts` | 重构 | -| `utils/saveImage.ts` | `platform/canvas-adapter.ts` | 合并到适配器 | -| `utils/downloadPrint.ts` | `services/print-service.ts` | 整合 | -| `utils/tracker.ts` | `services/stats-service.ts` | 整合 | -| `config/config.ts` | `core/models/print-config.ts` | 类型化 | +| 现有文件 | 目标位置 | 迁移动作 | +| -------------------------------- | -------------------------------------- | --------------------- | +| `constants/mathFunctions.ts` | `core/data/worksheets.ts` | 合并,增加字段 | +| `constants/focusFunctions.ts` | `core/data/worksheets.ts` | 合并,增加字段 | +| `constants/words.ts` | `core/data/words.ts` | 移动 | +| `constants/colors.ts` | `core/data/colors.ts` | 移动 | +| `constants/shapes.ts` | `core/data/shapes.ts` | 移动 | +| `service/baseDraw.ts` | `core/draw/base-draw.ts` | 重构,去除 wx.\* 依赖 | +| `service/wordDrawService.ts` | `core/draw/chinese-draw/word-draw.ts` | 移动,去除 wx.\* | +| `service/drawServiceFactory.ts` | `core/draw/draw-factory.ts` | 扩展 | +| `mathPages/shared/service/*.ts` | `core/draw/legacy/math-draw/*.ts` | 移入 legacy,去除 wx.\*,逐步迁移到模板引擎 | +| `focusPages/shared/service/*.ts` | `core/draw/legacy/focus-draw/*.ts` | 移入 legacy,去除 wx.\*,逐步迁移到模板引擎 | +| `base/pageMixin.ts` | `services/print-service.ts` + 页面代码 | 拆分职责 | +| `base/callCloud.ts` | `platform/cloud-adapter.ts` | 重构 | +| `utils/saveImage.ts` | `platform/canvas-adapter.ts` | 合并到适配器 | +| `utils/downloadPrint.ts` | `services/print-service.ts` | 整合 | +| `utils/tracker.ts` | `services/stats-service.ts` | 整合 | +| `config/config.ts` | `core/models/print-config.ts` | 类型化 | ## 附录 B:技术选型决策记录 -| 决策点 | 选项 | 决策 | 理由 | -|--------|------|------|------| -| 跨端框架 | Taro / uni-app / 原生 | **原生** | 项目已用原生开发,迁移成本高;Taro 等框架对 Canvas 2D 支持有限;core/ 层抽取足以实现代码复用 | -| 状态管理 | MobX / 自定义 / 原生 setData | **轻量自定义** | 小程序场景简单,不需要 Redux 级方案;页面级 setData + 全局 Store 够用 | -| UI 组件库 | Vant / 自研 | **Vant + 自定义组件** | 已用 Vant,保持;业务组件自研 | -| 云开发 vs 自建 | 云开发 / 云服务器 | **云开发** | 零运维、免费额度充足、原生集成鉴权 | -| PDF 方案 | pdfkit(云) / jsPDF(端) | **两者结合** | 小程序用云端 pdfkit,Web 用 jsPDF | -| Monorepo | pnpm workspace / Turborepo | **暂不采用** | 当前只有小程序,过早引入增加复杂度;core/ 作为目录组织,未来再拆包 | +| 决策点 | 选项 | 决策 | 理由 | +| -------------- | ---------------------------- | ------------------------ | -------------------------------------------------------------------------------------------------------------------------------- | +| 跨端框架 | Taro / uni-app / 原生 | **原生** | 项目已用原生开发,迁移成本高;Taro 等框架对 Canvas 2D 支持有限;core/ 层抽取足以实现代码复用 | +| 状态管理 | MobX / 自定义 / 原生 setData | **轻量自定义** | 小程序场景简单,不需要 Redux 级方案;页面级 setData + 全局 Store 够用 | +| UI 组件库 | Vant / 自研 | **Vant + 自定义组件** | 已用 Vant,保持;业务组件自研 | +| 云开发 vs 自建 | 云开发 / 云服务器 | **云开发** | 零运维、免费额度充足、原生集成鉴权 | +| 导出方案 | PNG 保存相册 / PDF | **PNG 为主,PDF 为增值** | PNG 保存到相册是手机端最短路径(用户教育成本低、零服务器开销);PDF 作为远期会员增值功能,小程序用云端 pdfkit 合并,Web 用 jsPDF | +| Monorepo | pnpm workspace / Turborepo | **暂不采用** | 当前只有小程序,过早引入增加复杂度;core/ 作为目录组织,未来再拆包 | diff --git a/docs/素材资源获取方案.md b/docs/素材资源获取方案.md new file mode 100644 index 0000000..df95bfd --- /dev/null +++ b/docs/素材资源获取方案.md @@ -0,0 +1,449 @@ +# 涂鸦丫 - 素材资源获取方案 + +> 解决涂色卡、手工模板等非程序化内容的素材生产问题 +> 最后更新:2026-03-24 + +--- + +## 一、问题背景 + +涂鸦丫的内容分为两大类: + +| 类型 | 示例 | 生产方式 | 现状 | +| -------------- | ---------------------------- | ---------------------- | --------- | +| **算法生成型** | 数学题、专注力训练、字母练习 | 代码随机生成,无限变化 | ✅ 已具备 | +| **素材模板型** | 涂色卡、折纸、手工、贴纸 | 需要人工绘制或外部素材 | ❌ 缺失 | + +素材模板型内容(如圣诞主题涂色卡、动物线稿等)不能用代码程序化生成,传统方式依赖设计师手工绘制,产出效率低、成本高。本文档梳理可行的替代方案,实现素材的低成本批量生产。 + +--- + +## 二、方案总览 + +``` +┌──────────────────────────────────────────────────────────────────┐ +│ 素材获取策略 │ +│ │ +│ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌──────────────┐ │ +│ │ 方案 1 │ │ 方案 2 │ │ 方案 3 │ │ 方案 4 │ │ +│ │ AI 生成线稿 │ │ 开源素材 │ │ 图片转线稿 │ │ 半程序化生成 │ │ +│ │ ⭐⭐⭐⭐⭐ │ │ ⭐⭐⭐⭐ │ │ ⭐⭐⭐ │ │ ⭐⭐⭐⭐ │ │ +│ │ 性价比最高 │ │ 零成本起步 │ │ 批量转化 │ │ 代码+素材混合 │ │ +│ └────────────┘ └────────────┘ └────────────┘ └──────────────┘ │ +│ │ +│ ┌────────────┐ │ +│ │ 方案 5 │ │ +│ │ 社区共创 │ │ +│ │ ⭐⭐ │ │ +│ │ 远期生态 │ │ +│ └────────────┘ │ +└──────────────────────────────────────────────────────────────────┘ +``` + +--- + +## 三、方案详解 + +### 3.1 AI 生成线稿(推荐,性价比最高) + +AI 图像生成工具已经能高质量地生成涂色卡线稿,是目前最推荐的方案。 + +#### 可用工具 + +| 工具 | 特点 | 成本 | 推荐度 | +| ------------------------------- | --------------------------------- | ------------ | ---------- | +| Midjourney | 线稿质量最好,风格一致性强 | ~$10/月 | ⭐⭐⭐⭐⭐ | +| Stable Diffusion (本地/ComfyUI) | 免费,可批量,可训练专属风格 LoRA | 需要 GPU | ⭐⭐⭐⭐⭐ | +| DALL-E 3 (ChatGPT/API) | 使用方便,质量不错 | API 按量计费 | ⭐⭐⭐⭐ | +| 可灵 / 通义万相 | 国内工具,中文 prompt 友好 | 有免费额度 | ⭐⭐⭐ | + +#### Prompt 模板 + +**通用涂色卡:** + +``` +coloring page for kids, cute [主题词], simple black outline, +no shading, no color, white background, clean lines, +thick outlines suitable for children, cartoon style, +A4 print ready --v 6 --style raw +``` + +**主题示例:** + +``` +# 动物系列 +coloring page for kids, cute baby elephant playing with water, +simple black outline, no shading, no color, white background, +clean lines, thick outlines, cartoon style --v 6 --style raw + +# 节日系列 +coloring page for kids, Christmas tree with presents and star, +simple black outline, no shading, no color, white background, +clean lines, thick outlines, cartoon style --v 6 --style raw + +# 交通工具系列 +coloring page for kids, friendly cartoon fire truck, +simple black outline, no shading, no color, white background, +clean lines, thick outlines, cartoon style --v 6 --style raw +``` + +#### 批量生产流程 + +``` +┌──────────────────────────────────────────────────────────────┐ +│ AI 线稿生产流水线 │ +│ │ +│ ① 规划主题清单 │ +│ 动物(20张) / 恐龙(15张) / 交通(15张) / 节日(20张) / │ +│ 食物(10张) / 海洋(15张) / 太空(10张) / ... │ +│ │ +│ ② 编写批量 Prompt │ +│ 为每个主题生成 3-5 个 prompt 变体 │ +│ 每个 prompt 生成 4 张 → 筛选最佳 1-2 张 │ +│ │ +│ ③ AI 生成 │ +│ 使用 Midjourney 或 ComfyUI 批量生成 │ +│ 预期淘汰率:30-50% │ +│ │ +│ ④ 人工筛选 │ +│ 标准:线条清晰 / 无断线 / 适合儿童 / 区域封闭可涂色 │ +│ │ +│ ⑤ 自动后处理(脚本) │ +│ → 二值化(去灰色调,纯黑白) │ +│ → 去背景噪点 │ +│ → 统一尺寸(A4 比例 595×842) │ +│ → 调整线条粗细(适合打印) │ +│ → 可选:PNG → SVG 矢量化(Potrace) │ +│ │ +│ ⑥ 质量检查 + 入库 │ +│ 标注元数据(主题/标签/适合年龄/难度) │ +│ 上传云存储 │ +│ │ +│ 产能预估:1 人 1 天 → 30-50 张成品线稿 │ +└──────────────────────────────────────────────────────────────┘ +``` + +#### 后处理脚本参考 + +```python +# tools/process_coloring_page.py +from PIL import Image, ImageFilter +import cv2 +import numpy as np + +def process_coloring_page(input_path, output_path): + """将 AI 生成的线稿处理为适合打印的涂色卡""" + img = cv2.imread(input_path, cv2.IMREAD_GRAYSCALE) + + # 二值化:去除灰色调,保留纯黑线条 + _, binary = cv2.threshold(img, 200, 255, cv2.THRESH_BINARY) + + # 去噪:移除小噪点 + kernel = np.ones((2, 2), np.uint8) + cleaned = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel) + + # 统一尺寸(A4 at 150 DPI = 1240×1754) + resized = cv2.resize(cleaned, (1240, 1754), interpolation=cv2.INTER_AREA) + + cv2.imwrite(output_path, resized) + +def batch_process(input_dir, output_dir): + """批量处理目录下所有线稿""" + import os + os.makedirs(output_dir, exist_ok=True) + for filename in os.listdir(input_dir): + if filename.lower().endswith(('.png', '.jpg', '.jpeg')): + process_coloring_page( + os.path.join(input_dir, filename), + os.path.join(output_dir, filename.rsplit('.', 1)[0] + '.png') + ) +``` + +#### Stable Diffusion 专属风格训练(进阶) + +如果需要统一的品牌风格,可以训练 LoRA 模型: + +``` +1. 收集 20-30 张「涂鸦丫」风格的线稿样本 +2. 使用 kohya_ss 训练 LoRA(约 1-2 小时 / 单 GPU) +3. 生成时加载 LoRA → 所有输出风格统一 +4. 好处:所有涂色卡风格一致,强化品牌辨识度 +``` + +--- + +### 3.2 开源 / 免费商用素材 + +大量免费可商用的线稿资源已经存在,可直接筛选使用。 + +#### 推荐素材来源 + +| 来源 | 数量 | 授权协议 | 适合度 | 备注 | +| -------------------------------------- | --------- | --------------------------- | -------- | ------------------------ | +| [OpenClipart](https://openclipart.org) | 10万+ SVG | CC0(完全免费商用) | ⭐⭐⭐⭐ | 质量参差,需仔细筛选 | +| [SVG Repo](https://www.svgrepo.com) | 50万+ SVG | 多为 CC0/MIT | ⭐⭐⭐ | 以图标为主,部分可做涂色 | +| [Pixabay](https://pixabay.com) 矢量类 | 大量 | Pixabay License(免费商用) | ⭐⭐⭐ | 搜索 "coloring page" | +| [Freepik](https://www.freepik.com) | 大量 | 免费需署名 / 付费不需要 | ⭐⭐⭐⭐ | 质量较高 | +| [Vecteezy](https://www.vecteezy.com) | 大量 | 免费需署名 | ⭐⭐⭐ | 有专门的涂色页分类 | +| [unDraw](https://undraw.co) | 500+ SVG | MIT | ⭐⭐ | 扁平风格插画,需转线稿 | + +#### 使用注意事项 + +``` +⚠️ 授权合规清单: +├── CC0 → 完全免费,可商用,无需署名 ✅ 最安全 +├── CC BY → 可商用,需要署名(在"关于我们"页注明) +├── CC BY-SA → 可商用,需署名 + 衍生作品同协议 +├── CC BY-NC → 不可商用 ❌ 不能用 +├── Pixabay License → 可商用,无需署名 ✅ +└── 其他 → 需逐一确认,记录授权来源 + +建议: +1. 优先使用 CC0 素材,避免法律风险 +2. 建立素材来源登记表,记录每个素材的出处和授权 +3. 使用付费素材时保留购买凭证 +``` + +--- + +### 3.3 图片 → 线稿转换 + +将现有的彩色图片自动转换为涂色卡线稿。 + +#### 工具方案对比 + +| 方式 | 工具 | 效果 | 适合场景 | +| ----------- | ----------------------------- | --------------- | ---------------------- | +| AI 风格转换 | SD ControlNet (Canny/Lineart) | ⭐⭐⭐⭐⭐ 最好 | 把卡通插画转为干净线稿 | +| 传统算法 | OpenCV Canny 边缘检测 | ⭐⭐⭐ 一般 | 快速批量处理,需调参 | +| 在线工具 | remove.bg + 线稿转换 | ⭐⭐ 有限 | 零代码快速尝试 | + +#### ControlNet 线稿提取流程(推荐) + +``` +输入:彩色卡通图片 + ↓ +Stable Diffusion + ControlNet + ├── 预处理器:lineart_anime 或 canny + ├── Prompt:clean line art, black outline, white background, + │ no shading, coloring page style + └── 输出:干净的黑白线稿 + ↓ +后处理:二值化 → 去噪 → 输出 +``` + +#### OpenCV 批量转换脚本 + +```python +# tools/photo_to_lineart.py +import cv2 +import numpy as np + +def photo_to_lineart(input_path, output_path, low=50, high=150, line_width=2): + """将彩色图片转换为线稿风格""" + img = cv2.imread(input_path) + gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) + blurred = cv2.GaussianBlur(gray, (5, 5), 0) + + # Canny 边缘检测 + edges = cv2.Canny(blurred, low, high) + + # 反转颜色(黑线白底) + inverted = cv2.bitwise_not(edges) + + # 加粗线条 + kernel = np.ones((line_width, line_width), np.uint8) + thick_lines = cv2.erode(inverted, kernel, iterations=1) + + cv2.imwrite(output_path, thick_lines) +``` + +**适合场景:** 已购买或已有大量卡通插画素材,需要批量转为涂色卡。 + +--- + +### 3.4 半程序化生成(代码 + 素材混合) + +部分涂色卡可以用代码生成结构框架,再填充少量素材元素。 + +#### 可程序化的涂色内容 + +| 类型 | 程序化程度 | 实现方式 | 需要素材 | +| ---------------------- | ---------- | -------------------------------- | -------------- | +| **曼陀罗涂色** | 100% | 对称几何图案,数学公式生成 | 无 | +| **几何花纹涂色** | 100% | 重复的几何形状拼接 | 无 | +| **字母/数字涂色** | 90% | 大号字体轮廓 + 装饰纹理 | 少量纹理 | +| **方格涂色(像素画)** | 100% | 按编号涂色的方格网,数字标注颜色 | 无 | +| **对称涂色** | 80% | 生成半边图案,另一半留空让孩子画 | 半边素材 | +| **场景涂色** | 50% | 代码生成天空/地面/分区框架 | 场景元素素材 | +| **节日边框涂色** | 60% | 代码生成装饰边框 | 中心主题图素材 | + +#### 曼陀罗涂色卡(100% 代码生成示例) + +``` +特点: +├── 纯数学生成,零素材成本 +├── 无限变化(随机种子) +├── 大人小孩都喜欢 +├── 可设置复杂度(简单→复杂) +└── 打印效果非常好 + +实现思路: +├── 圆形对称:围绕圆心旋转重复图案 +├── 基本元素:圆弧、花瓣、水滴形、菱形、锯齿 +├── 层级嵌套:内圈简单 → 外圈复杂 +└── Canvas 绘制,与现有渲染架构完全兼容 +``` + +#### 按编号涂色(Color by Number,100% 代码生成) + +``` +特点: +├── 在方格中标注数字,每个数字对应一种颜色 +├── 涂完后呈现一幅像素画 +├── 纯代码生成(方格 + 数字标注) +├── 可从任意简单图案生成(如爱心、星星、动物剪影) +└── 兼具涂色乐趣和数字认知训练 +``` + +--- + +### 3.5 社区共创 / UGC(远期) + +当用户量达到一定规模后,开放用户投稿。 + +#### 运作模式 + +``` +┌──────────────────────────────────────────────────────────┐ +│ 社区共创流程 │ +│ │ +│ 投稿者(家长/老师/绘画爱好者) │ +│ ↓ │ +│ 上传线稿(照片/扫描件/数字画) │ +│ ↓ │ +│ 平台审核(线条清晰度/内容适宜性/版权确认) │ +│ ↓ │ +│ 自动后处理(二值化/统一尺寸/质量增强) │ +│ ↓ │ +│ 入库上线 → 标注作者署名 │ +│ ↓ │ +│ 激励机制: │ +│ ├── 展示署名(「由 XX 妈妈投稿」) │ +│ ├── 积分奖励(可兑换会员时长) │ +│ └── 热门投稿者榜单 │ +└──────────────────────────────────────────────────────────┘ +``` + +**启动条件:** DAU > 2000,有稳定的用户社区基础。 + +--- + +## 四、推荐执行策略 + +### 第一阶段:立即可做(0 成本起步) + +``` +1. 曼陀罗涂色卡 → 纯代码生成,与现有架构兼容 + 开发成本:⭐⭐ | 内容产出:无限 + +2. 按编号涂色 → 纯代码生成 + 开发成本:⭐⭐ | 内容产出:无限 + +3. 开源 CC0 素材 → 从 OpenClipart 筛选 + 后处理 + 人力成本:1-2 天筛选出 50 张 | 费用:¥0 +``` + +### 第二阶段:批量生产(小额投入) + +``` +4. AI 生成线稿 → Midjourney 或 SD 批量生成 + 费用:~$10/月 | 产出:每天 30-50 张 + +5. 建立后处理脚本 → 自动化流水线 + 开发成本:1-2 天 | 长期复用 + +6. 按主题系列化: + ├── 动物系列(20 张) + ├── 恐龙系列(15 张) + ├── 交通工具系列(15 张) + ├── 海洋生物系列(15 张) + ├── 春节系列(10 张) + ├── 圣诞系列(10 张) + └── ... +``` + +### 第三阶段:品质升级 + +``` +7. SD LoRA 训练 → 统一「涂鸦丫」品牌风格 +8. ControlNet 图转线稿 → 拓展素材来源 +9. 半程序化模板 → 代码框架 + AI 素材填充 +``` + +### 第四阶段:生态建设 + +``` +10. 社区投稿机制 +11. 素材内容管理后台 +12. 节日/季节限定内容运营 +``` + +--- + +## 五、素材管理规范 + +### 5.1 文件命名 + +``` +{类别}_{主题}_{编号}.{格式} + +示例: +coloring_animal_elephant_001.png +coloring_dinosaur_trex_003.svg +coloring_holiday_christmas_tree_002.png +mandala_geometric_flower_012.png +``` + +### 5.2 元数据标注 + +每个素材入库时需标注: + +```typescript +interface AssetMeta { + id: string; + filename: string; + category: 'coloring' | 'origami' | 'craft' | 'sticker'; + theme: string; // 主题(animal/dinosaur/holiday/...) + tags: string[]; // 搜索标签 + ageRange: [number, number]; + difficulty: 1 | 2 | 3; // 线条密度/复杂度 + source: 'ai_generated' | 'open_source' | 'purchased' | 'ugc'; + license: 'CC0' | 'CC-BY' | 'purchased' | 'original'; + author?: string; // 素材作者/来源 + createdAt: string; +} +``` + +### 5.3 云存储目录 + +``` +cloud://doodle-xxx/assets/ +├── coloring/ ← 涂色卡线稿 +│ ├── animals/ +│ ├── dinosaurs/ +│ ├── vehicles/ +│ ├── holidays/ +│ │ ├── christmas/ +│ │ ├── chinese_new_year/ +│ │ └── mid_autumn/ +│ ├── ocean/ +│ ├── space/ +│ ├── food/ +│ └── mandala/ ← 曼陀罗(代码生成的也可存缓存) +├── origami/ ← 折纸展开图 +├── craft/ ← 手工模板 +├── stickers/ ← 贴纸素材 +└── meta/ + └── assets.json ← 素材元数据索引 +```