feat: 首页跳转到分类页指定分类优化

This commit is contained in:
R524809
2026-05-09 11:08:29 +08:00
parent c21ac9e935
commit debecd67c6
20 changed files with 1450 additions and 959 deletions
+262
View File
@@ -0,0 +1,262 @@
---
name: create-draw-page
description: >-
基于现有 draw 页面模板创建新的绘制页(worksheet page)。
当用户说「基于现有的draw页面来开发新页面」「基于draw页面开发新页面」
「新建绘制页」「创建一个新的draw页面」「新增一个worksheet页」时触发。
---
# 创建新的绘制页(Draw Page
基于 `englishPages/letterTracing` 模板,快速搭建一个新的 Canvas 绘制页。
## 模板参考
`miniprogram/englishPages/letterTracing` 为标准模板,新页面的文件结构与代码风格应与之对齐。创建前先阅读模板页的以下文件:
- `letterTracing.ts` — 页面逻辑
- `letterTracing.wxml` — 页面模板
- `letterTracing.less` — 页面样式
- `letterTracing.json` — 组件注册
- `letterTracing.config.ts` — worksheet 元数据配置
## 新页面必备文件
假设新页面名为 `newPage`,需要创建以下文件:
```
newPage/
├── newPage.ts # 页面逻辑(使用 createPage
├── newPage.wxml # 页面模板
├── newPage.less # 页面样式
├── newPage.json # 组件注册
├── newPage.config.ts # worksheet 元数据
└── draw/ # 绘制服务
└── newPageDraw.ts # 继承 BaseDrawService
```
## 必备要求
### 1. xxx.config.ts — worksheet 元数据配置
每个绘制页**必须**有对应的 `xxx.config.ts` 文件。参考 `letterTracing.config.ts` 的结构,至少包含:
**worksheet 定义数组**(核心):
```ts
interface XxxWorksheetDefinition {
id: string; // 唯一标识,格式:{pageName}-{variant}
icon: string; // 图标名(使用 toy-icon 支持的图标)
title: string; // 标题(简短,4-6 字)
subtitle: string; // 副标题(描述该模式的特点)
ageMin: number; // 最小适用年龄
ageMax: number; // 最大适用年龄
difficulty: 1 | 2 | 3 | 4; // 难度等级
tags: string[]; // 标签数组
sortOrder: number; // 排序权重
}
export const XXX_WORKSHEET_DEFINITIONS = [
{
id: 'xxx-default',
icon: 'icon-name',
title: '默认模式',
subtitle: '模式描述',
ageMin: 4,
ageMax: 7,
difficulty: 1,
tags: ['标签1', '标签2'],
sortOrder: 50,
},
// ... 更多模式
] as const satisfies ReadonlyArray<XxxWorksheetDefinition>;
```
**必须导出的辅助函数**(参照 `letterTracing.config.ts`):
- `getModeInfo(id)` — 返回 `{ title, desc }` 用于 `pageInfoLookup`
- `isValidMode(id)` — 校验 id 是否合法
- `getPublishMetaByMode(id)` — 生成 `DebugPublishMeta`,使用 `inferGradeFromAge` 推断年级
- 模式选项常量(如 `XXX_MODE_OPTIONS`
`getPublishMetaByMode` 中的 `category``subcategory` 需根据页面所属学科正确设置:
- `category``math` | `puzzle` | `pinyin` | `chinese` | `english` | `craft`
- `subcategory`:页面功能简称,如 `letter-tracing``word-coloring`
### 2. 必须使用的组件
每个绘制页**必须**在 `.json``.wxml` 中注册并使用以下组件:
```json
{
"usingComponents": {
"nav-bar": "../../components3.0/nav-bar/nav-bar",
"preview-card": "../../components3.0/preview-card/preview-card",
"preview-footer-actions": "../../components3.0/preview-footer-actions/preview-footer-actions",
"debug-publish-tools": "../../components3.0/debug-publish-tools/debug-publish-tools",
"share-guide-popup": "../../components/share-guide-popup/share-guide-popup",
"toy-icon": "../../toy/icon/icon"
}
}
```
> 路径中的 `../../` 需根据新页面实际所在目录调整层级。
**wxml 中的基本布局结构**
```xml
<nav-bar title="页面标题" />
<view class="page-wrapper">
<view class="page-main">
<preview-card
id="previewCard"
showRefresh="{{false}}"
showFavorite="{{true}}"
favorited="{{isPreviewFavorite}}"
bind:canvas-ready="onCanvasReady"
bind:favorite="onPreviewFavorite" />
<!-- 页面特有的交互区域放这里 -->
</view>
</view>
<preview-footer-actions
disabled="{{!hasContent}}"
bind:primary="exportToPrint"
bind:secondary="onShare" />
<debug-publish-tools
wx:if="{{isDevEnv && hasContent}}"
id="debugPublishTools"
visible="{{debugPublishVisible}}"
loading="{{debugPublishLoading}}"
meta="{{debugPublishMeta}}"
bind:open="onOpenDebugPublish"
bind:close="onCloseDebugPublish"
bind:confirm="onConfirmDebugPublish" />
<share-guide-popup
show="{{showShareDialog}}"
bind:onClose="onCloseShareDialog"
bind:onShareSuccess="onShareSuccess" />
```
### 3. 图标使用
图标**优先**使用 `toy-icon` 组件(路径 `../../toy/icon/icon`):
```xml
<toy-icon name="refresh" size="40rpx" color="#605b50" />
```
如果 `toy-icon` 没有所需图标,可直接引入 iconfont:
```less
@import '../../assets/fonts/iconfont.less';
```
### 4. 使用 createPage 创建页面
页面**必须**使用 `base/pageMixin.ts` 中的 `createPage` 函数创建,不能直接调用 `Page()`
```ts
import { createPage, type CanvasDataState } from '../../base/pageMixin';
createPage(
{
canvas: null as Canvas | null,
ctx: null as RenderingContext | null,
boxHeight: 0,
boxWidth: 0,
drawService: null as XxxDraw | null,
data: {
pageTitle: '页面标题',
functionId: '',
hasContent: false,
showShareDialog: false,
// ... 页面特有数据
isPreviewFavorite: false,
isDevEnv: false,
debugPublishVisible: false,
debugPublishLoading: false,
debugPublishMeta: null,
} as unknown as PageData,
onLoad(options: { id?: string }) {
// 1. syncDebugPublishEnv()
// 2. 解析路由参数、应用默认模式
// 3. 加载收藏状态
},
onCanvasReady(e: WechatMiniprogram.CustomEvent) {
this.initCanvasFromComponent(e.detail, {
createDrawService: (canvas, ctx, opts) =>
new XxxDraw(canvas, ctx, opts),
onCanvasReady: () => this.drawCanvas(),
});
},
async drawCanvas() {
// 生成数据 → 调用 drawService 渲染
},
getPublishMeta() {
// 调用 config 中的 getPublishMetaByMode
},
},
{
shareConfig: defaultShareConfig,
pageInfoLookup,
},
);
```
`createPage` 自动混入的公共方法包括:
- `initCanvas` / `initCanvasFromComponent` — Canvas 初始化
- `exportToPrint` — 导出打印
- `onShareAppMessage` / `onShareTimeline` — 分享
- `onCloseShareDialog` / `onShareSuccess` — 分享弹窗
- `syncDebugPublishEnv` / `onOpenDebugPublish` / `onCloseDebugPublish` / `onConfirmDebugPublish` — 调试发布
- `initPageInfo` — 页面标题初始化
- `getShareOptions` — 分享路径
**不要重复实现**这些方法,直接使用即可。
### 5. 主题色与设计风格
保持与模板页一致的暖色调主题,除非用户另行指定 UI 稿:
```less
@import '../../style/theme.less';
page {
background-color: @bg-page;
}
```
关键设计 token(来自 `theme.less`):
- 页面背景:`@bg-page`
- 卡片背景:`@bg-card`
- 品牌色/选中态:`@brand`
- 主标题色:`#6d3b00`
- 正文色:`@text-secondary`
- 选中文字色:`@text-selected-btn`
- 页面左右内边距:`@page-padding-x`
- 底部安全区留白:`calc(200rpx + env(safe-area-inset-bottom))`
- 圆角:`24rpx`(卡片)/ `32rpx`(按钮/chip
## 开发检查清单
创建完成后逐项确认:
- [ ]`xxx.config.ts`,包含 worksheet 定义数组和辅助函数
- [ ] `.json` 中注册了全部 5 个必备组件 + `toy-icon`
- [ ] `.wxml` 中包含 `nav-bar``preview-card``preview-footer-actions``debug-publish-tools``share-guide-popup`
- [ ] `.ts` 中使用 `createPage()` 创建页面
- [ ] `.less` 中引入 `theme.less` 并使用主题变量
- [ ]`draw/` 目录放置绘制服务
- [ ] `onLoad` 中调用了 `syncDebugPublishEnv()`
- [ ] 实现了 `getPublishMeta()` 方法
- [ ]`app.json` 中注册了新页面路径