【Harmony OS 5】数学公式学习助手 - ArkTS Stage模型

69 阅读6分钟

数学公式学习助手 - ArkTS Stage模型

我们将构建一个简单的数学学习应用,包含以下功能:

  • 展示数学公式列表
  • 点击进入公式详情页
  • 在详情页显示公式的解释和示例
import router from '@ohos.router';
import promptAction from '@ohos.promptAction';

@Entry
@Component
struct MathLearningHome {
  @State formulaList: FormulaItem[] = [];
  @State loading: boolean = true;

  // Stage模型生命周期钩子
  aboutToAppear() {
    this.loadFormulaData();
  }

  // 加载数据
  loadFormulaData() {
    setTimeout(() => {
      this.formulaList = [
        {
          id: "1",
          name: "勾股定理",
          formula: "c² = a² + b²",
          category: "几何公式",
          description: "直角三角形两直角边的平方和等于斜边的平方",
          favorite: false,
          mastered: false
        },
        {
          id: "2",
          name: "二次方程求根公式",
          formula: "x = [-b ± √(b²-4ac)] / 2a",
          category: "代数公式",
          description: "用于求一元二次方程解的公式",
          favorite: true,
          mastered: true
        },
        {
          id: "3",
          name: "圆的面积",
          formula: "S = πr²",
          category: "几何公式",
          description: "圆的面积公式,π约等于3.14159",
          favorite: false,
          mastered: false
        }
      ];
      this.loading = false;
    }, 1500);
  }

  // 导航到详情页
  navigateToDetail(item: FormulaItem) {
    router.pushUrl({
      url: 'pages/detail',
      params: { formulaData: JSON.stringify(item) }
    });
  }

  // 添加收藏
  toggleFavorite(item: FormulaItem, index: number) {
    const newList = [...this.formulaList];
    newList[index] = {...item, favorite: !item.favorite};
    this.formulaList = newList;
    
    // 显示提示
    promptAction.showToast({
      message: item.favorite ? '已取消收藏' : '已添加到收藏夹',
      duration: 1500
    });
  }

  build() {
    Stack() {
      if (this.loading) {
        // 加载状态
        Column() {
          Progress()
            .width(100)
            .height(100)
            .color('#0075e1')
          Text('加载数学公式中...')
            .fontSize(16)
            .margin({top: 20})
        }
        .width('100%')
        .height('100%')
        .justifyContent(FlexAlign.Center)
      } else {
        Column() {
          // 应用栏 - 使用系统图标
          AppBar({
            title: '数学公式学习助手',
            showBack: false,
            actions: [
              {
                icon: "magnifier",
                action: () => {
                  router.pushUrl({
                    url: 'pages/search'
                  });
                }
              },
              {
                icon: "starOutline",
                action: () => {
                  router.pushUrl({
                    url: 'pages/favorites'
                  });
                }
              }
            ]
          })
          
          // 学习卡片
          LearningCard({ formulas: this.formulaList })

          // 公式列表
          Text('全部公式')
            .fontSize(20)
            .fontWeight(FontWeight.Bold)
            .margin({ top: 25, left: 20, bottom: 15 })
          
          List({ space: 15 }) {
            ForEach(this.formulaList, (item, index) => {
              ListItem() {
                FormulaItemCard({
                  formula: item,
                  onTap: () => this.navigateToDetail(item),
                  onFavorite: () => this.toggleFavorite(item, index)
                })
              }
            }, item => item.id)
          }
          .divider({ strokeWidth: 1, color: '#f0f0f0', endMargin: 20, startMargin: 20 })
          .layoutWeight(1)
          .scrollBar(BarState.Off)
          .margin({ top: 10 })
        }
      }
    }
    .width('100%')
    .height('100%')
    .alignItems(HorizontalAlign.Center)
    .backgroundColor('#f5f8ff')
  }
}

@Component
struct LearningCard {
  @Prop formulas: FormulaItem[];
  
  // 计算学习进度
  getMasteredCount() {
    return this.formulas.filter(f => f.mastered).length;
  }

