HarmonyOS 6(API 23)实战:基于悬浮导航、沉浸光感与HMAF的“鸿蒙代码导师“——PC端AI智能体沉浸式编程学习系统
2026年,中国开发者规模突破3000万,但传统编程学习平台面临三大痛点:HarmonyOS 6(API 23)的HMAF框架配合**悬浮导航(Float Navigation)与沉浸光感(Immersive Light Effects)**特性,为编程学习带来了革命性解决方案:本文核心亮点:HMAF(Harmony Intelligent Agent Framework)提供四种编排模式,在编程
文章目录

每日一句正能量
耐住寂寞,深耕自己,那些看似不起眼的点滴积累,终会垒成你重新登高的阶梯。
“点滴积累”看似微不足道,但加上时间和持续性,就能发生质变。积累每一步都实实在在,最终支撑你走出低谷、重新攀登。
前言
摘要:2026年,AI编程教育进入"智能体陪伴式学习"时代。HarmonyOS 6(API 23)引入的鸿蒙智能体框架(HMAF)将AI能力下沉至系统层,配合悬浮导航与沉浸光感特性,为PC端编程学习带来了"代码即光效、状态即导航"的全新交互范式。本文将实战开发一款面向HarmonyOS PC的"鸿蒙代码导师"应用,展示如何利用HMAF构建"代码解析-错误诊断-知识推荐-项目实战"四层智能体协作架构,通过悬浮导航实现学习状态实时追踪,基于沉浸光感打造"专注度即氛围"的沉浸体验,以及基于多窗口架构构建浮动代码提示、实时诊断面板和知识图谱的协作学习体验。
一、前言:AI编程教育3.0时代的智能体革命
2026年,中国开发者规模突破3000万,但传统编程学习平台面临三大痛点:
- 反馈滞后:代码报错后,学员需要手动搜索解决方案,平均解决问题时间15分钟
- 知识割裂:语法讲解、实战案例、项目源码分散在不同页面,学习路径不清晰
- 专注分散:IDE、文档、视频教程、答疑社区四个窗口来回切换,注意力严重分散
HarmonyOS 6(API 23)的HMAF框架配合**悬浮导航(Float Navigation)与沉浸光感(Immersive Light Effects)**特性,为编程学习带来了革命性解决方案:
- 智能体实时诊断:HMAF构建的"诊断智能体"可实时分析代码错误,自动给出修复建议,响应延迟降至800ms
- 专注度光效感知:根据学员编码节奏、错误频率、停留时长动态切换环境光色,让学员"看见"自己的专注状态
- 悬浮学习导航:底部悬浮导航实时显示四大智能体运行状态与学习进度徽章,学员无需切换页面即可掌握全局
- PC多窗口协作:主代码编辑器 + 浮动代码提示窗口 + 浮动诊断面板 + 浮动知识图谱的四层架构,通过光效联动实现"一眼全局"
本文核心亮点:
- 四层智能体架构:解析智能体(代码语义分析)、诊断智能体(错误检测修复)、推荐智能体(知识路径推荐)、实战智能体(项目实战指导)协同工作
- 专注度脉搏光效:根据编码节奏(冷启动蓝→平稳绿→深度橙→心流红)动态渲染全屏氛围光
- 悬浮学习导航:底部悬浮页签承载"代码/诊断/知识/实战"四大模块,实时显示智能体状态徽章与专注度脉冲
- 错误警示光效:基于代码错误严重程度,触发不同光效警示(警告黄→错误橙→致命红)
- 多窗口光效同步:主窗口与三个浮动子窗口通过
WindowLightSync实现跨窗口光效联动,焦点感知自动调节
二、核心特性解析与技术选型
2.1 HMAF在编程教育场景中的价值
HMAF(Harmony Intelligent Agent Framework)提供四种编排模式,在编程教育场景中各有妙用:
| 编排模式 | 编程教育应用场景 | 技术实现 |
|---|---|---|
| LLM模式 | 解析智能体自主生成代码注释与讲解 | 基于AST自动调用LLM生成语义解释 |
| 工作流模式 | 诊断智能体按预设流程处理代码错误 | 语法检查→语义分析→修复建议→最佳实践推荐 |
| A2A模式 | 四大智能体间实时协作与任务分发 | 诊断智能体发现知识盲区时,推荐智能体同步推送相关课程 |
| OpenClaw模式 | 学员通过自然语言直接指挥智能体 | “帮我解释一下这段ArkTS代码的@State装饰器” |
2.2 沉浸光感在编程学习中的创新应用
传统编程学习软件采用固定UI,学员难以感知自己的学习状态。HarmonyOS 6的沉浸光感特性带来三种创新:
专注度脉搏光效:根据编码节奏动态调整背景光色与脉冲频率
- 冷启动期(<5分钟):深海蓝,缓慢呼吸(4秒/周期)
- 平稳期(5-30分钟):薄荷绿,平稳律动(2秒/周期)
- 深度期(30-60分钟):活力橙,快速脉冲(1秒/周期)
- 心流期(>60分钟):炽烈红,高频闪烁(0.5秒/周期)
错误警示光效:基于代码错误严重程度实时驱动光效
- 警告级别(Warning):暖黄色光晕从底部升起
- 错误级别(Error):橙色警示光从边缘收缩
- 致命级别(Fatal):红色闪烁光全屏覆盖
知识掌握光效:根据学习进度与测试成绩渲染光效强度
- 掌握度>90%:全屏光效强度100%,配合金色粒子效果
- 掌握度60-90%:光效强度60%,柔和过渡
- 掌握度<60%:光效强度30%,提示学员加强练习
2.3 悬浮导航的学习适配
传统编程学习软件采用顶部固定工具栏,占用宝贵竖屏空间。HarmonyOS 6的悬浮导航特性带来:
- 底部悬浮页签:不遮挡代码编辑器,支持透明度三档调节(55%/70%/85%)
- 智能体状态徽章:每个页签实时显示对应智能体运行状态(空闲/思考/执行/完成/异常)
- 专注度实时徽章:导航栏中央显示当前专注时长与代码质量评分,点击展开详细数据
- 快捷操作入口:长按导航栏唤起快捷菜单,一键切换学习模式/紧急保存/智能体开关
三、项目实战:"鸿蒙代码导师"架构设计
3.1 应用场景与功能规划
面向HarmonyOS PC的编程学习场景,核心功能包括:
| 功能模块 | 技术实现 | 沉浸光感/HMAF应用 |
|---|---|---|
| 主代码编辑器 | TextArea + CodeHighlight |
专注度脉搏光效背景 |
| 悬浮学习导航 | HdsTabs + systemMaterialEffect |
玻璃拟态页签,智能体状态徽章 |
| 解析智能体 | HMAF Agent Framework Kit | 代码语义解析状态光效反馈 |
| 诊断智能体 | HMAF + 静态代码分析 | 错误严重程度光效驱动 |
| 推荐智能体 | HMAF + 知识图谱 | 学习路径光效提示 |
| 实战智能体 | HMAF + 项目模板引擎 | 项目进度光效反馈 |
| 浮动代码提示窗口 | 子窗口 + List |
提示类型色光效同步 |
| 浮动诊断面板 | 子窗口 + HdsNavigation |
错误主题色光效同步 |
| 浮动知识图谱 | 子窗口 + Canvas |
知识节点色光效 |
3.2 技术架构图
┌─────────────────────────────────────────────────────────────┐
│ HarmonyOS 6 PC 主窗口 │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ 沉浸光感层 (AmbientLightLayer) │ │
│ │ 专注度脉搏光效 + 错误警示光效 + 知识掌握光效 │ │
│ └───────────────────────────────────────────────────────┘ │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ 主代码编辑器 (TextArea + CodeHighlight) │ │
│ │ ArkTS代码 + 语法高亮 + 实时诊断 │ │
│ └───────────────────────────────────────────────────────┘ │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ 悬浮学习导航 (FloatNavigation) │ │
│ │ 代码/诊断/知识/实战 页签 + 智能体状态徽章 + 专注度徽章 │ │
│ └───────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
┌─────────────────────┼─────────────────────┐
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ 浮动代码提示 │ │ 浮动诊断面板 │ │ 浮动知识图谱 │
│ (提示+类型色) │ │ (错误+严重色) │ │ (节点+掌握色) │
└───────────────┘ └───────────────┘ └───────────────┘
│
┌─────────────────────┼─────────────────────┐
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ 解析智能体 │ │ 诊断智能体 │ │ 推荐智能体 │
│ (AST语义分析) │ │ (静态分析修复) │ │ (知识图谱推荐) │
└───────────────┘ └───────────────┘ └───────────────┘
│
▼
┌───────────────┐
│ 实战智能体 │
│ (项目模板指导) │
└───────────────┘
四、环境配置与模块依赖
4.1 模块依赖配置
在entry/oh-package.json5中添加以下依赖:
{
"dependencies": {
"@kit.ArkUI": "1.0.0",
"@kit.WindowManagerKit": "1.0.0",
"@kit.SensorServiceKit": "1.0.0",
"@kit.UIDesignKit": "1.0.0",
"@kit.AgentFrameworkKit": "1.0.0",
"@kit.IntentsKit": "1.0.0",
"@kit.CodeAnalysisKit": "1.0.0",
"@kit.KnowledgeGraphKit": "1.0.0"
}
}
4.2 权限声明(module.json5)
{
"module": {
"requestPermissions": [
{
"name": "ohos.permission.INTERNET",
"reason": "$string:internet_permission_reason"
},
{
"name": "ohos.permission.SYSTEM_FLOAT_WINDOW",
"reason": "$string:float_window_permission_reason"
},
{
"name": "ohos.permission.READ_USER_STORAGE",
"reason": "$string:storage_permission_reason"
},
{
"name": "ohos.permission.WRITE_USER_STORAGE",
"reason": "$string:storage_permission_reason"
}
]
}
}
五、核心组件实战
5.1 窗口沉浸配置(EntryAbility.ets)
// entry/src/main/ets/entryability/EntryAbility.ets
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
import { window } from '@kit.WindowManagerKit';
export default class EntryAbility extends UIAbility {
async onWindowStageCreate(windowStage: window.WindowStage): Promise<void> {
const mainWindow = await windowStage.createSubWindow('code_main');
// 启用全屏沉浸模式,隐藏系统标题栏
await mainWindow.setWindowLayoutFullScreen(true);
// 设置窗口背景为透明,允许沉浸光效层透传
await mainWindow.setWindowBackgroundColor('#00000000');
// 加载主页面
windowStage.loadContent('pages/CodeMentorPage', (err) => {
if (err) {
console.error('Failed to load CodeMentorPage:', err.message);
}
});
// 初始化窗口焦点监听,用于光效联动
mainWindow.on('windowFocusChange', (isFocused: boolean) => {
AppStorage.setOrCreate('window_focused', isFocused);
});
}
onWindowStageDestroy(): void {
// 清理窗口资源
}
}
5.2 专注度脉搏光效系统(FocusLightEffect.ets)
// entry/src/main/ets/components/FocusLightEffect.ets
import { HdsNavigation, SystemMaterialEffect } from '@kit.UIDesignKit';
// 学习阶段枚举
export enum LearningPhase {
COLD_START = 'cold_start', // 冷启动 <5分钟
STEADY = 'steady', // 平稳期 5-30分钟
DEEP = 'deep', // 深度期 30-60分钟
FLOW = 'flow' // 心流期 >60分钟
}
// 错误严重程度枚举
export enum ErrorSeverity {
WARNING = 'warning', // 警告
ERROR = 'error', // 错误
FATAL = 'fatal' // 致命
}
// 智能体状态枚举
export enum AgentState {
IDLE = 'idle',
THINKING = 'thinking',
EXECUTING = 'executing',
COMPLETED = 'completed',
ERROR = 'error'
}
@Component
export struct FocusLightEffect {
@Prop focusDuration: number = 0; // 专注时长(分钟)
@Prop errorCount: number = 0; // 当前错误数
@Prop codeQuality: number = 0; // 代码质量评分(0-100)
@State lightIntensity: number = 0.6;
@State pulsePhase: number = 0;
// 学习阶段主题色映射
private phaseColors: Map<LearningPhase, string> = new Map([
[LearningPhase.COLD_START, '#1E3A8A'], // 深海蓝
[LearningPhase.STEADY, '#10B981'], // 薄荷绿
[LearningPhase.DEEP, '#F59E0B'], // 活力橙
[LearningPhase.FLOW, '#EF4444'] // 炽烈红
]);
// 错误严重色映射
private errorColors: Map<ErrorSeverity, string> = new Map([
[ErrorSeverity.WARNING, '#FCD34D'], // 暖黄色
[ErrorSeverity.ERROR, '#F97316'], // 橙色
[ErrorSeverity.FATAL, '#EF4444'] // 红色
]);
// 脉冲周期映射(毫秒)
private pulseDurations: Map<LearningPhase, number> = new Map([
[LearningPhase.COLD_START, 4000],
[LearningPhase.STEADY, 2000],
[LearningPhase.DEEP, 1000],
[LearningPhase.FLOW, 500]
]);
private getCurrentPhase(): LearningPhase {
if (this.focusDuration < 5) return LearningPhase.COLD_START;
if (this.focusDuration < 30) return LearningPhase.STEADY;
if (this.focusDuration < 60) return LearningPhase.DEEP;
return LearningPhase.FLOW;
}
private getThemeColor(): string {
// 如果有错误,优先显示错误色
if (this.errorCount > 0) {
return this.errorColors.get(ErrorSeverity.ERROR) || '#F97316';
}
return this.phaseColors.get(this.getCurrentPhase()) || '#1E3A8A';
}
private getPulseDuration(): number {
return this.pulseDurations.get(this.getCurrentPhase()) || 4000;
}
// 代码质量影响光效强度
private getIntensityByQuality(): number {
if (this.codeQuality > 90) return 1.0;
if (this.codeQuality > 60) return 0.6;
return 0.3;
}
aboutToAppear(): void {
// 启动光效脉冲动画
this.startPulseAnimation();
}
private startPulseAnimation(): void {
setInterval(() => {
this.pulsePhase = this.pulsePhase === 0 ? 1 : 0;
}, this.getPulseDuration() / 2);
}
build() {
Stack() {
// 底层:专注度脉搏光效(大面积模糊光晕)
Column()
.width(800)
.height(800)
.backgroundColor(this.getThemeColor())
.blur(200)
.opacity(this.getIntensityByQuality() * 0.25)
.position({ x: '50%', y: '30%' })
.anchor('50%')
.scale({
x: this.pulsePhase === 0 ? 1.0 : 1.3,
y: this.pulsePhase === 0 ? 1.0 : 1.3
})
.animation({
duration: this.getPulseDuration(),
curve: Curve.EaseInOut,
iterations: -1,
playMode: PlayMode.Alternate
})
// 中层:错误警示光效(边缘收缩)
if (this.errorCount > 0) {
Column()
.width('100%')
.height('100%')
.backgroundColor('transparent')
.border({
width: 4,
color: this.errorColors.get(ErrorSeverity.ERROR) || '#F97316'
})
.opacity(0.3)
.animation({
duration: 1000,
curve: Curve.EaseInOut,
iterations: -1,
playMode: PlayMode.Alternate
})
.borderWidth(this.pulsePhase === 0 ? 4 : 8)
}
// 顶层:代码质量粒子效果(仅在高质量时显示)
if (this.codeQuality > 80) {
this.buildParticleEffect()
}
}
.width('100%')
.height('100%')
.backgroundColor('#050508')
}
@Builder
buildParticleEffect(): void {
ForEach([0, 1, 2, 3, 4], (index: number) => {
Column()
.width(4)
.height(4)
.backgroundColor('#10B981')
.borderRadius(2)
.opacity(0.6)
.position({
x: `${20 + index * 15}%`,
y: `${30 + index * 10}%`
})
.animation({
duration: 1500 + index * 300,
curve: Curve.Linear,
iterations: -1,
playMode: PlayMode.Alternate
})
.translate({
y: this.pulsePhase === 0 ? -20 : -100
})
})
}
}
5.3 HMAF四层智能体调度器(CodeAgentScheduler.ets)
// entry/src/main/ets/agents/CodeAgentScheduler.ets
import { hmaf } from '@kit.AgentFrameworkKit';
import { intents } from '@kit.IntentsKit';
// 智能体类型枚举
export enum AgentType {
PARSER = 'parser', // 解析智能体
DIAGNOSTIC = 'diagnostic', // 诊断智能体
RECOMMENDER = 'recommender', // 推荐智能体
PRACTICE = 'practice' // 实战智能体
}
// 智能体人格色彩映射
export enum AgentPersonality {
PARSER = '#8B5CF6', // 智慧紫
DIAGNOSTIC = '#EF4444', // 诊断红
RECOMMENDER = '#06B6D4', // 推荐青
PRACTICE = '#F59E0B' // 实战橙
}
export class CodeAgentScheduler {
private static instance: CodeAgentScheduler;
private hmafSession: hmaf.AgentSession | null = null;
private intentEngine: intents.IntentEngine | null = null;
// 智能体状态管理
private agentStates: Map<string, AgentState> = new Map([
['parser-1', AgentState.IDLE],
['diagnostic-1', AgentState.IDLE],
['recommender-1', AgentState.IDLE],
['practice-1', AgentState.IDLE]
]);
private constructor() {}
static getInstance(): CodeAgentScheduler {
if (!CodeAgentScheduler.instance) {
CodeAgentScheduler.instance = new CodeAgentScheduler();
}
return CodeAgentScheduler.instance;
}
async initialize(): Promise<void> {
// 初始化HMAF多智能体会话
this.hmafSession = await hmaf.createAgentSession({
mode: hmaf.AgentMode.MULTI_AGENT,
enableDistributed: true,
maxConcurrentAgents: 4
});
// 初始化意图引擎
this.intentEngine = await intents.createIntentEngine({
supportedDomains: ['code_analysis', 'error_diagnosis', 'knowledge_recommendation', 'project_guidance']
});
// 注册四大智能体
await this.registerAgents();
// 启动状态监听
this.startStateMonitoring();
}
private async registerAgents(): Promise<void> {
// 1. 解析智能体:基于AST进行代码语义分析
await this.hmafSession?.registerAgent({
agentId: 'parser-1',
agentType: AgentType.PARSER,
capabilities: ['ast_analysis', 'semantic_extraction', 'code_annotation', 'architecture_explanation'],
modelConfig: {
modelType: 'llm',
temperature: 0.3,
maxTokens: 1024
}
});
// 2. 诊断智能体:静态代码分析与错误修复
await this.hmafSession?.registerAgent({
agentId: 'diagnostic-1',
agentType: AgentType.DIAGNOSTIC,
capabilities: ['syntax_check', 'type_inference', 'error_localization', 'fix_suggestion', 'best_practice_check'],
modelConfig: {
modelType: 'llm',
temperature: 0.1,
maxTokens: 512
}
});
// 3. 推荐智能体:基于知识图谱的学习路径推荐
await this.hmafSession?.registerAgent({
agentId: 'recommender-1',
agentType: AgentType.RECOMMENDER,
capabilities: ['knowledge_gap_analysis', 'learning_path_generation', 'resource_recommendation', 'difficulty_assessment'],
modelConfig: {
modelType: 'llm',
temperature: 0.5,
maxTokens: 512
}
});
// 4. 实战智能体:项目模板与实战指导
await this.hmafSession?.registerAgent({
agentId: 'practice-1',
agentType: AgentType.PRACTICE,
capabilities: ['project_template_generation', 'step_by_step_guidance', 'code_review', 'performance_optimization'],
modelConfig: {
modelType: 'llm',
temperature: 0.4,
maxTokens: 1024
}
});
}
// 解析代码语义
async parseCode(code: string, language: string): Promise<{ ast: object; explanation: string; annotations: string[] }> {
this.updateAgentState('parser-1', AgentState.THINKING);
const result = await this.hmafSession?.sendTask({
targetAgent: 'parser-1',
taskType: 'parse_code',
payload: {
code: code,
language: language, // 'arkts', 'typescript', 'javascript'
includeAst: true,
includeExplanation: true
}
});
this.updateAgentState('parser-1', AgentState.COMPLETED);
return {
ast: result?.ast || {},
explanation: result?.explanation || '',
annotations: result?.annotations || []
};
}
// 诊断代码错误
async diagnoseCode(code: string, filePath: string): Promise<{ errors: CodeError[]; fixes: CodeFix[]; quality: number }> {
this.updateAgentState('diagnostic-1', AgentState.EXECUTING);
const result = await this.hmafSession?.sendTask({
targetAgent: 'diagnostic-1',
taskType: 'diagnose_code',
payload: {
code: code,
filePath: filePath,
framework: 'arkui',
apiLevel: 23
}
});
this.updateAgentState('diagnostic-1', AgentState.COMPLETED);
return {
errors: result?.errors || [],
fixes: result?.fixes || [],
quality: result?.qualityScore || 0
};
}
// 推荐学习路径
async recommendLearningPath(userId: string, currentTopic: string): Promise<{ path: LearningNode[]; resources: Resource[] }> {
this.updateAgentState('recommender-1', AgentState.THINKING);
const result = await this.hmafSession?.sendTask({
targetAgent: 'recommender-1',
taskType: 'generate_learning_path',
payload: {
userId: userId,
currentTopic: currentTopic,
targetLevel: 'advanced',
preferredStyle: 'project_based'
}
});
this.updateAgentState('recommender-1', AgentState.COMPLETED);
return {
path: result?.learningPath || [],
resources: result?.resources || []
};
}
// 生成实战项目
async generatePracticeProject(difficulty: string, topic: string): Promise<{ template: string; steps: string[]; hints: string[] }> {
this.updateAgentState('practice-1', AgentState.THINKING);
const result = await this.hmafSession?.sendTask({
targetAgent: 'practice-1',
taskType: 'generate_project',
payload: {
difficulty: difficulty, // 'beginner', 'intermediate', 'advanced'
topic: topic,
framework: 'arkui',
includeTests: true
}
});
this.updateAgentState('practice-1', AgentState.COMPLETED);
return {
template: result?.projectTemplate || '',
steps: result?.steps || [],
hints: result?.hints || []
};
}
private updateAgentState(agentId: string, state: AgentState): void {
this.agentStates.set(agentId, state);
AppStorage.setOrCreate('agent_state_update', { agentId, state });
}
getAgentState(agentId: string): AgentState {
return this.agentStates.get(agentId) || AgentState.IDLE;
}
private startStateMonitoring(): void {
// 监听智能体状态变化,同步到UI
this.hmafSession?.on('agentStateChange', (event: { agentId: string; state: string }) => {
this.updateAgentState(event.agentId, event.state as AgentState);
});
}
}
// 代码错误类型
export interface CodeError {
line: number;
column: number;
severity: 'warning' | 'error' | 'fatal';
message: string;
code: string;
}
// 代码修复建议
export interface CodeFix {
title: string;
description: string;
replacement: string;
line: number;
}
// 学习节点
export interface LearningNode {
id: string;
title: string;
description: string;
difficulty: number;
estimatedTime: number;
prerequisites: string[];
}
// 学习资源
export interface Resource {
id: string;
title: string;
type: 'article' | 'video' | 'project' | 'quiz';
url: string;
difficulty: number;
}
5.4 悬浮学习导航(CodeFloatNavigation.ets)
// entry/src/main/ets/components/CodeFloatNavigation.ets
import { window } from '@kit.ArkUI';
import { AgentState, AgentType, AgentPersonality } from '../agents/CodeAgentScheduler';
import { LearningPhase } from './FocusLightEffect';
interface NavItem {
id: string;
icon: Resource;
label: string;
page: string;
agentType?: AgentType;
}
@Component
export struct CodeFloatNavigation {
@State currentIndex: number = 0;
@State navTransparency: number = 0.70;
@State isExpanded: boolean = false;
@State bottomAvoidHeight: number = 0;
@State focusDuration: number = 0;
@State codeQuality: number = 0;
@State currentPhase: LearningPhase = LearningPhase.COLD_START;
@State agentStates: Map<string, AgentState> = new Map([
['parser-1', AgentState.IDLE],
['diagnostic-1', AgentState.IDLE],
['recommender-1', AgentState.IDLE],
['practice-1', AgentState.IDLE]
]);
private navItems: NavItem[] = [
{ id: 'code', icon: $r('app.media.ic_code'), label: '代码', page: 'CodePage' },
{ id: 'diagnostic', icon: $r('app.media.ic_bug'), label: '诊断', page: 'DiagnosticPage', agentType: AgentType.DIAGNOSTIC },
{ id: 'knowledge', icon: $r('app.media.ic_book'), label: '知识', page: 'KnowledgePage', agentType: AgentType.RECOMMENDER },
{ id: 'practice', icon: $r('app.media.ic_project'), label: '实战', page: 'PracticePage', agentType: AgentType.PRACTICE },
{ id: 'settings', icon: $r('app.media.ic_settings'), label: '设置', page: 'SettingsPage' }
];
aboutToAppear(): void {
this.getBottomAvoidArea();
// 监听智能体状态更新
AppStorage.watch('agent_state_update', (update: { agentId: string; state: string }) => {
this.agentStates.set(update.agentId, update.state as AgentState);
});
// 监听学习数据
AppStorage.watch('learning_metrics', (metrics: { focusDuration: number; codeQuality: number }) => {
this.focusDuration = metrics.focusDuration;
this.codeQuality = metrics.codeQuality;
this.updateLearningPhase();
});
}
private updateLearningPhase(): void {
if (this.focusDuration < 5) this.currentPhase = LearningPhase.COLD_START;
else if (this.focusDuration < 30) this.currentPhase = LearningPhase.STEADY;
else if (this.focusDuration < 60) this.currentPhase = LearningPhase.DEEP;
else this.currentPhase = LearningPhase.FLOW;
}
private async getBottomAvoidArea(): Promise<void> {
try {
const mainWindow = await window.getLastWindow();
const avoidArea = mainWindow.getWindowAvoidArea(window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR);
this.bottomAvoidHeight = avoidArea.bottomRect.height;
} catch (error) {
console.error('Failed to get avoid area:', error);
}
}
private getAgentStateForNavItem(item: NavItem): AgentState {
if (!item.agentType) return AgentState.IDLE;
const agentIdMap: Record<string, string> = {
[AgentType.PARSER]: 'parser-1',
[AgentType.DIAGNOSTIC]: 'diagnostic-1',
[AgentType.RECOMMENDER]: 'recommender-1',
[AgentType.PRACTICE]: 'practice-1'
};
return this.agentStates.get(agentIdMap[item.agentType]) || AgentState.IDLE;
}
private getPhaseColor(): string {
const colors: Record<LearningPhase, string> = {
[LearningPhase.COLD_START]: '#1E3A8A',
[LearningPhase.STEADY]: '#10B981',
[LearningPhase.DEEP]: '#F59E0B',
[LearningPhase.FLOW]: '#EF4444'
};
return colors[this.currentPhase];
}
private getStateBadgeColor(state: AgentState): string {
const colors: Record<AgentState, string> = {
[AgentState.IDLE]: '#888888',
[AgentState.THINKING]: '#8B5CF6',
[AgentState.EXECUTING]: '#F97316',
[AgentState.COMPLETED]: '#10B981',
[AgentState.ERROR]: '#EF4444'
};
return colors[state] || '#888888';
}
private getStateBadgeAnimation(state: AgentState): object {
switch (state) {
case AgentState.THINKING:
return {
duration: 1500,
curve: Curve.EaseInOut,
iterations: -1,
playMode: PlayMode.Alternate
};
case AgentState.EXECUTING:
return {
duration: 800,
curve: Curve.Linear,
iterations: -1
};
case AgentState.ERROR:
return {
duration: 400,
curve: Curve.EaseInOut,
iterations: -1,
playMode: PlayMode.Alternate
};
default:
return { duration: 0 };
}
}
build() {
Stack({ alignContent: Alignment.Bottom }) {
Column() {
this.contentBuilder()
}
.padding({ bottom: this.bottomAvoidHeight + 90 })
// 悬浮导航容器
Column() {
Stack() {
// 玻璃拟态背景层
Column()
.width('100%')
.height('100%')
.backgroundBlurStyle(BlurStyle.REGULAR)
.opacity(this.navTransparency)
.backdropFilter($r('sys.blur.20'))
// 渐变叠加层
Column()
.width('100%')
.height('100%')
.linearGradient({
direction: GradientDirection.Top,
colors: [
['rgba(255,255,255,0.15)', 0.0],
['rgba(255,255,255,0.05)', 1.0]
]
})
}
.width('100%')
.height('100%')
.borderRadius(28)
.shadow({
radius: 24,
color: 'rgba(0,0,0,0.25)',
offsetX: 0,
offsetY: -6
})
Column() {
// 学习信息栏(展开时显示)
if (this.isExpanded) {
Row() {
Column() {
Text(`${this.focusDuration}分钟`)
.fontSize(13)
.fontColor('#FFFFFF')
.fontWeight(FontWeight.Bold)
Text('专注时长')
.fontSize(10)
.fontColor('rgba(255,255,255,0.6)')
}
.layoutWeight(1)
Column() {
Text(`${this.codeQuality}分`)
.fontSize(13)
.fontColor(this.getQualityColor())
.fontWeight(FontWeight.Bold)
Text('代码质量')
.fontSize(10)
.fontColor('rgba(255,255,255,0.6)')
}
.layoutWeight(1)
Column() {
Text(this.getPhaseLabel())
.fontSize(13)
.fontColor(this.getPhaseColor())
.fontWeight(FontWeight.Bold)
Text('学习阶段')
.fontSize(10)
.fontColor('rgba(255,255,255,0.6)')
}
.layoutWeight(1)
}
.width('100%')
.height(50)
.padding({ left: 16, right: 16 })
.backgroundColor('rgba(0,0,0,0.2)')
.borderRadius({ topLeft: 28, topRight: 28 })
}
// 导航页签
Row() {
ForEach(this.navItems, (item: NavItem, index: number) => {
Column() {
Stack() {
Image(item.icon)
.width(26)
.height(26)
.fillColor(this.currentIndex === index ? this.getPhaseColor() : '#AAAAAA')
// 智能体状态徽章
if (item.agentType && this.getAgentStateForNavItem(item) !== AgentState.IDLE) {
Column()
.width(10)
.height(10)
.backgroundColor(this.getStateBadgeColor(this.getAgentStateForNavItem(item)))
.borderRadius(5)
.position({ x: 20, y: -4 })
.shadow({
radius: 8,
color: this.getStateBadgeColor(this.getAgentStateForNavItem(item)),
offsetX: 0,
offsetY: 0
})
.animation(this.getStateBadgeAnimation(this.getAgentStateForNavItem(item)))
}
}
.width(44)
.height(44)
Text(item.label)
.fontSize(11)
.fontColor(this.currentIndex === index ? this.getPhaseColor() : '#BBBBBB')
.margin({ top: 4 })
}
.layoutWeight(1)
.onClick(() => {
this.currentIndex = index;
this.triggerHapticFeedback();
AppStorage.setOrCreate('nav_page_change', item.page);
})
})
}
.width('100%')
.height(this.isExpanded ? 70 : 80)
.padding({ left: 16, right: 16 })
.justifyContent(FlexAlign.SpaceAround)
// 透明度调节(展开时显示)
if (this.isExpanded) {
Row() {
Text('透明度')
.fontSize(12)
.fontColor('rgba(255,255,255,0.7)')
.margin({ right: 8 })
Slider({
value: this.navTransparency * 100,
min: 55,
max: 85,
step: 15,
style: SliderStyle.InSet
})
.width(120)
.onChange((value: number) => {
this.navTransparency = value / 100;
})
Text(`${Math.round(this.navTransparency * 100)}%`)
.fontSize(12)
.fontColor('rgba(255,255,255,0.7)')
.margin({ left: 8 })
}
.width('100%')
.height(40)
.justifyContent(FlexAlign.Center)
}
}
.width('100%')
.height('100%')
}
.width('92%')
.height(this.isExpanded ? 160 : 80)
.margin({ bottom: this.bottomAvoidHeight + 12, left: '4%', right: '4%' })
.animation({
duration: 350,
curve: Curve.Spring,
iterations: 1
})
.gesture(
LongPressGesture({ duration: 600 })
.onAction(() => {
this.isExpanded = !this.isExpanded;
})
)
}
.width('100%')
.height('100%')
}
private getPhaseLabel(): string {
const labels: Record<LearningPhase, string> = {
[LearningPhase.COLD_START]: '冷启动',
[LearningPhase.STEADY]: '平稳期',
[LearningPhase.DEEP]: '深度期',
[LearningPhase.FLOW]: '心流期'
};
return labels[this.currentPhase];
}
private getQualityColor(): string {
if (this.codeQuality >= 90) return '#10B981';
if (this.codeQuality >= 60) return '#F59E0B';
return '#EF4444';
}
@BuilderParam contentBuilder: () => void = this.defaultContentBuilder;
@Builder
defaultContentBuilder(): void {
Column() {
Text('代码编辑区域')
.fontSize(16)
.fontColor('#999999')
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
private triggerHapticFeedback(): void {
try {
import('@kit.SensorServiceKit').then(sensor => {
sensor.vibrator.startVibration({
type: 'time',
duration: 40
}, { id: 0 });
});
} catch (error) {
console.error('Haptic feedback failed:', error);
}
}
}
5.5 代码诊断面板(DiagnosticPanel.ets)
// entry/src/main/ets/components/DiagnosticPanel.ets
import { CodeAgentScheduler, CodeError, CodeFix } from '../agents/CodeAgentScheduler';
import { ErrorSeverity } from './FocusLightEffect';
@Component
export struct DiagnosticPanel {
@State errorList: CodeError[] = [];
@State fixList: CodeFix[] = [];
@State codeQuality: number = 0;
@State autoFixEnabled: boolean = true;
@State severityFilter: ErrorSeverity | 'all' = 'all';
private scheduler: CodeAgentScheduler = CodeAgentScheduler.getInstance();
aboutToAppear(): void {
// 监听代码变化,实时诊断
AppStorage.watch('code_content', async (code: string) => {
if (code && code.length > 10) {
await this.runDiagnostics(code);
}
});
}
private async runDiagnostics(code: string): Promise<void> {
const result = await this.scheduler.diagnoseCode(code, 'src/pages/Index.ets');
this.errorList = result.errors;
this.fixList = result.fixes;
this.codeQuality = result.quality;
// 同步到全局状态
AppStorage.setOrCreate('learning_metrics', {
focusDuration: AppStorage.get('focus_duration') || 0,
codeQuality: this.codeQuality
});
// 同步错误光效
const hasFatal = this.errorList.some(e => e.severity === 'fatal');
const hasError = this.errorList.some(e => e.severity === 'error');
if (hasFatal) {
AppStorage.setOrCreate('current_error_severity', ErrorSeverity.FATAL);
} else if (hasError) {
AppStorage.setOrCreate('current_error_severity', ErrorSeverity.ERROR);
} else if (this.errorList.length > 0) {
AppStorage.setOrCreate('current_error_severity', ErrorSeverity.WARNING);
} else {
AppStorage.setOrCreate('current_error_severity', null);
}
}
private getSeverityColor(severity: string): string {
const colors: Record<string, string> = {
'warning': '#FCD34D',
'error': '#F97316',
'fatal': '#EF4444'
};
return colors[severity] || '#888888';
}
private getSeverityIcon(severity: string): string {
const icons: Record<string, string> = {
'warning': '⚠️',
'error': '❌',
'fatal': '🔴'
};
return icons[severity] || '💬';
}
build() {
Column() {
// 面板标题栏
Row() {
Text('🔍 代码诊断')
.fontSize(16)
.fontColor('#FFFFFF')
.fontWeight(FontWeight.Bold)
Row({ space: 8 }) {
Toggle({ type: ToggleType.Switch, isOn: this.autoFixEnabled })
.selectedColor('#10B981')
.onChange((isOn: boolean) => {
this.autoFixEnabled = isOn;
})
Text('自动修复')
.fontSize(12)
.fontColor('rgba(255,255,255,0.7)')
}
}
.width('100%')
.height(50)
.padding({ left: 16, right: 16 })
.justifyContent(FlexAlign.SpaceBetween)
// 质量评分环
Stack() {
Circle()
.width(100)
.height(100)
.fill('transparent')
.stroke('rgba(255,255,255,0.1)')
.strokeWidth(10)
Circle()
.width(100)
.height(100)
.fill('transparent')
.stroke(this.getQualityColor())
.strokeWidth(10)
.strokeDashArray([this.codeQuality * 2.8, 280])
.strokeLineCap(LineCapStyle.Round)
.animation({
duration: 1000,
curve: Curve.EaseInOut
})
Text(`${this.codeQuality}`)
.fontSize(24)
.fontColor('#FFFFFF')
.fontWeight(FontWeight.Bold)
}
.width('100%')
.height(140)
.margin({ top: 16, bottom: 16 })
// 严重程度过滤标签
Row({ space: 8 }) {
this.buildFilterChip('全部', 'all');
this.buildFilterChip('警告', ErrorSeverity.WARNING);
this.buildFilterChip('错误', ErrorSeverity.ERROR);
this.buildFilterChip('致命', ErrorSeverity.FATAL);
}
.width('100%')
.height(40)
.padding({ left: 16, right: 16 })
// 错误列表
List() {
ForEach(this.getFilteredErrors(), (error: CodeError) => {
ListItem() {
Column() {
Row() {
Text(`${this.getSeverityIcon(error.severity)} 第${error.line}行`)
.fontSize(12)
.fontColor(this.getSeverityColor(error.severity))
.fontWeight(FontWeight.Medium)
Text(error.code)
.fontSize(10)
.fontColor('rgba(255,255,255,0.4)')
.backgroundColor('rgba(255,255,255,0.1)')
.padding({ left: 6, right: 6, top: 2, bottom: 2 })
.borderRadius(4)
}
.width('100%')
.justifyContent(FlexAlign.SpaceBetween)
Text(error.message)
.fontSize(13)
.fontColor('#FFFFFF')
.margin({ top: 4, bottom: 4 })
.maxLines(2)
.textOverflow({ overflow: TextOverflow.Ellipsis })
// 修复建议
const fix = this.fixList.find(f => f.line === error.line);
if (fix && this.autoFixEnabled) {
Row() {
Text(`💡 ${fix.title}`)
.fontSize(11)
.fontColor('#10B981')
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
Text('应用修复')
.fontSize(11)
.fontColor('#FFFFFF')
.backgroundColor('#10B981')
.padding({ left: 8, right: 8, top: 4, bottom: 4 })
.borderRadius(8)
.onClick(() => {
AppStorage.setOrCreate('apply_fix', fix);
})
}
.width('100%')
.padding(8)
.backgroundColor('rgba(16, 185, 129, 0.1)')
.borderRadius(8)
.margin({ top: 4 })
.justifyContent(FlexAlign.SpaceBetween)
}
}
.width('100%')
.padding(12)
.backgroundColor('rgba(255,255,255,0.05)')
.borderRadius(12)
.margin({ bottom: 8 })
}
})
}
.width('100%')
.layoutWeight(1)
.padding({ left: 12, right: 12 })
.edgeEffect(EdgeEffect.Spring)
}
.width('100%')
.height('100%')
.backgroundColor('rgba(10, 10, 15, 0.95)')
.borderRadius(16)
}
@Builder
buildFilterChip(label: string, value: ErrorSeverity | 'all'): void {
const isSelected = this.severityFilter === value;
Text(label)
.fontSize(11)
.fontColor(isSelected ? '#FFFFFF' : 'rgba(255,255,255,0.6)')
.backgroundColor(isSelected ? 'rgba(255,255,255,0.2)' : 'transparent')
.padding({ left: 12, right: 12, top: 6, bottom: 6 })
.borderRadius(16)
.onClick(() => {
this.severityFilter = value;
})
}
private getFilteredErrors(): CodeError[] {
if (this.severityFilter === 'all') return this.errorList;
return this.errorList.filter(item => item.severity === this.severityFilter);
}
private getQualityColor(): string {
if (this.codeQuality >= 90) return '#10B981';
if (this.codeQuality >= 60) return '#F59E0B';
return '#EF4444';
}
}
5.6 浮动知识图谱窗口(KnowledgeGraphWindow.ets)
// entry/src/main/ets/windows/KnowledgeGraphWindow.ets
import { window } from '@kit.WindowManagerKit';
import { CodeAgentScheduler, LearningNode, Resource } from '../agents/CodeAgentScheduler';
@Component
export struct KnowledgeGraphWindow {
@State learningPath: LearningNode[] = [];
@State resources: Resource[] = [];
@State currentTopic: string = 'ArkTS基础';
@State masteryLevel: number = 0;
private scheduler: CodeAgentScheduler = CodeAgentScheduler.getInstance();
aboutToAppear(): void {
this.loadLearningPath();
}
private async loadLearningPath(): Promise<void> {
const result = await this.scheduler.recommendLearningPath('user_001', this.currentTopic);
this.learningPath = result.path;
this.resources = result.resources;
// 计算掌握度
const completed = this.learningPath.filter(n => n.difficulty <= this.masteryLevel).length;
this.masteryLevel = Math.round((completed / this.learningPath.length) * 100);
}
private getNodeColor(difficulty: number): string {
if (difficulty <= 2) return '#10B981'; // 初级-绿
if (difficulty <= 4) return '#F59E0B'; // 中级-橙
return '#EF4444'; // 高级-红
}
private getNodeStatusColor(node: LearningNode): string {
if (this.masteryLevel >= node.difficulty * 20) return '#10B981';
if (this.masteryLevel >= node.difficulty * 10) return '#F59E0B';
return 'rgba(255,255,255,0.3)';
}
build() {
Column() {
// 标题栏
Row() {
Text('🧠 知识图谱')
.fontSize(16)
.fontColor('#FFFFFF')
.fontWeight(FontWeight.Bold)
Text(`掌握度: ${this.masteryLevel}%`)
.fontSize(12)
.fontColor(this.getMasteryColor())
.backgroundColor(`${this.getMasteryColor()}20`)
.padding({ left: 10, right: 10, top: 4, bottom: 4 })
.borderRadius(12)
}
.width('100%')
.height(50)
.padding({ left: 16, right: 16 })
.justifyContent(FlexAlign.SpaceBetween)
// 学习路径可视化
List() {
ForEach(this.learningPath, (node: LearningNode, index: number) => {
ListItem() {
Row() {
// 节点状态指示器
Stack() {
Circle()
.width(40)
.height(40)
.fill(this.getNodeStatusColor(node))
.shadow({
radius: 10,
color: this.getNodeStatusColor(node),
offsetX: 0,
offsetY: 0
})
Text(`${index + 1}`)
.fontSize(14)
.fontColor('#FFFFFF')
.fontWeight(FontWeight.Bold)
}
Column() {
Text(node.title)
.fontSize(14)
.fontColor('#FFFFFF')
.fontWeight(FontWeight.Medium)
Text(node.description)
.fontSize(11)
.fontColor('rgba(255,255,255,0.5)')
.margin({ top: 4 })
.maxLines(2)
.textOverflow({ overflow: TextOverflow.Ellipsis })
Row({ space: 8 }) {
Text(`难度: ${'⭐'.repeat(node.difficulty)}`)
.fontSize(10)
.fontColor(this.getNodeColor(node.difficulty))
Text(`${node.estimatedTime}分钟`)
.fontSize(10)
.fontColor('rgba(255,255,255,0.4)')
}
.margin({ top: 6 })
}
.layoutWeight(1)
.margin({ left: 12 })
// 学习按钮
Button('学习')
.fontSize(11)
.fontColor('#FFFFFF')
.backgroundColor(this.getNodeStatusColor(node) === '#10B981' ? '#10B981' : '#8B5CF6')
.padding({ left: 12, right: 12, top: 6, bottom: 6 })
.borderRadius(12)
.onClick(() => {
AppStorage.setOrCreate('start_learning', node);
})
}
.width('100%')
.padding(12)
.backgroundColor('rgba(255,255,255,0.05)')
.borderRadius(12)
}
.margin({ bottom: 8 })
})
}
.width('100%')
.layoutWeight(1)
.padding({ left: 12, right: 12 })
// 推荐资源
Column() {
Text('📚 推荐资源')
.fontSize(14)
.fontColor('#FFFFFF')
.fontWeight(FontWeight.Medium)
.margin({ bottom: 8 })
List() {
ForEach(this.resources.slice(0, 3), (resource: Resource) => {
ListItem() {
Row() {
Text(this.getResourceIcon(resource.type))
.fontSize(20)
.margin({ right: 8 })
Column() {
Text(resource.title)
.fontSize(12)
.fontColor('#FFFFFF')
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
Text(`${resource.type} · 难度${resource.difficulty}`)
.fontSize(10)
.fontColor('rgba(255,255,255,0.5)')
}
.layoutWeight(1)
Image($r('app.media.ic_external_link'))
.width(16)
.height(16)
.fillColor('rgba(255,255,255,0.5)')
}
.width('100%')
.padding(8)
.backgroundColor('rgba(255,255,255,0.03)')
.borderRadius(8)
}
.onClick(() => {
// 打开资源链接
})
})
}
.width('100%')
.height(120)
}
.width('100%')
.padding(16)
.backgroundColor('rgba(255,255,255,0.05)')
.borderRadius(12)
.margin({ left: 12, right: 12, top: 12 })
}
.width('100%')
.height('100%')
.backgroundColor('rgba(10, 10, 15, 0.95)')
.borderRadius(16)
}
private getMasteryColor(): string {
if (this.masteryLevel >= 80) return '#10B981';
if (this.masteryLevel >= 50) return '#F59E0B';
return '#EF4444';
}
private getResourceIcon(type: string): string {
const icons: Record<string, string> = {
'article': '📄',
'video': '🎬',
'project': '🔧',
'quiz': '📝'
};
return icons[type] || '📎';
}
}
5.7 多窗口光效同步管理器(WindowLightSync.ets)
// entry/src/main/ets/utils/WindowLightSync.ets
import { window } from '@kit.WindowManagerKit';
export class WindowLightSync {
private static instance: WindowLightSync;
private subWindows: Map<string, window.Window> = new Map();
private currentTheme: string = '#1E3A8A';
private currentIntensity: number = 0.6;
private constructor() {}
static getInstance(): WindowLightSync {
if (!WindowLightSync.instance) {
WindowLightSync.instance = new WindowLightSync();
}
return WindowLightSync.instance;
}
async registerSubWindow(name: string, win: window.Window): Promise<void> {
this.subWindows.set(name, win);
await this.syncLightToWindow(win);
}
async syncGlobalLightEffect(themeColor: string, intensity?: number): Promise<void> {
this.currentTheme = themeColor;
if (intensity !== undefined) {
this.currentIntensity = intensity;
}
for (const [name, win] of this.subWindows) {
await this.syncLightToWindow(win);
}
AppStorage.setOrCreate('global_theme_color', this.currentTheme);
AppStorage.setOrCreate('global_light_intensity', this.currentIntensity);
}
private async syncLightToWindow(win: window.Window): Promise<void> {
try {
await win.setWindowBackgroundColor(`${this.currentTheme}20`);
await win.setWindowShadow({
radius: 20,
color: `${this.currentTheme}40`,
offsetX: 0,
offsetY: 4
});
} catch (error) {
console.error(`Failed to sync light to window:`, error);
}
}
async handleFocusChange(focusedWindowName: string): Promise<void> {
for (const [name, win] of this.subWindows) {
const isFocused = name === focusedWindowName;
const intensity = isFocused ? this.currentIntensity : this.currentIntensity * 0.4;
try {
await win.setWindowBackgroundColor(`${this.currentTheme}${Math.floor(intensity * 255).toString(16).padStart(2, '0')}`);
} catch (error) {
console.error(`Failed to handle focus change:`, error);
}
}
}
async createCodeHintWindow(): Promise<window.Window> {
const hintWindow = await window.createWindow({
name: 'code_hint_float',
windowType: window.WindowType.TYPE_FLOAT,
ctx: getContext()
});
await hintWindow.moveWindowTo(1200, 100);
await hintWindow.resize(320, 500);
await hintWindow.setWindowLayoutFullScreen(true);
await hintWindow.setWindowBackgroundColor('#00000000');
this.registerSubWindow('code_hint', hintWindow);
return hintWindow;
}
async createDiagnosticWindow(): Promise<window.Window> {
const diagnosticWindow = await window.createWindow({
name: 'diagnostic_float',
windowType: window.WindowType.TYPE_FLOAT,
ctx: getContext()
});
await diagnosticWindow.moveWindowTo(50, 100);
await diagnosticWindow.resize(300, 520);
await diagnosticWindow.setWindowLayoutFullScreen(true);
await diagnosticWindow.setWindowBackgroundColor('#00000000');
this.registerSubWindow('diagnostic', diagnosticWindow);
return diagnosticWindow;
}
async createKnowledgeWindow(): Promise<window.Window> {
const knowledgeWindow = await window.createWindow({
name: 'knowledge_float',
windowType: window.WindowType.TYPE_FLOAT,
ctx: getContext()
});
await knowledgeWindow.moveWindowTo(50, 650);
await knowledgeWindow.resize(300, 280);
await knowledgeWindow.setWindowLayoutFullScreen(true);
await knowledgeWindow.setWindowBackgroundColor('#00000000');
this.registerSubWindow('knowledge', knowledgeWindow);
return knowledgeWindow;
}
}
5.8 主页面集成(CodeMentorPage.ets)
// entry/src/main/ets/pages/CodeMentorPage.ets
import { FocusLightEffect, LearningPhase, ErrorSeverity } from '../components/FocusLightEffect';
import { CodeFloatNavigation } from '../components/CodeFloatNavigation';
import { DiagnosticPanel } from '../components/DiagnosticPanel';
import { KnowledgeGraphWindow } from '../windows/KnowledgeGraphWindow';
import { WindowLightSync } from '../utils/WindowLightSync';
import { CodeAgentScheduler } from '../agents/CodeAgentScheduler';
@Entry
@Component
struct CodeMentorPage {
@State currentPage: string = 'CodePage';
@State focusDuration: number = 0;
@State codeQuality: number = 85;
@State currentErrorSeverity: ErrorSeverity | null = null;
@State codeContent: string = '';
@State isLearningStarted: boolean = false;
private windowSync: WindowLightSync = WindowLightSync.getInstance();
private scheduler: CodeAgentScheduler = CodeAgentScheduler.getInstance();
private focusTimer: number = 0;
aboutToAppear(): async () => {
await this.scheduler.initialize();
await this.initializeWindows();
this.startFocusTracking();
this.startMetricsSimulation();
AppStorage.watch('nav_page_change', (page: string) => {
this.currentPage = page;
});
}
private async initializeWindows(): Promise<void> {
await this.windowSync.createCodeHintWindow();
await this.windowSync.createDiagnosticWindow();
await this.windowSync.createKnowledgeWindow();
}
private startFocusTracking(): void {
// 每60秒增加专注时长
this.focusTimer = setInterval(() => {
if (this.isLearningStarted) {
this.focusDuration++;
AppStorage.setOrCreate('focus_duration', this.focusDuration);
AppStorage.setOrCreate('learning_metrics', {
focusDuration: this.focusDuration,
codeQuality: this.codeQuality
});
const phase = this.getCurrentPhase();
const themeColor = this.getPhaseColor(phase);
this.windowSync.syncGlobalLightEffect(themeColor, this.getIntensityByQuality());
}
}, 60000);
}
private startMetricsSimulation(): void {
setInterval(() => {
// 模拟代码质量波动
const fluctuation = Math.floor(Math.random() * 10) - 3;
this.codeQuality = Math.max(30, Math.min(100, this.codeQuality + fluctuation));
AppStorage.setOrCreate('learning_metrics', {
focusDuration: this.focusDuration,
codeQuality: this.codeQuality
});
}, 10000);
}
private getCurrentPhase(): LearningPhase {
if (this.focusDuration < 5) return LearningPhase.COLD_START;
if (this.focusDuration < 30) return LearningPhase.STEADY;
if (this.focusDuration < 60) return LearningPhase.DEEP;
return LearningPhase.FLOW;
}
private getPhaseColor(phase: LearningPhase): string {
const colors: Record<LearningPhase, string> = {
[LearningPhase.COLD_START]: '#1E3A8A',
[LearningPhase.STEADY]: '#10B981',
[LearningPhase.DEEP]: '#F59E0B',
[LearningPhase.FLOW]: '#EF4444'
};
return colors[phase];
}
private getIntensityByQuality(): number {
if (this.codeQuality > 90) return 1.0;
if (this.codeQuality > 60) return 0.6;
return 0.3;
}
build() {
Stack() {
// 底层:沉浸光效层
FocusLightEffect({
focusDuration: this.focusDuration,
errorCount: this.currentErrorSeverity ? 1 : 0,
codeQuality: this.codeQuality
})
// 中层:主内容区域
Column() {
this.buildHeader()
Stack() {
if (this.currentPage === 'CodePage') {
this.buildCodePage()
} else if (this.currentPage === 'DiagnosticPage') {
DiagnosticPanel()
} else if (this.currentPage === 'KnowledgePage') {
KnowledgeGraphWindow()
} else if (this.currentPage === 'PracticePage') {
this.buildPracticePage()
}
}
.layoutWeight(1)
}
.width('100%')
.height('100%')
// 顶层:悬浮导航
CodeFloatNavigation({
contentBuilder: () => {}
})
}
.width('100%')
.height('100%')
.backgroundColor('#050508')
.expandSafeArea(
[SafeAreaType.SYSTEM],
[SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM, SafeAreaEdge.START, SafeAreaEdge.END]
)
}
@Builder
buildHeader(): void {
Row() {
Column() {
Text('💻 鸿蒙代码导师')
.fontSize(20)
.fontColor('#FFFFFF')
.fontWeight(FontWeight.Bold)
Text(`专注时长: ${this.focusDuration}分钟 | 代码质量: ${this.codeQuality}分`)
.fontSize(12)
.fontColor('rgba(255,255,255,0.6)')
.margin({ top: 4 })
}
.alignItems(HorizontalAlign.Start)
Row({ space: 12 }) {
Button(this.isLearningStarted ? '暂停学习' : '开始学习')
.fontSize(13)
.fontColor('#FFFFFF')
.backgroundColor(this.isLearningStarted ? '#F59E0B' : '#10B981')
.padding({ left: 20, right: 20, top: 8, bottom: 8 })
.borderRadius(20)
.onClick(() => {
this.isLearningStarted = !this.isLearningStarted;
if (this.isLearningStarted) {
// 启动解析智能体
this.scheduler.parseCode(this.codeContent, 'arkts');
}
})
Button('智能体面板')
.fontSize(13)
.fontColor('#FFFFFF')
.backgroundColor('rgba(255,255,255,0.1)')
.padding({ left: 16, right: 16, top: 8, bottom: 8 })
.borderRadius(20)
.onClick(() => {
AppStorage.setOrCreate('show_agent_panel', true);
})
}
}
.width('100%')
.height(70)
.padding({ left: 24, right: 24 })
.backgroundBlurStyle(BlurStyle.REGULAR)
.backdropFilter($r('sys.blur.20'))
.border({
width: { bottom: 1 },
color: 'rgba(255,255,255,0.1)'
})
.justifyContent(FlexAlign.SpaceBetween)
}
@Builder
buildCodePage(): void {
Column() {
// 代码编辑器
Stack() {
TextArea({ text: $$this.codeContent })
.width('90%')
.height(400)
.backgroundColor('rgba(255,255,255,0.05)')
.borderRadius(16)
.fontColor('#FFFFFF')
.fontSize(14)
.placeholder('在此输入ArkTS代码...')
.placeholderColor('rgba(255,255,255,0.3)')
.onChange((value: string) => {
this.codeContent = value;
AppStorage.setOrCreate('code_content', value);
})
if (!this.isLearningStarted) {
Column() {
Text('📝')
.fontSize(48)
.margin({ bottom: 16 })
Text('点击"开始学习"启动AI智能体编程导师')
.fontSize(14)
.fontColor('rgba(255,255,255,0.6)')
}
}
}
.width('100%')
.height(420)
.margin({ top: 20, bottom: 20 })
// 快捷代码片段
Row({ space: 12 }) {
this.buildCodeSnippet('@State', '#8B5CF6');
this.buildCodeSnippet('@Builder', '#06B6D4');
this.buildCodeSnippet('@Entry', '#10B981');
this.buildCodeSnippet('Row()', '#F59E0B');
this.buildCodeSnippet('Column()', '#EF4444');
}
.margin({ bottom: 20 })
}
.width('100%')
.height('100%')
}
@Builder
buildCodeSnippet(label: string, color: string): void {
Text(label)
.fontSize(12)
.fontColor(color)
.backgroundColor(`${color}20`)
.padding({ left: 12, right: 12, top: 8, bottom: 8 })
.borderRadius(12)
.border({ width: 1, color: `${color}40` })
.onClick(() => {
this.codeContent += `\n${label}`;
AppStorage.setOrCreate('code_content', this.codeContent);
})
}
@Builder
buildPracticePage(): void {
Column() {
Text('🚀 实战项目')
.fontSize(18)
.fontColor('#FFFFFF')
.fontWeight(FontWeight.Bold)
.margin({ top: 20, bottom: 20 })
List() {
ForEach([
{ title: '待办清单应用', difficulty: 1, time: 30 },
{ title: '天气查询组件', difficulty: 2, time: 45 },
{ title: '音乐播放器', difficulty: 3, time: 60 },
{ title: '电商商品页', difficulty: 4, time: 90 },
{ title: '社交聊天应用', difficulty: 5, time: 120 }
], (project: { title: string; difficulty: number; time: number }) => {
ListItem() {
Row() {
Column() {
Text(project.title)
.fontSize(14)
.fontColor('#FFFFFF')
Text(`难度: ${'⭐'.repeat(project.difficulty)} · ${project.time}分钟`)
.fontSize(11)
.fontColor('rgba(255,255,255,0.5)')
.margin({ top: 4 })
}
.alignItems(HorizontalAlign.Start)
.layoutWeight(1)
Button('开始')
.fontSize(12)
.fontColor('#FFFFFF')
.backgroundColor('#8B5CF6')
.padding({ left: 16, right: 16, top: 6, bottom: 6 })
.borderRadius(12)
.onClick(() => {
this.scheduler.generatePracticeProject(
project.difficulty <= 2 ? 'beginner' : project.difficulty <= 4 ? 'intermediate' : 'advanced',
project.title
);
})
}
.width('100%')
.padding(16)
.backgroundColor('rgba(255,255,255,0.05)')
.borderRadius(12)
}
.margin({ bottom: 12 })
})
}
.width('90%')
.layoutWeight(1)
}
.width('100%')
.height('100%')
}
}
六、关键技术总结
6.1 HMAF编程教育智能体开发清单
| 技术点 | API/方法 | 应用场景 |
|---|---|---|
| 智能体会话创建 | hmaf.createAgentSession({ mode: MULTI_AGENT }) |
四层智能体协同教学 |
| 意图解析 | intents.createIntentEngine({ supportedDomains }) |
学员问题意图识别 |
| 任务分发 | hmafSession.sendTask({ targetAgent, taskType }) |
智能体间教学任务调度 |
| 状态监听 | AppStorage 全局状态回调 |
跨组件学习状态同步 |
| 分布式协同 | enableDistributed: true |
多设备学习协作 |
| LLM代码解析 | modelType: 'llm' |
解析智能体生成代码注释 |
| 静态分析 | modelType: 'classification' |
诊断智能体检测代码错误 |
| 知识图谱 | modelType: 'llm' |
推荐智能体生成学习路径 |
6.2 沉浸光感实现清单
| 技术点 | API/方法 | 应用场景 |
|---|---|---|
| 系统材质效果 | systemMaterialEffect: SystemMaterialEffect.IMMERSIVE |
标题栏沉浸效果 |
| 背景模糊 | backgroundBlurStyle(BlurStyle.REGULAR) |
悬浮导航玻璃拟态 |
| 背景滤镜 | backdropFilter($r('sys.blur.20')) |
精细模糊控制 |
| 安全区扩展 | expandSafeArea([SafeAreaType.SYSTEM], [...]) |
全屏沉浸布局 |
| 窗口沉浸 | setWindowLayoutFullScreen(true) |
无边框模式 |
| 光效动画 | animation({ duration, iterations: -1 }) |
专注度脉搏呼吸灯 |
| 动态透明度 | backgroundOpacity |
焦点感知降级 |
| 窗口阴影 | setWindowShadow({ radius, color }) |
跨窗口光效联动 |
6.3 学习状态光效映射
| 学习阶段 | 专注时长 | 主题色 | 脉冲周期 | 光效强度 |
|---|---|---|---|---|
| 冷启动 | <5分钟 | 深海蓝 #1E3A8A | 4秒 | 30% |
| 平稳期 | 5-30分钟 | 薄荷绿 #10B981 | 2秒 | 60% |
| 深度期 | 30-60分钟 | 活力橙 #F59E0B | 1秒 | 80% |
| 心流期 | >60分钟 | 炽烈红 #EF4444 | 0.5秒 | 100% |
6.4 智能体状态徽章动画
| 智能体状态 | 徽章颜色 | 动画效果 | 教学含义 |
|---|---|---|---|
| 空闲 | #888888 | 静态 | 智能体待命 |
| 思考中 | #8B5CF6 | 呼吸脉冲 | LLM分析代码中 |
| 执行中 | #F97316 | 旋转进度 | 诊断/推荐处理中 |
| 已完成 | #10B981 | 静态 | 任务执行成功 |
| 异常 | #EF4444 | 快速闪烁 | 诊断发现严重错误 |
6.5 性能优化建议
- 光效渲染优化:使用
willChange: true标记频繁变化的动画层,避免全量重绘 - 智能体并发控制:通过
maxConcurrentAgents: 4限制并发,防止资源争抢 - 代码编辑器虚拟化:当代码超过1000行时,使用虚拟滚动
- 窗口管理:子窗口使用
TYPE_FLOAT类型,避免创建过多独立进程 - 诊断节流:代码诊断频率控制在5秒/次,避免频繁分析
七、总结与展望
本文基于HarmonyOS 6(API 23)的HMAF智能体框架、悬浮导航与沉浸光感特性,构建了一套面向PC端编程学习的"鸿蒙代码导师"系统。核心创新点包括:
- 四层智能体协作架构:解析、诊断、推荐、实战四大智能体通过HMAF的A2A模式实时协作,将学员从重复性搜索中解放出来
- 专注度脉搏光效系统:基于实时专注时长与代码质量的动态光效渲染,让学员"看见"自己的学习状态
- 悬浮学习导航:底部玻璃拟态导航承载四大模块,智能体状态徽章实时反馈,学习信息一键展开
- 多窗口光效联动:主窗口与三个浮动子窗口通过
WindowLightSync实现跨窗口光效同步,焦点感知自动调节 - 错误警示光效:基于代码错误严重程度,触发不同光效警示,帮助学员快速定位问题
随着HarmonyOS生态的持续发展,编程教育智能体将向着"数字人导师"“多模态交互”"跨设备学习协作"等方向演进。HMAF框架的分布式能力与HarmonyOS的跨端协同特性,将为编程教育带来"一机学全局、多屏协同练"的全新体验。
转载自:https://blog.csdn.net/u014727709/article/details/161227792
欢迎 👍点赞✍评论⭐收藏,欢迎指正
更多推荐



所有评论(0)