HarmonyOS智慧农业管理应用开发教程--高高种地-- 第23篇:智能推荐系统

第23篇:智能推荐系统

📚 本篇导读

智能推荐是现代农业应用的核心功能之一,通过分析地块特征、气候条件、节气时令等多维度数据,为农户提供科学的种植建议和农事指导。本篇教程将实现一个完整的智能推荐系统,涵盖作物推荐、农事推荐、智能决策等功能。

本篇将实现

  • 🌱 作物种植推荐(基于气候、地块、节气)
  • 📅 农事操作推荐(基于作物生长周期)
  • 🤖 智能决策建议(基于数据分析)
  • 🌾 节气农事指导(二十四节气推荐)
  • 📊 产量预测分析(基于历史数据)

🎯 学习目标

完成本篇教程后,你将掌握:

  1. 如何设计智能推荐算法
  2. 如何整合多维度数据进行推荐
  3. 如何实现基于规则的推荐引擎
  4. 如何展示推荐结果
  5. 推荐系统的实际应用场景

一、智能推荐系统架构

1.1 系统架构设计

复制代码
智能推荐系统
├── 数据采集层
│   ├── 地块数据(面积、土壤、灌溉)
│   ├── 气候数据(温度、降雨、湿度)
│   ├── 节气数据(二十四节气)
│   └── 历史数据(种植记录、产量)
│
├── 推荐引擎层
│   ├── 作物推荐引擎
│   │   ├── 气候匹配算法
│   │   ├── 地块适配算法
│   │   └── 节气推荐算法
│   │
│   ├── 农事推荐引擎
│   │   ├── 生长周期分析
│   │   ├── 农事时机判断
│   │   └── 操作优先级排序
│   │
│   └── 智能决策引擎
│       ├── 产量预测模型
│       ├── 风险评估模型
│       └── 优化建议生成
│
└── 展示层
    ├── 推荐卡片展示
    ├── 详细说明页面
    └── 操作引导界面

1.2 推荐维度

推荐类型 数据来源 推荐依据
作物推荐 气候、地块、节气 温度、降雨、土壤类型、季节
农事推荐 作物生长数据 生长天数、生长阶段、天气
智能决策 历史数据、实时数据 产量预测、风险评估、优化建议
节气指导 二十四节气 传统农事经验、节气特点

1.3 核心服务类

本教程涉及以下核心服务:

  • PlantRecommendationService - 作物推荐服务
  • SolarTermService - 节气服务
  • SmartDecisionPage - 智能决策页面
  • FieldService - 地块服务
  • WeatherService - 天气服务

二、PlantRecommendationService 作物推荐服务

2.1 数据模型设计

文件位置entry/src/main/ets/services/PlantRecommendationService.ets

typescript 复制代码
/**
 * 作物推荐信息接口
 */
export interface PlantRecommendation {
  plantName: string;        // 植物名称
  plantType: string;        // 植物类型
  reason: string;           // 推荐理由
  difficulty: string;       // 种植难度
  growthPeriod: string;     // 生长周期
  icon: string;             // 图标
  suitableTemp: string;     // 适宜温度
  waterNeeds: string;       // 水分需求
}

/**
 * 推荐模式枚举
 */
export enum RecommendationMode {
  HOME_GARDENING = 'HOME_GARDENING',                    // 家庭园艺模式
  PROFESSIONAL_AGRICULTURE = 'PROFESSIONAL_AGRICULTURE'  // 专业农业模式
}

2.2 服务类实现

typescript 复制代码
export class PlantRecommendationService {
  private static instance: PlantRecommendationService;
  private locationClimateService: LocationClimateService;

  private constructor() {
    this.locationClimateService = LocationClimateService.getInstance();
  }

  public static getInstance(): PlantRecommendationService {
    if (!PlantRecommendationService.instance) {
      PlantRecommendationService.instance = new PlantRecommendationService();
    }
    return PlantRecommendationService.instance;
  }

  /**
   * 根据位置信息推荐植物
   * @param location 位置信息
   * @param mode 推荐模式
   */
  public getRecommendationsByLocation(
    location: LocationInfo,
    mode: RecommendationMode = RecommendationMode.HOME_GARDENING
  ): PlantRecommendation[] {
    // 获取气候数据
    const climateInfo = this.findClimateInfoByLocation(location);

    if (climateInfo) {
      return this.getRecommendationsByClimate(climateInfo, mode);
    }

    // 如果没有找到精确的气候数据,根据省份推荐
    return this.getRecommendationsByProvince(location.province, mode);
  }
}

2.3 基于气候的推荐算法

专业农业模式推荐
typescript 复制代码
/**
 * 专业农业模式推荐 - 推荐大田作物和经济作物
 */
