HarmonyOS 6(API 23)实战:基于悬浮导航、沉浸光感与HMAF的“直播智脑“——PC端AI智能体电商直播中控台
2026年,中国直播电商市场规模已突破8万亿元,但传统直播中控台面临三大痛点:HarmonyOS 6(API 23)的HMAF框架配合**悬浮导航(Float Navigation)与沉浸光感(Immersive Light Effects)**特性,为直播中控台带来了革命性解决方案:本文核心亮点:HMAF(Harmony Intelligent Agent Framework)提供四种编排模式,
文章目录

每日一句正能量
黑暗不是终点,而是为了让你更敏锐地感知光的方向。
黑暗(困难、未知、痛苦)不是要吞没你,而是因为消除了光的干扰,反而能让最微弱的光源显形。在低谷中不是绝望,而是训练自己的“感知力”——学会在微弱信号中找到出路。
前言
摘要:2026年,直播电商进入"智能体驱动"时代。HarmonyOS 6(API 23)引入的鸿蒙智能体框架(HMAF)将AI能力下沉至系统层,配合悬浮导航与沉浸光感特性,为PC端直播中控台带来了"数据即氛围、状态即导航"的全新交互范式。本文将实战开发一款面向HarmonyOS PC的"直播智脑"应用,展示如何利用HMAF构建"智能讲解-实时互动-数据洞察-风险管控"四层智能体协作架构,通过悬浮导航实现直播状态实时追踪,基于沉浸光感打造"流量即光效"的沉浸体验,以及基于多窗口架构构建浮动弹幕、数据看板和商品橱窗的协作直播体验。
一、前言:直播电商3.0时代的智能体革命
2026年,中国直播电商市场规模已突破8万亿元,但传统直播中控台面临三大痛点:
- 信息过载:主播需要同时盯着弹幕、数据、商品、互动四个面板,注意力严重分散
- 响应滞后:人工回复弹幕平均延迟15秒,错过最佳转化窗口
- 数据盲区:实时数据与历史趋势割裂,无法即时调整直播策略
HarmonyOS 6(API 23)的HMAF框架配合**悬浮导航(Float Navigation)与沉浸光感(Immersive Light Effects)**特性,为直播中控台带来了革命性解决方案:
- 智能体自动应答:HMAF构建的"互动智能体"可实时理解弹幕意图,自动回复常见问题,响应延迟降至500ms
- 流量光效感知:根据实时在线人数、GMV增速、互动热度动态切换环境光色,让主播"看见"数据变化
- 悬浮状态导航:底部悬浮导航实时显示四大智能体运行状态,主播无需切换页面即可掌握全局
- PC多窗口协作:主直播画面 + 浮动弹幕窗口 + 浮动数据看板 + 浮动商品橱窗的四层架构,通过光效联动实现"一眼全局"
本文核心亮点:
- 四层智能体架构:讲解智能体(商品解说)、互动智能体(弹幕应答)、洞察智能体(数据预测)、风控智能体(违规检测)协同工作
- 流量脉搏光效:根据实时GMV增速(冷启动蓝→平稳绿→爆发橙→峰值红)动态渲染全屏氛围光
- 悬浮直播导航:底部悬浮页签承载"直播/互动/数据/商品"四大模块,实时显示智能体状态徽章与流量脉冲
- 弹幕情绪光效:基于NLP实时分析弹幕情感倾向,正面情绪触发暖光脉冲,负面情绪触发冷光警示
- 多窗口光效同步:主窗口与三个浮动子窗口通过
WindowLightSync实现跨窗口光效联动,焦点感知自动调节
二、核心特性解析与技术选型
2.1 HMAF在直播场景中的价值
HMAF(Harmony Intelligent Agent Framework)提供四种编排模式,在直播场景中各有妙用:
| 编排模式 | 直播应用场景 | 技术实现 |
|---|---|---|
| LLM模式 | 智能讲解智能体自主生成商品解说词 | 基于商品SKU自动调用LLM生成卖点文案 |
| 工作流模式 | 互动智能体按预设流程处理弹幕问答 | 意图识别→知识库检索→答案生成→敏感词过滤 |
| A2A模式 | 四大智能体间实时协作与任务分发 | 讲解智能体触发促销时,洞察智能体同步预测库存 |
| OpenClaw模式 | 主播通过自然语言直接指挥智能体 | “把三号链接的讲解词换成夏季版本” |
2.2 沉浸光感在直播中的创新应用
传统直播软件采用固定UI,主播难以感知数据变化。HarmonyOS 6的沉浸光感特性带来三种创新:
流量脉搏光效:根据实时在线人数动态调整背景光色与脉冲频率
- 冷启动期(<100人):深海蓝,缓慢呼吸(4秒/周期)
- 成长期(100-1000人):薄荷绿,平稳律动(2秒/周期)
- 爆发期(1000-10000人):活力橙,快速脉冲(1秒/周期)
- 峰值期(>10000人):炽烈红,高频闪烁(0.5秒/周期)
弹幕情绪光效:基于NLP情感分析实时驱动光效
- 正面情绪(>0.6):暖金色光晕从底部升起
- 负面情绪(<-0.3):冰蓝色警示光从边缘收缩
- 中性情绪:保持当前主题色
GMV增速光效:根据成交额增速渲染光效强度
- 增速>50%:全屏光效强度100%,配合金色粒子效果
- 增速10-50%:光效强度60%,柔和过渡
- 增速<10%:光效强度30%,提示主播调整策略
2.3 悬浮导航的直播适配
传统直播软件采用顶部固定工具栏,占用宝贵竖屏空间。HarmonyOS 6的悬浮导航特性带来:
- 底部悬浮页签:不遮挡直播画面,支持透明度三档调节(55%/70%/85%)
- 智能体状态徽章:每个页签实时显示对应智能体运行状态(空闲/思考/执行/完成/异常)
- 流量实时徽章:导航栏中央显示当前在线人数与GMV,点击展开详细数据
- 快捷操作入口:长按导航栏唤起快捷菜单,一键切换讲解模式/紧急下播/智能体开关
三、项目实战:"直播智脑"架构设计
3.1 应用场景与功能规划
面向HarmonyOS PC的电商直播场景,核心功能包括:
| 功能模块 | 技术实现 | 沉浸光感/HMAF应用 |
|---|---|---|
| 主直播画面窗口 | Video + XComponent |
流量脉搏光效背景 |
| 悬浮直播导航 | HdsTabs + systemMaterialEffect |
玻璃拟态页签,智能体状态徽章 |
| 讲解智能体 | HMAF Agent Framework Kit | 讲解状态光效反馈 |
| 互动智能体 | HMAF + NLP意图识别 | 弹幕情绪光效驱动 |
| 洞察智能体 | HMAF + 时序预测模型 | 数据预警光效提示 |
| 风控智能体 | HMAF + 敏感词检测 | 违规警示红光闪烁 |
| 浮动弹幕窗口 | 子窗口 + List |
弹幕情感色光效同步 |
| 浮动数据看板 | 子窗口 + HdsNavigation |
数据主题色光效同步 |
| 浮动商品橱窗 | 子窗口 + Grid |
商品类别色光效 |
3.2 技术架构图
┌─────────────────────────────────────────────────────────────┐
│ HarmonyOS 6 PC 主窗口 │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ 沉浸光感层 (AmbientLightLayer) │ │
│ │ 流量脉搏光效 + 弹幕情绪光效 + GMV增速光效 │ │
│ └───────────────────────────────────────────────────────┘ │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ 主直播画面 (Video + XComponent) │ │
│ │ 摄像头画面 + 商品展示 + 美颜特效 │ │
│ └───────────────────────────────────────────────────────┘ │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ 悬浮直播导航 (FloatNavigation) │ │
│ │ 直播/互动/数据/商品 页签 + 智能体状态徽章 + 流量徽章 │ │
│ └───────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
┌─────────────────────┼─────────────────────┐
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ 浮动弹幕窗口 │ │ 浮动数据看板 │ │ 浮动商品橱窗 │
│ (弹幕+情感色) │ │ (实时GMV+光效)│ │ (SKU+类别色) │
└───────────────┘ └───────────────┘ └───────────────┘
│
┌─────────────────────┼─────────────────────┐
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ 讲解智能体 │ │ 互动智能体 │ │ 洞察智能体 │
│ (LLM生成文案) │ │ (NLP弹幕应答) │ │ (时序预测库存) │
└───────────────┘ └───────────────┘ └───────────────┘
│
▼
┌───────────────┐
│ 风控智能体 │
│ (敏感词+违规检测)│
└───────────────┘
四、环境配置与模块依赖
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.MediaKit": "1.0.0",
"@kit.NNKit": "1.0.0"
}
}
4.2 权限声明(module.json5)
{
"module": {
"requestPermissions": [
{
"name": "ohos.permission.CAMERA",
"reason": "$string:camera_permission_reason"
},
{
"name": "ohos.permission.MICROPHONE",
"reason": "$string:mic_permission_reason"
},
{
"name": "ohos.permission.INTERNET",
"reason": "$string:internet_permission_reason"
},
{
"name": "ohos.permission.SYSTEM_FLOAT_WINDOW",
"reason": "$string:float_window_permission_reason"
},
{
"name": "ohos.permission.DISTRIBUTED_DATASYNC",
"reason": "$string:distributed_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('live_main');
// 启用全屏沉浸模式,隐藏系统标题栏
await mainWindow.setWindowLayoutFullScreen(true);
// 设置窗口背景为透明,允许沉浸光效层透传
await mainWindow.setWindowBackgroundColor('#00000000');
// 加载主页面
windowStage.loadContent('pages/LiveControlPage', (err) => {
if (err) {
console.error('Failed to load LiveControlPage:', err.message);
}
});
// 初始化窗口焦点监听,用于光效联动
mainWindow.on('windowFocusChange', (isFocused: boolean) => {
AppStorage.setOrCreate('window_focused', isFocused);
});
}
onWindowStageDestroy(): void {
// 清理窗口资源
}
}
5.2 流量脉搏光效系统(TrafficLightEffect.ets)
// entry/src/main/ets/components/TrafficLightEffect.ets
import { HdsNavigation, SystemMaterialEffect } from '@kit.UIDesignKit';
// 直播阶段枚举
export enum LivePhase {
COLD_START = 'cold_start', // 冷启动 <100人
GROWTH = 'growth', // 成长期 100-1000人
EXPLOSION = 'explosion', // 爆发期 1000-10000人
PEAK = 'peak' // 峰值期 >10000人
}
// 弹幕情感枚举
export enum SentimentType {
POSITIVE = 'positive', // 正面 >0.6
NEUTRAL = 'neutral', // 中性 -0.3~0.6
NEGATIVE = 'negative' // 负面 <-0.3
}
// 智能体状态枚举
export enum AgentState {
IDLE = 'idle',
THINKING = 'thinking',
EXECUTING = 'executing',
COMPLETED = 'completed',
ERROR = 'error'
}
@Component
export struct TrafficLightEffect {
@Prop onlineCount: number = 0;
@Prop gmvSpeed: number = 0; // GMV增速百分比
@Prop sentiment: SentimentType = SentimentType.NEUTRAL;
@State lightIntensity: number = 0.6;
@State pulsePhase: number = 0;
// 流量阶段主题色映射
private phaseColors: Map<LivePhase, string> = new Map([
[LivePhase.COLD_START, '#1E3A8A'], // 深海蓝
[LivePhase.GROWTH, '#10B981'], // 薄荷绿
[LivePhase.EXPLOSION, '#F59E0B'], // 活力橙
[LivePhase.PEAK, '#EF4444'] // 炽烈红
]);
// 弹幕情感色映射
private sentimentColors: Map<SentimentType, string> = new Map([
[SentimentType.POSITIVE, '#FCD34D'], // 暖金色
[SentimentType.NEUTRAL, '#6B7280'], // 中性灰
[SentimentType.NEGATIVE, '#60A5FA'] // 冰蓝色
]);
// 脉冲周期映射(毫秒)
private pulseDurations: Map<LivePhase, number> = new Map([
[LivePhase.COLD_START, 4000],
[LivePhase.GROWTH, 2000],
[LivePhase.EXPLOSION, 1000],
[LivePhase.PEAK, 500]
]);
private getCurrentPhase(): LivePhase {
if (this.onlineCount < 100) return LivePhase.COLD_START;
if (this.onlineCount < 1000) return LivePhase.GROWTH;
if (this.onlineCount < 10000) return LivePhase.EXPLOSION;
return LivePhase.PEAK;
}
private getThemeColor(): string {
return this.phaseColors.get(this.getCurrentPhase()) || '#1E3A8A';
}
private getSentimentColor(): string {
return this.sentimentColors.get(this.sentiment) || '#6B7280';
}
private getPulseDuration(): number {
return this.pulseDurations.get(this.getCurrentPhase()) || 4000;
}
// GMV增速影响光效强度
private getIntensityByGMV(): number {
if (this.gmvSpeed > 50) return 1.0;
if (this.gmvSpeed > 10) 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.getIntensityByGMV() * 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
})
// 中层:弹幕情感光效(底部渐变)
Column()
.width('100%')
.height(300)
.backgroundColor(this.getSentimentColor())
.opacity(this.sentiment === SentimentType.NEUTRAL ? 0.03 : 0.12)
.blur(100)
.position({ x: 0, y: '70%' })
.linearGradient({
direction: GradientDirection.Top,
colors: [
[this.getSentimentColor(), 0.0],
['transparent', 1.0]
]
})
.animation({
duration: 2000,
curve: Curve.EaseInOut
})
// 顶层:GMV增速粒子效果(仅在爆发期显示)
if (this.getCurrentPhase() === LivePhase.EXPLOSION || this.getCurrentPhase() === LivePhase.PEAK) {
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('#FCD34D')
.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四层智能体调度器(LiveAgentScheduler.ets)
// entry/src/main/ets/agents/LiveAgentScheduler.ets
import { hmaf } from '@kit.AgentFrameworkKit';
import { intents } from '@kit.IntentsKit';
// 智能体类型枚举
export enum AgentType {
PRESENTER = 'presenter', // 讲解智能体
INTERACTION = 'interaction', // 互动智能体
INSIGHT = 'insight', // 洞察智能体
RISK = 'risk' // 风控智能体
}
// 智能体人格色彩映射
export enum AgentPersonality {
PRESENTER = '#8B5CF6', // 智慧紫
INTERACTION = '#F97316', // 活力橙
INSIGHT = '#06B6D4', // 洞察青
RISK = '#EF4444' // 警示红
}
export class LiveAgentScheduler {
private static instance: LiveAgentScheduler;
private hmafSession: hmaf.AgentSession | null = null;
private intentEngine: intents.IntentEngine | null = null;
// 智能体状态管理
private agentStates: Map<string, AgentState> = new Map([
['presenter-1', AgentState.IDLE],
['interaction-1', AgentState.IDLE],
['insight-1', AgentState.IDLE],
['risk-1', AgentState.IDLE]
]);
private constructor() {}
static getInstance(): LiveAgentScheduler {
if (!LiveAgentScheduler.instance) {
LiveAgentScheduler.instance = new LiveAgentScheduler();
}
return LiveAgentScheduler.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: ['live_commerce', 'product_qa', 'sentiment_analysis', 'risk_detection']
});
// 注册四大智能体
await this.registerAgents();
// 启动状态监听
this.startStateMonitoring();
}
private async registerAgents(): Promise<void> {
// 1. 讲解智能体:基于LLM生成商品解说词
await this.hmafSession?.registerAgent({
agentId: 'presenter-1',
agentType: AgentType.PRESENTER,
capabilities: ['product_description', 'selling_point_extraction', 'script_generation'],
modelConfig: {
modelType: 'llm',
temperature: 0.7,
maxTokens: 512
}
});
// 2. 互动智能体:NLP处理弹幕问答
await this.hmafSession?.registerAgent({
agentId: 'interaction-1',
agentType: AgentType.INTERACTION,
capabilities: ['intent_recognition', 'knowledge_retrieval', 'response_generation', 'sentiment_analysis'],
modelConfig: {
modelType: 'llm',
temperature: 0.5,
maxTokens: 256
}
});
// 3. 洞察智能体:时序预测与数据洞察
await this.hmafSession?.registerAgent({
agentId: 'insight-1',
agentType: AgentType.INSIGHT,
capabilities: ['time_series_prediction', 'anomaly_detection', 'inventory_forecast'],
modelConfig: {
modelType: 'timeseries',
predictionHorizon: 30 // 预测未来30分钟
}
});
// 4. 风控智能体:敏感词与违规检测
await this.hmafSession?.registerAgent({
agentId: 'risk-1',
agentType: AgentType.RISK,
capabilities: ['sensitive_word_detection', 'content_moderation', 'compliance_check'],
modelConfig: {
modelType: 'classification',
threshold: 0.85
}
});
}
// 主播发送讲解任务
async sendPresentationTask(productId: string, style: string): Promise<string> {
this.updateAgentState('presenter-1', AgentState.THINKING);
const result = await this.hmafSession?.sendTask({
targetAgent: 'presenter-1',
taskType: 'generate_script',
payload: {
productId: productId,
style: style, // 'professional', 'casual', 'enthusiastic'
duration: 60 // 60秒讲解词
}
});
this.updateAgentState('presenter-1', AgentState.COMPLETED);
return result?.content || '';
}
// 处理弹幕互动
async handleDanmaku(danmakuText: string, userId: string): Promise<{ reply: string; sentiment: number }> {
this.updateAgentState('interaction-1', AgentState.EXECUTING);
// 先进行风控检测
const riskResult = await this.hmafSession?.sendTask({
targetAgent: 'risk-1',
taskType: 'check_content',
payload: { content: danmakuText }
});
if (riskResult?.isViolated) {
this.updateAgentState('interaction-1', AgentState.ERROR);
return { reply: '', sentiment: -1 };
}
// 意图识别与应答
const intent = await this.intentEngine?.parseIntent(danmakuText);
const reply = await this.hmafSession?.sendTask({
targetAgent: 'interaction-1',
taskType: 'generate_reply',
payload: {
intent: intent,
originalText: danmakuText,
userId: userId
}
});
// 情感分析
const sentimentResult = await this.hmafSession?.sendTask({
targetAgent: 'interaction-1',
taskType: 'analyze_sentiment',
payload: { text: danmakuText }
});
this.updateAgentState('interaction-1', AgentState.COMPLETED);
return {
reply: reply?.content || '',
sentiment: sentimentResult?.score || 0
};
}
// 实时数据洞察
async generateInsight(currentGMV: number, onlineCount: number): Promise<string> {
this.updateAgentState('insight-1', AgentState.THINKING);
const insight = await this.hmafSession?.sendTask({
targetAgent: 'insight-1',
taskType: 'generate_insight',
payload: {
currentGMV: currentGMV,
onlineCount: onlineCount,
timestamp: Date.now()
}
});
this.updateAgentState('insight-1', AgentState.COMPLETED);
return insight?.content || '';
}
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);
});
}
}
5.4 悬浮直播导航(LiveFloatNavigation.ets)
// entry/src/main/ets/components/LiveFloatNavigation.ets
import { window } from '@kit.ArkUI';
import { AgentState, AgentType, AgentPersonality } from '../agents/LiveAgentScheduler';
import { LivePhase, SentimentType } from './TrafficLightEffect';
interface NavItem {
id: string;
icon: Resource;
label: string;
page: string;
agentType?: AgentType;
}
@Component
export struct LiveFloatNavigation {
@State currentIndex: number = 0;
@State navTransparency: number = 0.70;
@State isExpanded: boolean = false;
@State bottomAvoidHeight: number = 0;
@State onlineCount: number = 0;
@State currentGMV: number = 0;
@State livePhase: LivePhase = LivePhase.COLD_START;
@State agentStates: Map<string, AgentState> = new Map([
['presenter-1', AgentState.IDLE],
['interaction-1', AgentState.IDLE],
['insight-1', AgentState.IDLE],
['risk-1', AgentState.IDLE]
]);
private navItems: NavItem[] = [
{ id: 'live', icon: $r('app.media.ic_live'), label: '直播', page: 'LivePage' },
{ id: 'interaction', icon: $r('app.media.ic_chat'), label: '互动', page: 'InteractionPage', agentType: AgentType.INTERACTION },
{ id: 'data', icon: $r('app.media.ic_chart'), label: '数据', page: 'DataPage', agentType: AgentType.INSIGHT },
{ id: 'product', icon: $r('app.media.ic_package'), label: '商品', page: 'ProductPage', agentType: AgentType.PRESENTER },
{ 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('live_metrics', (metrics: { onlineCount: number; gmv: number }) => {
this.onlineCount = metrics.onlineCount;
this.currentGMV = metrics.gmv;
this.updateLivePhase();
});
}
private updateLivePhase(): void {
if (this.onlineCount < 100) this.livePhase = LivePhase.COLD_START;
else if (this.onlineCount < 1000) this.livePhase = LivePhase.GROWTH;
else if (this.onlineCount < 10000) this.livePhase = LivePhase.EXPLOSION;
else this.livePhase = LivePhase.PEAK;
}
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.PRESENTER]: 'presenter-1',
[AgentType.INTERACTION]: 'interaction-1',
[AgentType.INSIGHT]: 'insight-1',
[AgentType.RISK]: 'risk-1'
};
return this.agentStates.get(agentIdMap[item.agentType]) || AgentState.IDLE;
}
private getPhaseColor(): string {
const colors: Record<LivePhase, string> = {
[LivePhase.COLD_START]: '#1E3A8A',
[LivePhase.GROWTH]: '#10B981',
[LivePhase.EXPLOSION]: '#F59E0B',
[LivePhase.PEAK]: '#EF4444'
};
return colors[this.livePhase];
}
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.onlineCount.toLocaleString()}`)
.fontSize(13)
.fontColor('#FFFFFF')
.fontWeight(FontWeight.Bold)
Text('在线观众')
.fontSize(10)
.fontColor('rgba(255,255,255,0.6)')
}
.layoutWeight(1)
Column() {
Text(`¥${(this.currentGMV / 10000).toFixed(2)}万`)
.fontSize(13)
.fontColor('#FCD34D')
.fontWeight(FontWeight.Bold)
Text('实时GMV')
.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<LivePhase, string> = {
[LivePhase.COLD_START]: '冷启动',
[LivePhase.GROWTH]: '成长期',
[LivePhase.EXPLOSION]: '爆发期',
[LivePhase.PEAK]: '峰值期'
};
return labels[this.livePhase];
}
@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 弹幕互动面板(DanmakuPanel.ets)
// entry/src/main/ets/components/DanmakuPanel.ets
import { LiveAgentScheduler } from '../agents/LiveAgentScheduler';
import { SentimentType } from './TrafficLightEffect';
interface DanmakuItem {
id: string;
userId: string;
nickname: string;
content: string;
sentiment: number; // -1~1
sentimentType: SentimentType;
timestamp: number;
isReply: boolean; // 是否已自动回复
replyContent?: string;
}
@Component
export struct DanmakuPanel {
@State danmakuList: DanmakuItem[] = [];
@State autoReplyEnabled: boolean = true;
@State sentimentFilter: SentimentType | 'all' = 'all';
private scheduler: LiveAgentScheduler = LiveAgentScheduler.getInstance();
private listScroller: ListScroller = new ListScroller();
aboutToAppear(): void {
// 模拟弹幕数据接入
this.startDanmakuSimulation();
}
private startDanmakuSimulation(): void {
// 实际项目中应接入直播SDK的弹幕接口
setInterval(() => {
const mockDanmaku: DanmakuItem = {
id: `dm_${Date.now()}`,
userId: `user_${Math.floor(Math.random() * 1000)}`,
nickname: `观众${Math.floor(Math.random() * 1000)}`,
content: this.getMockContent(),
sentiment: Math.random() * 2 - 1,
sentimentType: this.calculateSentimentType(Math.random() * 2 - 1),
timestamp: Date.now(),
isReply: false
};
this.danmakuList.unshift(mockDanmaku);
if (this.danmakuList.length > 100) {
this.danmakuList.pop();
}
// 自动回复处理
if (this.autoReplyEnabled && !mockDanmaku.isReply) {
this.handleAutoReply(mockDanmaku);
}
// 同步情感光效到全局
AppStorage.setOrCreate('current_sentiment', mockDanmaku.sentimentType);
}, 2000);
}
private getMockContent(): string {
const contents = [
'这个多少钱?', '好用吗?', '已下单!', '主播讲解很详细',
'质量怎么样?', '能便宜点吗?', '发货快吗?', '颜色有哪些?',
'支持退换吗?', '想要链接', '太贵了', '比其他家贵',
'已关注', '主播好美', '产品质量不错', '物流太慢了'
];
return contents[Math.floor(Math.random() * contents.length)];
}
private calculateSentimentType(score: number): SentimentType {
if (score > 0.6) return SentimentType.POSITIVE;
if (score < -0.3) return SentimentType.NEGATIVE;
return SentimentType.NEUTRAL;
}
private async handleAutoReply(danmaku: DanmakuItem): Promise<void> {
const result = await this.scheduler.handleDanmaku(danmaku.content, danmaku.userId);
if (result.reply) {
const index = this.danmakuList.findIndex(item => item.id === danmaku.id);
if (index !== -1) {
this.danmakuList[index] = {
...this.danmakuList[index],
isReply: true,
replyContent: result.reply
};
}
}
}
private getSentimentColor(type: SentimentType): string {
const colors: Record<SentimentType, string> = {
[SentimentType.POSITIVE]: '#FCD34D',
[SentimentType.NEUTRAL]: '#9CA3AF',
[SentimentType.NEGATIVE]: '#60A5FA'
};
return colors[type];
}
private getSentimentIcon(type: SentimentType): string {
const icons: Record<SentimentType, string> = {
[SentimentType.POSITIVE]: '👍',
[SentimentType.NEUTRAL]: '💬',
[SentimentType.NEGATIVE]: '⚠️'
};
return icons[type];
}
build() {
Column() {
// 面板标题栏
Row() {
Text('💬 实时弹幕')
.fontSize(16)
.fontColor('#FFFFFF')
.fontWeight(FontWeight.Bold)
Row({ space: 8 }) {
Toggle({ type: ToggleType.Switch, isOn: this.autoReplyEnabled })
.selectedColor('#10B981')
.onChange((isOn: boolean) => {
this.autoReplyEnabled = isOn;
})
Text('自动回复')
.fontSize(12)
.fontColor('rgba(255,255,255,0.7)')
}
}
.width('100%')
.height(50)
.padding({ left: 16, right: 16 })
.justifyContent(FlexAlign.SpaceBetween)
// 情感过滤标签
Row({ space: 8 }) {
this.buildFilterChip('全部', 'all');
this.buildFilterChip('正面', SentimentType.POSITIVE);
this.buildFilterChip('中性', SentimentType.NEUTRAL);
this.buildFilterChip('负面', SentimentType.NEGATIVE);
}
.width('100%')
.height(40)
.padding({ left: 16, right: 16 })
// 弹幕列表
List({ scroller: this.listScroller }) {
ForEach(this.getFilteredDanmaku(), (item: DanmakuItem) => {
ListItem() {
Column() {
Row() {
Text(`${this.getSentimentIcon(item.sentimentType)} ${item.nickname}`)
.fontSize(12)
.fontColor(this.getSentimentColor(item.sentimentType))
.fontWeight(FontWeight.Medium)
Text(this.formatTime(item.timestamp))
.fontSize(10)
.fontColor('rgba(255,255,255,0.4)')
}
.width('100%')
.justifyContent(FlexAlign.SpaceBetween)
Text(item.content)
.fontSize(13)
.fontColor('#FFFFFF')
.margin({ top: 4, bottom: 4 })
.maxLines(2)
.textOverflow({ overflow: TextOverflow.Ellipsis })
if (item.isReply && item.replyContent) {
Row() {
Text(`🤖 ${item.replyContent}`)
.fontSize(11)
.fontColor('#10B981')
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
}
.width('100%')
.padding(8)
.backgroundColor('rgba(16, 185, 129, 0.1)')
.borderRadius(8)
.margin({ top: 4 })
}
}
.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: SentimentType | 'all'): void {
const isSelected = this.sentimentFilter === 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.sentimentFilter = value;
})
}
private getFilteredDanmaku(): DanmakuItem[] {
if (this.sentimentFilter === 'all') return this.danmakuList;
return this.danmakuList.filter(item => item.sentimentType === this.sentimentFilter);
}
private formatTime(timestamp: number): string {
const date = new Date(timestamp);
return `${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`;
}
}
5.6 浮动数据看板窗口(DataDashboardWindow.ets)
// entry/src/main/ets/windows/DataDashboardWindow.ets
import { window } from '@kit.WindowManagerKit';
@Component
export struct DataDashboardWindow {
@State currentGMV: number = 0;
@State targetGMV: number = 500000; // 目标50万
@State onlineCount: number = 0;
@State peakOnline: number = 0;
@State conversionRate: number = 0;
@State avgWatchTime: number = 0;
aboutToAppear(): void {
// 监听实时数据
AppStorage.watch('live_metrics', (metrics: { onlineCount: number; gmv: number }) => {
this.onlineCount = metrics.onlineCount;
this.currentGMV = metrics.gmv;
if (metrics.onlineCount > this.peakOnline) {
this.peakOnline = metrics.onlineCount;
}
// 模拟转化率与观看时长
this.conversionRate = Math.min(15, 2 + metrics.onlineCount / 1000);
this.avgWatchTime = Math.min(300, 30 + metrics.onlineCount / 100);
});
}
private getGMVProgress(): number {
return Math.min(100, (this.currentGMV / this.targetGMV) * 100);
}
private getProgressColor(): string {
const progress = this.getGMVProgress();
if (progress < 30) return '#60A5FA';
if (progress < 70) return '#10B981';
if (progress < 90) return '#F59E0B';
return '#EF4444';
}
build() {
Column() {
// 标题栏
Row() {
Text('📊 实时数据看板')
.fontSize(16)
.fontColor('#FFFFFF')
.fontWeight(FontWeight.Bold)
Text('实时')
.fontSize(11)
.fontColor('#10B981')
.backgroundColor('rgba(16, 185, 129, 0.2)')
.padding({ left: 8, right: 8, top: 2, bottom: 2 })
.borderRadius(10)
}
.width('100%')
.height(50)
.padding({ left: 16, right: 16 })
.justifyContent(FlexAlign.SpaceBetween)
// GMV进度环
Stack() {
// 背景圆环
Circle()
.width(140)
.height(140)
.fill('transparent')
.stroke('rgba(255,255,255,0.1)')
.strokeWidth(12)
// 进度圆环
Circle()
.width(140)
.height(140)
.fill('transparent')
.stroke(this.getProgressColor())
.strokeWidth(12)
.strokeDashArray([this.getGMVProgress() * 4.4, 440])
.strokeLineCap(LineCapStyle.Round)
.animation({
duration: 1000,
curve: Curve.EaseInOut
})
.shadow({
radius: 15,
color: this.getProgressColor(),
offsetX: 0,
offsetY: 0
})
// 中心数据
Column() {
Text(`¥${(this.currentGMV / 10000).toFixed(1)}万`)
.fontSize(20)
.fontColor('#FFFFFF')
.fontWeight(FontWeight.Bold)
Text(`目标: ¥${(this.targetGMV / 10000).toFixed(0)}万`)
.fontSize(11)
.fontColor('rgba(255,255,255,0.5)')
.margin({ top: 4 })
}
}
.width('100%')
.height(180)
.margin({ top: 16, bottom: 16 })
// 关键指标网格
Grid() {
GridItem() {
this.buildMetricCard('👥 在线人数', this.onlineCount.toLocaleString(), '#60A5FA')
}
GridItem() {
this.buildMetricCard('📈 峰值在线', this.peakOnline.toLocaleString(), '#8B5CF6')
}
GridItem() {
this.buildMetricCard('💰 转化率', `${this.conversionRate.toFixed(1)}%`, '#10B981')
}
GridItem() {
this.buildMetricCard('⏱️ 平均观看', `${Math.floor(this.avgWatchTime / 60)}分${this.avgWatchTime % 60}秒`, '#F59E0B')
}
}
.columnsTemplate('1fr 1fr')
.rowsTemplate('1fr 1fr')
.width('100%')
.height(200)
.padding({ left: 12, right: 12 })
.gap(12)
// 智能体洞察建议
Column() {
Text('🤖 智能体洞察')
.fontSize(14)
.fontColor('#FFFFFF')
.fontWeight(FontWeight.Medium)
.margin({ bottom: 8 })
Text(this.getInsightText())
.fontSize(12)
.fontColor('rgba(255,255,255,0.7)')
.maxLines(3)
.textOverflow({ overflow: TextOverflow.Ellipsis })
}
.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)
}
@Builder
buildMetricCard(label: string, value: string, color: string): void {
Column() {
Text(label)
.fontSize(11)
.fontColor('rgba(255,255,255,0.6)')
.margin({ bottom: 8 })
Text(value)
.fontSize(18)
.fontColor(color)
.fontWeight(FontWeight.Bold)
}
.width('100%')
.height('100%')
.backgroundColor('rgba(255,255,255,0.05)')
.borderRadius(12)
.justifyContent(FlexAlign.Center)
}
private getInsightText(): string {
if (this.onlineCount < 100) {
return '当前处于冷启动阶段,建议讲解智能体加强商品卖点输出,互动智能体主动发起话题引导评论。';
} else if (this.conversionRate < 3) {
return '流量增长但转化率偏低,洞察智能体分析发现用户价格敏感度较高,建议调整促销策略。';
} else if (this.getGMVProgress() > 80) {
return '即将达成今日GMV目标!建议风控智能体加强内容审核,确保冲刺阶段合规安全。';
}
return '直播数据表现平稳,四大智能体协同运行正常,继续保持当前节奏。';
}
}
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`); // 12%透明度
// 同步窗口阴影光效
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 createDanmakuWindow(): Promise<window.Window> {
const danmakuWindow = await window.createWindow({
name: 'danmaku_float',
windowType: window.WindowType.TYPE_FLOAT,
ctx: getContext()
});
await danmakuWindow.moveWindowTo(1200, 100);
await danmakuWindow.resize(320, 600);
await danmakuWindow.setWindowLayoutFullScreen(true);
await danmakuWindow.setWindowBackgroundColor('#00000000');
this.registerSubWindow('danmaku', danmakuWindow);
return danmakuWindow;
}
// 创建浮动数据看板窗口
async createDataWindow(): Promise<window.Window> {
const dataWindow = await window.createWindow({
name: 'data_float',
windowType: window.WindowType.TYPE_FLOAT,
ctx: getContext()
});
await dataWindow.moveWindowTo(50, 100);
await dataWindow.resize(300, 520);
await dataWindow.setWindowLayoutFullScreen(true);
await dataWindow.setWindowBackgroundColor('#00000000');
this.registerSubWindow('data', dataWindow);
return dataWindow;
}
// 创建浮动商品橱窗窗口
async createProductWindow(): Promise<window.Window> {
const productWindow = await window.createWindow({
name: 'product_float',
windowType: window.WindowType.TYPE_FLOAT,
ctx: getContext()
});
await productWindow.moveWindowTo(50, 650);
await productWindow.resize(300, 280);
await productWindow.setWindowLayoutFullScreen(true);
await productWindow.setWindowBackgroundColor('#00000000');
this.registerSubWindow('product', productWindow);
return productWindow;
}
}
5.8 主页面集成(LiveControlPage.ets)
// entry/src/main/ets/pages/LiveControlPage.ets
import { TrafficLightEffect, LivePhase, SentimentType } from '../components/TrafficLightEffect';
import { LiveFloatNavigation } from '../components/LiveFloatNavigation';
import { DanmakuPanel } from '../components/DanmakuPanel';
import { DataDashboardWindow } from '../windows/DataDashboardWindow';
import { WindowLightSync } from '../utils/WindowLightSync';
import { LiveAgentScheduler } from '../agents/LiveAgentScheduler';
@Entry
@Component
struct LiveControlPage {
@State currentPage: string = 'LivePage';
@State onlineCount: number = 156;
@State currentGMV: number = 128000;
@State currentSentiment: SentimentType = SentimentType.NEUTRAL;
@State isLiveStarted: boolean = false;
private windowSync: WindowLightSync = WindowLightSync.getInstance();
private scheduler: LiveAgentScheduler = LiveAgentScheduler.getInstance();
aboutToAppear(): async () => {
// 初始化智能体调度器
await this.scheduler.initialize();
// 初始化窗口管理
await this.initializeWindows();
// 启动数据模拟
this.startMetricsSimulation();
// 监听页面切换
AppStorage.watch('nav_page_change', (page: string) => {
this.currentPage = page;
});
}
private async initializeWindows(): Promise<void> {
// 创建三个浮动子窗口
await this.windowSync.createDanmakuWindow();
await this.windowSync.createDataWindow();
await this.windowSync.createProductWindow();
}
private startMetricsSimulation(): void {
setInterval(() => {
// 模拟流量波动
const fluctuation = Math.floor(Math.random() * 50) - 20;
this.onlineCount = Math.max(50, this.onlineCount + fluctuation);
this.currentGMV += Math.floor(Math.random() * 5000);
// 同步到全局状态
AppStorage.setOrCreate('live_metrics', {
onlineCount: this.onlineCount,
gmv: this.currentGMV
});
// 同步光效
const phase = this.getCurrentPhase();
const themeColor = this.getPhaseColor(phase);
this.windowSync.syncGlobalLightEffect(themeColor, this.getIntensityByGMV());
}, 3000);
}
private getCurrentPhase(): LivePhase {
if (this.onlineCount < 100) return LivePhase.COLD_START;
if (this.onlineCount < 1000) return LivePhase.GROWTH;
if (this.onlineCount < 10000) return LivePhase.EXPLOSION;
return LivePhase.PEAK;
}
private getPhaseColor(phase: LivePhase): string {
const colors: Record<LivePhase, string> = {
[LivePhase.COLD_START]: '#1E3A8A',
[LivePhase.GROWTH]: '#10B981',
[LivePhase.EXPLOSION]: '#F59E0B',
[LivePhase.PEAK]: '#EF4444'
};
return colors[phase];
}
private getIntensityByGMV(): number {
const gmvSpeed = this.currentGMV / 100000; // 假设基准
if (gmvSpeed > 50) return 1.0;
if (gmvSpeed > 10) return 0.6;
return 0.3;
}
build() {
Stack() {
// 底层:沉浸光效层
TrafficLightEffect({
onlineCount: this.onlineCount,
gmvSpeed: this.currentGMV / 100000,
sentiment: this.currentSentiment
})
// 中层:主内容区域
Column() {
this.buildHeader()
Stack() {
if (this.currentPage === 'LivePage') {
this.buildLivePage()
} else if (this.currentPage === 'InteractionPage') {
DanmakuPanel()
} else if (this.currentPage === 'DataPage') {
DataDashboardWindow()
} else if (this.currentPage === 'ProductPage') {
this.buildProductPage()
}
}
.layoutWeight(1)
}
.width('100%')
.height('100%')
// 顶层:悬浮导航
LiveFloatNavigation({
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.onlineCount.toLocaleString()} | GMV: ¥${(this.currentGMV / 10000).toFixed(2)}万`)
.fontSize(12)
.fontColor('rgba(255,255,255,0.6)')
.margin({ top: 4 })
}
.alignItems(HorizontalAlign.Start)
Row({ space: 12 }) {
Button(this.isLiveStarted ? '结束直播' : '开始直播')
.fontSize(13)
.fontColor('#FFFFFF')
.backgroundColor(this.isLiveStarted ? '#EF4444' : '#10B981')
.padding({ left: 20, right: 20, top: 8, bottom: 8 })
.borderRadius(20)
.onClick(() => {
this.isLiveStarted = !this.isLiveStarted;
if (this.isLiveStarted) {
// 启动讲解智能体
this.scheduler.sendPresentationTask('sku_001', 'enthusiastic');
}
})
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
buildLivePage(): void {
Column() {
// 直播画面占位(实际接入摄像头)
Stack() {
Column()
.width('100%')
.height('100%')
.backgroundColor('rgba(255,255,255,0.05)')
.borderRadius(16)
if (!this.isLiveStarted) {
Column() {
Text('📹')
.fontSize(48)
.margin({ bottom: 16 })
Text('点击"开始直播"启动智能体直播系统')
.fontSize(14)
.fontColor('rgba(255,255,255,0.6)')
}
} else {
Column() {
Text('🎥 直播中...')
.fontSize(16)
.fontColor('#10B981')
Text('讲解智能体运行中 | 互动智能体待命')
.fontSize(12)
.fontColor('rgba(255,255,255,0.5)')
.margin({ top: 8 })
}
}
}
.width('90%')
.height(400)
.margin({ top: 20, bottom: 20 })
// 快捷操作区
Row({ space: 16 }) {
this.buildQuickAction('🎁', '发福袋', '#F59E0B');
this.buildQuickAction('⚡', '秒杀', '#EF4444');
this.buildQuickAction('🎫', '优惠券', '#8B5CF6');
this.buildQuickAction('📢', '公告', '#06B6D4');
}
.margin({ bottom: 20 })
}
.width('100%')
.height('100%')
}
@Builder
buildQuickAction(icon: string, label: string, color: string): void {
Column() {
Text(icon)
.fontSize(24)
.margin({ bottom: 8 })
Text(label)
.fontSize(12)
.fontColor('#FFFFFF')
}
.width(70)
.height(80)
.backgroundColor(`${color}20`)
.borderRadius(16)
.border({ width: 1, color: `${color}40` })
.justifyContent(FlexAlign.Center)
.onClick(() => {
// 触发对应智能体任务
AppStorage.setOrCreate('quick_action', { type: label, color });
})
}
@Builder
buildProductPage(): void {
Column() {
Text('🛍️ 商品橱窗管理')
.fontSize(18)
.fontColor('#FFFFFF')
.fontWeight(FontWeight.Bold)
.margin({ top: 20, bottom: 20 })
List() {
ForEach([1, 2, 3, 4, 5], (index: number) => {
ListItem() {
Row() {
Column() {
Text(`商品 ${index}`)
.fontSize(14)
.fontColor('#FFFFFF')
Text(`¥${(99 + index * 50).toFixed(2)}`)
.fontSize(12)
.fontColor('#F59E0B')
.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.sendPresentationTask(`sku_00${index}`, 'professional');
})
}
.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: 'timeseries' |
洞察智能体预测GMV趋势 |
| 内容审核 | modelType: 'classification' |
风控智能体违规检测 |
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 直播状态光效映射
| 直播阶段 | 在线人数 | 主题色 | 脉冲周期 | 光效强度 |
|---|---|---|---|---|
| 冷启动 | <100 | 深海蓝 #1E3A8A | 4秒 | 30% |
| 成长期 | 100-1000 | 薄荷绿 #10B981 | 2秒 | 60% |
| 爆发期 | 1000-10000 | 活力橙 #F59E0B | 1秒 | 80% |
| 峰值期 | >10000 | 炽烈红 #EF4444 | 0.5秒 | 100% |
6.4 智能体状态徽章动画
| 智能体状态 | 徽章颜色 | 动画效果 | 直播含义 |
|---|---|---|---|
| 空闲 | #888888 | 静态 | 智能体待命 |
| 思考中 | #8B5CF6 | 呼吸脉冲 | LLM生成文案中 |
| 执行中 | #F97316 | 旋转进度 | 处理弹幕/数据中 |
| 已完成 | #10B981 | 静态 | 任务执行成功 |
| 异常 | #EF4444 | 快速闪烁 | 风控触发/错误 |
6.5 性能优化建议
- 光效渲染优化:使用
willChange: true标记频繁变化的动画层,避免全量重绘 - 智能体并发控制:通过
maxConcurrentAgents: 4限制并发,防止资源争抢 - 弹幕列表虚拟化:当弹幕超过100条时,使用
LazyForEach替代ForEach - 窗口管理:子窗口使用
TYPE_FLOAT类型,避免创建过多独立进程 - 数据节流:流量数据更新频率控制在3秒/次,避免UI频繁刷新
七、总结与展望
本文基于HarmonyOS 6(API 23)的HMAF智能体框架、悬浮导航与沉浸光感特性,构建了一套面向PC端电商直播的"直播智脑"系统。核心创新点包括:
- 四层智能体协作架构:讲解、互动、洞察、风控四大智能体通过HMAF的A2A模式实时协作,将主播从重复性工作中解放出来
- 流量脉搏光效系统:基于实时在线人数与GMV增速的动态光效渲染,让主播"看见"数据变化
- 悬浮直播导航:底部玻璃拟态导航承载四大模块,智能体状态徽章实时反馈,流量信息一键展开
- 多窗口光效联动:主窗口与三个浮动子窗口通过
WindowLightSync实现跨窗口光效同步,焦点感知自动调节 - 弹幕情感光效:NLP实时分析弹幕情感,正面情绪触发暖光脉冲,负面情绪触发冷光警示
随着HarmonyOS生态的持续发展,直播智能体将向着"数字人主播"“多模态交互”"跨设备直播协作"等方向演进。HMAF框架的分布式能力与HarmonyOS的跨端协同特性,将为直播电商带来"一机控全场、多屏协同播"的全新体验。
转载自:https://blog.csdn.net/u014727709/article/details/161227243
欢迎 👍点赞✍评论⭐收藏,欢迎指正
更多推荐



所有评论(0)