import { createFocusPage } from '../shared/common/focusPageMixin'; import { BaseDrawService } from '../../core/draw/baseDraw'; import { FOCUS_TYPE_CONFIGS, findTypeByRouteId, type FocusTypeConfig, type FocusTypeAction, } from './registry'; import { getPublishMetaByFocusState, FOCUS_WORKSHEET_DEFINITIONS } from './focusDraw.config'; import type { DebugPublishMeta } from '../../utils/debugPublish'; import { addFavorite, removeFavorite, batchCheckFavorited } from '../../utils/favorites'; const TYPE_LIST = FOCUS_TYPE_CONFIGS.map((t) => ({ id: t.id, title: t.title, icon: t.icon, })); createFocusPage({ canvas: null as Canvas | null, ctx: null as RenderingContext | null, boxHeight: 0, boxWidth: 0, drawService: null as BaseDrawService | null, currentTypeConfig: null as FocusTypeConfig | null, currentData: null as any, _favoritedMap: {} as Record, data: { pageTitle: '专注力练习', functionId: '', hasContent: false, showShareDialog: false, boxWidth: 0, boxHeight: 0, selectedTypeId: '', typeList: TYPE_LIST, showActions: false, actionsTitle: '选择模式', currentActions: [] as FocusTypeAction[], currentMode: '', isPreviewFavorite: false, isDevEnv: false, debugPublishVisible: false, debugPublishLoading: false, debugPublishMeta: null as DebugPublishMeta | null, }, onLoad(options: { id?: string; mode?: string }) { const routeId = options.id || FOCUS_TYPE_CONFIGS[0].id; const result = findTypeByRouteId(routeId); if (!result) return; this.syncDebugPublishEnv(); const { typeConfig, mode } = result; const initialMode = options.mode || mode || typeConfig.defaultMode || ''; this.currentTypeConfig = typeConfig; 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, }); this.initPageInfo(routeId, title); this.loadFavoritedMap(); }, 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 = FOCUS_TYPE_CONFIGS.find((t) => t.id === id); if (!typeConfig) return; this.currentTypeConfig = typeConfig; 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, isPreviewFavorite: !!this._favoritedMap[ getPublishMetaByFocusState(id, id, mode)?.id || id ], showActions: !!typeConfig.actions, currentActions: typeConfig.actions || [], actionsTitle: typeConfig.actionsTitle || '选择模式', currentMode: mode, }); 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, isPreviewFavorite: !!this._favoritedMap[this.getWorksheetStatsIdFor(value)], }); 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(); }, /** 执行 Canvas 绘制 */ async drawCanvas() { if (!this.ctx || !this.drawService || !this.currentData) return; try { await this.drawService.draw(this.currentData); this.setData({ hasContent: true }); } catch (error) { console.error('绘制失败:', error); this.setData({ hasContent: false }); } }, /** 随机生成数据并绘制 */ onRandom() { if (!this.currentTypeConfig) return; this.currentData = this.currentTypeConfig.generateData( this.data.currentMode, ); this.drawCanvas(); }, /** 打印预览角标:换一批,与「随机生成」相同逻辑 */ onPreviewRefresh() { this.onRandom(); }, async onPreviewFavorite() { const next = !this.data.isPreviewFavorite; this.setData({ isPreviewFavorite: next }); const id = this.getWorksheetStatsId(); if (id) { this._favoritedMap[id] = next; if (next) { addFavorite(id); } else { removeFavorite(id); } } wx.showToast({ title: next ? '收藏成功' : '已取消收藏', icon: 'none', }); }, getWorksheetStatsId(): string { const meta = getPublishMetaByFocusState( this.data.functionId, this.data.selectedTypeId, this.data.currentMode, ); return meta?.id || this.data.functionId; }, getWorksheetStatsIdFor(mode: string): string { const meta = getPublishMetaByFocusState( this.data.functionId, this.data.selectedTypeId, mode, ); return meta?.id || this.data.functionId; }, async loadFavoritedMap() { const ids = FOCUS_WORKSHEET_DEFINITIONS.map((d) => d.id); this._favoritedMap = await batchCheckFavorited(ids); const currentId = this.getWorksheetStatsId(); if (this._favoritedMap[currentId]) { this.setData({ isPreviewFavorite: true }); } }, getPublishMeta(): DebugPublishMeta { const meta = getPublishMetaByFocusState( this.data.functionId, this.data.selectedTypeId, this.data.currentMode, ); if (!meta) { throw new Error('当前题型配置不存在'); } return meta; }, });