private getProfessionalAgricultureRecommendations(climate: TownInfo): PlantRecommendation[] {
  const recommendations: PlantRecommendation[] = [];
  const temp = climate.avgTemperature;
  const rainfall = climate.annualRainfall;

  // 温带作物(10-20℃)
  if (temp >= 10 && temp <= 20) {
    if (rainfall >= 800) {
      recommendations.push({
        plantName: '小麦',
        plantType: '粮食作物',
        reason: `当地年均温度${temp}℃,降雨量${rainfall}mm,适合小麦规模种植`,
        difficulty: '中等',
        growthPeriod: '8-10个月',
        icon: '🌾',
        suitableTemp: '12-22℃',
        waterNeeds: '中等'
      });

      recommendations.push({
        plantName: '玉米',
        plantType: '粮食作物',
        reason: `温暖湿润,玉米产量高,经济效益好`,
        difficulty: '简单',
        growthPeriod: '4-5个月',
        icon: '🌽',
        suitableTemp: '15-27℃',
        waterNeeds: '中等'
      });
    }

    recommendations.push({
      plantName: '马铃薯',
      plantType: '经济作物',
      reason: `凉爽气候,马铃薯适应性强,市场需求大`,
      difficulty: '简单',
      growthPeriod: '3-4个月',
      icon: '🥔',
      suitableTemp: '15-25℃',
      waterNeeds: '中等'
    });
  }

  // 亚热带作物(15-25℃)
  if (temp >= 15 && temp <= 25) {
    if (rainfall >= 1000) {
      recommendations.push({
        plantName: '水稻',
        plantType: '粮食作物',
        reason: `温暖多雨,水稻是主要粮食作物,产量稳定`,
        difficulty: '中等',
        growthPeriod: '4-6个月',
        icon: '🌾',
        suitableTemp: '20-30℃',
        waterNeeds: '高'
      });
    }

    recommendations.push({
      plantName: '大豆',
      plantType: '经济作物',
      reason: `温暖气候,大豆营养丰富,市场价值高`,
      difficulty: '简单',
      growthPeriod: '3-4个月',
      icon: '🫘',
      suitableTemp: '20-28℃',
      waterNeeds: '中等'
    });

    recommendations.push({
      plantName: '花生',
      plantType: '经济作物',
      reason: `适宜温度,花生经济效益好,耐旱性强`,
      difficulty: '简单',
      growthPeriod: '4-5个月',
      icon: '🥜',
      suitableTemp: '20-30℃',
      waterNeeds: '中等'
    });
  }

  // 热带作物(>20℃)
  if (temp > 20 && rainfall >= 1500) {
    recommendations.push({
      plantName: '甘蔗',
      plantType: '经济作物',
      reason: `高温多雨,甘蔗产量高,制糖原料`,
      difficulty: '中等',
      growthPeriod: '12-18个月',
      icon: '🎋',
      suitableTemp: '25-32℃',
      waterNeeds: '高'
    });

    recommendations.push({
      plantName: '香蕉',
      plantType: '水果',
      reason: `热带气候,香蕉生长快,经济价值高`,
      difficulty: '中等',
      growthPeriod: '10-12个月',
      icon: '🍌',
      suitableTemp: '24-32℃',
      waterNeeds: '高'
    });
  }

  return recommendations.slice(0, 6);
}

推荐逻辑说明

  1. 温度匹配:根据年均温度推荐适宜作物
  2. 降雨量考虑:高降雨地区推荐水稻等喜水作物
  3. 经济效益:优先推荐市场价值高的作物
  4. 种植难度:标注难度等级,便于农户选择

2.4 季节性推荐

typescript 复制代码
/**
 * 获取当前季节推荐
 * @param mode 推荐模式
 */
public getSeasonalRecommendations(
  mode: RecommendationMode = RecommendationMode.HOME_GARDENING
): PlantRecommendation[] {
  const month = new Date().getMonth() + 1; // 1-12
  const recommendations: PlantRecommendation[] = [];

  // 春季(3-5月)
  if (month >= 3 && month <= 5) {
    recommendations.push(
      {
        plantName: '番茄',
        plantType: '蔬菜',
        reason: '春季播种,夏季收获',
        difficulty: '简单',
        growthPeriod: '3-4个月',
        icon: '🍅',
        suitableTemp: '15-28℃',
        waterNeeds: '中等'
      },
      {
        plantName: '黄瓜',
        plantType: '蔬菜',
        reason: '春播夏收,生长快',
        difficulty: '简单',
        growthPeriod: '2-3个月',
        icon: '🥒',
        suitableTemp: '18-32℃',
        waterNeeds: '较高'
      }
    );
  }

  // 夏季(6-8月)
  if (month >= 6 && month <= 8) {
    recommendations.push(
      {
        plantName: '空心菜',
        plantType: '蔬菜',
        reason: '耐热速生,夏季主打蔬菜',
        difficulty: '简单',
        growthPeriod: '1-2个月',
        icon: '🥬',
        suitableTemp: '25-35℃',
        waterNeeds: '高'
      },
      {
        plantName: '丝瓜',
        plantType: '蔬菜',
        reason: '夏季种植,产量高',
        difficulty: '简单',
        growthPeriod: '2-3个月',
        icon: '🥒',
        suitableTemp: '20-30℃',
        waterNeeds: '中等'
      }
    );
  }

  // 秋季(9-11月)
  if (month >= 9 && month <= 11) {
    recommendations.push(
      {
        plantName: '白菜',
        plantType: '蔬菜',
        reason: '秋季种植,冬季收获',
        difficulty: '简单',
        growthPeriod: '2-3个月',
        icon: '🥬',
        suitableTemp: '10-22℃',
        waterNeeds: '中等'
      },
      {
        plantName: '萝卜',
        plantType: '蔬菜',
        reason: '秋播冬收,营养丰富',
        difficulty: '简单',
        growthPeriod: '2-3个月',
        icon: '🥕',
        suitableTemp: '15-25℃',
        waterNeeds: '中等'
      }
    );
  }

  // 冬季(12-2月)
  if (month === 12 || month <= 2) {
    recommendations.push(
      {
        plantName: '菠菜',
        plantType: '蔬菜',
        reason: '耐寒蔬菜,冬季可种',
        difficulty: '简单',
        growthPeriod: '1-2个月',
        icon: '🥬',
        suitableTemp: '5-20℃',
        waterNeeds: '中等'
      },
      {
        plantName: '大蒜',
        plantType: '蔬菜',
        reason: '秋冬种植,春季收获',
        difficulty: '简单',
        growthPeriod: '6-8个月',
        icon: '🧄',
        suitableTemp: '12-25℃',
        waterNeeds: '较低'
      }
    );
  }

  return recommendations;
}

三、SolarTermService 节气推荐服务

3.1 节气数据模型

