演示架构师-PPT大纲生成的HarmonyOS开发实践

App36-演示架构师:PPT大纲生成的HarmonyOS开发实践

引言

在职场沟通中,PPT演示文稿是仅次于口头表达的第二大信息传递载体。无论是产品发布会上的战略宣讲,还是内部周会上的项目汇报,一份结构清晰、逻辑严密的PPT大纲往往是成功演讲的基石。但现实是,大多数职场人并非专业的演示设计师------他们知道要讲什么,却不知道如何组织内容、如何划分章节、如何为每页幻灯片匹配合适的视觉元素。

据微软Office团队2024年发布的调研报告,全球每天有超过3500万场PPT演示在进行,但其中超过60%的演讲者表示「构建大纲」是他们最耗时的环节。更令人意外的是,受访者平均花费在PPT大纲设计上的时间,竟然超过了实际制作幻灯片的时间。这揭示了一个被长期忽视的痛点:内容结构化本身就是一个高门槛的脑力劳动。

正是在这样的背景下,我开发了「演示架构师」------一个基于HarmonyOS的AI PPT大纲生成工具。它的核心逻辑是:用户输入演示主题、目标受众和期望页数,系统通过AI能力自动生成一份结构化的演示文稿大纲,包含每页幻灯片的标题、要点列表和视觉建议。与传统的PPT模板工具不同,「演示架构师」不是简单地提供设计模板,而是真正介入内容层面------帮助用户构建「讲什么」的骨架。

本文将按照6A工作流(Align对齐、Architect架构、Atomize原子化、Approve审批、Automate自动化执行、Assess评估)来完整复盘「演示架构师」的设计与开发过程。文中将重点探讨PPT大纲结构化生成的核心挑战------场景化数据建模、多页幻灯片的逻辑连贯性、以及AI API Stub模式在前端先行开发中的应用。同时,我们将结合鸿蒙ArkUI框架、鸿蒙PC端适配策略以及鸿蒙Flutter框架的对比分析,为鸿蒙生态下的AI应用开发者提供体系化的技术参考。

---

一、Align对齐阶段:从模糊需求到精确规范

1.1 项目上下文分析

「演示架构师」是鸿蒙AI应用矩阵中的第36号应用,位于一个包含40个AI小应用的工程中。项目采用HarmonyOS NEXT(API 26)作为目标SDK,使用Stage模型和ArkTS/ArkUI声明式框架进行开发。在现有的应用分类体系中,它被划分到「AI创作」类别,与「文字抛光机」「名字炼金术」「镜头故事家」等应用共同构成了AI辅助内容创作的完整矩阵。

工程结构如下:

复制代码
e:\ai40\
├── entry/
│   ├── src/main/
│   │   ├── ets/pages/app36/Index.ets   # 应用主页面
│   │   ├── ets/pages/app1~40/          # 40个AI应用
│   │   ├── module.json5                # 模块配置
│   │   └── resources/                  # 资源文件
│   ├── build-profile.json5
│   └── oh-package.json5
├── build-profile.json5
└── oh-package.json5

通过分析兄弟应用(如app21「文字抛光机」、app35「家装计算器」、app37「镜头故事家」),我们识别出统一的设计模式:所有AI应用均采用Mock数据驱动的前端先行开发策略 ,通过generateMockData()方法模拟AI API的响应行为,在真实AI接口就绪前即可完成UI开发和交互验证。这种模式被称为AI API Stub模式,是鸿蒙生态中AI应用开发的推荐范式。

1.2 原始需求

「演示架构师」的原始需求可以概括为三个核心诉求:

  1. 主题输入:用户输入演示文稿的主题,如「人工智能发展趋势」「新能源汽车市场分析」
  2. 受众设定:用户指定目标受众,如「技术团队」「投资团队」「管理层」
  3. 页数控制:用户设定期望的幻灯片页数(3-30页范围)
  4. 大纲生成:系统生成结构化的演示大纲,每页包含标题、要点列表和视觉建议

这个需求看似简单直接,但在对齐阶段,我们需要挖掘出隐藏在表面之下的深层约束。

1.3 需求拆解与边界确认

在Align阶段,我们需要回答以下关键问题:

问题一:PPT大纲的「结构化」标准是什么?

一份专业的PPT大纲并非简单的标题列表,而是需要包含三个层次的信息:页面标题 (告诉观众这一页在讲什么)、核心要点 (支撑标题的论据或数据)、视觉建议(建议用什么类型的图表或视觉元素来呈现)。这三个层次的完整度,决定了生成的大纲是「可用」还是「敷衍」。

更重要的是,页面之间的逻辑关系必须连贯。第1页的封面引出主题,第2页的目录概述框架,第3-N页逐个展开论点,最后一页总结收尾。这种「起承转合」的结构是优秀演示文稿的共性特征,也是AI生成大纲时需要遵循的隐性规则。

问题二:受众如何影响大纲结构?

同一主题面对不同受众,大纲的结构和侧重点应该完全不同。以「人工智能发展趋势」为例:

  • 面对技术团队:侧重技术细节,如大模型参数规模、推理能力、多模态架构等,术语密度高
  • 面对投资团队:侧重商业价值,如市场规模、竞争格局、投资回报率等,数据驱动
  • 面对管理层:侧重战略影响,如组织变革、人才需求、风险评估等,决策导向

这意味着,受众参数不是简单的「标签」,而是大纲生成的核心约束条件。在大纲生成逻辑中,受众决定了内容的深度、广度、术语难度和论证方式。

问题三:页数如何影响信息密度?

用户设定的页数从3页到30页不等,跨度达到10倍。这意味着生成逻辑需要具备「弹性扩展」能力:

  • 3页大纲:封面 + 核心内容 + 总结,要点的信息密度极高
  • 10页大纲:封面 + 目录 + 6-7个主题页 + 总结,中等密度
  • 30页大纲:封面 + 目录 + 25+个主题页 + 总结,每个主题页聚焦一个细分观点

在Architect阶段,我们需要设计一种能够根据页数自适应调整内容粒度的机制。

问题四:视觉建议如何生成?

