feat: 英语字母描红修改
This commit is contained in:
@@ -5,39 +5,43 @@ import { getWorksheetById } from '../../core/data/worksheets';
|
||||
import {
|
||||
generateLetterTracing,
|
||||
mergeLetterTracingConfig,
|
||||
normalizeLetter,
|
||||
type LetterTracingGeneratorConfig,
|
||||
type LetterTracingMode,
|
||||
} from '../../core/generators/letter-tracing-generator';
|
||||
} from '../shared/generators/letter-tracing-generator';
|
||||
import { LETTERS_UPPER } from '../../core/data/alphabet';
|
||||
|
||||
/** 各 worksheetId 对应的页面标题和描述 */
|
||||
const PAGE_META: Record<string, { title: string; desc: string }> = {
|
||||
'letter-tracing-single': {
|
||||
title: '字母学习页',
|
||||
desc: '单字母配图与描红',
|
||||
title: '看图描红',
|
||||
desc: '配图、例句与六行描红',
|
||||
},
|
||||
'letter-tracing-full': {
|
||||
title: '26 字母描红',
|
||||
desc: '整页字母书写练习',
|
||||
title: '分栏对照',
|
||||
desc: '半组字母左大写右小写',
|
||||
},
|
||||
'letter-tracing-upper-lower': {
|
||||
title: '大小写字母对照',
|
||||
desc: '一页认识 A-Z 与 a-z',
|
||||
title: '字母总览',
|
||||
desc: 'Uppercase / Lowercase 总览',
|
||||
},
|
||||
'letter-tracing-two-column': {
|
||||
title: '字母描红(两列)',
|
||||
desc: 'A–M / N–Z 两列练习',
|
||||
title: '大小写配对',
|
||||
desc: '左 A–M、右 N–Z 配对描红',
|
||||
},
|
||||
};
|
||||
|
||||
/** 根据 worksheetId 查找页面元信息 */
|
||||
function pageInfoLookup(id: string) {
|
||||
return PAGE_META[id];
|
||||
}
|
||||
|
||||
/** 模式选择器的选项列表 */
|
||||
const MODE_OPTIONS = [
|
||||
{ id: 'letter-tracing-single', label: '单字母学习页' },
|
||||
{ id: 'letter-tracing-full', label: '整页描红' },
|
||||
{ id: 'letter-tracing-upper-lower', label: '大小写对照' },
|
||||
{ id: 'letter-tracing-two-column', label: '两列描红' },
|
||||
{ id: 'letter-tracing-single', label: '看图描红' },
|
||||
{ id: 'letter-tracing-full', label: '分栏对照' },
|
||||
{ id: 'letter-tracing-upper-lower', label: '字母总览' },
|
||||
{ id: 'letter-tracing-two-column', label: '大小写配对' },
|
||||
] as const;
|
||||
|
||||
type PageData = CanvasDataState & {
|
||||
@@ -66,7 +70,7 @@ createPage(
|
||||
hasContent: false,
|
||||
showShareDialog: false,
|
||||
worksheetId: 'letter-tracing-single',
|
||||
traceMode: 'single-letter',
|
||||
traceMode: 'picture-tracing',
|
||||
selectedLetter: 'A',
|
||||
letterCaseLower: false,
|
||||
showLetterPicker: true,
|
||||
@@ -76,6 +80,7 @@ createPage(
|
||||
modeOptions: [...MODE_OPTIONS],
|
||||
} as unknown as PageData,
|
||||
|
||||
/** 页面加载:从路由参数获取 worksheetId 并应用 */
|
||||
onLoad(options: { id?: string }) {
|
||||
const worksheetId =
|
||||
options.id && PAGE_META[options.id]
|
||||
@@ -84,6 +89,7 @@ createPage(
|
||||
this.applyWorksheet(worksheetId);
|
||||
},
|
||||
|
||||
/** 用户点击模式选择器时切换 worksheet */
|
||||
onSelectMode(e: WechatMiniprogram.TouchEvent) {
|
||||
const id = e.currentTarget.dataset.id as string | undefined;
|
||||
if (!id || id === this.data.worksheetId) return;
|
||||
@@ -93,6 +99,7 @@ createPage(
|
||||
});
|
||||
},
|
||||
|
||||
/** 页面就绪:初始化 Canvas 和绘制服务,完成后触发首次绘制 */
|
||||
onReady() {
|
||||
this.initCanvas({
|
||||
createDrawService: (
|
||||
@@ -102,7 +109,6 @@ createPage(
|
||||
) => new LetterTracingDraw(canvas, ctx, options),
|
||||
drawServiceOptions: {
|
||||
title: this.data.pageTitle,
|
||||
subTitle: this.data.subTitle || '',
|
||||
},
|
||||
onCanvasReady: () => {
|
||||
this.drawCanvas();
|
||||
@@ -110,12 +116,13 @@ createPage(
|
||||
});
|
||||
},
|
||||
|
||||
/** 构建运行时生成器配置:合并 worksheet 预设 + 当前页面状态 */
|
||||
buildRuntimeConfig(): LetterTracingGeneratorConfig {
|
||||
const def = getWorksheetById(this.data.worksheetId);
|
||||
const base = (def?.generatorConfig ??
|
||||
{}) as Partial<LetterTracingGeneratorConfig>;
|
||||
const letterCase =
|
||||
this.data.traceMode === 'single-letter'
|
||||
this.data.traceMode === 'picture-tracing'
|
||||
? (base.letterCase ?? 'upper')
|
||||
: this.data.letterCaseLower
|
||||
? 'lower'
|
||||
@@ -123,14 +130,23 @@ createPage(
|
||||
return mergeLetterTracingConfig(base, {
|
||||
selectedLetter: this.data.selectedLetter,
|
||||
letterCase,
|
||||
...(this.data.traceMode === 'column-compare'
|
||||
? {
|
||||
alphabetHalf: this.data.letterCaseLower
|
||||
? 'N-Z'
|
||||
: 'A-M',
|
||||
}
|
||||
: {}),
|
||||
});
|
||||
},
|
||||
|
||||
/** 执行 Canvas 绘制:生成数据 → 调用 drawService 渲染 */
|
||||
async drawCanvas() {
|
||||
if (!this.ctx || !this.drawService) return;
|
||||
try {
|
||||
const config = this.buildRuntimeConfig();
|
||||
const data = generateLetterTracing(config);
|
||||
console.log('drawCanvas data', data);
|
||||
await (this.drawService as LetterTracingDraw).draw(data);
|
||||
this.setData({ hasContent: true });
|
||||
} catch (e) {
|
||||
@@ -139,6 +155,7 @@ createPage(
|
||||
}
|
||||
},
|
||||
|
||||
/** 用户在字母网格中选择了一个字母 */
|
||||
onSelectLetter(e: WechatMiniprogram.TouchEvent) {
|
||||
const letter = e.currentTarget.dataset.letter as string;
|
||||
if (!letter) return;
|
||||
@@ -146,16 +163,19 @@ createPage(
|
||||
this.drawCanvas();
|
||||
},
|
||||
|
||||
/** 切换为大写模式并重绘 */
|
||||
onSelectCaseUpper() {
|
||||
this.setData({ letterCaseLower: false });
|
||||
this.drawCanvas();
|
||||
},
|
||||
|
||||
/** 切换为小写模式并重绘 */
|
||||
onSelectCaseLower() {
|
||||
this.setData({ letterCaseLower: true });
|
||||
this.drawCanvas();
|
||||
},
|
||||
|
||||
/** 跳到下一个字母(循环 A→Z→A)并重绘 */
|
||||
onNextLetter() {
|
||||
const list = LETTERS_UPPER;
|
||||
const i = list.indexOf(this.data.selectedLetter);
|
||||
@@ -164,6 +184,13 @@ createPage(
|
||||
this.drawCanvas();
|
||||
},
|
||||
|
||||
/**
|
||||
* 应用指定的 worksheet 配置到页面状态
|
||||
* 根据 worksheet 的 generatorConfig 决定 UI 控件的显隐(字母选择器、大小写切换等)
|
||||
* @param worksheetId - 要应用的 worksheet ID
|
||||
* @param options.preserveLetter - 是否保留当前选中的字母(模式切换时使用)
|
||||
* @param options.redraw - 是否立即重绘 Canvas
|
||||
*/
|
||||
applyWorksheet(
|
||||
worksheetId: string,
|
||||
options?: {
|
||||
@@ -172,22 +199,24 @@ createPage(
|
||||
},
|
||||
) {
|
||||
const def = getWorksheetById(worksheetId);
|
||||
console.log('def', def);
|
||||
const base = (def?.generatorConfig ??
|
||||
{}) as Partial<LetterTracingGeneratorConfig>;
|
||||
const merged = mergeLetterTracingConfig(base, {});
|
||||
|
||||
const traceMode = merged.mode;
|
||||
const showLetterPicker = traceMode === 'single-letter';
|
||||
const showCaseToggle =
|
||||
traceMode === 'full-alphabet' || traceMode === 'two-column';
|
||||
const showNextLetter = traceMode === 'single-letter';
|
||||
const showLetterPicker = traceMode === 'picture-tracing';
|
||||
const showCaseToggle = traceMode === 'column-compare';
|
||||
const showNextLetter = traceMode === 'picture-tracing';
|
||||
const selectedLetter = options?.preserveLetter
|
||||
? this.data.selectedLetter
|
||||
: normalizePick(merged.selectedLetter);
|
||||
? (this.data.selectedLetter ?? 'A')
|
||||
: normalizeLetter(merged.selectedLetter ?? '');
|
||||
const letterCaseLower =
|
||||
traceMode === 'single-letter'
|
||||
? merged.letterCase === 'lower'
|
||||
: this.data.letterCaseLower;
|
||||
traceMode === 'column-compare'
|
||||
? merged.alphabetHalf === 'N-Z'
|
||||
: traceMode === 'picture-tracing'
|
||||
? merged.letterCase === 'lower'
|
||||
: false;
|
||||
|
||||
this.setData(
|
||||
{
|
||||
@@ -208,8 +237,6 @@ createPage(
|
||||
|
||||
if (this.drawService) {
|
||||
this.drawService.options.title = this.data.pageTitle;
|
||||
this.drawService.options.subTitle =
|
||||
this.data.subTitle || '';
|
||||
}
|
||||
|
||||
if (options?.redraw) {
|
||||
@@ -224,8 +251,3 @@ createPage(
|
||||
pageInfoLookup,
|
||||
},
|
||||
);
|
||||
|
||||
function normalizePick(c?: string): string {
|
||||
if (!c || c.length === 0) return 'A';
|
||||
return c.trim().toUpperCase().charAt(0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user