文件位置entry/src/main/ets/services/SolarTermService.ets

typescript 复制代码
export interface SolarTermRecommendation {
  solarTerm: string;           // 节气名称
  period: string;              // 时间段
  temperature: string;         // 温度特点
  poem: string;                // 代表诗词
  poemAuthor: string;          // 诗词作者
  vegetables: string[];        // 推荐蔬菜
  fruits: string[];           // 推荐水果
  grains: string[];           // 推荐粮食作物
  flowers: string[];          // 推荐花卉
  precautions: string[];      // 注意事项
  farmWork: string[];         // 农事活动
}

3.2 获取当前节气

typescript 复制代码
export class SolarTermService {
  private static instance: SolarTermService;

  public static getInstance(): SolarTermService {
    if (!SolarTermService.instance) {
      SolarTermService.instance = new SolarTermService();
    }
    return SolarTermService.instance;
  }

  /**
   * 获取当前节气
   */
  public getCurrentSolarTerm(): string {
    const now = new Date();
    const month = now.getMonth() + 1;
    const day = now.getDate();

    // 简化的节气判断(基于公历日期)
    if (month === 1) {
      if (day < 6) return '小寒';
      if (day < 20) return '大寒';
      return '立春';
    } else if (month === 2) {
      if (day < 4) return '立春';
      if (day < 19) return '雨水';
      return '惊蛰';
    } else if (month === 3) {
      if (day < 6) return '惊蛰';
      if (day < 21) return '春分';
      return '清明';
    } else if (month === 4) {
      if (day < 5) return '清明';
      if (day < 20) return '谷雨';
      return '立夏';
    }
    // ... 其他月份判断

    return '立春';
  }

  /**
   * 获取节气种植推荐
   */
  public getSolarTermRecommendation(solarTerm?: string): SolarTermRecommendation {
    const term = solarTerm || this.getCurrentSolarTerm();
    const recommendations = this.getAllRecommendations();
    return recommendations[term] || recommendations['立春'];
  }
}

3.3 节气推荐数据示例

typescript 复制代码
/**
 * 获取所有节气推荐数据
 */
private getAllRecommendations(): Record<string, SolarTermRecommendation> {
  return {
    '立春': {
      solarTerm: '立春',
      period: '2月3-5日',
      temperature: '气温回升,万物复苏',
      poem: '律回岁晚冰霜少,春到人间草木知',
      poemAuthor: '张栻',
      vegetables: ['菠菜', '生菜', '芹菜', '香菜', '小白菜'],
      fruits: ['草莓', '枇杷'],
      grains: ['春小麦', '春玉米', '早稻'],
      flowers: ['迎春花', '水仙', '梅花'],
      precautions: [
        '注意倒春寒,做好防寒措施',
        '及时清理田间杂草',
        '检查灌溉设施'
      ],
      farmWork: [
        '整地施肥,准备春耕',
        '修剪果树,清理枯枝',
        '播种耐寒蔬菜',
        '检查农机具'
      ]
    },
    '雨水': {
      solarTerm: '雨水',
      period: '2月18-20日',
      temperature: '降雨增多,气温回升',
      poem: '好雨知时节,当春乃发生',
      poemAuthor: '杜甫',
      vegetables: ['豌豆', '蚕豆', '韭菜', '茼蒿'],
      fruits: ['草莓', '樱桃'],
      grains: ['春小麦', '春玉米'],
      flowers: ['桃花', '杏花', '梨花'],
      precautions: [
        '注意排水防涝',
        '预防倒春寒',
        '加强田间管理'
      ],
      farmWork: [
        '春耕备耕',
        '播种春季作物',
        '果树嫁接',
        '追施返青肥'
      ]
    },
    '清明': {
      solarTerm: '清明',
      period: '4月4-6日',
      temperature: '气温适宜,雨水充沛',
      poem: '清明时节雨纷纷,路上行人欲断魂',
      poemAuthor: '杜牧',
      vegetables: ['黄瓜', '番茄', '茄子', '辣椒', '豆角'],
      fruits: ['樱桃', '草莓', '桑葚'],
      grains: ['早稻', '春玉米', '大豆'],
      flowers: ['牡丹', '芍药', '杜鹃'],
      precautions: [
        '注意病虫害防治',
        '及时中耕除草',
        '做好排水工作'
      ],
      farmWork: [
        '播种春季蔬菜',
        '移栽秧苗',
        '果树授粉',
        '茶叶采摘'
      ]
    },
    '芒种': {
      solarTerm: '芒种',
      period: '6月5-7日',
      temperature: '气温升高,雨量充沛',
      poem: '时雨及芒种,四野皆插秧',
      poemAuthor: '陆游',
      vegetables: ['空心菜', '苋菜', '丝瓜', '冬瓜'],
      fruits: ['西瓜', '荔枝', '杨梅'],
      grains: ['晚稻', '夏玉米', '大豆'],
      flowers: ['荷花', '栀子花', '茉莉'],
      precautions: [
        '抢收抢种,不误农时',
        '注意防暑降温',
        '加强田间管理'
      ],
      farmWork: [
        '收获小麦',
        '插秧种稻',
        '播种夏季作物',
        '果树疏果'
      ]
    }
    // ... 其他节气数据
  };
}

节气推荐特点

  • 结合传统农事经验
  • 考虑节气气候特点
  • 提供具体农事指导
  • 包含文化元素(诗词)

四、智能决策系统

4.1 SmartDecisionPage 页面设计

文件位置entry/src/main/ets/pages/Services/SmartDecisionPage.ets

typescript 复制代码
interface DecisionItem {
  title: string;
  content: string;
  priority: string;      // high/medium/low
  icon: string;
  category: string;
}