视觉建议是「演示架构师」区别于普通大纲生成器的核心差异化功能。它告诉用户每一页应该用什么视觉元素来辅助表达------是柱状图、饼图、时间轴,还是SWOT矩阵、雷达图、流程图。这些建议需要与页面内容高度相关,而不是随机分配。

问题五:边缘情况如何处理?

当用户输入的主题过于宽泛(如「科技」)、受众过于模糊(如「所有人」)、页数超出合理范围时,系统需要智能降级而非直接报错。我们设计了多层兜底策略:主题为空时使用默认主题,受众为空时默认为「通用受众」,页数超出3-30范围时自动钳制到边界值。

1.4 数据模型定义

基于以上分析,我们在对齐阶段定义了核心数据模型:

typescript 复制代码
// 单页幻灯片
interface SlideItem {
  title: string;      // 页面标题,如 "封面:人工智能发展趋势"
  points: string[];   // 核心要点,如 ["大模型演进", "多模态AI", "AI Agent"]
  visual: string;     // 视觉建议,如 "AI神经网络可视化背景图"
}

// 演示文稿结果
interface PresentationResult {
  slides: SlideItem[];   // 幻灯片列表
}

// 场景化数据
interface PresentationScenario {
  scenario: string;              // 场景键,如 "人工智能发展趋势_技术团队_10"
  result: PresentationResult;    // 对应的演示大纲
}

SlideItem是整个系统的核心数据单元。它的三个字段分别对应了演示文稿的三个设计维度:结构 (title决定了页面在整体叙述中的位置和角色)、内容 (points是页面要传达的核心信息)、视觉(visual是页面呈现方式的建议)。这三个维度的分离设计,使得我们可以独立地优化每个维度,而不影响其他两个。

PresentationScenario引入了场景键(Scenario Key)的概念。场景键由三个参数拼接而成:主题_受众_页数,例如人工智能发展趋势_技术团队_10。这种设计将多维度的用户输入压缩为一个可索引的字符串键,为后续的Mock数据匹配和AI API调用提供了统一的接口抽象。

1.5 共识文档关键结论

经过对齐讨论,我们达成了以下共识:

维度 决策
大纲结构 每页包含标题(title)、要点列表(points)、视觉建议(visual)三个字段
输入参数 3个参数:主题(自由文本)、受众(自由文本)、页数(3-30整数)
受众影响 受众作为核心约束条件,影响内容深度、术语难度和论证方式
页数弹性 支持3-30页的弹性范围,生成逻辑需自适应调整内容粒度
视觉建议 与页面内容高度相关,涵盖图表、矩阵、时间轴、流程图等类型
异常兜底 输入为空时使用默认值,页数超出范围时自动钳制
数据匹配 场景键精确匹配,匹配失败回退到默认场景
输出格式 JSON,固定Schema(PresentationResult),含slides数组

二、Architect架构阶段:从共识到系统设计

2.1 整体架构

「演示架构师」采用四层架构模型:UI交互层、状态管理层、数据匹配层和数据模型层。这种分层设计在鸿蒙ArkUI框架下实现了清晰的职责分离。

复制代码
┌────────────────────────────────────────────────────────────┐
│                       ArkUI 层                              │
│  ┌──────────────────────────────────────────────────────┐  │
│  │  返回按钮 + 标题"演示架构师" + 副标题                  │  │
│  └──────────────────────────────────────────────────────┘  │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐                   │
│  │ 主题输入  │ │ 受众输入  │ │ 页数输入  │                   │
│  └──────────┘ └──────────┘ └──────────┘                   │
│  ┌──────────────────────────────────────────────────────┐  │
│  │           生成大纲 按钮(紫色主题)                    │  │
│  └──────────────────────────────────────────────────────┘  │
│  ┌──────────────────────────────────────────────────────┐  │
│  │  演示大纲 结果区域(条件渲染)                         │  │
│  │  ┌────────────────────────────────────────────────┐  │  │
│  │  │ P1 封面 ··· 标题 + 要点 + 视觉建议               │  │  │
│  │  │ P2 目录 ··· 标题 + 要点 + 视觉建议               │  │  │
│  │  │ ...  ForEach 遍历渲染                           │  │  │
│  │  └────────────────────────────────────────────────┘  │  │
│  └──────────────────────────────────────────────────────┘  │
└────────────────────────────────────────────────────────────┘
                          │
                          ▼
┌────────────────────────────────────────────────────────────┐
│                状态管理层(@State)                          │
│  topic, audience, slides, showResult, currentResult         │
└────────────────────────────────────────────────────────────┘
                          │
                          ▼
┌────────────────────────────────────────────────────────────┐
│                 数据匹配层                                   │
│  getMockData(): 场景键拼接 → 遍历匹配 → 返回结果            │
│  callAIAPI(): 预留,Prompt构建 → API调用 → JSON解析         │
└────────────────────────────────────────────────────────────┘
                          │
                          ▼
┌────────────────────────────────────────────────────────────┐
│                 数据模型层                                   │
│  SlideItem { title, points: string[], visual }              │
│  PresentationResult { slides: SlideItem[] }                 │
│  PresentationScenario { scenario, result }                  │
│  mockScenarios: PresentationScenario[] (3个场景)            │
└────────────────────────────────────────────────────────────┘

2.2 SlideItem模型与三要素设计

SlideItem是整个系统最核心的数据单元。它的设计承载了演示文稿领域特有的「结构化表达」语义:

typescript 复制代码
interface SlideItem {
  title: string;      // "封面:人工智能发展趋势"
  points: string[];   // ["2025年AI技术全景展望", "演讲人:AI研究团队"]
  visual: string;     // "AI神经网络可视化背景图"
}

三个字段各有其设计考量:

title的设计:标题不仅描述页面内容,还隐式地传达了页面在整体叙述中的角色。我们采用「角色前缀 + 核心内容」的命名模式,如「封面:人工智能发展趋势」「总结与展望」。这种模式让用户一眼就能理解每页的定位------是开篇、是过渡、是论证还是收官。

points的设计:要点列表是页面的内容骨架。在设计中,我们遵循「3-5个要点」的黄金法则------少于3个要点,页面信息量不足;多于5个要点,观众认知负荷过重。在Mock数据中,每页的要点数量严格控制在2-5个之间,确保用户体验的一致性。

