feat:九九乘法表

This commit is contained in:
R524809
2026-01-16 18:02:16 +08:00
parent 7dd10c7902
commit 9c13b44806
25 changed files with 1388 additions and 13 deletions
@@ -0,0 +1,14 @@
{
"navigationBarTitleText": "计算练习题",
"navigationBarBackgroundColor": "#FFD719",
"homeButton": true,
"backgroundColor": "#F6F6F6",
"enablePullDownRefresh": false,
"usingComponents": {
"toy-button": "../../ui/button/button",
"share-guide-popup": "../../components/share-guide-popup/share-guide-popup",
"math-bottom-buttons": "../../components/math-bottom-buttons/math-bottom-buttons",
"math-type-selector": "../../components/math-type-selector/math-type-selector",
"draw-ad": "../../components/draw-ad/draw-ad"
}
}
@@ -0,0 +1,2 @@
// 计算练习题页面样式
@import '../../base/baseDrawPage.wxss';
@@ -0,0 +1,208 @@
import CalculationPracticeDraw from '../shared/service/calculationPracticeDraw';
import {
createMathPage,
CanvasDataState,
} from '../shared/common/mathPageMixin';
type OperationType = 'addition' | 'subtraction' | 'mixed';
createMathPage({
canvas: null as Canvas | null,
ctx: null as RenderingContext | null,
boxHeight: 0,
boxWidth: 0,
drawService: null as CalculationPracticeDraw | null,
calculationPracticeData: null as {
problems: Array<{
left: number;
operator: '+' | '-';
right: number;
result: number;
}>;
} | null,
data: {
pageTitle: '计算练习题',
functionId: '',
hasContent: false,
showShareDialog: false,
operationType: 'addition' as OperationType, // 运算类型:加法、减法、混合
currentMode: 'within-10', // 默认10以内
currentModeName: '10以内',
typeActions: [
{ name: '10以内', value: 'within-10' },
{ name: '20以内', value: 'within-20' },
{ name: '50以内', value: 'within-50' },
{ name: '100以内', value: 'within-100' },
],
} as CanvasDataState & {
operationType: OperationType;
currentMode: string;
currentModeName: string;
typeActions: Array<{ name: string; value: string }>;
},
onLoad(options: { id?: string; type?: string }) {
const functionId = options.id || 'practice-addition';
// 根据 functionId 确定运算类型
let operationType: OperationType = 'addition';
if (functionId === 'practice-subtraction') {
operationType = 'subtraction';
} else if (functionId === 'practice-mixed') {
operationType = 'mixed';
} else if (options.type) {
operationType = options.type as OperationType;
}
let pageTitle = '计算练习题';
if (operationType === 'addition') {
pageTitle = '加法运算';
} else if (operationType === 'subtraction') {
pageTitle = '减法运算';
} else if (operationType === 'mixed') {
pageTitle = '混合运算';
}
this.setData({
operationType,
pageTitle,
});
this.initPageInfo(functionId, pageTitle);
},
onReady() {
this.initCanvas({
createDrawService: (
canvas: Canvas,
ctx: RenderingContext,
options?: Record<string, any>,
) => {
return new CalculationPracticeDraw(canvas, ctx, options);
},
drawServiceOptions: {},
onCanvasReady: () => {
// 初始随机生成
this.onRandom();
},
});
},
/**
* 绘制Canvas内容
*/
async drawCanvas() {
if (!this.ctx || !this.drawService || !this.calculationPracticeData) {
return;
}
try {
await this.drawService.draw(this.calculationPracticeData);
this.setData({ hasContent: true });
} catch (error) {
console.error('绘制失败:', error);
this.setData({ hasContent: false });
}
},
/**
* 随机生成
*/
onRandom() {
// 根据当前模式确定最大值
let maxValue = 10;
if (this.data.currentMode === 'within-20') {
maxValue = 20;
} else if (this.data.currentMode === 'within-50') {
maxValue = 50;
} else if (this.data.currentMode === 'within-100') {
maxValue = 100;
}
const problems: Array<{
left: number;
operator: '+' | '-';
right: number;
result: number;
}> = [];
const usedProblems = new Set<string>();
let attempts = 0;
const maxAttempts = 2000;
const targetCount = 11 * 3; // 12行3列 = 36道题
while (problems.length < targetCount && attempts < maxAttempts) {
attempts++;
let left: number;
let right: number;
let operator: '+' | '-';
let result: number;
// 根据运算类型生成题目
if (this.data.operationType === 'addition') {
// 加法:left + right <= maxValue
left = Math.floor(Math.random() * (maxValue - 1)) + 1; // 1 到 maxValue-1
const maxRight = maxValue - left;
right = Math.floor(Math.random() * maxRight) + 1; // 1 到 maxRight
operator = '+';
result = left + right;
} else if (this.data.operationType === 'subtraction') {
// 减法:left - right >= 0, left <= maxValue
left = Math.floor(Math.random() * maxValue) + 1; // 1 到 maxValue
right = Math.floor(Math.random() * left) + 1; // 1 到 left
operator = '-';
result = left - right;
} else {
// 混合运算:随机选择加法或减法
const isAddition = Math.random() < 0.5;
if (isAddition) {
left = Math.floor(Math.random() * (maxValue - 1)) + 1;
const maxRight = maxValue - left;
right = Math.floor(Math.random() * maxRight) + 1;
operator = '+';
result = left + right;
} else {
left = Math.floor(Math.random() * maxValue) + 1;
right = Math.floor(Math.random() * left) + 1;
operator = '-';
result = left - right;
}
}
// 使用 "left,operator,right" 作为唯一标识,避免重复
const problemKey = `${left},${operator},${right}`;
if (usedProblems.has(problemKey)) {
continue;
}
usedProblems.add(problemKey);
problems.push({
left,
operator,
right,
result,
});
}
if (problems.length < targetCount) {
console.warn(
`只生成了 ${problems.length} 道题目,可能符合条件的题目组合不足`,
);
}
this.calculationPracticeData = { problems };
this.drawCanvas();
},
/** 选择类型 */
onSelectType(event: any) {
const { name, value } = event.detail;
this.setData({
currentMode: value,
currentModeName: name,
});
// 重新生成数据
this.onRandom();
},
});
@@ -0,0 +1,6 @@
<!-- 模版不能跨包引用 -->
<import src="../shared/templates/canvas-page-template.wxml" />
<template
is="canvasPageTemplate"
data="{{boxWidth: boxWidth, boxHeight: boxHeight, hasTypeSelector: true, currentModeName: currentModeName, typeActions: typeActions, adType: 'mathDraw', disabled: !hasContent, showShareDialog: showShareDialog}}" />