@Entry
@ComponentV2
export struct SmartDecisionPage {
  @Local decisions: DecisionItem[] = [];
  @Local selectedCategory: string = '全部';
  @Local isLoading: boolean = true;

  private fieldService = FieldService.getInstance();
  private weatherService = WeatherService.getInstance();

  // 决策类别
  private categories: string[] = [
    '全部', '产量预测', '种植建议',
    '灌溉决策', '施肥方案', '病虫害预警', '收获时机'
  ];

  async aboutToAppear(): Promise<void> {
    await this.loadData();
  }

  async loadData(): Promise<void> {
    try {
      await this.generateDecisions();
      this.isLoading = false;
    } catch (error) {
      console.error('Failed to load decisions:', error);
      this.isLoading = false;
    }
  }
}

4.2 决策生成算法

typescript 复制代码
/**
 * 生成智能决策建议
 */
async generateDecisions(): Promise<void> {
  const decisions: DecisionItem[] = [];

  // 1. 基于天气的决策
  const weather = await this.weatherService.getCurrentWeather();
  if (weather) {
    // 高温灌溉提醒
    if (weather.temperature > 30) {
      decisions.push({
        title: '高温灌溉提醒',
        content: `当前温度较高(${weather.temperature}°C),建议在清晨或傍晚进行灌溉,避免高温时段`,
        priority: 'high',
        icon: '💧',
        category: '灌溉决策'
      });
    }

    // 高湿度预警
    if (weather.humidity > 80) {
      decisions.push({
        title: '高湿度预警',
        content: `当前湿度较高(${weather.humidity}%),注意病虫害防治,保持田间通风`,
        priority: 'medium',
        icon: '🌧️',
        category: '病虫害预警'
      });
    }
  }

  // 2. 基于地块数据的决策
  const fields = await this.fieldService.getAllFields();
  for (const field of fields) {
    if (field.currentCrop) {
      const growthDays = Math.floor(
        (Date.now() - field.currentCrop.plantingDate) / (24 * 60 * 60 * 1000)
      );

      // 产量预测
      if (growthDays > 20) {
        const predictedYield = this.calculateYieldPrediction(
          field.area,
          field.currentCrop.cropName,
          growthDays
        );

        decisions.push({
          title: `${field.name} 产量预测`,
          content: `${field.currentCrop.cropName}当前生长${growthDays}天,预计总产量约${predictedYield.total}公斤,亩产${predictedYield.perMu}公斤`,
          priority: 'medium',
          icon: '📊',
          category: '产量预测'
        });
      }

      // 收获时机建议
      if (field.currentCrop.expectedHarvestDate &&
          field.currentCrop.expectedHarvestDate - Date.now() < 7 * 24 * 60 * 60 * 1000) {
        decisions.push({
          title: `${field.name} 即将收获`,
          content: `${field.currentCrop.cropName}种植已${growthDays}天,预计在一周内可以收获`,
          priority: 'high',
          icon: '🌾',
          category: '收获时机'
        });
      }

      // 施肥建议
      if (growthDays >= 30 && growthDays <= 40) {
        decisions.push({
          title: `${field.name} 追肥建议`,
          content: `${field.currentCrop.cropName}进入营养生长旺盛期,建议进行追肥`,
          priority: 'medium',
          icon: '🌿',
          category: '施肥方案'
        });
      }
    }
  }

  // 3. 添加默认建议
  if (decisions.length === 0) {
    decisions.push({
      title: '定期巡查',
      content: '建议每周至少巡查一次田地,及时发现和处理问题',
      priority: 'low',
      icon: '👨‍🌾',
      category: '种植建议'
    });
  }

  this.decisions = decisions;
}

4.3 产量预测算法

typescript 复制代码
/**
 * 计算产量预测
 */
private calculateYieldPrediction(
  area: number,
  cropName: string,
  growthDays: number
): { total: number; perMu: number } {
  // 基础亩产数据(公斤/亩)
  const baseYieldPerMu: Record<string, number> = {
    '小麦': 400,
    '水稻': 500,
    '玉米': 450,
    '大豆': 200,
    '花生': 300,
    '马铃薯': 1500,
    '番茄': 3000,
    '黄瓜': 2500,
    '白菜': 2000
  };

  // 获取基础亩产
  let perMu = baseYieldPerMu[cropName] || 300;

  // 根据生长天数调整(生长周期越接近完成,预测越准确)
  const growthFactor = Math.min(growthDays / 100, 1.0);
  perMu = perMu * growthFactor;

  // 计算总产量
  const total = Math.round(perMu * area);
  perMu = Math.round(perMu);

  return { total, perMu };
}

预测逻辑说明

  1. 基础数据:使用作物平均亩产作为基准
  2. 生长因子:根据生长天数调整预测值
  3. 面积计算:总产量 = 亩产 × 面积
  4. 动态调整:可根据实际情况优化算法

五、推荐结果展示

5.1 决策卡片组件

