import { getRandomNumberColor } from '../../constants/colors'; import MissingNumberDraw from '../service/missingNumberDraw'; import { applyMathPageMixin, CanvasDataState } from '../common/mathPageMixin'; Page( applyMathPageMixin( { canvas: null as Canvas | null, ctx: null as RenderingContext | null, boxHeight: 0, boxWidth: 0, drawService: null as MissingNumberDraw | null, missingNumberData: null as { grids: Array<{ numbers: (number | null)[]; colors: (string | null)[]; }>; maxNumber: number; } | null, data: { pageTitle: '填上缺少的数字', subTitle: '在数字序列中找出并填写缺失的数字', functionId: '', hasContent: false, showShareDialog: false, showTypeSelector: true, currentType: 10, currentTypeName: '10以内', typeActions: [ { name: '10以内', value: 10 }, { name: '20以内', value: 20 }, { name: '40以内', value: 40 }, { name: '50以内', value: 50 }, { name: '80以内', value: 80 }, { name: '100以内', value: 100 }, { name: '120以内', value: 120 }, ], } as CanvasDataState & { showTypeSelector: boolean; currentType: number; currentTypeName: string; typeActions: Array<{ name: string; value: number }>; }, onLoad(options: { id?: string }) { const functionId = options.id || 'missing-number'; this.initPageInfo(functionId, '填上缺少的数字'); }, onReady() { this.initCanvas({ createDrawService: ( canvas: Canvas, ctx: RenderingContext, options?: Record, ) => { return new MissingNumberDraw(canvas, ctx, options); }, drawServiceOptions: { subTitle: this.data.subTitle, }, onCanvasReady: () => { // Canvas 初始化完成后,生成初始数据 this.onRandom(); }, }); }, /** * 绘制Canvas内容 */ async drawCanvas() { if (!this.ctx || !this.drawService || !this.missingNumberData) { return; } try { await this.drawService.draw( this.missingNumberData, String(this.data.currentType), ); this.setData({ hasContent: true }); } catch (error) { console.error('绘制失败:', error); this.setData({ hasContent: false }); } }, /** * 随机生成 */ onRandom() { const maxNumber = this.data.currentType; this.generateMissingNumberData(maxNumber); this.drawCanvas(); }, /** * 生成缺失数字数据 */ generateMissingNumberData(maxNumber: number) { const grids: Array<{ numbers: (number | null)[]; colors: (string | null)[]; }> = []; const gridMap = { 10: { gridCount: 3, }, 20: { gridCount: 2, }, 40: { gridCount: 2, }, 50: { gridCount: 2, }, 80: { gridCount: 1, }, 100: { gridCount: 1, }, 120: { gridCount: 1, }, }; const { gridCount } = gridMap[maxNumber as keyof typeof gridMap]; // 生成多个网格 for (let gridIndex = 0; gridIndex < gridCount; gridIndex++) { let startNumber = 1; let endNumber = maxNumber; const actualNumbersPerGrid = endNumber - startNumber + 1; const numbers: number[] = Array.from( { length: actualNumbersPerGrid }, (_, i) => startNumber + i, ); // 随机隐藏一部分数字(隐藏40-60%) const hideCount = Math.floor( actualNumbersPerGrid * (0.4 + Math.random() * 0.2), ); const hiddenIndices = new Set(); while (hiddenIndices.size < hideCount) { const randomIndex = Math.floor( Math.random() * actualNumbersPerGrid, ); hiddenIndices.add(randomIndex); } const gridNumbers: (number | null)[] = numbers.map( (num, index) => (hiddenIndices.has(index) ? null : num), ); // 为每个数字分配颜色(包括null位置) const gridColors: (string | null)[] = gridNumbers.map( (num) => (num ? this.getRandomNumberColor() : null), ); grids.push({ numbers: gridNumbers, colors: gridColors }); } this.missingNumberData = { grids, maxNumber, }; }, /** * 获取随机数字颜色 */ getRandomNumberColor(): string { return getRandomNumberColor(); }, /** 选择类型 */ onSelectType(event: any) { const { name, value } = event.detail; this.setData({ currentType: value, currentTypeName: name, }); // 重新生成数据 this.onRandom(); }, }, { pagePath: 'missingNumber/missingNumber', }, ), );