HarmonyOS 6(API 23)实战:基于悬浮导航、沉浸光感与HMAF的“图谱智脑“——PC端AI智能体沉浸式知识图谱构建工作台

文章目录

    • 每日一句正能量
    • 前言
    • 一、前言:知识图谱构建的交互范式革新
    • 二、技术架构与核心亮点
      • [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 悬浮导航适配要点

  1. 安全区避让 :通过 getWindowAvoidArea 获取底部导航指示器高度,内容区域动态预留空间
  2. 悬浮层级设计 :导航栏脱离底边,使用 barBottomMargin: 16 实现四周留白
  3. 透明度动态调节:支持强/平衡/弱三档,通过Slider或预设按钮实时调整
  4. 模式徽章系统:当前图谱模式(浏览/编辑/推理/问答)通过顶部脉冲光条和页签颜色双重指示
  5. 关系统计徽章:实时显示强关系、弱关系、推理关系数量,帮助用户感知图谱复杂度

六、运行效果展示

6.1 浏览模式 - 人物实体光效

当用户选中"阿尔伯特·爱因斯坦"人物实体时,界面切换为暖橙色光效:标题栏边框泛出橙光晕,节点外发光呈智慧橙色调,环境背景渲染淡橙渐变,整个界面传递"人物"类型的温暖与睿智感。

6.2 编辑模式 - 组织实体光效

切换到"普林斯顿高等研究院"组织实体时,光效变为冷蓝色调:传递机构的理性与信任感,编辑状态下的节点边框加粗,脉冲光环提示当前选中状态。

6.3 推理模式 - 概念实体光效

执行"相对论与量子力学的关系"推理时,界面切换为银白色调:概念节点的缓慢脉冲(3500ms周期)与推理关系的紫色虚线共同营造学术沉思氛围。

6.4 问答模式 - 多类型光效混合

当用户提问"爱因斯坦在哪些机构工作过"时,问答Agent遍历图谱找到人物→组织的多跳关系,界面光效在人物橙与组织蓝之间渐变过渡,直观展示答案的跨类型关联。


七、总结与展望

本文基于HarmonyOS 6(API 23)的悬浮导航沉浸光感HMAF智能体框架特性,完整实战了一款面向PC端的"图谱智脑"AI智能体知识图谱构建工作台。核心创新点总结:

  1. HMAF四层智能体协作:基于Agent Framework Kit构建实体抽取Agent(识别人物/组织/地点/事件/概念)、关系推理Agent(区分强/弱/推理关系)、可视化Agent(力导向/层级/环形布局)、问答Agent(图谱遍历与路径查找),实现"输入文本→自动构建→可视化→智能问答"的全链路自动化

  2. 实体类型光效系统:每种实体类型拥有专属光效人格(人物暖橙、组织冷蓝、地点翠绿、事件紫红、概念银白),根据当前聚焦实体动态切换全局环境光、节点光晕和导航材质,实现"知识直觉感知"

  3. 悬浮图谱导航:底部悬浮页签不仅承载浏览/编辑/推理/问答四种模式切换,更实时显示关系类型徽章(强关系数/弱关系数/推理关系数),玻璃拟态设计+三档透明度调节,最大化图谱画布区域

  4. PC级多窗口知识协作 :主图谱画布窗口 + 浮动实体属性面板 + 浮动关系编辑器 + 浮动推理路径窗口的四层架构,通过AppStorage实现跨窗口光效联动与焦点感知,符合知识图谱构建者的专业工作习惯

  5. 意图驱动光效:通过Intents Kit解析用户查询意图,自动识别涉及的实体类型并切换对应光效氛围,实现"查询即氛围"的沉浸体验

未来扩展方向

  • 分布式图谱协作:通过鸿蒙分布式软总线,实现手机语音输入→平板实体审核→PC图谱构建的无缝流转
  • AR空间图谱:接入Face AR与Body AR,支持手势拖拽3D节点、眼神聚焦自动高亮、语音指令触发推理
  • 实时协作编辑:多人同时编辑同一知识图谱,通过不同颜色光效区分协作者,实时同步节点位置与关系变更
  • AI辅助补全:基于当前图谱结构,AI预测缺失关系并推荐新增实体,以"幽灵节点"形式在画布上预展示
  • 多模态实体:支持图片、视频、音频作为实体属性,点击节点时自动播放相关多媒体内容

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

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

相关推荐
仔仔 v1.01 小时前
第四章: AI图像生成与视频制作实战指南
人工智能
ZengLiangYi1 小时前
如何解析 5 种完全不同格式的 AI 对话
javascript·人工智能·算法
写做四月一日的四月一日1 小时前
在安卓手机上安装小龙虾openclaw并配置QQ机器人接入
android·人工智能
@小阿宝1 小时前
PPF(Point-Pair Feature,点对特征)
人工智能·机器学习
IronMurphy1 小时前
AI Agent学习day6 从 MCP 到 RAG 记忆:AI Agent 项目中的三块核心基础
人工智能·学习
cxr8281 小时前
高分子复合材料 AI 逆向设计合——生态级专业补充与产业部署框架
人工智能·材料逆向设计合成
想你依然心痛1 小时前
HarmonyOS 6(API 23)实战:基于悬浮导航、沉浸光感与HMAF的“律界智脑“——PC端AI智能体沉浸式法律文档智能审查工作台
人工智能·华为·ar·harmonyos·智能体
特立独行的猫a1 小时前
鸿蒙 PC 平台 Python 第三方库移植全景指南
python·华为·harmonyos·三方库移植·鸿蒙pc
deephub1 小时前
视频 RAG 中分块策略:基于停顿、滑动窗口与基于 LLM 的方法
人工智能·大语言模型·rag·视频分块