typescript 复制代码
@Builder
buildDecisionCard(decision: DecisionItem) {
  Column({ space: 12 }) {
    // 头部:图标和标题
    Row({ space: 12 }) {
      Text(decision.icon)
        .fontSize(32)

      Column({ space: 4 }) {
        Text(decision.title)
          .fontSize(16)
          .fontWeight(FontWeight.Bold)
          .fontColor($r('app.color.text_primary'))

        Text(decision.category)
          .fontSize(12)
          .fontColor($r('app.color.text_tertiary'))
      }
      .alignItems(HorizontalAlign.Start)
      .layoutWeight(1)

      // 优先级标签
      Text(this.getPriorityLabel(decision.priority))
        .fontSize(11)
        .fontColor(this.getPriorityColor(decision.priority))
        .padding({ left: 8, right: 8, top: 4, bottom: 4 })
        .backgroundColor(this.getPriorityBgColor(decision.priority))
        .borderRadius(10)
    }
    .width('100%')

    // 内容
    Text(decision.content)
      .fontSize(14)
      .fontColor($r('app.color.text_secondary'))
      .lineHeight(22)
      .width('100%')

    // 操作按钮
    Row({ space: 8 }) {
      Button('查看详情')
        .height(36)
        .fontSize(14)
        .layoutWeight(1)
        .backgroundColor($r('app.color.card_background'))
        .fontColor($r('app.color.primary_professional'))
        .onClick(() => {
          this.showDecisionDetail(decision);
        })

      Button('标记完成')
        .height(36)
        .fontSize(14)
        .layoutWeight(1)
        .backgroundColor($r('app.color.primary_professional'))
        .onClick(() => {
          this.markAsCompleted(decision);
        })
    }
    .width('100%')
  }
  .width('100%')
  .padding(16)
  .backgroundColor($r('app.color.card_background'))
  .borderRadius(12)
  .shadow({ radius: 4, color: $r('app.color.shadow_light'), offsetY: 2 })
}

/**
 * 获取优先级标签
 */
private getPriorityLabel(priority: string): string {
  const labels: Record<string, string> = {
    'high': '紧急',
    'medium': '重要',
    'low': '一般'
  };
  return labels[priority] || '一般';
}

/**
 * 获取优先级颜色
 */
private getPriorityColor(priority: string): string {
  const colors: Record<string, string> = {
    'high': '#F5222D',
    'medium': '#FA8C16',
    'low': '#52C41A'
  };
  return colors[priority] || '#52C41A';
}

/**
 * 获取优先级背景色
 */
private getPriorityBgColor(priority: string): string {
  const bgColors: Record<string, string> = {
    'high': '#FFF1F0',
    'medium': '#FFF7E6',
    'low': '#F6FFED'
  };
  return bgColors[priority] || '#F6FFED';
}

5.2 类别筛选器

typescript 复制代码
@Builder
buildCategoryFilter() {
  Scroll() {
    Row({ space: 8 }) {
      ForEach(this.categories, (category: string) => {
        Text(category)
          .fontSize(14)
          .fontColor(this.selectedCategory === category ?
            Color.White : $r('app.color.text_primary'))
          .padding({ left: 16, right: 16, top: 8, bottom: 8 })
          .backgroundColor(this.selectedCategory === category ?
            $r('app.color.primary_professional') : $r('app.color.card_background'))
          .borderRadius(16)
          .onClick(() => {
            this.selectedCategory = category;
          })
      })
    }
    .padding({ left: 16, right: 16, top: 16 })
  }
  .scrollable(ScrollDirection.Horizontal)
  .scrollBar(BarState.Off)
  .width('100%')
  .margin({ bottom: 16 })
}

/**
 * 获取筛选后的决策
 */
private getFilteredDecisions(): DecisionItem[] {
  if (this.selectedCategory === '全部') {
    return this.decisions;
  }
  return this.decisions.filter(d => d.category === this.selectedCategory);
}

六、推荐系统集成

6.1 在服务页面集成推荐

文件位置entry/src/main/ets/pages/Services/ServicesPage.ets

typescript 复制代码
@Entry
@ComponentV2
export struct ServicesPage {
  @Local recommendations: PlantRecommendation[] = [];
  @Local currentSolarTerm: string = '';

  private plantRecommendationService = PlantRecommendationService.getInstance();
  private solarTermService = SolarTermService.getInstance();

  async aboutToAppear(): Promise<void> {
    await this.loadRecommendations();
  }

  async loadRecommendations(): Promise<void> {
    // 获取季节推荐
    this.recommendations = this.plantRecommendationService.getSeasonalRecommendations(
      RecommendationMode.PROFESSIONAL_AGRICULTURE
    );

    // 获取当前节气
    this.currentSolarTerm = this.solarTermService.getCurrentSolarTerm();
  }

  build() {
    Column() {
      // 推荐卡片
      this.buildRecommendationSection()

      // 服务功能列表
      this.buildServiceList()
    }
    .width('100%')
    .height('100%')
  }

  @Builder
  buildRecommendationSection() {
    Column({ space: 12 }) {
      Row() {
        Text('🌱 智能推荐')
          .fontSize(18)
          .fontWeight(FontWeight.Bold)
          .layoutWeight(1)

        Text('查看更多 >')
          .fontSize(14)
          .fontColor($r('app.color.primary_professional'))
          .onClick(() => {
            router.pushUrl({
              url: 'pages/Services/SmartDecisionPage'
            });
          })
      }
      .width('100%')
      .padding({ left: 16, right: 16 })

      // 当前节气
      Row({ space: 8 }) {
        Text('📅')
          .fontSize(20)

        Text(`当前节气:${this.currentSolarTerm}`)
          .fontSize(14)
          .fontColor($r('app.color.text_secondary'))
      }
      .width('100%')
      .padding({ left: 16, right: 16 })

      // 推荐列表
      Scroll() {
        Row({ space: 12 }) {
          ForEach(this.recommendations.slice(0, 3), (item: PlantRecommendation) => {
            this.buildRecommendationCard(item)
          })
        }
        .padding({ left: 16, right: 16 })
      }
      .scrollable(ScrollDirection.Horizontal)
      .scrollBar(BarState.Off)
      .width('100%')
    }
    .width('100%')
    .padding({ top: 16, bottom: 16 })
    .backgroundColor($r('app.color.background'))
  }

