HarmonyOS 6 悬浮导航 + 沉浸光感:打造鸿蒙智能体驱动的沉浸式语言学习伙伴

文章目录

    • 每日一句正能量
    • 一、前言:当AI语言伙伴常驻屏幕边缘
    • 二、应用场景设计
      • [2.1 场景一:阅读辅助学习](#2.1 场景一:阅读辅助学习)
      • [2.2 场景二:口语实时纠音](#2.2 场景二:口语实时纠音)
      • [2.3 场景三:碎片时间复习](#2.3 场景三:碎片时间复习)
    • 三、技术架构
    • 四、核心代码实现
      • [4.1 学习上下文感知引擎(LearningContextEngine)](#4.1 学习上下文感知引擎(LearningContextEngine))
      • [4.2 沉浸光感学习反馈(LearningLightingController)](#4.2 沉浸光感学习反馈(LearningLightingController))
      • [4.3 语言学习智能体引擎(LanguageAgentEngine)](#4.3 语言学习智能体引擎(LanguageAgentEngine))
      • [4.4 悬浮窗学习面板(LearningFloatWindow)](#4.4 悬浮窗学习面板(LearningFloatWindow))
      • [4.5 学习胶囊页面(LearningCapsulePage)](#4.5 学习胶囊页面(LearningCapsulePage))
      • [4.6 学习卡片页面(LearningCardPage)](#4.6 学习卡片页面(LearningCardPage))
      • [4.7 主入口与系统集成(Index.ets)](#4.7 主入口与系统集成(Index.ets))
    • 五、配置文件
    • 六、效果展示与使用场景
      • [6.1 典型学习场景](#6.1 典型学习场景)
      • [6.2 光效语义设计](#6.2 光效语义设计)
    • 七、性能与隐私优化
      • [7.1 学习数据策略](#7.1 学习数据策略)
      • [7.2 隐私保护](#7.2 隐私保护)
    • 八、总结与展望

每日一句正能量

想得开是一种释然,成全别人更放过自己。

释然不是冷漠,而是明白"改变能改变的,接受不能改变的"。当你不再强求别人符合你的期待,你就同时释放了别人和自己。

一、前言:当AI语言伙伴常驻屏幕边缘

在全球化交流日益频繁的今天,语言学习已成为职场人士和学生群体的刚需。然而,传统语言学习应用存在明显的碎片化问题:需要专门打开APP进行学习,难以融入日常使用场景;缺乏实时反馈,发音错误无人纠正;学习进度孤立,无法与真实应用场景结合。

HarmonyOS 6(API 23)带来的悬浮导航(Floating Navigation) 沉浸光感(Immersive Lighting)能力,让我们有机会打造一个常驻屏幕边缘的AI语言学习伙伴------它像一位耐心的外教,在你浏览英文网页、观看美剧、与国际友人聊天时静静悬浮在屏幕角落,遇到生词即时翻译,听到发音即时纠正;它通过光效反馈学习状态,在掌握新词时以绿色光效确认,在需要复习时以琥珀色光效提醒,在达成学习目标时以彩虹光效庆祝。

核心创新点:

  • 🌍 跨应用语言捕获:悬浮窗实时捕获屏幕中的外语内容,即时翻译与解析
  • 💡 学习状态光感:通过设备边框光效颜色变化,反映词汇掌握度与学习节奏
  • 🤖 情境化智能体:自动识别学习场景(阅读/听力/口语/写作),动态调整辅助策略
  • 🎯 间隔重复记忆:基于艾宾浩斯遗忘曲线,在最佳时机推送复习提醒

二、应用场景设计

2.1 场景一:阅读辅助学习

用户正在浏览器中阅读英文技术文档,遇到生词"immutable"。悬浮胶囊自动识别并显示中文释义"不可变的",点击展开显示例句、词根词缀、同义词对比。用户标记为"已学",边框泛起绿色确认光效,该词自动加入记忆队列。

2.2 场景二:口语实时纠音

用户与外国客户视频会议中,AI智能体在后台监听发音。当用户把"schedule"读成/ˈskedʒuːl/(美式)而设定目标为英式发音/ˈʃedjuːl/时,悬浮窗轻微震动并显示正确发音口型动画,边框泛起蓝色提示光效。

2.3 场景三:碎片时间复习

等电梯的30秒,悬浮窗自动推送"今日待复习5词",用户快速滑动浏览。每个词掌握后边框光效从琥珀色变为绿色,全部掌握后彩虹渐变庆祝。学习数据同步至云端,与PC端学习进度无缝衔接。

三、技术架构

复制代码
┌─────────────────────────────────────────────────────────────┐
│         HarmonyOS Language Learning Companion Agent         │
├─────────────┬─────────────┬─────────────┬───────────────────┤
│  悬浮窗UI   │  沉浸光感   │  智能体引擎  │   语言处理模块     │
│  FloatUI    │  Lighting   │  AI Engine  │   LanguageProcessor│
├─────────────┴─────────────┴─────────────┴───────────────────┤
│                    学习感知层(Learning Context)              │
│   文本识别 │ 语音分析 │ 记忆算法 │ 场景检测 │ 进度追踪        │
├─────────────────────────────────────────────────────────────┤
│              HarmonyOS 6 (API 23) 系统服务层                 │
│   悬浮导航 │ 光感服务 │ 智能体框架 │ OCR │ TTS │ 语音识别 │ 剪贴板 │
└─────────────────────────────────────────────────────────────┘

四、核心代码实现

4.1 学习上下文感知引擎(LearningContextEngine)

这是整个系统的"语言之眼",通过OCR、剪贴板监听、语音捕获实时感知学习场景。

typescript 复制代码
// engine/LearningContextEngine.ets
import { systemPasteboard } from '@kit.BasicServicesKit';
import { textRecognition } from '@kit.VisionKit';
import { audio } from '@kit.AudioKit';
import { BusinessError } from '@kit.BasicServicesKit';

export interface LearningContext {
  currentScene: LearningScene;    // 当前学习场景
  detectedText: string;           // 检测到的文本
  detectedLanguage: string;       // 检测到的语言
  difficulty: number;             // 难度等级 1-5
  knownWords: number;             // 已掌握词汇数
  newWords: VocabularyItem[];     // 新词列表
  reviewQueue: VocabularyItem[];  // 待复习队列
  sessionStats: SessionStats;     // 本次学习统计
  lastInteraction: number;        // 最后交互时间
}

export enum LearningScene {
  READING = 'reading',           // 阅读场景
  LISTENING = 'listening',       // 听力场景
  SPEAKING = 'speaking',         // 口语场景
  WRITING = 'writing',           // 写作场景
  REVIEW = 'review',             // 复习场景
  IDLE = 'idle'                  // 空闲
}

export interface VocabularyItem {
  id: string;
  word: string;
  pronunciation: string;
  meaning: string;
  example: string;
  context: string;                // 学习时的上下文
  difficulty: number;
  masteryLevel: number;           // 掌握度 0-100
  lastReview: number;             // 上次复习时间
  nextReview: number;             // 下次复习时间(基于SM-2算法)
  reviewCount: number;            // 复习次数
  correctCount: number;           // 正确次数
  tags: string[];                 // 标签(如:技术、商务、日常)
}

export interface SessionStats {
  startTime: number;
  wordsLearned: number;
  wordsReviewed: number;
  correctRate: number;
  duration: number;
}

export class LearningContextEngine {
  private pasteboard: systemPasteboard.SystemPasteboard | null = null;
  private textRecognizer: textRecognition.TextRecognizer | null = null;
  private audioCapturer: audio.AudioCapturer | null = null;
  private contextCallbacks: Array<(context: LearningContext) => void> = [];
  private currentContext: LearningContext | null = null;
  private vocabularyDB: Map<string, VocabularyItem> = new Map();
  private lastClipboardContent: string = '';
  private updateInterval: number = 0;

  /**
   * 初始化学习上下文感知
   * 亮点:多源文本捕获(剪贴板+OCR+语音)+ 智能场景识别
   */
  async init(): Promise<void> {
    try {
      // 初始化剪贴板监听
      this.pasteboard = systemPasteboard.getSystemPasteboard();
      this.pasteboard.on('contentChanged', () => {
        this.handleClipboardChange();
      });

      // 初始化文本识别
      this.textRecognizer = await textRecognition.createTextRecognizer({
        language: 'en'
      });

      // 初始化音频捕获(用于口语场景)
      const capturerInfo: audio.AudioCapturerInfo = {
        source: audio.SourceType.MIC,
        capturerFlags: 0
      };
      const audioStreamInfo: audio.AudioStreamInfo = {
        samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_16000,
        channels: audio.AudioChannel.CHANNEL_1,
        sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE,
        encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW
      };
      this.audioCapturer = await audio.createAudioCapturer(capturerInfo, audioStreamInfo);

      // 加载本地词库
      await this.loadVocabularyDB();

      // 启动定时刷新
      this.updateInterval = setInterval(() => this.refreshContext(), 3000);

      console.info('[LearningContext] 学习上下文感知引擎初始化完成');
    } catch (err) {
      console.error(`[LearningContext] 初始化失败: ${JSON.stringify(err)}`);
    }
  }

  /**
   * 处理剪贴板变化
   */
  private async handleClipboardChange(): Promise<void> {
    try {
      const pasteData = await this.pasteboard?.getData();
      const text = pasteData?.getPrimaryText() || '';
      
      if (text && text !== this.lastClipboardContent && this.isForeignLanguage(text)) {
        this.lastClipboardContent = text;
        console.info('[LearningContext] 检测到外语内容:', text.substring(0, 50));
        
        // 分析文本中的词汇
        const words = await this.analyzeText(text);
        
        // 更新学习上下文
        await this.updateContext(LearningScene.READING, text, words);
      }
    } catch (err) {
      console.error(`[LearningContext] 剪贴板处理失败: ${JSON.stringify(err)}`);
    }
  }

  /**
   * 识别屏幕文本(OCR)
   */
  async recognizeScreenText(image: ArrayBuffer): Promise<void> {
    try {
      if (!this.textRecognizer) return;

      const result = await this.textRecognizer.detect(image, {
        detectType: textRecognition.DetectType.DETECT_TYPE_TEXT
      });

      const text = result.text || '';
      if (text && this.isForeignLanguage(text)) {
        const words = await this.analyzeText(text);
        await this.updateContext(LearningScene.READING, text, words);
      }
    } catch (err) {
      console.error(`[LearningContext] OCR识别失败: ${JSON.stringify(err)}`);
    }
  }

  /**
   * 分析文本中的词汇
   */
  private async analyzeText(text: string): Promise<<VocabularyItem[]> {
    // 分词(简化实现,实际应使用NLP库)
    const words = text.toLowerCase()
      .replace(/[^\w\s]/g, '')
      .split(/\s+/)
      .filter(w => w.length > 2 && !this.isCommonWord(w));

    const vocabularyItems: VocabularyItem[] = [];
    const uniqueWords = [...new Set(words)];

    for (const word of uniqueWords.slice(0, 10)) { // 最多分析10个词
      const item = await this.getOrCreateVocabularyItem(word, text);
      vocabularyItems.push(item);
    }

    return vocabularyItems;
  }

  /**
   * 获取或创建词汇项
   */
  private async getOrCreateVocabularyItem(word: string, context: string): Promise<<VocabularyItem> {
    // 检查是否已存在
    if (this.vocabularyDB.has(word)) {
      return this.vocabularyDB.get(word)!;
    }

    // 创建新词汇项
    const item: VocabularyItem = {
      id: `word_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
      word,
      pronunciation: '', // 实际应调用词典API
      meaning: '',       // 实际应调用翻译API
      example: context,
      context,
      difficulty: this.estimateDifficulty(word),
      masteryLevel: 0,
      lastReview: 0,
      nextReview: Date.now(),
      reviewCount: 0,
      correctCount: 0,
      tags: this.inferTags(context)
    };

    this.vocabularyDB.set(word, item);
    return item;
  }

  /**
   * 估算词汇难度
   */
  private estimateDifficulty(word: string): number {
    // 基于词频和长度估算
    const length = word.length;
    if (length <= 4) return 1;
    if (length <= 6) return 2;
    if (length <= 8) return 3;
    if (length <= 10) return 4;
    return 5;
  }

  /**
   * 推断标签
   */
  private inferTags(context: string): string[] {
    const tags: string[] = [];
    const techKeywords = ['api', 'code', 'function', 'database', 'algorithm'];
    const businessKeywords = ['meeting', 'deadline', 'budget', 'client', 'proposal'];
    const dailyKeywords = ['food', 'weather', 'travel', 'family', 'hobby'];

    const lowerContext = context.toLowerCase();
    
    if (techKeywords.some(k => lowerContext.includes(k))) tags.push('技术');
    if (businessKeywords.some(k => lowerContext.includes(k))) tags.push('商务');
    if (dailyKeywords.some(k => lowerContext.includes(k))) tags.push('日常');

    return tags.length > 0 ? tags : ['通用'];
  }

  /**
   * 判断是否为外语
   */
  private isForeignLanguage(text: string): boolean {
    // 简化:检测是否包含大量ASCII字符
    const asciiCount = (text.match(/[a-zA-Z]/g) || []).length;
    return asciiCount / text.length > 0.5 && text.length > 10;
  }

  /**
   * 判断是否为常见词
   */
  private isCommonWord(word: string): boolean {
    const commonWords = new Set([
      'the', 'be', 'to', 'of', 'and', 'a', 'in', 'that', 'have', 'i',
      'it', 'for', 'not', 'on', 'with', 'he', 'as', 'you', 'do', 'at'
    ]);
    return commonWords.has(word.toLowerCase());
  }

  /**
   * 更新学习上下文
   */
  private async updateContext(
    scene: LearningScene,
    text: string,
    words: VocabularyItem[]
  ): Promise<void> {
    const newWords = words.filter(w => w.masteryLevel < 50);
    const reviewQueue = this.getReviewQueue();

    const context: LearningContext = {
      currentScene: scene,
      detectedText: text,
      detectedLanguage: 'en',
      difficulty: Math.round(words.reduce((sum, w) => sum + w.difficulty, 0) / words.length) || 1,
      knownWords: this.vocabularyDB.size,
      newWords,
      reviewQueue,
      sessionStats: this.currentContext?.sessionStats || {
        startTime: Date.now(),
        wordsLearned: 0,
        wordsReviewed: 0,
        correctRate: 0,
        duration: 0
      },
      lastInteraction: Date.now()
    };

    this.currentContext = context;
    this.contextCallbacks.forEach(cb => cb(context));
  }

  /**
   * 获取待复习队列(基于SM-2算法)
   */
  private getReviewQueue(): VocabularyItem[] {
    const now = Date.now();
    const reviewItems: VocabularyItem[] = [];

    this.vocabularyDB.forEach(item => {
      if (item.nextReview <= now && item.masteryLevel > 0 && item.masteryLevel < 100) {
        reviewItems.push(item);
      }
    });

    // 按下次复习时间排序
    return reviewItems.sort((a, b) => a.nextReview - b.nextReview).slice(0, 10);
  }

  /**
   * 更新词汇掌握度(SM-2算法)
   */
  updateMastery(word: string, quality: number): void {
    const item = this.vocabularyDB.get(word);
    if (!item) return;

    // quality: 0-5,5表示完全掌握
    const q = Math.max(0, Math.min(5, quality));
    
    if (q < 3) {
      // 回答错误,重置
      item.reviewCount = 0;
      item.nextReview = Date.now() + 60000; // 1分钟后复习
    } else {
      // 回答正确
      item.reviewCount++;
      item.correctCount++;
      
      // 计算间隔(天)
      let interval: number;
      if (item.reviewCount === 1) interval = 1;
      else if (item.reviewCount === 2) interval = 6;
      else interval = Math.round((item.nextReview - item.lastReview) / 86400000 * 2.5);

      item.nextReview = Date.now() + interval * 86400000;
    }

    // 更新掌握度
    item.masteryLevel = Math.min(100, item.masteryLevel + q * 10);
    item.lastReview = Date.now();

    this.vocabularyDB.set(word, item);
  }

  /**
   * 刷新学习上下文
   */
  private refreshContext(): void {
    if (!this.currentContext) return;

    const duration = Math.round((Date.now() - this.currentContext.sessionStats.startTime) / 1000);
    
    this.currentContext = {
      ...this.currentContext,
      sessionStats: {
        ...this.currentContext.sessionStats,
        duration
      }
    };

    this.contextCallbacks.forEach(cb => cb(this.currentContext!));
  }

  /**
   * 启动口语监听
   */
  async startSpeakingPractice(): Promise<void> {
    await this.audioCapturer?.start();
    // 注册音频处理回调
    // 实际应使用语音识别分析发音
  }

  async stopSpeakingPractice(): Promise<void> {
    await this.audioCapturer?.stop();
  }

  onContextChange(callback: (context: LearningContext) => void): void {
    this.contextCallbacks.push(callback);
  }

  getCurrentContext(): LearningContext | null {
    return this.currentContext;
  }

  getVocabularyDB(): Map<string, VocabularyItem> {
    return this.vocabularyDB;
  }

  private async loadVocabularyDB(): Promise<void> {
    // 从本地存储加载词库
    // 简化实现
  }

  destroy(): void {
    clearInterval(this.updateInterval);
    this.pasteboard?.off('contentChanged');
    this.audioCapturer?.release();
  }
}

4.2 沉浸光感学习反馈(LearningLightingController)

光效是学习状态的"可视化延伸",让用户无需看屏幕就能感知学习节奏。

typescript 复制代码
// lighting/LearningLightingController.ets
import { lighting } from '@kit.ArkUI';
import { VocabularyItem } from '../engine/LearningContextEngine';

export class LearningLightingController {
  private currentMode: string = 'normal';

  /**
   * 初始化学习光感
   * 设计哲学:光效应成为学习的"情绪节拍器"
   */
  async init(): Promise<void> {
    if (!lighting.isImmersiveLightSupported()) {
      console.warn('[LearningLight] 设备不支持沉浸光感');
      return;
    }

    await this.setLightEffect({
      type: 'solid',
      position: 'bottom_edge',
      color: '#E0E0E0',
      brightness: 15,
      duration: 0
    });

    console.info('[LearningLight] 学习光感初始化完成');
  }

  /**
   * 根据学习状态更新光效
   */
  async updateByLearning(context: {
    newWordsCount: number;
    reviewCount: number;
    masteryProgress: number;
    sessionCorrectRate: number;
  }): Promise<void> {
    // 新词发现
    if (context.newWordsCount > 0) {
      await this.setNewWordAlert(context.newWordsCount);
      return;
    }

    // 待复习提醒
    if (context.reviewCount > 0) {
      await this.setReviewReminder(context.reviewCount);
      return;
    }

    // 学习进度
    await this.setProgressLighting(context.masteryProgress, context.sessionCorrectRate);
  }

  /**
   * 新词发现光效
   */
  private async setNewWordAlert(count: number): Promise<void> {
    const brightness = Math.min(20 + count * 5, 50);

    await lighting.setImmersiveLight({
      type: 'flashing',
      position: 'bottom_edge',
      color: '#448AFF',
      brightness,
      duration: 1500,
      flashCount: Math.min(count, 3)
    });
  }

  /**
   * 复习提醒光效
   */
  private async setReviewReminder(count: number): Promise<void> {
    await lighting.setImmersiveLight({
      type: 'breathing',
      position: 'bottom_edge',
      color: '#FF9100',
      brightness: 30,
      duration: 0,
      frequency: 2500
    });
  }

  /**
   * 学习进度光效
   */
  private async setProgressLighting(progress: number, correctRate: number): Promise<void> {
    // 根据正确率选择颜色
    let color: string;
    if (correctRate >= 80) color = '#00E676';
    else if (correctRate >= 60) color = '#FFD600';
    else color = '#FF9100';

    // 根据进度调整亮度
    const brightness = 15 + (progress / 100) * 35;

    await lighting.setImmersiveLight({
      type: 'solid',
      position: 'bottom_edge',
      color,
      brightness,
      duration: 0
    });
  }

  /**
   * 词汇掌握确认光效
   */
  async confirmMastery(word: string, quality: number): Promise<void> {
    const colors = ['#FF1744', '#FF9100', '#FFD600', '#69F0AE', '#00E676'];
    const color = colors[quality] || '#00E676';

    await lighting.setImmersiveLight({
      type: 'flashing',
      position: 'bottom_edge',
      color,
      brightness: 40,
      duration: 500,
      flashCount: 1
    });
  }

  /**
   * 学习目标达成庆祝
   */
  async celebrateGoal(): Promise<void> {
    const colors = ['#00E676', '#00B0FF', '#2979FF', '#7C4DFF', '#F50057', '#FF9100'];

    for (const color of colors) {
      await lighting.setImmersiveLight({
        type: 'solid',
        position: 'all_edges',
        color,
        brightness: 50,
        duration: 150
      });
      await new Promise(resolve => setTimeout(resolve, 150));
    }

    await this.reset();
  }

  /**
   * 发音正确反馈
   */
  async pronunciationCorrect(): Promise<void> {
    await lighting.setImmersiveLight({
      type: 'flashing',
      position: 'right_edge',
      color: '#00E676',
      brightness: 40,
      duration: 300,
      flashCount: 1
    });
  }

  /**
   * 发音错误反馈
   */
  async pronunciationIncorrect(): Promise<void> {
    await lighting.setImmersiveLight({
      type: 'flashing',
      position: 'left_edge',
      color: '#FF1744',
      brightness: 40,
      duration: 300,
      flashCount: 2
    });
  }

  /**
   * 专注模式
   */
  async setFocusMode(): Promise<void> {
    await lighting.setImmersiveLight({
      type: 'solid',
      position: 'bottom_edge',
      color: '#4A148C',
      brightness: 10,
      duration: 0
    });
  }

  async reset(): Promise<void> {
    await lighting.resetImmersiveLight();
  }
}

4.3 语言学习智能体引擎(LanguageAgentEngine)

这是系统的"语言大脑",负责翻译、解析、生成学习内容。

typescript 复制代码
// agent/LanguageAgentEngine.ets
import { ai } from '@kit.AiKit';
import { VocabularyItem, LearningScene } from '../engine/LearningContextEngine';

export interface TranslationResult {
  original: string;
  translated: string;
  pronunciation: string;
  partOfSpeech: string;
  definitions: Definition[];
  examples: Example[];
  etymology?: string;
  synonyms: string[];
  antonyms: string[];
}

export interface Definition {
  meaning: string;
  example: string;
  context: string;
}

export interface Example {
  sentence: string;
  translation: string;
  audio?: string;
}

export interface PracticeExercise {
  type: 'flashcard' | 'fill_blank' | 'listen_choose' | 'speak_repeat';
  question: string;
  options?: string[];
  correctAnswer: string;
  hint: string;
}

export class LanguageAgentEngine {
  private agent: ai.AgentSession | null = null;
  private translationCache: Map<string, TranslationResult> = new Map();

  /**
   * 初始化语言智能体
   */
  async init(): Promise<void> {
    const model = await ai.createModel({
      modelId: 'harmonyos-language-v1',
      type: ai.ModelType.LOCAL,
      capabilities: ['translation', 'nlp', 'pronunciation_analysis']
    });

    this.agent = await ai.createAgentSession({
      model: model,
      systemPrompt: `你是一位专业的语言学习助手,精通英语教学与语言学。
        请提供:
        1. 准确的翻译与释义
        2. 词根词缀分析
        3. 地道例句
        4. 同义词/反义词对比
        5. 发音指导(音标+口型提示)
        6. 情境化练习
        
        回答要求:
        - 释义简洁准确
        - 例句贴近实际场景
        - 难度分级清晰
        - 使用中文解释,英文示例`
    });

    console.info('[LangAgent] 语言智能体初始化完成');
  }

  /**
   * 翻译与解析词汇
   */
  async translateAndAnalyze(word: string, context: string): Promise<<TranslationResult> {
    // 检查缓存
    if (this.translationCache.has(word)) {
      return this.translationCache.get(word)!;
    }

    if (!this.agent) {
      return this.fallbackTranslation(word);
    }

    const prompt = `请详细解析以下词汇:
      词汇:${word}
      上下文:${context}
      
      请提供:
      1. 中文释义(分词性)
      2. 音标(英式+美式)
      3. 词根词缀分析
      4. 3个地道例句(含中文翻译)
      5. 5个同义词及区别
      6. 常见搭配`;

    const result = await this.agent.invoke({
      input: { question: prompt },
      options: { maxTokens: 1024, temperature: 0.2 }
    });

    const translation = this.parseTranslationResult(result, word);
    this.translationCache.set(word, translation);

    return translation;
  }

  /**
   * 生成练习
   */
  async generateExercise(item: VocabularyItem, scene: LearningScene): Promise<<PracticeExercise> {
    if (!this.agent) {
      return this.fallbackExercise(item);
    }

    const prompt = `为以下词汇生成${scene}场景的练习:
      词汇:${item.word}
      释义:${item.meaning}
      难度:${item.difficulty}/5
      掌握度:${item.masteryLevel}%
      
      请生成一个适合的练习题。`;

    const result = await this.agent.invoke({
      input: { question: prompt },
      options: { maxTokens: 512, temperature: 0.4 }
    });

    return this.parseExercise(result, item);
  }

  /**
   * 分析发音
   */
  async analyzePronunciation(
    targetWord: string,
    audioData: ArrayBuffer
  ): Promise<<{
    score: number;
    feedback: string;
    correctPhonemes: string[];
    incorrectPhonemes: string[];
  }> {
    if (!this.agent) {
      return { score: 0, feedback: '无法分析', correctPhonemes: [], incorrectPhonemes: [] };
    }

    // 实际应调用语音识别API分析发音
    // 简化实现
    return {
      score: 85,
      feedback: '发音基本正确,注意/θ/音的咬舌位置',
      correctPhonemes: ['s', 'k', 'ɛ', 'dʒ'],
      incorrectPhonemes: []
    };
  }

  /**
   * 生成每日学习报告
   */
  async generateDailyReport(stats: {
    wordsLearned: number;
    wordsReviewed: number;
    correctRate: number;
    studyTime: number;
  }): Promise<<string> {
    const prompt = `生成今日学习报告:
      新学词汇:${stats.wordsLearned}
      复习词汇:${stats.wordsReviewed}
      正确率:${stats.correctRate}%
      学习时长:${stats.studyTime}分钟
      
      请生成一段鼓励性的学习报告(100字以内)。`;

    const result = await this.agent!.invoke({
      input: { question: prompt },
      options: { maxTokens: 256, temperature: 0.6 }
    });

    return result.data?.report || '今日学习完成,继续保持!';
  }

  private parseTranslationResult(result: ai.ModelOutput, word: string): TranslationResult {
    const data = result.data || {};
    
    return {
      original: word,
      translated: data.translated || '',
      pronunciation: data.pronunciation || '',
      partOfSpeech: data.partOfSpeech || '',
      definitions: data.definitions || [],
      examples: data.examples || [],
      etymology: data.etymology,
      synonyms: data.synonyms || [],
      antonyms: data.antonyms || []
    };
  }

  private parseExercise(result: ai.ModelOutput, item: VocabularyItem): PracticeExercise {
    const data = result.data || {};
    
    return {
      type: data.type || 'flashcard',
      question: data.question || `What does "${item.word}" mean?`,
      options: data.options,
      correctAnswer: data.correctAnswer || item.meaning,
      hint: data.hint || `Think about: ${item.context}`
    };
  }

  private fallbackTranslation(word: string): TranslationResult {
    return {
      original: word,
      translated: '翻译服务暂不可用',
      pronunciation: '',
      partOfSpeech: '',
      definitions: [{ meaning: '请稍后重试', example: '', context: '' }],
      examples: [],
      synonyms: [],
      antonyms: []
    };
  }

  private fallbackExercise(item: VocabularyItem): PracticeExercise {
    return {
      type: 'flashcard',
      question: `What is the meaning of "${item.word}"?`,
      correctAnswer: item.meaning,
      hint: `Context: ${item.context}`
    };
  }

  destroy(): void {
    this.agent?.destroy();
  }
}

4.4 悬浮窗学习面板(LearningFloatWindow)

typescript 复制代码
// float/LearningFloatWindow.ets
import { window } from '@kit.ArkUI';
import { emitter } from '@kit.BasicServicesKit';
import { LearningContext, VocabularyItem } from '../engine/LearningContextEngine';
import { TranslationResult, PracticeExercise } from '../agent/LanguageAgentEngine';

export class LearningFloatWindow {
  private floatWin: window.Window | null = null;
  private currentLevel: 'capsule' | 'card' | 'panel' = 'capsule';

  async create(): Promise<void> {
    const option: window.WindowOption = {
      name: 'LanguagePartner',
      windowType: window.WindowType.TYPE_FLOAT,
      ctx: getContext(this)
    };

    this.floatWin = await window.createWindow(getContext(this), option);
    
    // 胶囊形态:显示学习统计
    await this.floatWin.resize({ width: 110, height: 90 });
    await this.floatWin.moveWindowTo({ x: 940, y: 130 });
    await this.floatWin.setWindowTouchable(true);
    await this.floatWin.setUIContent('pages/LearningCapsulePage');
    await this.floatWin.showWindow();
  }

  async expandToCard(word: VocabularyItem, translation: TranslationResult): Promise<void> {
    if (!this.floatWin) return;
    
    this.currentLevel = 'card';
    await this.floatWin.resize({ width: 380, height: 520 });
    await this.floatWin.moveWindowTo({ x: 660, y: 100 });
    await this.floatWin.setUIContent('pages/LearningCardPage');
    
    emitter.emit('showLearningCard', { data: { word, translation } });
  }

  async expandToPanel(context: LearningContext): Promise<void> {
    if (!this.floatWin) return;
    
    this.currentLevel = 'panel';
    await this.floatWin.resize({ width: 460, height: 780 });
    await this.floatWin.moveWindowTo({ x: 560, y: 60 });
    await this.floatWin.setUIContent('pages/LearningPanelPage');
    
    emitter.emit('showLearningPanel', { data: context });
  }

  async collapseToCapsule(): Promise<void> {
    if (!this.floatWin) return;
    
    this.currentLevel = 'capsule';
    await this.floatWin.resize({ width: 110, height: 90 });
    await this.floatWin.moveWindowTo({ x: 940, y: 130 });
    await this.floatWin.setUIContent('pages/LearningCapsulePage');
  }

  destroy(): void {
    this.floatWin?.destroyWindow();
  }
}

4.5 学习胶囊页面(LearningCapsulePage)

typescript 复制代码
// pages/LearningCapsulePage.ets
import { emitter } from '@kit.BasicServicesKit';

@Entry
@Component
struct LearningCapsulePage {
  @State knownWords: number = 0;
  @State newWordsCount: number = 0;
  @State reviewCount: number = 0;
  @State todayLearned: number = 0;
  @State isActive: boolean = false;

  aboutToAppear() {
    emitter.on('updateLearningContext', (event) => {
      const ctx = event.data;
      this.knownWords = ctx?.knownWords || 0;
      this.newWordsCount = ctx?.newWords?.length || 0;
      this.reviewCount = ctx?.reviewQueue?.length || 0;
      this.todayLearned = ctx?.sessionStats?.wordsLearned || 0;
      this.isActive = ctx?.currentScene !== 'idle';
    });
  }

  build() {
    Stack() {
      // 新词发现脉冲
      if (this.newWordsCount > 0) {
        Circle()
          .width(120)
          .height(120)
          .fill('#448AFF')
          .opacity(0.15)
          .animation({
            duration: 1000,
            iterations: -1,
            curve: Curve.EaseInOut,
            playMode: PlayMode.Alternate
          })
      }

      Column() {
        // 今日学习数
        Text(`${this.todayLearned}`)
          .fontSize(26)
          .fontWeight(FontWeight.Bold)
          .fontColor('#2979FF')

        // 词汇统计
        Text(`${this.knownWords}词`)
          .fontSize(11)
          .fontColor('#666')

        // 待复习提示
        if (this.reviewCount > 0) {
          Text(`📋${this.reviewCount}`)
            .fontSize(10)
            .fontColor('#FF9100')
            .backgroundColor('#FFF3E0')
            .padding({ left: 6, right: 6, top: 2, bottom: 2 })
            .borderRadius(8)
            .margin({ top: 2 })
        }
      }
      .width(110)
      .height(90)
      .justifyContent(FlexAlign.Center)
      .backgroundColor('rgba(255, 255, 255, 0.95)')
      .borderRadius(20)
      .shadow({ radius: 12, color: 'rgba(0,0,0,0.12)' })
      .gesture(
        GestureGroup(GestureMode.Sequence,
          TapGesture({ count: 1 })
            .onAction(() => emitter.emit('expandToPanel')),
          LongPressGesture({ duration: 800 })
            .onAction(() => emitter.emit('startQuickReview'))
        )
      )
    }
    .width('100%')
    .height('100%')
    .align(Alignment.Center)
  }
}

4.6 学习卡片页面(LearningCardPage)

typescript 复制代码
// pages/LearningCardPage.ets
import { emitter } from '@kit.BasicServicesKit';
import { VocabularyItem } from '../engine/LearningContextEngine';
import { TranslationResult } from '../agent/LanguageAgentEngine';

@Entry
@Component
struct LearningCardPage {
  @State word: VocabularyItem | null = null;
  @State translation: TranslationResult | null = null;
  @State showAnswer: boolean = false;
  @State selectedQuality: number = -1;

  aboutToAppear() {
    emitter.on('showLearningCard', (event) => {
      this.word = event.data?.word;
      this.translation = event.data?.translation;
      this.showAnswer = false;
      this.selectedQuality = -1;
    });
  }

  build() {
    Column() {
      // 顶部
      Row() {
        Text('📖 词汇卡片')
          .fontSize(16)
          .fontWeight(FontWeight.Bold)
          .layoutWeight(1)
        
        Button('✕')
          .fontSize(14)
          .backgroundColor('transparent')
          .fontColor('#999')
          .onClick(() => emitter.emit('collapseToCapsule'))
      }
      .width('100%')
      .padding(12)

      if (this.word && this.translation) {
        // 单词
        Text(this.word.word)
          .fontSize(32)
          .fontWeight(FontWeight.Bold)
          .fontColor('#333')
          .margin({ top: 8 })

        // 音标
        Text(this.translation.pronunciation)
          .fontSize(14)
          .fontColor('#666')
          .margin({ top: 4 })

        // 播放发音按钮
        Button('🔊')
          .fontSize(20)
          .backgroundColor('#E3F2FD')
          .width(48)
          .height(48)
          .borderRadius(24)
          .margin({ top: 8 })
          .onClick(() => this.playPronunciation())

        // 释义区(可展开)
        if (this.showAnswer) {
          Column() {
            // 词性
            Text(this.translation.partOfSpeech)
              .fontSize(12)
              .fontColor('#999')
              .width('100%')

            // 中文释义
            Text(this.translation.translated)
              .fontSize(16)
              .fontColor('#333')
              .width('100%')
              .margin({ top: 4 })

            // 例句
            Text('例句:')
              .fontSize(12)
              .fontWeight(FontWeight.Medium)
              .fontColor('#666')
              .width('100%')
              .margin({ top: 8 })

            ForEach(this.translation.examples.slice(0, 2), (ex: any) => {
              Column() {
                Text(ex.sentence)
                  .fontSize(13)
                  .fontColor('#333')
                  .width('100%')
                Text(ex.translation)
                  .fontSize(12)
                  .fontColor('#999')
                  .width('100%')
                  .margin({ top: 2 })
              }
              .padding(8)
              .backgroundColor('#f8f9fa')
              .borderRadius(6)
              .margin({ top: 4 })
            })

            // 同义词
            if (this.translation.synonyms.length > 0) {
              Text(`同义词:${this.translation.synonyms.join(', ')}`)
                .fontSize(12)
                .fontColor('#448AFF')
                .width('100%')
                .margin({ top: 8 })
            }
          }
          .width('100%')
          .padding(12)
          .margin({ top: 8 })
        } else {
          // 显示提示
          Button('查看释义')
            .fontSize(14)
            .backgroundColor('#E3F2FD')
            .fontColor('#2979FF')
            .margin({ top: 16 })
            .onClick(() => this.showAnswer = true)
        }

        // 掌握度评分
        if (this.showAnswer) {
          Text('掌握程度?')
            .fontSize(14)
            .fontColor('#666')
            .margin({ top: 16 })

          Row() {
            ForEach([0, 1, 2, 3, 4, 5], (quality: number) => {
              Button(`${quality}`)
                .fontSize(14)
                .backgroundColor(this.selectedQuality === quality ? '#2979FF' : '#f0f0f0')
                .fontColor(this.selectedQuality === quality ? '#FFF' : '#666')
                .width(40)
                .height(40)
                .borderRadius(20)
                .margin({ left: 4, right: 4 })
                .onClick(() => this.rateMastery(quality))
            })
          }
          .margin({ top: 8 })
        }
      }
    }
    .width('100%')
    .height('100%')
    .padding(16)
    .backgroundColor('#FFF')
    .borderRadius(16)
  }

  private playPronunciation() {
    emitter.emit('playPronunciation', { data: { word: this.word?.word } });
  }

  private rateMastery(quality: number) {
    this.selectedQuality = quality;
    emitter.emit('rateMastery', { 
      data: { 
        word: this.word?.word, 
        quality 
      } 
    });
    
    // 延迟收起
    setTimeout(() => {
      emitter.emit('collapseToCapsule');
    }, 500);
  }
}

4.7 主入口与系统集成(Index.ets)

typescript 复制代码
// Index.ets
import { LearningContextEngine, LearningScene } from './engine/LearningContextEngine';
import { LearningLightingController } from './lighting/LearningLightingController';
import { LearningFloatWindow } from './float/LearningFloatWindow';
import { LanguageAgentEngine } from './agent/LanguageAgentEngine';
import { emitter } from '@kit.BasicServicesKit';

@Entry
@Component
struct LanguagePartnerApp {
  private learningEngine: LearningContextEngine = new LearningContextEngine();
  private lightController: LearningLightingController = new LearningLightingController();
  private floatWindow: LearningFloatWindow = new LearningFloatWindow();
  private agentEngine: LanguageAgentEngine = new LanguageAgentEngine();

  aboutToAppear() {
    this.initSystem();
  }

  aboutToDisappear() {
    this.learningEngine.destroy();
    this.lightController.reset();
    this.floatWindow.destroy();
    this.agentEngine.destroy();
  }

  async initSystem() {
    // 1. 初始化沉浸光感
    await this.lightController.init();

    // 2. 初始化悬浮窗
    await this.floatWindow.create();

    // 3. 初始化智能体引擎
    await this.agentEngine.init();

    // 4. 初始化学习引擎
    await this.learningEngine.init();

    // 当学习上下文变化时,更新光效和悬浮窗
    this.learningEngine.onContextChange(async (context) => {
      // 更新光效
      await this.lightController.updateByLearning({
        newWordsCount: context.newWords.length,
        reviewCount: context.reviewQueue.length,
        masteryProgress: context.knownWords > 0 ? 50 : 0,
        sessionCorrectRate: context.sessionStats.correctRate
      });
      
      // 新词自动展示
      if (context.newWords.length > 0 && context.currentScene === LearningScene.READING) {
        const word = context.newWords[0];
        const translation = await this.agentEngine.translateAndAnalyze(word.word, word.context);
        await this.floatWindow.expandToCard(word, translation);
      }
      
      // 更新悬浮窗
      emitter.emit('updateLearningContext', { data: context });
    });

    // 5. 设置事件监听
    this.setupEventListeners();
  }

  private setupEventListeners() {
    emitter.on('expandToPanel', async () => {
      const context = this.learningEngine.getCurrentContext();
      if (context) {
        await this.floatWindow.expandToPanel(context);
      }
    });

    emitter.on('collapseToCapsule', async () => {
      await this.floatWindow.collapseToCapsule();
    });

    emitter.on('startQuickReview', async () => {
      const context = this.learningEngine.getCurrentContext();
      if (context && context.reviewQueue.length > 0) {
        const word = context.reviewQueue[0];
        const translation = await this.agentEngine.translateAndAnalyze(word.word, word.context);
        await this.floatWindow.expandToCard(word, translation);
      }
    });

    emitter.on('playPronunciation', (event) => {
      const word = event.data?.word;
      // 调用TTS播放发音
    });

    emitter.on('rateMastery', (event) => {
      const { word, quality } = event.data || {};
      if (word) {
        this.learningEngine.updateMastery(word, quality);
        this.lightController.confirmMastery(word, quality);
      }
    });
  }

  build() {
    Column() {
      Text('🌍 HarmonyOS语言学习伙伴')
        .fontSize(24)
        .fontWeight(FontWeight.Bold)
        .margin({ bottom: 8 })
      
      Text('AI智能体正在辅助您的语言学习...')
        .fontSize(14)
        .fontColor('#666')
      
      Text('复制英文内容即可自动解析,悬浮窗常驻显示')
        .fontSize(12)
        .fontColor('#999')
        .margin({ top: 4 })
        .textAlign(TextAlign.Center)

      // 学习统计
      Column() {
        Text('📊 今日学习')
          .fontSize(16)
          .fontWeight(FontWeight.Medium)
          .margin({ bottom: 12 })

        Row() {
          Column() {
            Text('12')
              .fontSize(28)
              .fontWeight(FontWeight.Bold)
              .fontColor('#2979FF')
            Text('新学词汇')
              .fontSize(12)
              .fontColor('#999')
          }
          .layoutWeight(1)

          Column() {
            Text('8')
              .fontSize(28)
              .fontWeight(FontWeight.Bold)
              .fontColor('#00C853')
            Text('已掌握')
              .fontSize(12)
              .fontColor('#999')
          }
          .layoutWeight(1)

          Column() {
            Text('5')
              .fontSize(28)
              .fontWeight(FontWeight.Bold)
              .fontColor('#FF9100')
            Text('待复习')
              .fontSize(12)
              .fontColor('#999')
          }
          .layoutWeight(1)
        }
        .width('100%')
      }
      .width('90%')
      .padding(20)
      .backgroundColor('#f8f9fa')
      .borderRadius(12)
      .margin({ top: 32 })

      // 当前状态
      Row() {
        Text('系统状态:')
          .fontSize(14)
          .fontColor('#666')
        
        Text('🟢 学习中')
          .fontSize(14)
          .fontColor('#00C853')
          .fontWeight(FontWeight.Medium)
      }
      .margin({ top: 20 })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

五、配置文件

json 复制代码
// module.json5
{
  "module": {
    "name": "LanguagePartner",
    "type": "entry",
    "description": "鸿蒙智能体语言学习伙伴",
    "mainElement": "EntryAbility",
    "deviceTypes": ["phone", "tablet", "2in1"],
    "pages": "$profile:main_pages",
    "abilities": [
      {
        "name": "EntryAbility",
        "srcEntry": "./ets/entryability/EntryAbility.ets",
        "description": "语言学习伙伴主入口",
        "icon": "$media:layered_image",
        "label": "AI语言伙伴",
        "startWindowIcon": "$media:startIcon",
        "startWindowBackground": "$color:start_window_background",
        "exported": true,
        "skills": [
          {
            "entities": ["entity.system.home"],
            "actions": ["action.system.home"]
          }
        ]
      }
    ],
    "requestPermissions": [
      {
        "name": "ohos.permission.SYSTEM_FLOAT_WINDOW",
        "reason": "需要悬浮窗权限以常驻显示学习状态"
      },
      {
        "name": "ohos.permission.READ_PASTEBOARD",
        "reason": "读取剪贴板内容以检测外语文本"
      },
      {
        "name": "ohos.permission.INTERNET",
        "reason": "连接翻译与智能体服务"
      },
      {
        "name": "ohos.permission.ACCESS_AI_MODEL",
        "reason": "使用端侧AI模型进行语言分析"
      },
      {
        "name": "ohos.permission.MICROPHONE",
        "reason": "支持口语练习与发音分析"
      }
    ]
  }
}

六、效果展示与使用场景

6.1 典型学习场景

场景A:技术文档阅读

开发者小李正在阅读React官方文档,复制"immutable state"到剪贴板。悬浮胶囊边框泛起蓝色脉冲光效,提示发现新词。点击展开词汇卡片,显示"immutable: 不可变的",附带例句"In React, state should be immutable."小李标记为掌握,边框绿色确认光效,该词加入记忆队列。

场景B:碎片时间复习

等电梯时,悬浮窗自动推送"今日待复习5词"。第一个词"reciprocate",小李回忆释义后点击查看答案"回报; reciprocate",选择掌握度4分。边框从琥珀色变为绿色,继续下一个。全部完成后彩虹渐变庆祝。

场景C:口语练习

小李跟读"thorough",AI检测发音将/θ/读成了/s/。左侧边框红色双闪提示,悬浮窗显示咬舌发音口型动画。纠正后右侧边框绿色单闪确认,发音评分从65提升至88。

6.2 光效语义设计

学习状态 光效表现 学习提示
空闲待机 底部灰色微光 等待学习内容
发现新词 底部蓝色脉冲 点击查看释义
复习提醒 底部琥珀呼吸 有待复习词汇
掌握确认 底部绿色单闪 已记录掌握度
发音正确 右侧绿色单闪 发音准确
发音错误 左侧红色双闪 注意纠正
目标达成 彩虹渐变 今日目标完成
专注模式 底部紫色微光 深度学习中

七、性能与隐私优化

7.1 学习数据策略

typescript 复制代码
// 学习数据优化
const learningStrategy = {
  // 缓存策略
  cache: {
    translation: { ttl: 86400000, maxSize: 1000 },  // 翻译缓存1天
    vocabulary: { ttl: Infinity, maxSize: 5000 }     // 词汇永久缓存
  },
  
  // 同步策略
  sync: {
    interval: 300000,  // 5分钟同步一次
    priority: ['mastery', 'review_schedule']  // 优先同步掌握度
  },
  
  // 预加载
  preload: {
    enabled: true,
    nextReviewCount: 10  // 预加载接下来10个复习词
  }
};

7.2 隐私保护

  • 本地优先:词汇库本地存储,学习记录本地分析
  • 脱敏传输:必须同步时仅上传词汇哈希,不上传上下文
  • 用户控制:可随时导出/删除个人学习数据
  • 无痕模式:支持临时学习不记录历史

八、总结与展望

本文展示了如何基于HarmonyOS 6(API 23)的悬浮导航沉浸光感 能力,构建一个鸿蒙智能体驱动的沉浸式语言学习伙伴。与传统语言学习APP不同,它具备三个核心创新:

  1. 情境学习:悬浮窗实时捕获学习内容,无需切换应用即可学习
  2. 光效反馈:通过设备边框光效实现"无屏感知"的学习状态反馈
  3. 智能记忆:基于SM-2算法的间隔重复,在最佳时机推送复习

未来演进方向:

  • 多语言支持:支持日语、韩语、法语等更多语言
  • AR实景学习:摄像头识别实物,悬浮窗显示外语名称
  • 社交学习:学习数据好友排行,互相激励
  • 考试对接:与雅思、托福等考试对接,生成针对性训练

HarmonyOS 6的智能体框架和系统级交互创新,正在让"AI语言伙伴常驻身边"成为现实。对于语言学习者而言,这不仅是一个翻译工具,更是一位24小时在线、懂语境、懂记忆、懂鼓励的智能学习伙伴。


转载自:https://blog.csdn.net/u014727709/article/details/161445047

欢迎 👍点赞✍评论⭐收藏,欢迎指正

相关推荐
意图共鸣2 小时前
意图共鸣科技发布《认知智能白皮书》:从华为“逻辑折叠”看认知架构(CA)的“感知-仲裁”解耦设计
科技·华为·架构
sakiko_2 小时前
Swift学习笔记33-多线程与UI渲染
笔记·学习·swiftui·swift
飞yu流星2 小时前
SSRF学习笔记
笔记·学习
爱喝水的鱼丶2 小时前
SAP-ABAP:条件判断与循环控制语句(7篇) 第三篇:循环基础:for、while、do-while三种循环的差异与适用场景
运维·学习·性能优化·sap·abap·erp
Highcharts.js2 小时前
|Highcharts图表专家智能体+Highcharts GPT +MCP 服务=智能图表开发服务体系
gpt·信息可视化·llm·图表·智能体·highcharts·图表开发
小新同学^O^2 小时前
简单学习 --> llm是怎么训练出来的?
人工智能·深度学习·学习
Swift社区2 小时前
鸿蒙 PC 与 AI Runtime:下一代桌面交互
人工智能·交互·harmonyos
wuxinyan1232 小时前
工业级大模型学习之路028:多智能体系统基础与双智能体协作
人工智能·python·学习
星恒随风3 小时前
从零开始理解 CNN(上):为什么图像任务需要卷积神经网络?
人工智能·笔记·神经网络·学习·cnn