文章目录
-
- 每日一句正能量
- 前言
- 一、前言:知识图谱构建的交互范式革新
- 二、技术架构与核心亮点
-
- [2.1 系统架构设计](#2.1 系统架构设计)
- [2.2 核心亮点预览](#2.2 核心亮点预览)
- 三、环境准备与项目搭建
-
- [3.1 开发环境](#3.1 开发环境)
- [3.2 模块配置(module.json5)](#3.2 模块配置(module.json5))
- 四、核心代码实战
-
- [4.1 沉浸光感主题系统:实体类型感知光效](#4.1 沉浸光感主题系统:实体类型感知光效)
- [4.2 悬浮导航:图谱模式实时切换与关系徽章](#4.2 悬浮导航:图谱模式实时切换与关系徽章)
- [4.3 HMAF四层智能体协作引擎](#4.3 HMAF四层智能体协作引擎)
- [4.4 主图谱画布:Canvas 2D + 动态光效渲染](#4.4 主图谱画布:Canvas 2D + 动态光效渲染)
- [4.5 浮动实体属性面板:多窗口光效联动](#4.5 浮动实体属性面板:多窗口光效联动)
- [4.6 入口页面与窗口配置](#4.6 入口页面与窗口配置)
- 五、关键技术总结
-
- [5.1 HMAF智能体协作开发清单](#5.1 HMAF智能体协作开发清单)
- [5.2 沉浸光感实现清单](#5.2 沉浸光感实现清单)
- [5.3 悬浮导航适配要点](#5.3 悬浮导航适配要点)
- 六、运行效果展示
-
- [6.1 浏览模式 - 人物实体光效](#6.1 浏览模式 - 人物实体光效)
- [6.2 编辑模式 - 组织实体光效](#6.2 编辑模式 - 组织实体光效)
- [6.3 推理模式 - 概念实体光效](#6.3 推理模式 - 概念实体光效)
- [6.4 问答模式 - 多类型光效混合](#6.4 问答模式 - 多类型光效混合)
- 七、总结与展望

每日一句正能量
"顺境教会我们珍惜,逆境教会我们成长,欢喜让我们感受温暖,伤痛让我们学会坚强。"
不否认顺逆境、欢喜伤痛的存在,但拒绝把它们分成"好的"和"坏的"。每一极都附带一份礼物------顺境不是用来懈怠的,而是用来练习珍惜;逆境不是惩罚,而是成长的私教。允许一切发生,并从中萃取意义。
前言
摘要:2026年,知识图谱正从"静态数据仓库"跃升为"动态智能体协作网络"。HarmonyOS 6(API 23)引入的鸿蒙智能体框架(HMAF)将AI能力下沉至系统层,配合悬浮导航与沉浸光感特性,为PC端知识图谱构建带来了"实体即光效、关系即导航"的全新交互范式。本文将实战开发一款面向HarmonyOS PC的"图谱智脑"应用,展示如何利用HMAF构建"实体抽取-关系推理-图谱可视化-知识问答"四层智能体协作架构,通过悬浮导航实现图谱模式实时切换,基于沉浸光感打造"知识密度即氛围"的沉浸体验,以及基于多窗口架构构建浮动实体详情、关系面板和推理路径窗口的协作构建体验。
一、前言:知识图谱构建的交互范式革新
2026年,大语言模型与知识图谱的深度融合催生了"动态知识网络"的新范式。传统的知识图谱工具(如Neo4j Browser、Protégé)往往采用固定的侧边栏导航和扁平的节点展示,在HarmonyOS PC的大屏环境下缺乏空间沉浸感和操作直观性。开发者需要在海量实体与关系中进行高频切换,传统界面已无法满足"所见即所得"的构建需求。
HarmonyOS 6(API 23)引入的**悬浮导航(Float Navigation)与沉浸光感(Immersive Light Effects)**特性,配合HMAF智能体框架,为知识图谱构建带来了"实体即氛围、推理即光效"的全新可能。本文将实战开发一款"图谱智脑"应用,核心创新在于:
- 实体类型光效:根据实体类型(人物/组织/地点/事件/概念)动态切换环境光色与节点光晕
- 关系强度导航:底部悬浮页签显示关系类型徽章,支持图谱模式(浏览/编辑/推理/问答)实时切换
- HMAF四层协作:实体抽取Agent、关系推理Agent、可视化Agent、问答Agent协同工作
- 多窗口知识协作:主图谱画布 + 浮动实体属性面板 + 浮动关系编辑器 + 浮动推理路径窗口的光效联动
- 知识密度沉浸感知:通过Intents Kit实时理解用户查询意图,自动调整界面光效与导航形态
二、技术架构与核心亮点
2.1 系统架构设计
┌─────────────────────────────────────────────────────────┐
│ 图谱智脑 - 应用层 │
├─────────────┬─────────────┬─────────────┬──────────────┤
│ 实体抽取Agent │ 关系推理Agent │ 可视化Agent │ 问答Agent │
├─────────────┴─────────────┴─────────────┴──────────────┤
│ HMAF 鸿蒙智能体框架(API 23) │
├─────────────────────────────────────────────────────────┤
│ 悬浮导航(Float Navigation) │ 沉浸光感(Immersive Light) │
├─────────────────────────────────────────────────────────┤
│ ArkUI / ArkTS / Canvas 2D │
├─────────────────────────────────────────────────────────┤
│ HarmonyOS 6.1.0 (API 23) PC端 │
└─────────────────────────────────────────────────────────┘
2.2 核心亮点预览
| 技术特性 | 实现方式 | 用户体验 |
|---|---|---|
| 实体类型光效 | systemMaterialEffect + 动态主题色 |
人物实体暖橙光、组织实体冷蓝光、地点实体翠绿光、事件实体紫红光、概念实体银白光 |
| 关系强度导航 | HdsTabs 悬浮样式 + 实时徽章 |
强弱关系用不同透明度与脉冲节奏区分 |
| HMAF四层协作 | Agent Framework Kit 多Agent会话 |
四个智能体并行处理,结果实时汇聚到图谱画布 |
| 多窗口光效联动 | AppStorage 全局状态 + WindowManager |
主窗口聚焦时环境光增强,浮动窗口失焦时自动柔化 |
| 知识密度感知 | Intents Kit 意图解析 + 光效映射 |
查询"爱因斯坦相对论"时自动切换为学术蓝调光效 |
三、环境准备与项目搭建
3.1 开发环境
- DevEco Studio: 5.0.3.900 及以上版本
- HarmonyOS SDK: API 23(6.1.0 及以上)
- 目标设备: HarmonyOS PC(2K/4K 大屏优先)
- 依赖库 :
@kit.UIDesignKit、@kit.AgentFrameworkKit、@kit.IntentsKit、@kit.WindowManagerKit
3.2 模块配置(module.json5)
json
{
"module": {
"name": "entry",
"type": "entry",
"description": "图谱智脑 - AI智能体知识图谱构建工作台",
"mainElement": "EntryAbility",
"deviceTypes": ["2in1"],
"abilities": [
{
"name": "EntryAbility",
"srcEntry": "./ets/entryability/EntryAbility.ets",
"description": "主图谱画布窗口",
"icon": "$media:icon",
"label": "$string:EntryAbility_label",
"startWindowIcon": "$media:startIcon",
"startWindowBackground": "$color:start_window_background",
"exported": true,
"skills": [
{
"actions": ["action.system.home"],
"entities": ["entity.system.home"]
}
]
},
{
"name": "EntityPanelAbility",
"srcEntry": "./ets/entityability/EntityPanelAbility.ets",
"description": "浮动实体属性面板",
"launchType": "multiton"
},
{
"name": "RelationEditorAbility",
"srcEntry": "./ets/relationability/RelationEditorAbility.ets",
"description": "浮动关系编辑器",
"launchType": "multiton"
},
{
"name": "ReasoningPathAbility",
"srcEntry": "./ets/reasoningability/ReasoningPathAbility.ets",
"description": "浮动推理路径窗口",
"launchType": "multiton"
}
],
"requestPermissions": [
{ "name": "ohos.permission.INTERNET" },
{ "name": "ohos.permission.GET_NETWORK_INFO" }
]
}
}
四、核心代码实战
4.1 沉浸光感主题系统:实体类型感知光效
代码亮点 :本模块实现了"实体类型即光效"的沉浸感知系统。通过EntityType枚举定义五种实体类型的专属光效人格,利用systemMaterialEffect为标题栏和导航组件注入物理光照级的光晕效果,结合Canvas绘制动态呼吸光背景,实现知识图谱的"氛围即内容"体验。
typescript
// entry/src/main/ets/theme/KnowledgeLightTheme.ets
import { hdsMaterial, SystemMaterialEffect } from '@kit.UIDesignKit';
/**
* 实体类型枚举 - 每种类型对应专属光效人格
*/
export enum EntityType {
PERSON = 'person', // 人物 - 智慧暖橙
ORGANIZATION = 'org', // 组织 - 信任冷蓝
LOCATION = 'location', // 地点 - 生机翠绿
EVENT = 'event', // 事件 - 激情紫红
CONCEPT = 'concept' // 概念 - 理性银白
}
/**
* 光效配置接口
*/
export interface LightEffectConfig {
primaryColor: string; // 主色调
ambientColor: string; // 环境光色
glowColor: string; // 光晕色
pulseSpeed: number; // 脉冲速度(ms)
materialEffect: SystemMaterialEffect; // 系统材质效果
}
/**
* 知识光效主题管理器
* 核心创新:根据当前聚焦实体类型,动态切换全局光效氛围
*/
export class KnowledgeLightTheme {
// 五种实体类型的光效配置
private static readonly LIGHT_MAP: Record<EntityType, LightEffectConfig> = {
[EntityType.PERSON]: {
primaryColor: '#FF8C42', // 暖橙
ambientColor: '#FFF5EB', // 淡橙环境
glowColor: '#FFB380', // 橙光晕
pulseSpeed: 3000, // 温和脉冲
materialEffect: SystemMaterialEffect.IMMERSIVE
},
[EntityType.ORGANIZATION]: {
primaryColor: '#4A90E2', // 冷蓝
ambientColor: '#EBF5FF', // 淡蓝环境
glowColor: '#80B8FF', // 蓝光晕
pulseSpeed: 2500, // 稳定脉冲
materialEffect: SystemMaterialEffect.IMMERSIVE
},
[EntityType.LOCATION]: {
primaryColor: '#50C878', // 翠绿
ambientColor: '#EBFFF2', // 淡绿环境
glowColor: '#80E6A0', // 绿光晕
pulseSpeed: 2800, // 自然脉冲
materialEffect: SystemMaterialEffect.IMMERSIVE
},
[EntityType.EVENT]: {
primaryColor: '#E74C3C', // 紫红
ambientColor: '#FFEBEB', // 淡红环境
glowColor: '#FF8080', // 红光晕
pulseSpeed: 2000, // 急促脉冲
materialEffect: SystemMaterialEffect.IMMERSIVE
},
[EntityType.CONCEPT]: {
primaryColor: '#B8B8B8', // 银白
ambientColor: '#F5F5F5', // 灰白环境
glowColor: '#D0D0D0', // 银光晕
pulseSpeed: 3500, // 缓慢脉冲
materialEffect: SystemMaterialEffect.IMMERSIVE
}
};
// 当前主题状态(全局共享)
@StorageLink('currentEntityType') currentType: EntityType = EntityType.CONCEPT;
@StorageLink('ambientLightColor') ambientColor: string = '#F5F5F5';
@StorageLink('primaryLightColor') primaryColor: string = '#B8B8B8';
/**
* 切换实体类型光效
* @param type 实体类型
*/
public switchEntityLight(type: EntityType): void {
const config = KnowledgeLightTheme.LIGHT_MAP[type];
this.currentType = type;
this.ambientColor = config.ambientColor;
this.primaryColor = config.primaryColor;
// 触发全局光效同步事件
AppStorage.setOrCreate('lightEffectChanged', Date.now());
}
/**
* 获取当前光效配置
*/
public getCurrentConfig(): LightEffectConfig {
return KnowledgeLightTheme.LIGHT_MAP[this.currentType];
}
/**
* 获取HdsNavigation的系统材质配置
* 用于标题栏的沉浸光感效果
*/
public getNavigationMaterial(): object {
const config = this.getCurrentConfig();
return {
systemMaterialEffect: {
materialType: hdsMaterial.MaterialType.ADAPTIVE,
materialLevel: hdsMaterial.MaterialLevel.ADAPTIVE,
effect: config.materialEffect
}
};
}
}
// 导出单例
export const knowledgeTheme = new KnowledgeLightTheme();
4.2 悬浮导航:图谱模式实时切换与关系徽章
代码亮点 :本模块实现了"关系即导航"的悬浮页签系统。底部悬浮导航不仅承载页面切换,更实时显示当前图谱模式徽章(浏览模式/编辑模式/推理模式/问答模式)和关系类型统计。采用HdsTabs悬浮样式配合systemMaterialEffect实现玻璃拟态+沉浸光感的双重效果,支持透明度三档调节,最大化图谱画布区域。
typescript
// entry/src/main/ets/components/FloatingGraphNav.ets
import { HdsTabs, HdsTabsController, hdsMaterial } from '@kit.UIDesignKit';
import { SymbolGlyphModifier } from '@kit.ArkUI';
import { knowledgeTheme, EntityType } from '../theme/KnowledgeLightTheme';
/**
* 图谱模式枚举
*/
export enum GraphMode {
BROWSE = 'browse', // 浏览模式 - 紫光徽章
EDIT = 'edit', // 编辑模式 - 蓝光徽章
REASONING = 'reasoning', // 推理模式 - 青光徽章
QA = 'qa' // 问答模式 - 粉光徽章
}
/**
* 关系类型统计接口
*/
export interface RelationStats {
strongRelations: number; // 强关系数量
weakRelations: number; // 弱关系数量
inferredRelations: number; // 推理关系数量
}
@Component
export struct FloatingGraphNav {
@StorageLink('currentGraphMode') currentMode: GraphMode = GraphMode.BROWSE;
@StorageLink('currentEntityType') currentType: EntityType = EntityType.CONCEPT;
@StorageLink('navTransparency') navTransparency: number = 0.7; // 透明度 0.3-1.0
@State relationStats: RelationStats = { strongRelations: 0, weakRelations: 0, inferredRelations: 0 };
private hdsTabController: HdsTabsController = new HdsTabsController();
// 模式对应的光效配置
private readonly MODE_LIGHT_MAP: Record<<GraphMode, { color: string; icon: Resource }> = {
[GraphMode.BROWSE]: { color: '#9B59B6', icon: $r('app.media.icon_browse') },
[GraphMode.EDIT]: { color: '#3498DB', icon: $r('app.media.icon_edit') },
[GraphMode.REASONING]: { color: '#1ABC9C', icon: $r('app.media.icon_reasoning') },
[GraphMode.QA]: { color: '#E91E63', icon: $r('app.media.icon_qa') }
};
aboutToAppear(): void {
// 监听关系统计变化
AppStorage.link('relationStats').onChange((value: RelationStats) => {
this.relationStats = value;
});
}
build() {
Column() {
// 模式徽章指示器
this.ModeBadgeIndicator()
// HdsTabs 悬浮导航
HdsTabs({
controller: this.hdsTabController,
barPosition: BarPosition.End
}) {
// 浏览模式页签
TabContent() {
this.BrowseModeContent()
}
.tabBar(this.buildTabBar('浏览', GraphMode.BROWSE, this.relationStats.strongRelations))
// 编辑模式页签
TabContent() {
this.EditModeContent()
}
.tabBar(this.buildTabBar('编辑', GraphMode.EDIT, this.relationStats.weakRelations))
// 推理模式页签
TabContent() {
this.ReasoningModeContent()
}
.tabBar(this.buildTabBar('推理', GraphMode.REASONING, this.relationStats.inferredRelations))
// 问答模式页签
TabContent() {
this.QAModeContent()
}
.tabBar(this.buildTabBar('问答', GraphMode.QA, 0))
}
.width('96%')
.height(72)
.backgroundColor(`rgba(255, 255, 255, ${this.navTransparency})`)
.borderRadius(20)
.shadow({
radius: 16,
color: 'rgba(0, 0, 0, 0.12)',
offsetX: 0,
offsetY: 4
})
// 核心:沉浸光感材质配置
.barFloatingStyle({
barBottomMargin: 16,
gradientMask: {
maskColor: '#66F1F3F5',
maskHeight: 92
},
systemMaterialEffect: {
materialType: hdsMaterial.MaterialType.ADAPTIVE,
materialLevel: hdsMaterial.MaterialLevel.ADAPTIVE
}
})
// 动态光效边框
.border({
width: 1,
color: this.MODE_LIGHT_MAP[this.currentMode].color + '33',
radius: 20
})
}
.width('100%')
.padding({ bottom: 12 })
}
/**
* 构建带徽章的页签
*/
@Builder
buildTabBar(title: string, mode: GraphMode, badgeCount: number): void {
Column() {
Stack() {
// 图标
Image(this.MODE_LIGHT_MAP[mode].icon)
.width(24)
.height(24)
.fillColor(this.currentMode === mode ? this.MODE_LIGHT_MAP[mode].color : '#666666')
// 关系数量徽章
if (badgeCount > 0) {
Text(badgeCount.toString())
.fontSize(10)
.fontColor('#FFFFFF')
.backgroundColor(this.MODE_LIGHT_MAP[mode].color)
.borderRadius(8)
.padding({ left: 4, right: 4 })
.position({ x: 16, y: -6 })
}
}
.width(32)
.height(32)
Text(title)
.fontSize(12)
.fontColor(this.currentMode === mode ? this.MODE_LIGHT_MAP[mode].color : '#999999')
.margin({ top: 4 })
}
.width('100%')
.onClick(() => {
this.currentMode = mode;
// 切换模式时触发光效同步
AppStorage.setOrCreate('graphModeChanged', mode);
})
}
/**
* 模式徽章指示器 - 顶部脉冲光条
*/
@Builder
ModeBadgeIndicator(): void {
Row() {
// 当前模式脉冲光条
Row()
.width(40)
.height(3)
.backgroundColor(this.MODE_LIGHT_MAP[this.currentMode].color)
.borderRadius(2)
.animation({
duration: 2000,
iterations: -1,
curve: Curve.EaseInOut
})
.opacity(0.8)
}
.width('100%')
.justifyContent(FlexAlign.Center)
.margin({ bottom: 8 })
}
@Builder
BrowseModeContent(): void { /* 浏览模式内容 */ }
@Builder
EditModeContent(): void { /* 编辑模式内容 */ }
@Builder
ReasoningModeContent(): void { /* 推理模式内容 */ }
@Builder
QAModeContent(): void { /* 问答模式内容 */ }
}
4.3 HMAF四层智能体协作引擎
代码亮点 :本模块是应用的核心智能层,实现了"实体抽取-关系推理-图谱可视化-知识问答"四层智能体协作架构。通过Agent Framework Kit创建多智能体会话,四个Agent并行处理用户输入,结果实时汇聚到图谱画布。关键创新在于利用Intents Kit解析用户的图谱操作意图(如"查找爱因斯坦的所有关系"),自动触发对应Agent协作并调整界面光效。
typescript
// entry/src/main/ets/agents/GraphAgentEngine.ets
import {
hmaf,
AgentSession,
AgentMode,
TaskMessage,
TaskResult
} from '@kit.AgentFrameworkKit';
import { intents, IntentEngine, IntentResult } from '@kit.IntentsKit';
import { knowledgeTheme, EntityType } from '../theme/KnowledgeLightTheme';
/**
* 智能体类型定义
*/
export enum AgentType {
ENTITY_EXTRACTOR = 'entity_extractor', // 实体抽取Agent
RELATION_REASONER = 'relation_reasoner', // 关系推理Agent
GRAPH_VISUALIZER = 'graph_visualizer', // 可视化Agent
KNOWLEDGE_QA = 'knowledge_qa' // 问答Agent
}
/**
* 图谱实体接口
*/
export interface GraphEntity {
id: string;
name: string;
type: EntityType;
properties: Record<string, string>;
x: number;
y: number;
confidence: number; // 抽取置信度
}
/**
* 图谱关系接口
*/
export interface GraphRelation {
id: string;
source: string; // 源实体ID
target: string; // 目标实体ID
relationType: string; // 关系类型
strength: number; // 关系强度 0-1
isInferred: boolean; // 是否为推理生成
evidence: string[]; // 推理证据
}
/**
* HMAF图谱智能体引擎
* 核心:四层智能体协作,实现知识图谱的自动构建与可视化
*/
export class GraphAgentEngine {
private session: AgentSession | null = null;
private intentEngine: IntentEngine | null = null;
// 实体库与关系库
private entities: Map<string, GraphEntity> = new Map();
private relations: Map<string, GraphRelation> = new Map();
// 回调监听
private onEntityExtracted?: (entities: GraphEntity[]) => void;
private onRelationInferred?: (relations: GraphRelation[]) => void;
private onGraphUpdated?: () => void;
private onAnswerReady?: (answer: string) => void;
/**
* 初始化智能体会话
*/
public async initialize(): Promise<void> {
// 创建多智能体会话
this.session = await hmaf.createAgentSession({
mode: AgentMode.MULTI_AGENT,
config: {
maxConcurrentAgents: 4,
timeout: 30000,
enableDistributed: true // 支持分布式协同
}
});
// 初始化意图引擎
this.intentEngine = await intents.createIntentEngine({
supportedDomains: ['knowledge_graph', 'entity_search', 'relation_query', 'reasoning']
});
// 注册四个智能体
await this.registerAgents();
console.info('GraphAgentEngine initialized successfully');
}
/**
* 注册四层智能体
*/
private async registerAgents(): Promise<void> {
if (!this.session) return;
// 1. 实体抽取Agent - 从文本中识别实体
await this.session.registerAgent({
agentId: AgentType.ENTITY_EXTRACTOR,
capabilities: ['named_entity_recognition', 'entity_linking', 'type_classification'],
promptTemplate: `
你是知识图谱实体抽取专家。从用户输入中提取所有实体,并分类为:
- 人物(PERSON): 具体的人名
- 组织(ORGANIZATION): 公司、机构、团体
- 地点(LOCATION): 国家、城市、地标
- 事件(EVENT): 历史事件、会议、活动
- 概念(CONCEPT): 抽象概念、理论、术语
返回JSON格式: [{"name": "实体名", "type": "类型", "confidence": 0.95}]
`
});
// 2. 关系推理Agent - 推断实体间关系
await this.session.registerAgent({
agentId: AgentType.RELATION_REASONER,
capabilities: ['relation_extraction', 'causal_reasoning', 'temporal_analysis'],
promptTemplate: `
你是关系推理专家。分析给定实体对之间的可能关系:
- 强关系(strong): 直接关联、因果关系、从属关系
- 弱关系(weak): 间接关联、相关关系、共现关系
- 推理关系(inferred): 基于知识库推断的隐含关系
返回JSON格式: [{"source": "源实体", "target": "目标实体", "relationType": "关系类型", "strength": 0.8, "evidence": ["证据1"]}]
`
});
// 3. 可视化Agent - 优化图谱布局
await this.session.registerAgent({
agentId: AgentType.GRAPH_VISUALIZER,
capabilities: ['force_directed_layout', 'hierarchical_layout', 'circular_layout'],
promptTemplate: `
你是图谱可视化专家。根据实体类型和关系强度,计算最优布局坐标:
- 人物实体居中偏上
- 组织实体环绕布局
- 地点实体地理映射
- 事件实体时间轴排列
- 概念实体层级分布
返回JSON格式: [{"id": "实体ID", "x": 100, "y": 200, "layoutType": "force"}]
`
});
// 4. 知识问答Agent - 基于图谱回答问题
await this.session.registerAgent({
agentId: AgentType.KNOWLEDGE_QA,
capabilities: ['graph_traversal', 'path_finding', 'summarization'],
promptTemplate: `
你是知识图谱问答专家。基于当前图谱数据回答用户问题:
- 使用图谱遍历找到相关实体和路径
- 综合多跳关系给出完整答案
- 标注答案来源和置信度
返回JSON格式: {"answer": "答案文本", "confidence": 0.9, "evidencePath": ["实体A->关系->实体B"]}
`
});
}
/**
* 处理用户输入 - 意图解析 + 智能体分发
* @param input 用户输入文本
*/
public async processUserInput(input: string): Promise<void> {
if (!this.session || !this.intentEngine) {
throw new Error('Engine not initialized');
}
// 第一步:意图解析
const intentResult: IntentResult = await this.intentEngine.parseIntent(input);
const intent = intentResult.primaryIntent;
console.info(`Detected intent: ${intent.domain}/${intent.action}, confidence: ${intent.confidence}`);
// 根据意图调整光效氛围
this.adjustLightByIntent(intent);
// 第二步:智能体任务分发
switch (intent.action) {
case 'extract_entities':
await this.dispatchEntityExtraction(input);
break;
case 'find_relations':
await this.dispatchRelationReasoning(intent.entities);
break;
case 'visualize_graph':
await this.dispatchVisualization();
break;
case 'ask_question':
await this.dispatchQA(input, intent);
break;
case 'build_graph':
// 全链路:抽取->推理->可视化
await this.dispatchFullPipeline(input);
break;
default:
// 默认执行全链路
await this.dispatchFullPipeline(input);
}
}
/**
* 根据意图调整光效
*/
private adjustLightByIntent(intent: IntentResult['primaryIntent']): void {
const entityMap: Record<string, EntityType> = {
'person': EntityType.PERSON,
'organization': EntityType.ORGANIZATION,
'location': EntityType.LOCATION,
'event': EntityType.EVENT,
'concept': EntityType.CONCEPT
};
// 如果意图涉及特定实体类型,切换对应光效
if (intent.entities && intent.entities.length > 0) {
const firstEntity = intent.entities[0];
const type = entityMap[firstEntity.type] || EntityType.CONCEPT;
knowledgeTheme.switchEntityLight(type);
}
}
/**
* 分发实体抽取任务
*/
private async dispatchEntityExtraction(text: string): Promise<void> {
const task: TaskMessage = {
targetAgent: AgentType.ENTITY_EXTRACTOR,
taskType: 'extract',
payload: { text },
priority: 1
};
const result: TaskResult = await this.session!.sendTask(task);
const extractedEntities: GraphEntity[] = JSON.parse(result.data);
// 存储实体
extractedEntities.forEach(entity => {
entity.id = `entity_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
entity.x = Math.random() * 800 + 100; // 初始随机位置
entity.y = Math.random() * 600 + 100;
this.entities.set(entity.id, entity);
});
// 触发回调
this.onEntityExtracted?.(extractedEntities);
// 更新关系统计
this.updateRelationStats();
}
/**
* 分发关系推理任务
*/
private async dispatchRelationReasoning(entityIds: string[]): Promise<void> {
const targetEntities = entityIds.map(id => this.entities.get(id)).filter(Boolean);
const task: TaskMessage = {
targetAgent: AgentType.RELATION_REASONER,
taskType: 'reason',
payload: { entities: targetEntities },
priority: 2
};
const result: TaskResult = await this.session!.sendTask(task);
const inferredRelations: GraphRelation[] = JSON.parse(result.data);
inferredRelations.forEach(relation => {
relation.id = `relation_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
this.relations.set(relation.id, relation);
});
this.onRelationInferred?.(inferredRelations);
this.updateRelationStats();
}
/**
* 分发可视化任务
*/
private async dispatchVisualization(): Promise<void> {
const allEntities = Array.from(this.entities.values());
const task: TaskMessage = {
targetAgent: AgentType.GRAPH_VISUALIZER,
taskType: 'layout',
payload: {
entities: allEntities,
relations: Array.from(this.relations.values()),
canvasWidth: 1920,
canvasHeight: 1080
},
priority: 3
};
const result: TaskResult = await this.session!.sendTask(task);
const layoutData = JSON.parse(result.data);
// 更新实体坐标
layoutData.forEach((item: { id: string; x: number; y: number }) => {
const entity = this.entities.get(item.id);
if (entity) {
entity.x = item.x;
entity.y = item.y;
}
});
this.onGraphUpdated?.();
}
/**
* 分发问答任务
*/
private async dispatchQA(question: string, intent: IntentResult['primaryIntent']): Promise<void> {
const task: TaskMessage = {
targetAgent: AgentType.KNOWLEDGE_QA,
taskType: 'answer',
payload: {
question,
graphData: {
entities: Array.from(this.entities.values()),
relations: Array.from(this.relations.values())
},
relevantEntities: intent.entities
},
priority: 1
};
const result: TaskResult = await this.session!.sendTask(task);
const answer = JSON.parse(result.data);
this.onAnswerReady?.(answer.answer);
}
/**
* 全链路调度:抽取 -> 推理 -> 可视化
*/
private async dispatchFullPipeline(text: string): Promise<void> {
// 并行执行实体抽取和意图解析
await this.dispatchEntityExtraction(text);
// 获取所有实体ID进行关系推理
const allEntityIds = Array.from(this.entities.keys());
if (allEntityIds.length >= 2) {
await this.dispatchRelationReasoning(allEntityIds);
}
// 最后执行可视化布局
await this.dispatchVisualization();
}
/**
* 更新关系统计到全局状态
*/
private updateRelationStats(): void {
const stats = {
strongRelations: Array.from(this.relations.values()).filter(r => r.strength > 0.7 && !r.isInferred).length,
weakRelations: Array.from(this.relations.values()).filter(r => r.strength <= 0.7 && !r.isInferred).length,
inferredRelations: Array.from(this.relations.values()).filter(r => r.isInferred).length
};
AppStorage.setOrCreate('relationStats', stats);
}
// 设置回调
public setCallbacks(callbacks: {
onEntityExtracted?: (entities: GraphEntity[]) => void;
onRelationInferred?: (relations: GraphRelation[]) => void;
onGraphUpdated?: () => void;
onAnswerReady?: (answer: string) => void;
}): void {
this.onEntityExtracted = callbacks.onEntityExtracted;
this.onRelationInferred = callbacks.onRelationInferred;
this.onGraphUpdated = callbacks.onGraphUpdated;
this.onAnswerReady = callbacks.onAnswerReady;
}
/**
* 获取当前图谱数据
*/
public getGraphData(): { entities: GraphEntity[]; relations: GraphRelation[] } {
return {
entities: Array.from(this.entities.values()),
relations: Array.from(this.relations.values())
};
}
}
// 导出单例
export const graphAgentEngine = new GraphAgentEngine();
4.4 主图谱画布:Canvas 2D + 动态光效渲染
代码亮点:本模块实现了知识图谱的核心可视化层。基于ArkUI的Canvas组件绘制力导向图谱,每个节点根据实体类型渲染专属光晕效果,关系连线根据强度显示不同粗细和透明度。关键创新在于"呼吸光"动画系统------节点在获得焦点时触发脉冲光效,整个画布背景根据当前主题色渲染动态环境光,实现"知识即氛围"的沉浸体验。
typescript
// entry/src/main/ets/pages/GraphCanvasPage.ets
import { Canvas, CanvasRenderingContext2D, Animation } from '@kit.ArkUI';
import { window } from '@kit.WindowManagerKit';
import { knowledgeTheme, EntityType, LightEffectConfig } from '../theme/KnowledgeLightTheme';
import { graphAgentEngine, GraphEntity, GraphRelation } from '../agents/GraphAgentEngine';
import { FloatingGraphNav, GraphMode } from '../components/FloatingGraphNav';
@Entry
@Component
struct GraphCanvasPage {
@StorageLink('currentEntityType') currentType: EntityType = EntityType.CONCEPT;
@StorageLink('ambientLightColor') ambientColor: string = '#F5F5F5';
@StorageLink('primaryLightColor') primaryColor: string = '#B8B8B8';
@StorageLink('currentGraphMode') currentMode: GraphMode = GraphMode.BROWSE;
@State entities: GraphEntity[] = [];
@State relations: GraphRelation[] = [];
@State selectedEntityId: string = '';
@State canvasWidth: number = 1920;
@State canvasHeight: number = 1080;
@State pulsePhase: number = 0; // 呼吸光相位
private canvasContext: CanvasRenderingContext2D | null = null;
private animationId: number = 0;
private readonly NODE_RADIUS: number = 30;
private readonly GLOW_RADIUS: number = 60;
aboutToAppear(): void {
// 初始化引擎
graphAgentEngine.initialize().then(() => {
// 设置回调
graphAgentEngine.setCallbacks({
onEntityExtracted: (newEntities) => {
this.entities = [...this.entities, ...newEntities];
this.invalidateCanvas();
},
onRelationInferred: (newRelations) => {
this.relations = [...this.relations, ...newRelations];
this.invalidateCanvas();
},
onGraphUpdated: () => {
this.entities = graphAgentEngine.getGraphData().entities;
this.relations = graphAgentEngine.getGraphData().relations;
this.invalidateCanvas();
}
});
// 启动示例数据
this.loadDemoData();
});
// 启动呼吸光动画
this.startPulseAnimation();
// 设置窗口全屏沉浸
this.setupImmersiveWindow();
}
aboutToDisappear(): void {
if (this.animationId) {
cancelAnimationFrame(this.animationId);
}
}
/**
* 设置窗口沉浸模式
*/
private async setupImmersiveWindow(): Promise<void> {
const win = await window.getLastWindow(getContext());
await win.setWindowLayoutFullScreen(true);
await win.setWindowSystemBarEnable([]);
// 扩展安全区
const rootLayout = win.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM);
this.canvasWidth = display.getDefaultDisplaySync().width;
this.canvasHeight = display.getDefaultDisplaySync().height;
}
/**
* 启动呼吸光动画循环
*/
private startPulseAnimation(): void {
const animate = () => {
this.pulsePhase = (this.pulsePhase + 0.02) % (Math.PI * 2);
this.invalidateCanvas();
this.animationId = requestAnimationFrame(animate);
};
animate();
}
/**
* 加载示例数据
*/
private async loadDemoData(): Promise<void> {
await graphAgentEngine.processUserInput(
'阿尔伯特·爱因斯坦是理论物理学家,出生于德国乌尔姆。他提出了相对论,在普林斯顿高等研究院工作。' +
'相对论包括狭义相对论和广义相对论。诺贝尔物理学奖授予了他。'
);
}
/**
* 渲染图谱画布
*/
private renderGraph(ctx: CanvasRenderingContext2D): void {
const config = knowledgeTheme.getCurrentConfig();
// 1. 绘制动态环境光背景
this.drawAmbientBackground(ctx, config);
// 2. 绘制关系连线
this.drawRelations(ctx);
// 3. 绘制实体节点
this.drawEntities(ctx, config);
// 4. 绘制选中高亮
if (this.selectedEntityId) {
this.drawSelectionHighlight(ctx, config);
}
}
/**
* 绘制动态环境光背景
* 核心:根据当前主题色渲染呼吸光背景
*/
private drawAmbientBackground(ctx: CanvasRenderingContext2D, config: LightEffectConfig): void {
const width = this.canvasWidth;
const height = this.canvasHeight;
// 创建径向渐变背景
const gradient = ctx.createRadialGradient(
width / 2, height / 2, 0,
width / 2, height / 2, Math.max(width, height) / 2
);
// 呼吸光透明度计算
const breatheAlpha = 0.03 + Math.sin(this.pulsePhase) * 0.02;
const ambientRGBA = this.hexToRGBA(config.ambientColor, breatheAlpha);
const centerRGBA = this.hexToRGBA(config.primaryColor, breatheAlpha * 1.5);
gradient.addColorStop(0, centerRGBA);
gradient.addColorStop(0.5, ambientRGBA);
gradient.addColorStop(1, 'rgba(255, 255, 255, 0)');
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, width, height);
// 绘制 subtle grid
ctx.strokeStyle = config.primaryColor + '0D'; // 5%透明度
ctx.lineWidth = 0.5;
const gridSize = 50;
for (let x = 0; x < width; x += gridSize) {
ctx.beginPath();
ctx.moveTo(x, 0);
ctx.lineTo(x, height);
ctx.stroke();
}
for (let y = 0; y < height; y += gridSize) {
ctx.beginPath();
ctx.moveTo(0, y);
ctx.lineTo(width, y);
ctx.stroke();
}
}
/**
* 绘制关系连线
* 根据关系强度显示不同粗细和透明度
*/
private drawRelations(ctx: CanvasRenderingContext2D): void {
this.relations.forEach(relation => {
const source = this.entities.find(e => e.id === relation.source);
const target = this.entities.find(e => e.id === relation.target);
if (!source || !target) return;
ctx.beginPath();
ctx.moveTo(source.x, source.y);
ctx.lineTo(target.x, target.y);
// 关系强度映射到线条样式
ctx.lineWidth = relation.strength * 4 + 0.5;
ctx.strokeStyle = relation.isInferred
? `rgba(155, 89, 182, ${relation.strength * 0.6})` // 推理关系:紫色虚线
: `rgba(100, 100, 100, ${relation.strength * 0.8})`; // 事实关系:灰色实线
if (relation.isInferred) {
ctx.setLineDash([5, 5]);
} else {
ctx.setLineDash([]);
}
ctx.stroke();
// 绘制关系标签
const midX = (source.x + target.x) / 2;
const midY = (source.y + target.y) / 2;
ctx.fillStyle = '#666666';
ctx.font = '12px sans-serif';
ctx.textAlign = 'center';
ctx.fillText(relation.relationType, midX, midY - 5);
});
}
/**
* 绘制实体节点
* 每个类型拥有专属光效人格
*/
private drawEntities(ctx: CanvasRenderingContext2D, config: LightEffectConfig): void {
this.entities.forEach(entity => {
const isSelected = entity.id === this.selectedEntityId;
const isHovered = false; // 可通过手势检测实现
// 1. 绘制外发光光晕
const glowIntensity = isSelected ? 1.0 : (isHovered ? 0.7 : 0.4);
const glowRadius = this.GLOW_RADIUS + Math.sin(this.pulsePhase + entity.x * 0.01) * 5;
const glowGradient = ctx.createRadialGradient(
entity.x, entity.y, this.NODE_RADIUS,
entity.x, entity.y, glowRadius
);
const glowColor = this.getEntityGlowColor(entity.type);
glowGradient.addColorStop(0, glowColor + Math.floor(glowIntensity * 255).toString(16).padStart(2, '0'));
glowGradient.addColorStop(1, glowColor + '00');
ctx.fillStyle = glowGradient;
ctx.beginPath();
ctx.arc(entity.x, entity.y, glowRadius, 0, Math.PI * 2);
ctx.fill();
// 2. 绘制节点圆形
ctx.beginPath();
ctx.arc(entity.x, entity.y, this.NODE_RADIUS, 0, Math.PI * 2);
ctx.fillStyle = '#FFFFFF';
ctx.fill();
// 节点边框
ctx.strokeStyle = this.getEntityColor(entity.type);
ctx.lineWidth = isSelected ? 3 : 2;
ctx.stroke();
// 3. 绘制实体名称
ctx.fillStyle = '#333333';
ctx.font = isSelected ? 'bold 14px sans-serif' : '13px sans-serif';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(entity.name, entity.x, entity.y);
// 4. 绘制类型图标(简化为圆点颜色)
ctx.beginPath();
ctx.arc(entity.x + this.NODE_RADIUS - 5, entity.y - this.NODE_RADIUS + 5, 4, 0, Math.PI * 2);
ctx.fillStyle = this.getEntityColor(entity.type);
ctx.fill();
});
}
/**
* 绘制选中高亮效果
*/
private drawSelectionHighlight(ctx: CanvasRenderingContext2D, config: LightEffectConfig): void {
const entity = this.entities.find(e => e.id === this.selectedEntityId);
if (!entity) return;
// 脉冲光环
const pulseRadius = this.NODE_RADIUS + 10 + Math.sin(this.pulsePhase * 2) * 5;
ctx.beginPath();
ctx.arc(entity.x, entity.y, pulseRadius, 0, Math.PI * 2);
ctx.strokeStyle = config.primaryColor;
ctx.lineWidth = 2;
ctx.setLineDash([3, 3]);
ctx.stroke();
ctx.setLineDash([]);
}
/**
* 获取实体类型颜色
*/
private getEntityColor(type: EntityType): string {
const colorMap: Record<EntityType, string> = {
[EntityType.PERSON]: '#FF8C42',
[EntityType.ORGANIZATION]: '#4A90E2',
[EntityType.LOCATION]: '#50C878',
[EntityType.EVENT]: '#E74C3C',
[EntityType.CONCEPT]: '#B8B8B8'
};
return colorMap[type] || '#B8B8B8';
}
/**
* 获取实体光晕颜色(带透明度)
*/
private getEntityGlowColor(type: EntityType): string {
const colorMap: Record<EntityType, string> = {
[EntityType.PERSON]: '#FFB380',
[EntityType.ORGANIZATION]: '#80B8FF',
[EntityType.LOCATION]: '#80E6A0',
[EntityType.EVENT]: '#FF8080',
[EntityType.CONCEPT]: '#D0D0D0'
};
return colorMap[type] || '#D0D0D0';
}
/**
* HEX转RGBA
*/
private hexToRGBA(hex: string, alpha: number): string {
const r = parseInt(hex.slice(1, 3), 16);
const g = parseInt(hex.slice(3, 5), 16);
const b = parseInt(hex.slice(5, 7), 16);
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
}
/**
* 处理画布点击事件
*/
private handleCanvasClick(event: ClickEvent): void {
const x = event.x;
const y = event.y;
// 检测点击的实体
const clickedEntity = this.entities.find(entity => {
const dx = entity.x - x;
const dy = entity.y - y;
return Math.sqrt(dx * dx + dy * dy) <= this.NODE_RADIUS;
});
if (clickedEntity) {
this.selectedEntityId = clickedEntity.id;
// 切换实体类型光效
knowledgeTheme.switchEntityLight(clickedEntity.type);
// 打开实体详情浮动窗口
this.openEntityPanel(clickedEntity);
} else {
this.selectedEntityId = '';
}
this.invalidateCanvas();
}
/**
* 打开实体详情浮动窗口
*/
private async openEntityPanel(entity: GraphEntity): Promise<void> {
const context = getContext();
const want = {
deviceId: '',
bundleName: context.applicationInfo.name,
abilityName: 'EntityPanelAbility',
parameters: {
entityId: entity.id,
entityData: JSON.stringify(entity)
}
};
await context.startAbility(want);
}
/**
* 触发画布重绘
*/
private invalidateCanvas(): void {
if (this.canvasContext) {
this.canvasContext.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
this.renderGraph(this.canvasContext);
}
}
build() {
Stack() {
// 主画布
Canvas(this.canvasContext)
.width('100%')
.height('100%')
.backgroundColor('#FAFAFA')
.onReady((context) => {
this.canvasContext = context;
this.invalidateCanvas();
})
.onClick((event) => {
this.handleCanvasClick(event);
})
.expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])
// 顶部标题栏 - 沉浸光感
Row() {
Text('图谱智脑')
.fontSize(20)
.fontWeight(FontWeight.Bold)
.fontColor(this.primaryColor)
Blank()
// 当前模式指示器
Row() {
Circle()
.width(8)
.height(8)
.fill(this.primaryColor)
.animation({
duration: 2000,
iterations: -1,
curve: Curve.EaseInOut
})
Text(this.currentMode === GraphMode.BROWSE ? '浏览模式' :
this.currentMode === GraphMode.EDIT ? '编辑模式' :
this.currentMode === GraphMode.REASONING ? '推理模式' : '问答模式')
.fontSize(12)
.fontColor(this.primaryColor)
.margin({ left: 6 })
}
}
.width('100%')
.height(56)
.padding({ left: 24, right: 24 })
.backgroundColor('rgba(255, 255, 255, 0.8)')
.backdropFilter($r('sys.blur.20')) // 背景模糊
.alignItems(VerticalAlign.Center)
.position({ x: 0, y: 0 })
// 底部悬浮导航
Column() {
FloatingGraphNav()
}
.width('100%')
.position({ x: 0, y: '100%' })
.translate({ y: '-100%' })
.padding({ bottom: 12 })
}
.width('100%')
.height('100%')
.backgroundColor(this.ambientColor)
}
}
4.5 浮动实体属性面板:多窗口光效联动
代码亮点 :本模块实现了浮动实体详情窗口,通过WindowManager创建独立的子窗口。关键创新在于"跨窗口光效同步"------当主窗口切换实体类型时,浮动窗口通过AppStorage全局状态自动同步主题色,实现"一窗变色,全局联动"的沉浸体验。窗口采用圆角+阴影+背景模糊的现代设计,失焦时自动降低透明度。
typescript
// entry/src/main/ets/entityability/EntityPanelAbility.ets
import { window } from '@kit.WindowManagerKit';
import { knowledgeTheme, EntityType } from '../theme/KnowledgeLightTheme';
@Entry
@Component
struct EntityPanelPage {
@StorageLink('currentEntityType') currentType: EntityType = EntityType.CONCEPT;
@StorageLink('primaryLightColor') primaryColor: string = '#B8B8B8';
@StorageLink('ambientLightColor') ambientColor: string = '#F5F5F5';
@State entityData: GraphEntity | null = null;
@State isWindowFocused: boolean = true;
aboutToAppear(): void {
// 获取启动参数
const params = getContext().abilityInfo?.parameters;
if (params?.entityData) {
this.entityData = JSON.parse(params.entityData);
}
// 监听窗口焦点变化
this.setupFocusListener();
}
/**
* 设置窗口焦点监听
*/
private async setupFocusListener(): Promise<void> {
const win = await window.getLastWindow(getContext());
win.on('windowFocusChange', (isFocused: boolean) => {
this.isWindowFocused = isFocused;
});
}
build() {
Column() {
// 窗口标题栏 - 光效联动
Row() {
// 实体类型光晕指示
Circle()
.width(12)
.height(12)
.fill(this.primaryColor)
.shadow({
radius: 8,
color: this.primaryColor + '66',
offsetX: 0,
offsetY: 0
})
Text(this.entityData?.name || '实体详情')
.fontSize(16)
.fontWeight(FontWeight.Bold)
.fontColor('#333333')
.margin({ left: 8 })
Blank()
// 置信度徽章
if (this.entityData?.confidence) {
Text(`置信度 ${(this.entityData.confidence * 100).toFixed(1)}%`)
.fontSize(11)
.fontColor(this.primaryColor)
.backgroundColor(this.primaryColor + '1A')
.borderRadius(10)
.padding({ left: 8, right: 8, top: 2, bottom: 2 })
}
}
.width('100%')
.height(48)
.padding({ left: 16, right: 16 })
.backgroundColor('rgba(255, 255, 255, 0.9)')
.borderRadius({ topLeft: 16, topRight: 16 })
// 属性列表
List() {
// 类型属性
ListItem() {
this.PropertyRow('类型', this.entityData?.type || '-')
}
// 其他属性
if (this.entityData?.properties) {
ForEach(Object.entries(this.entityData.properties), (item: [string, string]) => {
ListItem() {
this.PropertyRow(item[0], item[1])
}
})
}
}
.width('100%')
.layoutWeight(1)
.padding(16)
// 操作按钮
Row() {
Button('查看关系')
.backgroundColor(this.primaryColor)
.fontColor('#FFFFFF')
.borderRadius(8)
.onClick(() => {
this.openRelationEditor();
})
Button('推理路径')
.backgroundColor(this.primaryColor + '33')
.fontColor(this.primaryColor)
.borderRadius(8)
.margin({ left: 8 })
.onClick(() => {
this.openReasoningPath();
})
}
.width('100%')
.padding(16)
.justifyContent(FlexAlign.Center)
}
.width('100%')
.height('100%')
.backgroundColor('rgba(255, 255, 255, 0.85)')
.backdropFilter($r('sys.blur.20'))
.borderRadius(16)
.shadow({
radius: 24,
color: 'rgba(0, 0, 0, 0.15)',
offsetX: 0,
offsetY: 8
})
// 焦点感知:失焦时降低透明度
.opacity(this.isWindowFocused ? 1.0 : 0.7)
.animation({
duration: 300,
curve: Curve.EaseInOut
})
}
@Builder
PropertyRow(label: string, value: string): void {
Row() {
Text(label)
.fontSize(13)
.fontColor('#999999')
.width(80)
Text(value)
.fontSize(13)
.fontColor('#333333')
.layoutWeight(1)
}
.width('100%')
.height(40)
.borderBottom({ width: 0.5, color: '#EEEEEE' })
}
private async openRelationEditor(): Promise<void> {
const want = {
deviceId: '',
bundleName: getContext().applicationInfo.name,
abilityName: 'RelationEditorAbility',
parameters: { entityId: this.entityData?.id }
};
await getContext().startAbility(want);
}
private async openReasoningPath(): Promise<void> {
const want = {
deviceId: '',
bundleName: getContext().applicationInfo.name,
abilityName: 'ReasoningPathAbility',
parameters: { entityId: this.entityData?.id }
};
await getContext().startAbility(want);
}
}
4.6 入口页面与窗口配置
typescript
// entry/src/main/ets/entryability/EntryAbility.ets
import { UIAbility, Want, AbilityConstant } 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.createMainWindow('GraphCanvasPage');
// 设置全屏沉浸
await mainWindow.setWindowLayoutFullScreen(true);
await mainWindow.setWindowSystemBarEnable([]);
// 设置窗口背景为透明,允许底层光效透出
await mainWindow.setWindowBackgroundColor('#00000000');
// 加载主页面
await mainWindow.loadContent('pages/GraphCanvasPage');
await mainWindow.show();
console.info('GraphCanvas main window created with immersive mode');
}
onWindowStageDestroy(): void {
console.info('EntryAbility window stage destroyed');
}
}
五、关键技术总结
5.1 HMAF智能体协作开发清单
| 技术点 | API/方法 | 应用场景 |
|---|---|---|
| 多智能体会话创建 | hmaf.createAgentSession({ mode: MULTI_AGENT }) |
四层Agent并行协作 |
| 意图解析 | intents.createIntentEngine({ supportedDomains }) |
用户查询意图理解 |
| 任务分发 | hmafSession.sendTask({ targetAgent, taskType }) |
Agent间任务调度 |
| 实体抽取 | AgentType.ENTITY_EXTRACTOR |
从文本识别实体 |
| 关系推理 | AgentType.RELATION_REASONER |
推断实体间关系 |
| 可视化布局 | AgentType.GRAPH_VISUALIZER |
计算最优节点坐标 |
| 知识问答 | AgentType.KNOWLEDGE_QA |
基于图谱回答问题 |
| 状态监听 | AppStorage 全局状态回调 |
跨组件图谱状态同步 |
| 分布式协同 | enableDistributed: true |
多设备图谱协作 |
5.2 沉浸光感实现清单
| 技术点 | API/方法 | 应用场景 |
|---|---|---|
| 系统材质效果 | systemMaterialEffect: SystemMaterialEffect.IMMERSIVE |
HdsNavigation标题栏 |
| 背景模糊 | backgroundBlurStyle(BlurStyle.REGULAR) |
悬浮导航玻璃拟态 |
| 背景滤镜 | backdropFilter($r('sys.blur.20')) |
精细模糊控制 |
| 安全区扩展 | expandSafeArea([SafeAreaType.SYSTEM], [...]) |
全屏沉浸布局 |
| 窗口沉浸 | setWindowLayoutFullScreen(true) |
无边框模式 |
| 呼吸光动画 | animation({ duration, iterations: -1 }) |
节点脉冲光晕 |
| 动态透明度 | opacity + animation |
焦点感知降级 |
| 径向渐变 | createRadialGradient() |
环境光背景 |
| 主题色同步 | AppStorage 全局状态 |
跨窗口光效联动 |
5.3 悬浮导航适配要点
- 安全区避让 :通过
getWindowAvoidArea获取底部导航指示器高度,内容区域动态预留空间 - 悬浮层级设计 :导航栏脱离底边,使用
barBottomMargin: 16实现四周留白 - 透明度动态调节:支持强/平衡/弱三档,通过Slider或预设按钮实时调整
- 模式徽章系统:当前图谱模式(浏览/编辑/推理/问答)通过顶部脉冲光条和页签颜色双重指示
- 关系统计徽章:实时显示强关系、弱关系、推理关系数量,帮助用户感知图谱复杂度
六、运行效果展示
6.1 浏览模式 - 人物实体光效
当用户选中"阿尔伯特·爱因斯坦"人物实体时,界面切换为暖橙色光效:标题栏边框泛出橙光晕,节点外发光呈智慧橙色调,环境背景渲染淡橙渐变,整个界面传递"人物"类型的温暖与睿智感。
6.2 编辑模式 - 组织实体光效
切换到"普林斯顿高等研究院"组织实体时,光效变为冷蓝色调:传递机构的理性与信任感,编辑状态下的节点边框加粗,脉冲光环提示当前选中状态。
6.3 推理模式 - 概念实体光效
执行"相对论与量子力学的关系"推理时,界面切换为银白色调:概念节点的缓慢脉冲(3500ms周期)与推理关系的紫色虚线共同营造学术沉思氛围。
6.4 问答模式 - 多类型光效混合
当用户提问"爱因斯坦在哪些机构工作过"时,问答Agent遍历图谱找到人物→组织的多跳关系,界面光效在人物橙与组织蓝之间渐变过渡,直观展示答案的跨类型关联。
七、总结与展望
本文基于HarmonyOS 6(API 23)的悬浮导航 、沉浸光感 与HMAF智能体框架特性,完整实战了一款面向PC端的"图谱智脑"AI智能体知识图谱构建工作台。核心创新点总结:
-
HMAF四层智能体协作:基于Agent Framework Kit构建实体抽取Agent(识别人物/组织/地点/事件/概念)、关系推理Agent(区分强/弱/推理关系)、可视化Agent(力导向/层级/环形布局)、问答Agent(图谱遍历与路径查找),实现"输入文本→自动构建→可视化→智能问答"的全链路自动化
-
实体类型光效系统:每种实体类型拥有专属光效人格(人物暖橙、组织冷蓝、地点翠绿、事件紫红、概念银白),根据当前聚焦实体动态切换全局环境光、节点光晕和导航材质,实现"知识直觉感知"
-
悬浮图谱导航:底部悬浮页签不仅承载浏览/编辑/推理/问答四种模式切换,更实时显示关系类型徽章(强关系数/弱关系数/推理关系数),玻璃拟态设计+三档透明度调节,最大化图谱画布区域
-
PC级多窗口知识协作 :主图谱画布窗口 + 浮动实体属性面板 + 浮动关系编辑器 + 浮动推理路径窗口的四层架构,通过
AppStorage实现跨窗口光效联动与焦点感知,符合知识图谱构建者的专业工作习惯 -
意图驱动光效:通过Intents Kit解析用户查询意图,自动识别涉及的实体类型并切换对应光效氛围,实现"查询即氛围"的沉浸体验
未来扩展方向:
- 分布式图谱协作:通过鸿蒙分布式软总线,实现手机语音输入→平板实体审核→PC图谱构建的无缝流转
- AR空间图谱:接入Face AR与Body AR,支持手势拖拽3D节点、眼神聚焦自动高亮、语音指令触发推理
- 实时协作编辑:多人同时编辑同一知识图谱,通过不同颜色光效区分协作者,实时同步节点位置与关系变更
- AI辅助补全:基于当前图谱结构,AI预测缺失关系并推荐新增实体,以"幽灵节点"形式在画布上预展示
- 多模态实体:支持图片、视频、音频作为实体属性,点击节点时自动播放相关多媒体内容
转载自:https://blog.csdn.net/u014727709/article/details/161557606
欢迎 👍点赞✍评论⭐收藏,欢迎指正