  @Builder
  buildRecommendationCard(item: PlantRecommendation) {
    Column({ space: 8 }) {
      Text(item.icon)
        .fontSize(40)

      Text(item.plantName)
        .fontSize(15)
        .fontWeight(FontWeight.Bold)
        .fontColor($r('app.color.text_primary'))

      Text(item.plantType)
        .fontSize(12)
        .fontColor($r('app.color.text_tertiary'))

      Text(item.growthPeriod)
        .fontSize(11)
        .fontColor($r('app.color.text_secondary'))
        .padding({ left: 8, right: 8, top: 3, bottom: 3 })
        .backgroundColor($r('app.color.background'))
        .borderRadius(10)
    }
    .width(120)
    .padding(12)
    .backgroundColor($r('app.color.card_background'))
    .borderRadius(12)
    .onClick(() => {
      this.showRecommendationDetail(item);
    })
  }
}

6.2 推荐详情对话框

typescript 复制代码
/**
 * 显示推荐详情
 */
private showRecommendationDetail(item: PlantRecommendation): void {
  AlertDialog.show({
    title: `${item.icon} ${item.plantName}`,
    message: `
类型:${item.plantType}
难度:${item.difficulty}
周期:${item.growthPeriod}
温度:${item.suitableTemp}
水分:${item.waterNeeds}

推荐理由:
${item.reason}
    `,
    primaryButton: {
      value: '添加到种植计划',
      action: () => {
        this.addToPlantingPlan(item);
      }
    },
    secondaryButton: {
      value: '关闭',
      action: () => {}
    }
  });
}

/**
 * 添加到种植计划
 */
private async addToPlantingPlan(item: PlantRecommendation): Promise<void> {
  // 跳转到添加作物页面,预填充推荐信息
  router.pushUrl({
    url: 'pages/Management/AddCropPage',
    params: {
      recommendedCrop: item.plantName,
      cropType: item.plantType
    }
  });
}

七、实操练习

练习1:添加基于地块的推荐

任务:根据地块特征(土壤、灌溉、面积)推荐合适作物

提示

  1. PlantRecommendationService 中添加 getRecommendationsByField 方法
  2. 考虑土壤类型、灌溉条件、地块面积
  3. 返回最适合的3-5个作物

参考代码

typescript 复制代码
/**
 * 根据地块特征推荐作物
 */
public getRecommendationsByField(field: FieldInfo): PlantRecommendation[] {
  const recommendations: PlantRecommendation[] = [];

  // 根据土壤类型推荐
  if (field.soilType === '黑土') {
    recommendations.push({
      plantName: '玉米',
      plantType: '粮食作物',
      reason: '黑土肥沃,适合玉米生长',
      difficulty: '简单',
      growthPeriod: '4-5个月',
      icon: '🌽',
      suitableTemp: '15-27℃',
      waterNeeds: '中等'
    });
  }

  // 根据灌溉条件推荐
  if (field.irrigation === IrrigationSystem.DRIP) {
    recommendations.push({
      plantName: '番茄',
      plantType: '蔬菜',
      reason: '滴灌系统适合番茄精细化管理',
      difficulty: '简单',
      growthPeriod: '3-4个月',
      icon: '🍅',
      suitableTemp: '15-28℃',
      waterNeeds: '中等'
    });
  }

  return recommendations;
}

练习2:添加历史数据分析

任务:基于历史种植记录,推荐表现良好的作物

提示

  1. 分析历史产量数据
  2. 计算作物成功率
  3. 推荐高产、稳定的作物

参考代码

typescript 复制代码
/**
 * 基于历史数据推荐
 */
public async getRecommendationsByHistory(): Promise<PlantRecommendation[]> {
  const fields = await this.fieldService.getAllFields();
  const cropStats: Map<string, { count: number; avgYield: number }> = new Map();

  // 统计历史数据
  for (const field of fields) {
    if (field.currentCrop) {
      const cropName = field.currentCrop.cropName;
      const stats = cropStats.get(cropName) || { count: 0, avgYield: 0 };
      stats.count++;
      // 这里可以添加实际产量统计
      cropStats.set(cropName, stats);
    }
  }

  // 推荐种植次数多的作物
  const recommendations: PlantRecommendation[] = [];
  cropStats.forEach((stats, cropName) => {
    if (stats.count >= 2) {
      recommendations.push({
        plantName: cropName,
        plantType: '经验作物',
        reason: `您已成功种植${stats.count}次,经验丰富`,
        difficulty: '简单',
        growthPeriod: '根据作物而定',
        icon: '🌾',
        suitableTemp: '根据作物而定',
        waterNeeds: '中等'
      });
    }
  });

  return recommendations;
}

练习3:添加市场价格推荐

任务:结合市场价格,推荐经济效益好的作物

提示

  1. 维护作物市场价格数据
  2. 计算预期收益
  3. 推荐高收益作物

八、常见问题

问题1:推荐结果不准确

原因

  • 数据不完整或不准确
  • 推荐算法过于简单
  • 未考虑地域差异

解决方案

typescript 复制代码
// 添加数据验证
public getRecommendationsByLocation(
  location: LocationInfo,
  mode: RecommendationMode
): PlantRecommendation[] {
  // 验证位置信息
  if (!location || !location.province) {
    console.warn('Invalid location info, using default recommendations');
    return this.getDefaultRecommendations(mode);
  }

  // 获取气候数据
  const climateInfo = this.findClimateInfoByLocation(location);

  if (!climateInfo) {
    console.warn(`No climate data for ${location.province}, using province-based recommendations`);
    return this.getRecommendationsByProvince(location.province, mode);
  }

  return this.getRecommendationsByClimate(climateInfo, mode);
}

/**
 * 获取默认推荐
 */
private getDefaultRecommendations(mode: RecommendationMode): PlantRecommendation[] {
  // 返回适应性强的作物
  return [
    {
      plantName: '小葱',
      plantType: '蔬菜',
      reason: '适应性强,四季可种',
      difficulty: '简单',
      growthPeriod: '1-2个月',
      icon: '🧅',
      suitableTemp: '12-28℃',
      waterNeeds: '中等'
    }
  ];
}

