import { createMathPage } from '../shared/common/mathPageMixin'; import { BaseDrawService } from '../../core/draw/baseDraw'; import { MATH_TYPE_CONFIGS, findTypeByRouteId, type MathTypeConfig, type MathTypeAction, } from './registry'; const TYPE_LIST = MATH_TYPE_CONFIGS.map((t) => ({ id: t.id, title: t.title, icon: t.icon, })); createMathPage({ canvas: null as Canvas | null, ctx: null as RenderingContext | null, boxHeight: 0, boxWidth: 0, drawService: null as BaseDrawService | null, currentTypeConfig: null as MathTypeConfig | null, currentData: null as any, routeExtra: null as Record | null, data: { pageTitle: '数学练习', functionId: '', hasContent: false, showShareDialog: false, boxWidth: 0, boxHeight: 0, selectedTypeId: '', typeList: TYPE_LIST, showActions: false, actionsTitle: '选择模式', currentActions: [] as MathTypeAction[], currentMode: '', showNumberGrid: false, numberList: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], selectedNumber: 0, isPreviewFavorite: false, }, onLoad(options: { id?: string; mode?: string }) { const routeId = options.id || MATH_TYPE_CONFIGS[0].id; const result = findTypeByRouteId(routeId); if (!result) return; const { typeConfig, mode, extra } = result; const initialMode = options.mode || mode || typeConfig.defaultMode || ''; this.currentTypeConfig = typeConfig; this.routeExtra = extra || null; const title = typeConfig.getTitle ? typeConfig.getTitle(initialMode) : typeConfig.title; this.setData({ selectedTypeId: typeConfig.id, functionId: routeId, pageTitle: title, showActions: !!typeConfig.actions, currentActions: typeConfig.actions || [], actionsTitle: typeConfig.actionsTitle || '选择模式', currentMode: initialMode, showNumberGrid: !!typeConfig.hasNumberGrid, selectedNumber: typeConfig.hasNumberGrid ? Math.floor(Math.random() * 10) + 1 : 0, }); this.initPageInfo(routeId, title); }, onCanvasReady(e: WechatMiniprogram.CustomEvent) { if (!this.currentTypeConfig) return; const typeConfig = this.currentTypeConfig; const mode = this.data.currentMode; this.initCanvasFromComponent(e.detail, { createDrawService: ( canvas: Canvas, ctx: RenderingContext, options?: Record, ) => typeConfig.createDrawService(canvas, ctx, options), drawServiceOptions: { title: this.data.pageTitle, subTitle: typeConfig.getSubTitle ? typeConfig.getSubTitle(mode) : typeConfig.subTitle, functionId: this.data.functionId, }, onCanvasReady: () => { this.onRandom(); }, }); }, /** 切换练习类型 */ onSelectType(e: WechatMiniprogram.TouchEvent) { const id = e.currentTarget.dataset.id as string; if (!id || id === this.data.selectedTypeId) return; const typeConfig = MATH_TYPE_CONFIGS.find((t) => t.id === id); if (!typeConfig) return; this.currentTypeConfig = typeConfig; this.routeExtra = null; const mode = typeConfig.defaultMode || ''; const title = typeConfig.getTitle ? typeConfig.getTitle(mode) : typeConfig.title; const subTitle = typeConfig.getSubTitle ? typeConfig.getSubTitle(mode) : typeConfig.subTitle; this.setData({ selectedTypeId: id, functionId: id, pageTitle: title, showActions: !!typeConfig.actions, currentActions: typeConfig.actions || [], actionsTitle: typeConfig.actionsTitle || '选择模式', currentMode: mode, showNumberGrid: !!typeConfig.hasNumberGrid, selectedNumber: typeConfig.hasNumberGrid ? Math.floor(Math.random() * 10) + 1 : 0, }); this.initPageInfo(id, title); if (this.canvas && this.ctx) { this.drawService = typeConfig.createDrawService( this.canvas, this.ctx, { title, subTitle, functionId: id }, ); this.onRandom(); } }, /** 切换子选项(模式) */ onSelectMode(e: WechatMiniprogram.TouchEvent) { const value = e.currentTarget.dataset.value as string; if (!value || value === this.data.currentMode) return; const typeConfig = this.currentTypeConfig; if (!typeConfig) return; const title = typeConfig.getTitle ? typeConfig.getTitle(value) : typeConfig.title; const subTitle = typeConfig.getSubTitle ? typeConfig.getSubTitle(value) : typeConfig.subTitle; this.setData({ currentMode: value, pageTitle: title, }); this.initPageInfo(this.data.functionId, title); if (this.drawService) { (this.drawService as any).options.title = title; (this.drawService as any).options.subTitle = subTitle; } this.onRandom(); }, /** 选择数字(numberFind 专用) */ onSelectNumber(e: WechatMiniprogram.TouchEvent) { const number = parseInt(e.currentTarget.dataset.number); if (isNaN(number) || number === this.data.selectedNumber) return; this.setData({ selectedNumber: number }); this.drawCanvas(); }, /** 执行 Canvas 绘制 */ async drawCanvas() { if (!this.ctx || !this.drawService || !this.currentData) return; try { const typeId = this.data.selectedTypeId; const mode = this.data.currentMode; if (typeId === 'number-find') { await this.drawService.draw(this.data.selectedNumber); } else if ( typeId === 'counting-matching' || typeId === 'number-coloring' || typeId === 'number-object-match' ) { await this.drawService.draw(this.currentData, mode); } else if (typeId === 'missing-number') { await this.drawService.draw(this.currentData, mode); } else if (typeId === 'addition') { if (this.drawService) { (this.drawService as any).options.title = this.data.pageTitle; } await this.drawService.draw(this.currentData, mode); } else if (typeId === 'counting-select') { const drawMode = this.routeExtra?.functionId === 'counting-fill' ? 'fill' : 'select'; await this.drawService.draw(this.currentData, drawMode); } else if (typeId === 'multiplication-table') { await this.drawService.draw({}); } else { await this.drawService.draw(this.currentData); } this.setData({ hasContent: true }); } catch (error) { console.error('绘制失败:', error); this.setData({ hasContent: false }); } }, /** 随机生成数据并绘制 */ onRandom() { if (!this.currentTypeConfig) return; const extra = { selectedNumber: this.data.selectedNumber, functionId: this.data.functionId, ...this.routeExtra, }; if (this.currentTypeConfig.hasNumberGrid) { const num = Math.floor(Math.random() * 10) + 1; this.setData({ selectedNumber: num }); extra.selectedNumber = num; } this.currentData = this.currentTypeConfig.generateData( this.data.currentMode, extra, ); this.drawCanvas(); }, onPreviewRefresh() { this.onRandom(); }, onPreviewFavorite() { const next = !this.data.isPreviewFavorite; this.setData({ isPreviewFavorite: next }); wx.showToast({ title: next ? '收藏成功' : '已取消收藏', icon: 'none', }); }, });