文章目录
-
- 每日一句正能量
- 一、前言:当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不同,它具备三个核心创新:
- 情境学习:悬浮窗实时捕获学习内容,无需切换应用即可学习
- 光效反馈:通过设备边框光效实现"无屏感知"的学习状态反馈
- 智能记忆:基于SM-2算法的间隔重复,在最佳时机推送复习
未来演进方向:
- 多语言支持:支持日语、韩语、法语等更多语言
- AR实景学习:摄像头识别实物,悬浮窗显示外语名称
- 社交学习:学习数据好友排行,互相激励
- 考试对接:与雅思、托福等考试对接,生成针对性训练
HarmonyOS 6的智能体框架和系统级交互创新,正在让"AI语言伙伴常驻身边"成为现实。对于语言学习者而言,这不仅是一个翻译工具,更是一位24小时在线、懂语境、懂记忆、懂鼓励的智能学习伙伴。
转载自:https://blog.csdn.net/u014727709/article/details/161445047
欢迎 👍点赞✍评论⭐收藏,欢迎指正