visual的设计:视觉建议是「演示架构师」的差异化功能。它不只是简单的「图表」或「文字」,而是具体到「AI神经网络可视化背景图」「SWOT分析矩阵」「全球AI监管地图」这种粒度。这种具体性来自于对页面内容的深度理解------只有当系统知道这一页在讲什么时,它才能给出真正有用的视觉建议。

2.3 场景键(Scenario Key)设计

场景键是Mock数据匹配的核心机制。我们采用「参数拼接」策略,将用户输入的3个参数按照固定顺序拼接为一个字符串键:

复制代码
场景键格式:主题_受众_页数
示例:人工智能发展趋势_技术团队_10

这种设计有以下几个优点:

  1. 精确匹配:每个场景键唯一对应一个预置的演示大纲,匹配逻辑清晰,不会出现二义性。
  2. 可读性好:场景键本身就是对场景的完整描述,无需查看数据内容就能理解场景含义。
  3. 扩展简单 :新增场景只需在mockScenarios数组中追加一个新元素,键名遵循相同格式即可。
  4. 兜底友好 :当用户输入的参数组合没有预置Mock数据时,自动回退到mockScenarios[0](默认场景),确保用户始终能获得结果。

与App35「家装计算器」的4参数场景键相比,「演示架构师」的场景键只有3个参数,但参数本身是自由文本而非枚举值。这意味着场景键的匹配空间是无限的,但Mock数据只能覆盖有限的场景------这正是AI API Stub模式的核心设计理念:用有限的Mock数据覆盖典型场景,用预留的API接口处理长尾场景。

2.4 currentResult的初始化模式

在ArkTS中,@State装饰的变量必须有初始值。对于PresentationResult这种复杂对象,我们不能简单地将currentResult初始化为null或undefined,因为ArkTS不支持any和unknown类型。我们采用了「空值初始化」模式:

typescript 复制代码
@State currentResult: PresentationResult = { slides: [] };

slides初始化为空数组。UI层通过this.showResult布尔变量控制结果区域的显示/隐藏,初始状态为false。当用户点击生成按钮且数据匹配成功后,currentResult被赋值为真实的演示大纲数据,同时showResult变为true,触发UI的条件渲染。

这种模式确保了在任何时刻,currentResult都是一个合法的PresentationResult对象,不会出现类型不一致导致的运行时错误。

2.5 AI API Stub模式设计

「演示架构师」当前采用Mock数据驱动,但架构上已经为真实AI API调用预留了接口。AI API Stub模式的核心设计如下:

typescript 复制代码
// 当前:Mock模式
generateMockData(): void {
  this.getMockData();  // 从预置场景中匹配数据
}

// 未来:AI API模式(预留)
// generateWithAI(): void {
//   const prompt: string = this.buildPrompt();
//   this.callAIAPI(prompt).then((result: PresentationResult) => {
//     this.currentResult = result;
//     this.showResult = true;
//   });
// }
//
// private buildPrompt(): string {
//   return `你是一位专业的演示文稿架构师。请为主题"${this.topic}"、
//           面向"${this.audience}"、生成${this.slides}页演示大纲。
//           每页需包含标题、3-5个要点和视觉建议。输出JSON格式。`;
// }

AI API Stub模式的核心价值在于:前端开发不依赖后端AI能力的就绪时间 。在UI开发、交互验证、数据流测试等阶段,Mock数据提供了确定性的、可重复的测试环境。当真实AI API就绪后,只需替换generateMockData()中的调用逻辑,UI层和数据模型层完全不需要修改。

这种模式在鸿蒙PC端开发中尤为重要。鸿蒙PC端的应用分发节奏与手机端不同,AI能力的接入需要经过更长的审核周期。AI API Stub模式让开发者可以在审核期间持续优化UI体验,而不会被后端阻塞。

2.6 紫色主题设计