  build() {
    Stack() {
      // 使用系统组件创建背景
      Row() {
        Column() {
          Text('学习进度')
            .fontSize(18)
            .fontWeight(FontWeight.Medium)
            .foregroundColor('#fff')
            .margin({ top: 30, left: 25 })
          
          Row() {
            Text('已掌握')
              .fontSize(16)
              .foregroundColor('rgba(255,255,255,0.8)')
            Text(`${this.getMasteredCount()}/${this.formulas.length}`)
              .fontSize(18)
              .fontWeight(FontWeight.Medium)
              .foregroundColor('#fff')
              .margin({ left: 8 })
          }
          .margin({ top: 5, left: 25 })
          
          Progress({
            value: Math.min(this.getMasteredCount() / this.formulas.length * 100, 100),
            type: ProgressType.Linear
          })
          .color(Color.White)
          .height(8)
          .margin({ top: 10, left: 25, right: 25 })
        }
        
        // 使用系统组件创建学习图标
        Column() {
          Image($rawfile('common/icon_learn.png'))
            .width(80)
            .height(80)
            .margin({ right: 30 })
        }
        .align(Alignment.End)
        .layoutWeight(1)
      }
    }
    .width('90%')
    .height(160)
    .backgroundImage($rawfile('common/bg_card.png'))
    .backgroundImageSize(ImageSize.Cover)
    .borderRadius(24)
    .shadow({ radius: 15, color: '#d0e4ff' })
    .margin({ top: 15 })
  }
}

@Component
struct FormulaItemCard {
  @Prop formula: FormulaItem;
  @Prop onTap: () => void;
  @Prop onFavorite: () => void;

  build() {
    Row() {
      // 公式图标 - 使用系统图标组件
      Column() {
        if (this.formula.category === '几何公式') {
          Image($rawfile('common/icon_geometry.png'))
            .width(40)
            .height(40)
        } else if (this.formula.category === '代数公式') {
          Image($rawfile('common/icon_algebra.png'))
            .width(40)
            .height(40)
        } else {
          Image($rawfile('common/icon_math.png'))
            .width(40)
            .height(40)
        }
      }
      .margin({ right: 15 })
      
      // 公式信息
      Column() {
        Text(this.formula.name)
          .fontSize(18)
          .fontWeight(FontWeight.Bold)
          .foregroundColor('#1a2c4c')
        
        Text(this.formula.formula)
          .fontSize(16)
          .margin({ top: 5 })
          .foregroundColor('#5e7a9c')
          .fontFamily('monospace')
      }
      .layoutWeight(1)
      
      // 收藏按钮 - 使用系统图标组件
      Column() {
        if (this.formula.favorite) {
          Image($rawfile('common/icon_favorite_filled.png'))
            .width(30)
            .height(30)
        } else {
          Image($rawfile('common/icon_favorite.png'))
            .width(30)
            .height(30)
        }
      }
      .onClick(() => this.onFavorite())
    }
    .padding(20)
    .backgroundColor('#ffffff')
    .borderRadius(20)
    .shadow({ radius: 5, color: '#0000000d' })
    .margin({ left: 20, right: 20 })
    .onClick(() => this.onTap())
  }
}

@Component
struct AppBar {
  @Prop title: string;
  @Prop showBack: boolean;
  @Prop actions: Array<{icon: string, action: () => void}>;
  
  build() {
    Row() {
      if (this.showBack) {
        // 使用系统返回图标
        Image($rawfile('common/icon_back.png'))
          .width(24)
          .height(24)
          .margin({ left: 15, right: 10 })
          .onClick(() => router.back())
      }
      
      Text(this.title)
        .fontSize(20)
        .fontWeight(FontWeight.Bold)
        .layoutWeight(1)
        .margin({ left: this.showBack ? 0 : 20 })
      
      Row() {
        ForEach(this.actions, (action) => {
          // 使用系统图标组件
          Column() {
            if (action.icon === "magnifier") {
              Image($rawfile('common/icon_search.png'))
                .width(28)
                .height(28)
            } else if (action.icon === "starOutline") {
              Image($rawfile('common/icon_star_outline.png'))
                .width(28)
                .height(28)
            }
          }
          .margin({ left: 15, right: 15 })
          .onClick(action.action)
        })
      }
    }
    .width('100%')
    .height(56)
    .justifyContent(FlexAlign.SpaceBetween)
    .backgroundColor('#ffffff')
    .zIndex(10)
    .shadow({ radius: 2, color: '#0000000a' })
  }
}