问题2:节气判断不准确

原因

  • 简化的节气计算方法
  • 未考虑闰年
  • 公历与农历转换误差

解决方案

typescript 复制代码
/**
 * 精确计算节气(使用天文算法)
 */
public getAccurateSolarTerm(): string {
  const now = new Date();
  const year = now.getFullYear();

  // 使用寿星天文历算法计算节气
  // 这里简化处理,实际应用可以使用专业的农历库
  const solarTermDates = this.calculateSolarTermDates(year);

  for (const [term, date] of Object.entries(solarTermDates)) {
    if (now >= date && now < this.getNextTermDate(term, solarTermDates)) {
      return term;
    }
  }

  return '立春';
}

问题3:产量预测偏差大

原因

  • 使用固定的基础数据
  • 未考虑实际种植条件
  • 缺少历史数据支持

解决方案

typescript 复制代码
/**
 * 改进的产量预测算法
 */
private calculateYieldPrediction(
  area: number,
  cropName: string,
  growthDays: number,
  field: FieldInfo
): { total: number; perMu: number } {
  // 基础亩产
  let perMu = this.getBaseYield(cropName);

  // 土壤因子(0.8-1.2)
  const soilFactor = this.getSoilFactor(field.soilType);
  perMu *= soilFactor;

  // 灌溉因子(0.9-1.1)
  const irrigationFactor = this.getIrrigationFactor(field.irrigation);
  perMu *= irrigationFactor;

  // 生长因子(0-1.0)
  const growthFactor = Math.min(growthDays / this.getOptimalGrowthDays(cropName), 1.0);
  perMu *= growthFactor;

  // 天气因子(基于历史天气数据)
  const weatherFactor = await this.getWeatherFactor(field.id);
  perMu *= weatherFactor;

  const total = Math.round(perMu * area);
  perMu = Math.round(perMu);

  return { total, perMu };
}

/**
 * 获取土壤因子
 */
private getSoilFactor(soilType: string): number {
  const factors: Record<string, number> = {
    '黑土': 1.2,
    '黄土': 1.0,
    '红土': 0.9,
    '沙土': 0.8
  };
  return factors[soilType] || 1.0;
}

/**
 * 获取灌溉因子
 */
private getIrrigationFactor(irrigation: IrrigationSystem): number {
  const factors: Record<string, number> = {
    [IrrigationSystem.DRIP]: 1.1,
    [IrrigationSystem.SPRINKLER]: 1.05,
    [IrrigationSystem.FURROW]: 1.0,
    [IrrigationSystem.NONE]: 0.9
  };
  return factors[irrigation] || 1.0;
}

九、功能扩展建议

1. 机器学习推荐

功能描述

  • 使用机器学习算法优化推荐
  • 基于用户行为学习偏好
  • 持续优化推荐准确度

实现思路

typescript 复制代码
/**
 * 基于机器学习的推荐(概念示例)
 */
class MLRecommendationEngine {
  private userPreferences: Map<string, number> = new Map();

  /**
   * 记录用户选择
   */
  recordUserChoice(cropName: string, accepted: boolean): void {
    const score = this.userPreferences.get(cropName) || 0;
    this.userPreferences.set(cropName, score + (accepted ? 1 : -1));
  }

  /**
   * 获取个性化推荐
   */
  getPersonalizedRecommendations(
    baseRecommendations: PlantRecommendation[]
  ): PlantRecommendation[] {
    // 根据用户偏好排序
    return baseRecommendations.sort((a, b) => {
      const scoreA = this.userPreferences.get(a.plantName) || 0;
      const scoreB = this.userPreferences.get(b.plantName) || 0;
      return scoreB - scoreA;
    });
  }
}

2. 协同过滤推荐

功能描述

  • 基于相似用户的选择推荐
  • "种植这个作物的用户还种植了..."
  • 社区推荐功能

实现思路

typescript 复制代码
/**
 * 协同过滤推荐
 */
class CollaborativeFiltering {
  /**
   * 获取相似用户推荐
   */
  async getSimilarUsersRecommendations(
    userId: string
  ): Promise<PlantRecommendation[]> {
    // 1. 找到相似用户
    const similarUsers = await this.findSimilarUsers(userId);

    // 2. 统计他们的种植选择
    const cropCounts: Map<string, number> = new Map();
    for (const user of similarUsers) {
      const crops = await this.getUserCrops(user.id);
      crops.forEach(crop => {
        cropCounts.set(crop, (cropCounts.get(crop) || 0) + 1);
      });
    }

    // 3. 推荐热门作物
    const recommendations: PlantRecommendation[] = [];
    cropCounts.forEach((count, cropName) => {
      if (count >= 3) {
        recommendations.push(this.getCropRecommendation(cropName, count));
      }
    });

    return recommendations;
  }
}

3. 实时市场价格集成

功能描述

  • 集成农产品市场价格API
  • 实时更新价格信息
  • 推荐高收益作物

实现思路

typescript 复制代码
/**
 * 市场价格服务
 */
class MarketPriceService {
  /**
   * 获取作物市场价格
   */
  async getCropPrice(cropName: string): Promise<number> {
    // 调用市场价格API
    const response = await fetch(`https://api.example.com/price/${cropName}`);
    const data = await response.json();
    return data.price;
  }

  /**
   * 计算预期收益
   */
  async calculateExpectedRevenue(
    cropName: string,
    area: number,
    yieldPerMu: number
  ): Promise<number> {
    const price = await this.getCropPrice(cropName);
    const totalYield = area * yieldPerMu;
    return totalYield * price;
  }