「演示架构师」选择了紫色(#7B1FA2)作为主题色。这个选择基于以下专业考量:

  1. 创意与专业性的平衡:紫色在色彩心理学中代表创造力、智慧和专业,恰好契合「演示架构师」的定位------既有AI的创意生成能力,又有架构师的专业严谨。
  2. 视觉识别度:在40个AI应用矩阵中,紫色主题与蓝色(职场)、橙色(生活)、绿色(健康)等主题形成差异化,用户一眼就能识别出「AI创作」类应用。
  3. 演讲场景关联:紫色常被用于高端演讲和发布会场景(如TED演讲的经典配色),与演示文稿的商务场景天然契合。

三、Atomize原子化阶段:任务分解与执行

3.1 原子任务分解

在Atomize阶段,我们将整个开发任务分解为以下原子单元:

序号 原子任务 依赖 预估工时
A1 定义SlideItem、PresentationResult、PresentationScenario接口 无 5min
A2 编写3个场景Mock数据(含页数验证和要点验证) A1 40min
A3 实现主题、受众、页数3个TextInput输入控件 无 15min
A4 实现场景键拼接与Mock匹配逻辑 A1, A2 15min
A5 实现输入参数校验与边界处理逻辑 A3 10min
A6 实现Prompt构建逻辑(预留API调用) A1 10min
A7 实现生成按钮与交互逻辑 A3 10min
A8 实现Slide卡片列表UI(ForEach渲染) A1 25min
A9 实现紫色主题与整体UI整合 A3-A8 20min
A10 实现返回按钮与路由导航 无 5min

3.2 关键原子任务详解

A2:3场景Mock数据设计

Mock数据的设计需要兼顾多样性和专业性。我们为3个预置场景设计了不同主题、不同受众和不同页数的组合,以覆盖PPT大纲生成的主要使用场景。

场景一:人工智能发展趋势 / 技术团队 / 10页

这是最典型的AI主题演示场景,也是兜底场景。10页的篇幅符合「中等深度」的演示需求,结构从封面、目录、多个主题页到总结展望,形成了完整的「起承转合」叙述线。

10页幻灯片的逻辑结构如下:

  • P1 封面:确立主题和演讲者身份,建立第一印象
  • P2 目录:概述整体框架,让观众预览演讲结构
  • P3-P7 主体:5个主题页,分别覆盖大语言模型、多模态AI、AI Agent、AI安全治理、行业应用案例------这是最核心的论证部分
  • P8-P9 深化:行业应用案例(医疗、教育),将抽象的技术趋势落地到具体场景
  • P10 总结:挑战与机遇 + 总结展望,收束全文

这个场景的要点设计遵循了「从宏观到微观、从技术到应用」的递进逻辑。大语言模型和多模态AI是技术前沿,AI Agent是应用形态,AI安全是治理视角,行业应用是落地验证------五者形成了完整的论证闭环。

场景二:新能源汽车市场分析 / 投资团队 / 8页

这个场景面向投资团队,因此内容侧重数据和商业分析。8页的结构从市场概览到竞争格局、技术路线、供应链洞察、政策环境,最终落脚到投资机会和风险提示。每一页的视觉建议都匹配了投资分析领域的专业图表类型:柱状图、饼图、对比表、瀑布图、热力图、风险-收益矩阵。

值得注意的是,面向投资团队的大纲在设计上刻意减少了「技术细节」的权重,增加了「市场数据」「竞争分析」「政策影响」的权重。这正是受众参数影响大纲结构的具体体现------投资团队关心的是趋势和回报,而非技术实现细节。

场景三:团队建设与管理 / 管理层 / 6页

这个场景面向管理层(HR部门),聚焦于组织管理话题。6页的篇幅相对紧凑,重点覆盖了团队诊断、人才招聘、培养体系、激励保留和行动计划五个管理核心环节。视觉建议匹配了管理咨询领域的专业图表:雷达图、招聘漏斗、成长路径图、激励金字塔、甘特图。

面向管理层的大纲在设计上强调「可执行性」------每页的要点不仅是理论,更包含具体的行动指引。例如「新人90天融入计划」「导师制升级」「技能矩阵与培训地图」这些要点,都是可以直接转化为管理动作的具体建议。

场景键对照表:

场景键 主题 受众 页数 风格
人工智能发展趋势_技术团队_10 AI趋势 技术团队 10 技术深度型
新能源汽车市场分析_投资团队_8 汽车市场 投资团队 8 数据分析型
团队建设与管理_管理层_6 团队管理 管理层 6 行动导向型

3.3 场景键匹配逻辑

typescript 复制代码
getMockData(): void {
  let key: string = this.topic + '_' + this.audience + '_' + this.slides.toString();
  let found: PresentationScenario | null = null;
  for (let i = 0; i < this.mockScenarios.length; i++) {
    if (this.mockScenarios[i].scenario === key) {
      found = this.mockScenarios[i];
      break;
    }
  }
  if (found === null) {
    found = this.mockScenarios[0];
  }
  if (found !== null) {
    this.currentResult = found.result;
  }
  this.showResult = true;
}

匹配逻辑的关键设计点:

  1. 场景键拼接 :使用下划线连接三个参数,this.slides.toString()确保数字类型转换为字符串。这与场景键的格式保持一致。
  2. 常规for循环 :使用for (let i = 0; i < ...; i++)而非for...in或数组的find方法,以符合ArkTS的语法约束。ArkTS不支持for...in遍历对象,也不支持某些高阶数组方法。
  3. 显式null检查 :ArkTS不支持any和unknown类型,因此found变量声明为PresentationScenario | null联合类型。在使用前进行两次null检查(found === null和found !== null),确保类型安全。
  4. 兜底机制 :匹配失败时回退到mockScenarios[0],确保无论用户输入什么参数,都能获得一个可用的演示大纲。对于AI应用来说,宁可返回一个不完美但可用的结果,也不应该返回空白或错误。

3.4 输入参数校验与边界处理

typescript 复制代码
// 页数输入的边界处理
.onChange((value: string) => {
  let num: number = parseInt(value) || 5;
  if (num < 3) { num = 3; }
  if (num > 30) { num = 30; }
  this.slides = num;
})

页数输入框使用InputType.Number类型,弹出数字键盘。当用户输入非数字字符时,parseInt(value)返回NaN,|| 5确保默认值为5页。下界钳制到3页(至少需要封面+内容+总结),上界钳制到30页(超过30页的演示文稿在实际场景中几乎不存在,且会给观众带来严重的认知负担)。

这种三层防护(默认值 -> 下界钳制 -> 上界钳制)确保了this.slides在任何情况下都是一个合法的整数值,避免了后续UI渲染中的异常。

3.5 Slide卡片列表UI实现

Slide卡片列表是「演示架构师」最具视觉识别度的部分。每个Slide卡片由P编号标签、标题、要点列表和视觉建议四部分组成:

复制代码
┌──────────────────────────────────────────────┐
│  P1 │ 封面:人工智能发展趋势                    │
│     │  • 2025年AI技术全景展望                   │
│     │  • 演讲人:AI研究团队                     │
│     │  视觉: AI神经网络可视化背景图              │
├──────────────────────────────────────────────┤
│  P2 │ 目录                                    │
│     │  • 大模型演进                            │
│     │  • 多模态AI                              │
│     │  • AI Agent                             │
│     │  • AI安全与治理                          │
│     │  • 行业应用案例                          │
│     │  视觉: 思维导图样式目录                   │
├──────────────────────────────────────────────┤
│  P3 │ 大语言模型的里程碑                       │
│     │  ...                                    │
└──────────────────────────────────────────────┘

实现要点:

  1. P编号标签 :使用紫色圆角背景(#7B1FA2) + 白色文字,borderRadius(12)实现胶囊形状,视觉效果醒目且专业。
  2. 标题 :fontSize(15) + fontWeight(FontWeight.Bold),在一行中与P标签横向排列,layoutWeight(1)让标题自动填充剩余空间。
  3. 要点列表 :使用ForEach嵌套遍历slide.points数组,每条要点以•开头,fontSize(13),fontColor('#555555'),保持适中的信息密度。
  4. 视觉建议 :使用fontStyle(FontStyle.Italic)和fontColor('#999999'),以斜体和浅灰色与正文内容区分,形成「辅助信息」的视觉定位。
  5. 分隔线 :每张Slide卡片之间使用Divider(),颜色为#E8E8E8,提供清晰的视觉边界。

ForEach嵌套渲染的关键代码:

typescript 复制代码
ForEach(this.currentResult.slides, (slide: SlideItem, index: number) => {
  Column() {
    Row() {
      // P编号标签
      Text('P' + (index + 1).toString())
        .fontSize(12)
        .fontColor('#FFFFFF')
        .backgroundColor('#7B1FA2')
        .borderRadius(12)
        .padding({ left: 10, right: 10, top: 2, bottom: 2 })
      
      // 标题
      Text(' ' + slide.title)
        .fontSize(15)
        .fontWeight(FontWeight.Bold)
        .fontColor('#333333')
        .layoutWeight(1)
    }
    .width('100%')
    .padding({ bottom: 6 })

    // 要点列表(嵌套ForEach)
    ForEach(slide.points, (point: string) => {
      Text('  • ' + point)
        .fontSize(13)
        .fontColor('#555555')
        .width('100%')
        .padding({ bottom: 2 })
    })

    // 视觉建议
    Text('视觉: ' + slide.visual)
      .fontSize(11)
      .fontColor('#999999')
      .fontStyle(FontStyle.Italic)
      .width('100%')
      .padding({ top: 4, bottom: 8 })

    Divider()
      .color('#E8E8E8')
      .margin({ bottom: 4 })
  }
  .width('100%')
})

外层ForEach遍历this.currentResult.slides,内层ForEach遍历slide.points。这种双层ForEach结构是ArkUI中处理嵌套列表数据的标准模式。由于ArkTS不支持for...in和某些高阶数组方法,ForEach组件是列表渲染的唯一推荐方式。

3.6 整体UI布局设计

「演示架构师」的UI布局采用「固定头部 + 可滚动内容」的结构:

复制代码
┌─────────────────────────────────────────┐
│  ← 返回                                  │  ← 固定头部区域
│  演示架构师 (24px Bold)                 │
│  AI帮你构建专业演示文稿大纲 (14px #999)  │
├─────────────────────────────────────────┤
│  ┌─────────────────────────────────┐    │
│  │ 演示主题 TextInput               │    │  ← 可滚动内容区域
│  ├─────────────────────────────────┤    │  (Scroll + layoutWeight)
│  │ 目标受众 TextInput               │    │
│  ├─────────────────────────────────┤    │
│  │ 幻灯片页数 TextInput(Number)    │    │
│  ├─────────────────────────────────┤    │
│  │       [ 生成大纲 ] 紫色按钮       │    │
│  ├─────────────────────────────────┤    │
│  │  演示大纲                         │    │
│  │  ┌───────────────────────────┐  │    │
│  │  │ P1 ···                    │  │    │
│  │  │ P2 ···                    │  │    │
│  │  │ ...                       │  │    │
│  │  └───────────────────────────┘  │    │
│  └─────────────────────────────────┘    │
└─────────────────────────────────────────┘

头部的固定区域包含返回按钮、应用标题和副标题,使用白色背景(#FFFFFF)与内容区域的灰色背景(#F5F5F5)形成视觉分层。内容区域使用Scroll组件包裹,layoutWeight(1)使其自动填充剩余空间,确保在长内容的场景下可以滚动浏览。


四、Approve审批阶段:质量门控与合规检查

4.1 ArkTS语法合规性检查

在审批阶段,我们需要逐项检查代码是否符合ArkTS的严格语法约束。

检查项1:接口定义完整性

typescript 复制代码
interface SlideItem {
  title: string;
  points: string[];
  visual: string;
}

interface PresentationResult {
  slides: SlideItem[];
}

interface PresentationScenario {
  scenario: string;
  result: PresentationResult;
}

所有interface定义紧凑,字段类型显式声明。没有使用条件类型别名、映射类型、交叉类型、索引签名等ArkTS不支持的TypeScript高级特性。没有使用any或unknown类型。三个接口之间通过嵌套引用形成了清晰的数据层级关系。

检查项2:状态变量初始化

typescript 复制代码
@State topic: string = '人工智能发展趋势';
@State audience: string = '技术团队';
@State slides: number = 10;
@State showResult: boolean = false;
@State currentResult: PresentationResult = { slides: [] };

每个@State变量都有明确的类型标注和初始值。没有使用let v!: T确定性赋值断言,也没有使用var关键字。currentResult的初始化使用了对象字面量,由于PresentationResult是显式声明的接口(无方法、无参数化构造函数、无只读字段),对象字面量初始化是合法的。

检查项3:Mock数据中的对象字面量与类型断言

typescript 复制代码
private mockScenarios: PresentationScenario[] = [
  {
    scenario: '人工智能发展趋势_技术团队_10',
    result: {
      slides: [
        {
          title: '封面:人工智能发展趋势',
          points: ['2025年AI技术全景展望', '演讲人:AI研究团队'],
          visual: 'AI神经网络可视化背景图'
        },
        // ... 更多幻灯片
      ]
    }
  },
  // ... 场景二、场景三
];

Mock数据中的嵌套对象字面量需要被编译器推断为已知类型。由于mockScenarios的类型注解为PresentationScenario[],TypeScript编译器可以沿着类型链向下推断:数组元素 -> PresentationScenario -> result -> PresentationResult -> slides -> SlideItem[] -> 数组元素 -> SlideItem。这种推断依赖于类型链的完整性------如果中间任何一个环节缺少类型标注,编译器就会报错。

检查项4:数组遍历

typescript 复制代码
// 正确:使用ForEach组件进行列表渲染
ForEach(this.currentResult.slides, (slide: SlideItem, index: number) => {
  // 渲染Slide卡片
})

// 正确:使用ForEach嵌套渲染要点列表
ForEach(slide.points, (point: string) => {
  Text('  • ' + point)
})

// 正确:使用常规for循环遍历数组
for (let i = 0; i < this.mockScenarios.length; i++) {
  if (this.mockScenarios[i].scenario === key) {
    found = this.mockScenarios[i];
    break;
  }
}

ArkTS不支持for...in遍历对象,但ForEach组件和常规for循环都是原生支持的。我们使用了两种遍历方式:UI渲染使用ForEach组件,数据匹配使用常规for循环。

检查项5:router导入与使用

typescript 复制代码
import { router } from '@kit.ArkUI';

// 返回上一页
router.back();

router从@kit.ArkUI导入,这是HarmonyOS NEXT中路由模块的标准导入路径。router.back()是返回上一页的标准API,无需额外配置。

检查项6:字符串拼接

typescript 复制代码
let key: string = this.topic + '_' + this.audience + '_' + this.slides.toString();
Text('P' + (index + 1).toString())

ArkTS中字符串拼接使用+运算符。this.slides.toString()将数字转为字符串,(index + 1).toString()将索引+1后转为字符串。注意括号的使用------(index + 1).toString()是正确的,因为需要先计算加法再调用toString()。

4.2 Mock数据质量验证

场景一的页数验证:

场景一(人工智能发展趋势_技术团队_10)的Mock数据包含10张幻灯片,与场景键中的页数参数一致。每张幻灯片包含2-5个要点,符合「3-5个要点」的黄金法则。视觉建议与页面内容高度相关,如「AI神经网络可视化背景图」对应封面、「思维导图样式目录」对应目录页、「SWOT分析矩阵」对应挑战与机遇页。

场景二的页数验证:

场景二(新能源汽车市场分析_投资团队_8)的Mock数据包含8张幻灯片,与场景键中的页数参数一致。要点设计以数据驱动为主,如「全球新能源车销量突破2000万辆」「中国市场占比超60%」「同比增长35%」等具体数字。视觉建议匹配投资分析场景,如「市场份额饼图+品牌矩阵」「投资价值评估热力图」「风险-收益矩阵」。

场景三的页数验证:

场景三(团队建设与管理_管理层_6)的Mock数据包含6张幻灯片,与场景键中的页数参数一致。要点设计以行动导向为主,如「新人90天融入计划」「导师制升级」「技能矩阵与培训地图」等可执行的具体措施。视觉建议匹配管理咨询场景,如「诊断雷达图」「成长路径图」「激励模型金字塔」「甘特图+OKR分解」。

4.3 输入校验逻辑验证

页数输入框的校验逻辑需要验证以下边界情况:

输入值 期望输出 验证结果
空字符串 5(默认值) 通过
"abc" 5(非数字,默认值) 通过
"0" 3(下界钳制) 通过
"2" 3(下界钳制) 通过
"3" 3(下界边界) 通过
"10" 10(正常值) 通过
"30" 30(上界边界) 通过
"31" 30(上界钳制) 通过
"100" 30(上界钳制) 通过
"-5" 3(负数钳制到下界) 通过

4.4 兜底逻辑验证

当用户输入的主题和受众组合在Mock数据中不存在时(如量子计算_学生_5),系统应该回退到默认场景(场景一)。验证结果:getMockData()正确地匹配到mockScenarios[0]并返回了AI发展趋势的演示大纲。


五、Automate自动化执行阶段:从代码到界面

5.1 完整UI代码实现

「演示架构师」的UI代码采用ArkUI声明式语法,整个页面在一个build()方法中完成构建。核心结构如下:

typescript 复制代码
@Entry
@Component
struct App36 {
  @State topic: string = '人工智能发展趋势';
  @State audience: string = '技术团队';
  @State slides: number = 10;
  @State showResult: boolean = false;
  @State currentResult: PresentationResult = { slides: [] };

  // Mock数据定义(3个场景)
  private mockScenarios: PresentationScenario[] = [ /* ... */ ];

  // 数据匹配方法
  getMockData(): void { /* ... */ }
  generateMockData(): void { /* ... */ }

  build() {
    Column() {
      // 固定头部:返回按钮 + 标题 + 副标题
      Row() { /* ... */ }
      Text('演示架构师') /* ... */
      Text('AI帮你构建专业演示文稿大纲') /* ... */

      // 可滚动内容区域
      Scroll() {
        Column() {
          // 主题输入
          TextInput({ text: this.topic }) /* ... */
          
          // 受众输入
          TextInput({ text: this.audience }) /* ... */
          
          // 页数输入
          TextInput({ text: this.slides.toString() }) /* ... */
          
          // 生成按钮
          Button('生成大纲') /* ... */
          
          // 条件渲染结果区域
          if (this.showResult) {
            // ForEach渲染Slide卡片列表
          }
        }
      }
      .layoutWeight(1)
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F5F5F5')
  }
}

5.2 生成按钮与交互流

生成按钮是用户交互的核心入口。点击后触发generateMockData()方法,该方法内部调用getMockData()进行场景键匹配,匹配成功后将结果赋值给currentResult并将showResult置为true。

typescript 复制代码
Button('生成大纲')
  .width('calc(100% - 32px)')
  .height(48)
  .backgroundColor('#7B1FA2')
  .fontColor('#FFFFFF')
  .fontSize(16)
  .fontWeight(FontWeight.Medium)
  .borderRadius(24)
  .margin({ top: 24, left: 16, right: 16 })
  .onClick(() => {
    this.generateMockData();
  })

按钮的设计要点:

  • 宽度 :calc(100% - 32px),左右各留16px边距,与输入框的边距保持一致
  • 高度:48px,符合移动端触控区域的最小推荐尺寸(44px)
  • 圆角:24px,实现胶囊形状,视觉上更柔和
  • 颜色 :紫色背景(#7B1FA2)+ 白色文字,与主题色一致

5.3 条件渲染与结果展示

结果区域使用if (this.showResult)条件渲染,这是ArkUI中控制UI显示/隐藏的标准方式。当showResult为false时,结果区域完全不存在于组件树中,不占用任何渲染资源。

typescript 复制代码
if (this.showResult) {
  Column() {
    Text('演示大纲')
      .fontSize(18)
      .fontWeight(FontWeight.Bold)
      .padding({ top: 8, bottom: 12 })
      .width('100%')

    ForEach(this.currentResult.slides, (slide: SlideItem, index: number) => {
      // Slide卡片渲染
    })
  }
  .width('calc(100% - 32px)')
  .backgroundColor('#FFFFFF')
  .borderRadius(12)
  .padding(16)
  .margin({ top: 16, left: 16, right: 16, bottom: 24 })
}

结果区域使用白色卡片样式(backgroundColor('#FFFFFF') + borderRadius(12)),与灰色背景形成对比,突出显示。

5.4 紫色主题的整体实现

整个应用的主题色统一为紫色(#7B1FA2),在以下位置使用:

  • 生成按钮:背景色
  • P编号标签:背景色
  • 标题文字:字体颜色(与P标签形成视觉关联)

其余UI元素使用中性灰色调(#F5F5F5背景、#333333标题、#555555正文、#999999辅助信息、#E8E8E8分隔线),形成「紫色突出关键信息,中性色作为背景和正文」的视觉层次。

5.5 鸿蒙PC端适配策略

虽然「演示架构师」当前主要面向移动端,但在架构设计上已经考虑了鸿蒙PC端的适配需求。鸿蒙PC端与移动端的关键差异在于:

  1. 屏幕尺寸:PC端屏幕通常在13-27英寸,远超移动端的5-7英寸。这意味着UI布局可以从单列变为多列,充分利用横向空间。
  2. 输入方式:PC端以键盘和鼠标为主,触摸为辅。输入框可以更大,按钮可以更小(因为鼠标精度高于手指)。
  3. 窗口模式:PC端支持自由窗口和分屏模式,应用需要适配不同窗口尺寸。

对于「演示架构师」的鸿蒙PC端适配,推荐以下策略:

  • 输入区域:将主题、受众、页数三个输入框改为水平排列,充分利用PC端的横向空间
  • 结果区域:将Slide卡片列表改为两列或三列网格布局,让用户能同时看到更多内容
  • 响应式断点:使用ArkUI的响应式布局能力,在窗口宽度小于一定阈值时自动切换为移动端单列布局
  • 键盘快捷键:支持Ctrl+Enter快速生成大纲,提升键盘用户的操作效率

5.6 鸿蒙Flutter框架对比分析

在鸿蒙生态中,除了ArkUI声明式框架外,鸿蒙Flutter框架也是一个重要的UI开发选项。以下是两者在开发「演示架构师」这类AI应用时的对比:

维度 ArkUI(ArkTS) 鸿蒙Flutter框架
语言 ArkTS(TypeScript超集) Dart
组件模型 声明式UI(@Component) Widget树
状态管理 @State / @Prop / @Link setState / Provider / Bloc
列表渲染 ForEach组件 ListView.builder
条件渲染 if / if else if / Visibility / Offstage
原生API访问 直接导入@kit.* 通过Platform Channel
性能 原生渲染,无桥接开销 Skia渲染引擎,有桥接开销
学习曲线 低(TypeScript开发者友好) 中(Dart语言学习成本)
生态成熟度 华为官方主推,持续更新 社区驱动,适配进度滞后

对于「演示架构师」这种轻量级AI工具应用,ArkUI + ArkTS的方案具有明显的优势:原生渲染性能更好、HarmonyOS API调用更直接、TypeScript开发者学习成本更低。但鸿蒙Flutter框架在跨平台代码复用方面有其独特的价值------如果未来需要同时支持Android和iOS,Flutter的代码复用率可以达到90%以上。


六、Assess评估阶段:回顾与展望

6.1 成果回顾

「演示架构师」在功能层面实现了以下目标:

功能 状态 说明
主题输入 完成 自由文本输入,默认为「人工智能发展趋势」
受众输入 完成 自由文本输入,默认为「技术团队」
页数输入 完成 数字键盘,3-30范围,边界自动钳制
大纲生成 完成 场景键匹配,3场景Mock数据
Slide卡片展示 完成 P编号标签 + 标题 + 要点 + 视觉建议
双层ForEach渲染 完成 外层遍历幻灯片,内层遍历要点
条件渲染 完成 showResult控制结果区域的显示/隐藏
紫色主题 完成 统一的紫色视觉风格
返回导航 完成 router.back()标准路由
异常兜底 完成 匹配失败回退默认场景

6.2 幻灯片结构的逻辑连贯性分析

生成的演示大纲在逻辑连贯性方面表现良好。以场景一(AI发展趋势)为例,10张幻灯片的叙述线如下:

复制代码
封面 → 目录 → 大模型 → 多模态 → AI Agent → AI安全 → 
医疗应用 → 教育应用 → 挑战机遇 → 总结展望

这条叙述线符合「技术演进 → 应用落地 → 挑战反思 → 未来展望」的经典论证结构。每一页的标题都自然地引向下一页,形成了清晰的信息流。

但我们也识别出了一些可改进之处:

  1. 过渡页缺失:在「医疗应用」和「教育应用」之间缺少一个行业应用的总览页,导致两个案例之间的跳跃感较强。
  2. 目录与内容不完全对应:目录中列出了5个主题,但实际展开时「行业应用案例」被拆分为两个独立的页面(医疗和教育),而非一个综合页面。这是一种合理的处理方式(两个具体案例比一个抽象概述更有说服力),但目录可以更精确地反映这种拆分。

6.3 受众感知的深度验证

场景一(技术团队)和场景二(投资团队)的要点设计,体现了不同受众对内容深度的差异化需求:

技术团队场景的关键词分析:

  • 技术术语密度高:GPT-4到GPT-5、上下文窗口、100万tokens、推理能力、多模态融合、Sora类模型、跨模态理解、Agent协作、对齐问题、红队测试、可解释性
  • 数据导向:准确率达95%、周期缩短60%

投资团队场景的关键词分析:

  • 商业术语密度高:市场占比、竞争格局、第一梯队、市场份额、量产突破、成本下降路径、自主化进程、国产替代、购置税减免、双积分政策、反补贴调查、碳交易、产能过剩、价格战、推荐标的
  • 数据导向:销量突破2000万辆、占比超60%、同比增长35%

这种术语层面的差异,说明Mock数据的设计确实考虑了受众参数的影响。但当前的实现中,受众参数仅用于场景键匹配,没有在生成逻辑中实现动态的内容调整。未来接入真实AI API后,Prompt中的受众参数将成为驱动内容差异化生成的核心引擎。

6.4 扩展性分析

真实AI API接入

当前「演示架构师」采用AI API Stub模式,Mock数据驱动的开发体验已经完整验证了UI交互和数据流。接入真实AI API时,只需替换generateMockData()中的调用逻辑:

typescript 复制代码
// 未来:通过Prompt调用AI API
async generateWithAI(): Promise<void> {
  const prompt: string = 
    `你是一位专业的演示文稿架构师。请为主题"${this.topic}"、
     面向"${this.audience}"、生成${this.slides}页演示大纲。
     每页需包含:标题(title)、3-5个要点(points)、
     视觉建议(visual)。输出JSON格式:
     { "slides": [{ "title": "...", "points": ["..."], "visual": "..." }] }`;
  
  try {
    const response: string = await this.callAIAPI(prompt);
    const result: PresentationResult = JSON.parse(response) as PresentationResult;
    this.currentResult = result;
    this.showResult = true;
  } catch (e) {
    // API调用失败时回退到Mock数据
    this.getMockData();
  }
}

关键设计点:API调用失败时自动回退到Mock数据。这确保了在任何情况下用户都能获得一个可用的演示大纲,即使AI服务暂时不可用。

风格模板扩展

当前的大纲生成只关注内容结构,没有涉及视觉风格。未来可以增加一个「风格选择」参数,让用户选择「商务蓝」「科技紫」「创意橙」等配色方案,并在视觉建议中融入风格信息。例如,在「商务蓝」风格下,视觉建议会推荐蓝色系的图表和数据可视化;在「创意橙」风格下,视觉建议会推荐更活泼的插画和图标。

多页联动优化

当前每张幻灯片是独立生成的,页面之间的过渡关系依赖于内容本身的逻辑连贯性。未来可以在Prompt中增加「页面过渡」约束,要求AI在生成每页内容时考虑与前后页的衔接关系,并可以在视觉建议中推荐过渡动画类型(如「淡入淡出」「推入」「翻页」等)。

导出功能

当前的大纲只在应用内展示,用户无法导出到外部工具。未来可以增加导出功能,支持导出为Markdown、JSON、甚至直接生成PPTX文件。导出为PPTX文件需要使用HarmonyOS的文件系统API和第三方库(如PPTX生成库),这涉及到更复杂的文件操作和权限管理。

6.5 鸿蒙PC端深度适配展望

随着鸿蒙PC的持续发展,越来越多的AI应用将面临PC端适配的需求。对于「演示架构师」而言,PC端适配不仅是布局调整,更是使用场景的转变:

  1. 双屏模式:在PC端,用户可能在主屏上编辑演示大纲,在副屏上预览PPT效果。这需要「演示架构师」支持多窗口模式,将大纲编辑和预览分离到两个窗口。
  2. 拖拽排序:在PC端,用户可能希望拖拽Slide卡片来调整页面顺序。这需要实现拖拽交互,使用ArkUI的拖拽API。
  3. 批量编辑:在PC端,用户可能希望批量修改所有页面的视觉建议或字体样式。这需要增加批量编辑面板。
  4. 协作编辑:在PC端,多个用户可以同时编辑同一份演示大纲。这需要引入实时协作能力,通过HarmonyOS的分布式能力实现设备间的数据同步。

这些PC端特有的功能需要在架构层面预留扩展点,但不应在当前的MVP阶段过度设计。

6.6 总结

「演示架构师」作为一个轻量级的AI PPT大纲生成工具,在HarmonyOS平台上实现了从需求对齐到自动化执行的全流程开发。它展示了AI API Stub模式在前端先行开发中的有效性,体现了ArkUI声明式框架在复杂嵌套列表渲染中的优势,并以紫色主题和Slide卡片设计树立了独特的视觉识别。

在技术层面,本文深入探讨了以下关键主题:

  • 场景化数据建模:通过场景键(Scenario Key)设计,将多维度的用户输入映射为可索引的字符串键,实现了灵活的Mock数据匹配和兜底机制。
  • 双层ForEach渲染 :在ArkTS的语法约束下,使用ForEach嵌套处理幻灯片列表和要点列表,确保了列表渲染的性能和可维护性。
  • AI API Stub模式:通过Mock数据驱动的前端先行开发策略,解耦了UI开发与后端AI能力的依赖关系,为鸿蒙AI应用开发提供了可复用的技术范式。
  • 鸿蒙PC端适配:分析了移动端与PC端的核心差异,提出了响应式布局、多窗口模式、键盘快捷键等适配策略。
  • 鸿蒙Flutter框架对比:从语言、性能、生态、学习曲线等维度对比了ArkUI和鸿蒙Flutter框架的适用场景。

「演示架构师」的代码虽然简洁(仅356行),但其背后的设计理念和技术决策,体现了鸿蒙AI应用开发的核心方法论:用最小的代码量实现最大的用户价值,用架构设计的前瞻性换取未来的扩展空间。希望本文能为同样在鸿蒙生态中探索AI应用开发的开发者提供一些参考和启发。


本文基于HarmonyOS NEXT(API 26)开发环境,代码示例使用ArkTS语言,UI组件基于ArkUI声明式框架。文中涉及的AI API Stub模式、场景键设计、双层ForEach渲染等模式,均来源于实际项目中的工程实践。

相关推荐
tomlone8 小时前
AI 实践:OpenClaw + 本地 Ollama + Qwen3.5
人工智能·自然语言处理·ai写作
盘古开天16668 小时前
windows鱼塘可交互鱼群动态桌面资源
人工智能·chatgpt·开源
零基础1238 小时前
Agentic Identity:智能体身份识别的核心技术、应用场景与实践指南
人工智能
指针向南9 小时前
canvas最大尺寸是多少:三个浏览器能画、能导出的上限
图像处理·人工智能·计算机视觉
零基础1239 小时前
LLM Agent 驱动的物模型构建:从设备手册到边缘接入的自动化实践
运维·人工智能·经验分享·python·自动化
这张生成的图像能检测吗9 小时前
(论文速读)LINN:液体神经网络与脉冲神经元融合的可解释旋转机械故障诊断
人工智能·深度学习·神经网络·故障诊断
东方佑9 小时前
v24 (Hybrid2Fast) 架构与实验报告
人工智能·深度学习·语言模型·自然语言处理·架构
阿部多瑞 ABU9 小时前
重复的辩证法:从哲学僵尸到历史唯物主义——论意识、重复与人类解放
人工智能·ai写作
枫叶丹49 小时前
从一次推理请求出发:模型、显存、网络与服务系统如何共同决定性能
网络·人工智能·chatgpt·开源·agent·codex