// 公式详情页面
@Entry
@Component
struct FormulaDetailPage {
  @State formulaData: FormulaItem = {
    id: "",
    name: "",
    formula: "",
    category: "",
    description: "",
    favorite: false,
    mastered: false
  };

  @State favorite: boolean = false;
  @State mastered: boolean = false;

  aboutToAppear() {
    const params = router.getParams();
    if (params && params['formulaData']) {
      this.formulaData = JSON.parse(params['formulaData']);
      this.favorite = this.formulaData.favorite;
      this.mastered = this.formulaData.mastered;
    }
  }

  // 保存学习状态
  saveLearningStatus() {
    // 实际应用中此处应调用Service保存数据
    promptAction.showToast({
      message: this.mastered ? '标记为已掌握' : '标记为学习中',
      duration: 1500
    });
  }

  build() {
    Column() {
      AppBar({
        title: '公式详情',
        showBack: true,
        actions: [
          {
            icon: "favorite",
            action: () => this.favorite = !this.favorite
          }
        ]
      })
      
      Scroll() {
        Column() {
          // 公式卡片
          Text(this.formulaData.formula)
            .fontSize(36)
            .fontFamily('monospace')
            .margin({ top: 30, bottom: 10 })
            .textAlign(TextAlign.Center)
            .fontWeight(FontWeight.Bold)
            .foregroundColor('#003c7a')
          
          Text(this.formulaData.name)
            .fontSize(22)
            .fontWeight(FontWeight.Medium)
            .foregroundColor('#0053a6')
            .textAlign(TextAlign.Center)
            .margin({ bottom: 30 })
          
          // 分类标签
          Row() {
            Text(this.formulaData.category)
              .fontSize(14)
              .foregroundColor('#0075e1')
              .padding(6, 12)
              .backgroundColor('#e6f1ff')
              .borderRadius(20)
          }
          .justifyContent(FlexAlign.Center)
          .margin({ bottom: 25 })
          
          // 公式描述
          Text(this.formulaData.description)
            .fontSize(16)
            .foregroundColor('#456187')
            .lineHeight(26)
            .margin({ left: 25, right: 25, bottom: 40 })
          
          // 学习状态标记
          Row() {
            Button(this.mastered ? '已掌握' : '标记为已掌握')
              .width(180)
              .height(50)
              .fontSize(18)
              .backgroundColor(this.mastered ? '#e8f5e9' : '#e3f2fd')
              .foregroundColor(this.mastered ? '#2e7d32' : '#0075e1')
              .borderRadius(25)
              .onClick(() => {
                this.mastered = !this.mastered;
                this.saveLearningStatus();
              })
          }
          .justifyContent(FlexAlign.Center)
          .margin({ bottom: 40 })
          
          // 应用示例
          Text('应用示例')
            .fontSize(18)
            .fontWeight(FontWeight.Bold)
            .foregroundColor('#1a2c4c')
            .margin({ left: 25, bottom: 15 })
          
          FormulaExample({ category: this.formulaData.category })
        }
        .width('100%')
      }
      .scrollBar(BarState.Off)
      
      // 底部操作栏 - 使用系统图标组件
      Row() {
        // 收藏按钮
        Column() {
          if (this.favorite) {
            Image($rawfile('common/icon_heart_filled.png'))
              .width(24)
              .height(24)
              .margin({ bottom: 5 })
          } else {
            Image($rawfile('common/icon_heart_outline.png'))
              .width(24)
              .height(24)
              .margin({ bottom: 5 })
          }
          Text('收藏')
            .fontSize(14)
        }
        .layoutWeight(1)
        .height(50)
        .justifyContent(FlexAlign.Center)
        .backgroundColor(this.favorite ? '#ff336611' : '#f5f5f7')
        .foregroundColor(this.favorite ? '#ff3366' : '#666')
        .onClick(() => this.favorite = !this.favorite)
        
        // 练习按钮
        Column() {
          Image($rawfile('common/icon_practice.png'))
            .width(24)
            .height(24)
            .margin({ bottom: 5 })
          Text('练习题')
            .fontSize(14)
        }
        .layoutWeight(1)
        .height(50)
        .justifyContent(FlexAlign.Center)
        .backgroundColor('#e3f2fd')
        .foregroundColor('#0075e1')
        .onClick(() => {
          // 导航到练习题页面
        })
      }
      .height(60)
      .width('100%')
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#ffffff')
  }
}

@Component
struct FormulaExample {
  @Prop category: string;
  