  /**
   * 推荐高收益作物
   */
  async getHighRevenueRecommendations(
    area: number
  ): Promise<PlantRecommendation[]> {
    const crops = ['小麦', '玉米', '大豆', '花生'];
    const recommendations: Array<PlantRecommendation & { revenue: number }> = [];

    for (const crop of crops) {
      const yieldPerMu = this.getAverageYield(crop);
      const revenue = await this.calculateExpectedRevenue(crop, area, yieldPerMu);

      recommendations.push({
        plantName: crop,
        plantType: '经济作物',
        reason: `预期收益:¥${revenue}`,
        difficulty: '中等',
        growthPeriod: '根据作物而定',
        icon: '💰',
        suitableTemp: '根据作物而定',
        waterNeeds: '中等',
        revenue
      });
    }

    // 按收益排序
    return recommendations.sort((a, b) => b.revenue - a.revenue);
  }
}

4. 风险评估系统

功能描述

  • 评估种植风险
  • 预警极端天气影响
  • 提供风险规避建议

实现思路

typescript 复制代码
/**
 * 风险评估服务
 */
class RiskAssessmentService {
  /**
   * 评估种植风险
   */
  async assessPlantingRisk(
    cropName: string,
    field: FieldInfo
  ): Promise<{ level: string; factors: string[] }> {
    const riskFactors: string[] = [];
    let riskScore = 0;

    // 气候风险
    const weather = await this.weatherService.getForecast(7);
    if (weather.some(w => w.temperature > 35)) {
      riskFactors.push('未来一周有高温天气');
      riskScore += 2;
    }

    // 病虫害风险
    if (this.isPestSeason(cropName)) {
      riskFactors.push('当前是病虫害高发期');
      riskScore += 1;
    }

    // 市场风险
    const priceVolatility = await this.getPriceVolatility(cropName);
    if (priceVolatility > 0.3) {
      riskFactors.push('市场价格波动较大');
      riskScore += 1;
    }

    // 确定风险等级
    let level = '低';
    if (riskScore >= 3) level = '高';
    else if (riskScore >= 2) level = '中';

    return { level, factors: riskFactors };
  }
}

十、本篇总结

10.1 核心知识点

本篇教程完整实现了智能推荐系统,涵盖以下核心内容:

  1. 推荐算法设计

    • 基于气候的推荐算法
    • 基于季节的推荐算法
    • 基于节气的推荐算法
    • 基于地块的推荐算法
  2. 数据整合

    • 气候数据
    • 地块数据
    • 节气数据
    • 历史数据
  3. 智能决策

    • 产量预测模型
    • 农事时机判断
    • 风险评估
    • 优化建议生成
  4. UI展示

    • 推荐卡片设计
    • 类别筛选
    • 详情展示
    • 交互优化

10.2 技术要点

  • 多维度推荐:整合气候、地块、节气等多维度数据
  • 规则引擎:基于规则的推荐算法实现
  • 数据分析:产量预测、风险评估等分析功能
  • 用户体验:直观的推荐展示和交互设计
  • 可扩展性:易于添加新的推荐维度和算法

10.3 实际应用价值

智能推荐系统解决了以下实际问题:

  1. 降低决策难度:为农户提供科学的种植建议
  2. 提高种植成功率:推荐适合当地的作物
  3. 优化资源配置:根据地块特征合理安排种植
  4. 提升经济效益:推荐高产、高收益作物
  5. 传承农事经验:结合节气等传统农事智慧

10.4 下一篇预告

第24篇:学习中心 - 课程体系设计

下一篇将实现学习中心功能,包括:

  • 📚 课程分类体系设计
  • 📖 课程列表展示
  • 🎓 学习进度管理
  • 🏆 学习成就系统
  • 📝 学习笔记功能

附录:完整代码文件清单

服务层

  • entry/src/main/ets/services/PlantRecommendationService.ets - 作物推荐服务
  • entry/src/main/ets/services/SolarTermService.ets - 节气服务
  • entry/src/main/ets/services/LocationClimateService.ets - 气候服务

页面层

  • entry/src/main/ets/pages/Services/SmartDecisionPage.ets - 智能决策页面
  • entry/src/main/ets/pages/Services/ServicesPage.ets - 服务页面
相关推荐
熊猫钓鱼>_>5 小时前
【开源鸿蒙跨平台开发先锋训练营】Day 19: 开源鸿蒙React Native动效体系构建与混合开发复盘
react native·华为·开源·harmonyos·鸿蒙·openharmony
2601_949593655 小时前
基础入门 React Native 鸿蒙跨平台开发:BackHandler 返回键控制
react native·react.js·harmonyos
mocoding5 小时前
使用Flutter强大的图标库fl_chart优化鸿蒙版天气预报温度、降水量、湿度展示
flutter·华为·harmonyos
Cobboo6 小时前
i单词上架鸿蒙应用市场之路:一次从 Android 到 HarmonyOS 的完整实战
android·华为·harmonyos
2601_949593656 小时前
高级进阶 React Native 鸿蒙跨平台开发:LinearGradient 动画渐变效果
react native·react.js·harmonyos
熊猫钓鱼>_>6 小时前
【开源鸿蒙跨平台开发先锋训练营】鸿蒙应用开发 Day 10 - React Native for OpenHarmony 实战:多端响应式布局与高可用交互设计
华为·开源·交互·harmonyos·鸿蒙·rn·gridrow
摘星编程7 小时前
React Native鸿蒙:自定义useField字段状态绑定
react native·react.js·harmonyos
Miguo94well8 小时前
Flutter框架跨平台鸿蒙开发——学校校历APP的开发流程
flutter·华为·harmonyos·鸿蒙
一起养小猫8 小时前
Flutter for OpenHarmony网络请求与数据持久化完全指南
开发语言·网络·jvm·数据库·flutter·harmonyos
讯方洋哥9 小时前
HarmonyOS App开发 ——鸿蒙录音机应用App开发
华为·harmonyos