  build() {
    Column() {
      if (this.category.includes('几何')) {
        GeometryExamples()
      } else if (this.category.includes('代数')) {
        AlgebraExamples()
      }
    }
  }
}

@Builder
function GeometryExamples() {
  Column() {
    Text('1. 已知直角三角形两条直角边分别为3cm和4cm,求斜边长度?')
      .margin({ bottom: 10 })
    
    Text('解: 使用勾股定理 c = √(a² + b²) = √(3² + 4²) = √(9 + 16) = √25 = 5cm')
      .fontSize(14)
      .foregroundColor('#5e7a9c')
      .margin({ bottom: 20 })
    
    Text('2. 已知一个圆的半径 r = 5cm,求其面积?')
      .margin({ bottom: 10 })
    
    Text('解: 面积 S = πr² = 3.14 × 25 = 78.5 cm²')
      .fontSize(14)
      .foregroundColor('#5e7a9c')
  }
  .padding(15)
  .margin({ horizontal: 20 })
  .backgroundColor('#f9fbff')
  .borderRadius(12)
  .border({ width: 1, color: '#e8f1ff' })
}

@Builder
function AlgebraExamples() {
  Column() {
    Text('1. 解方程: x² - 5x + 6 = 0')
      .margin({ bottom: 10 })
    
    Text('解: a=1, b=-5, c=6')
      .fontSize(14)
      .foregroundColor('#5e7a9c')
      .margin({ bottom: 5 })
    
    Text('x = [5 ± √(25-24)] / 2')
      .fontSize(14)
      .foregroundColor('#5e7a9c')
      .margin({ bottom: 5 })
    
    Text('x = (5 ± 1)/2 => x1=3, x2=2')
      .fontSize(14)
      .foregroundColor('#5e7a9c')
      .margin({ bottom: 20 })
    
    Text('2. 解方程: 2x² + 4x - 6 = 0')
      .margin({ bottom: 10 })
  }
  .padding(15)
  .margin({ horizontal: 20 })
  .backgroundColor('#f9fbff')
  .borderRadius(12)
  .border({ width: 1, color: '#e8f1ff' })
}

// 模型数据定义
class FormulaItem {
  id: string = "";
  name: string = "";
  formula: string = "";
  category: string = "";
  description: string = "";
  favorite: boolean = false;
  mastered: boolean = false;
}

功能说明

主页功能 (Index.ets)

  1. ​学习进度卡片​​:展示已掌握公式数量及总进度
  2. ​公式列表​​:按分类展示数学公式
  3. ​公式卡片组件​​:显示公式名、公式内容、分类及状态
  4. ​收藏功能​​:一键收藏重要公式
  5. ​导航系统​​:点击卡片进入详情页

详情页功能 (FormulaDetail.ets)

  1. ​公式详情展示​​:大字展示核心公式
  2. ​公式描述​​:详细说明公式原理和应用
  3. ​应用示例​​:提供实际解题示例
  4. ​学习状态管理​​:标记掌握状态
  5. ​练习功能​​:提供练习入口

组件库 (Common.ets)

  1. ​公式数据模型​​:定义FormulaItem数据结构
  2. ​示例数据​​:提供样本公式数据
  3. ​共享组件​​:可复用的UI组件