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 原始需求
「演示架构师」的原始需求可以概括为三个核心诉求:
- 主题输入:用户输入演示文稿的主题,如「人工智能发展趋势」「新能源汽车市场分析」
- 受众设定:用户指定目标受众,如「技术团队」「投资团队」「管理层」
- 页数控制:用户设定期望的幻灯片页数(3-30页范围)
- 大纲生成:系统生成结构化的演示大纲,每页包含标题、要点列表和视觉建议
这个需求看似简单直接,但在对齐阶段,我们需要挖掘出隐藏在表面之下的深层约束。
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
这种设计有以下几个优点:
- 精确匹配:每个场景键唯一对应一个预置的演示大纲,匹配逻辑清晰,不会出现二义性。
- 可读性好:场景键本身就是对场景的完整描述,无需查看数据内容就能理解场景含义。
- 扩展简单 :新增场景只需在
mockScenarios数组中追加一个新元素,键名遵循相同格式即可。 - 兜底友好 :当用户输入的参数组合没有预置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)作为主题色。这个选择基于以下专业考量:
- 创意与专业性的平衡:紫色在色彩心理学中代表创造力、智慧和专业,恰好契合「演示架构师」的定位------既有AI的创意生成能力,又有架构师的专业严谨。
- 视觉识别度:在40个AI应用矩阵中,紫色主题与蓝色(职场)、橙色(生活)、绿色(健康)等主题形成差异化,用户一眼就能识别出「AI创作」类应用。
- 演讲场景关联:紫色常被用于高端演讲和发布会场景(如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;
}
匹配逻辑的关键设计点:
- 场景键拼接 :使用下划线连接三个参数,
this.slides.toString()确保数字类型转换为字符串。这与场景键的格式保持一致。 - 常规for循环 :使用
for (let i = 0; i < ...; i++)而非for...in或数组的find方法,以符合ArkTS的语法约束。ArkTS不支持for...in遍历对象,也不支持某些高阶数组方法。 - 显式null检查 :ArkTS不支持
any和unknown类型,因此found变量声明为PresentationScenario | null联合类型。在使用前进行两次null检查(found === null和found !== null),确保类型安全。 - 兜底机制 :匹配失败时回退到
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 │ 大语言模型的里程碑 │
│ │ ... │
└──────────────────────────────────────────────┘
实现要点:
- P编号标签 :使用紫色圆角背景(
#7B1FA2) + 白色文字,borderRadius(12)实现胶囊形状,视觉效果醒目且专业。 - 标题 :
fontSize(15)+fontWeight(FontWeight.Bold),在一行中与P标签横向排列,layoutWeight(1)让标题自动填充剩余空间。 - 要点列表 :使用
ForEach嵌套遍历slide.points数组,每条要点以•开头,fontSize(13),fontColor('#555555'),保持适中的信息密度。 - 视觉建议 :使用
fontStyle(FontStyle.Italic)和fontColor('#999999'),以斜体和浅灰色与正文内容区分,形成「辅助信息」的视觉定位。 - 分隔线 :每张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端与移动端的关键差异在于:
- 屏幕尺寸:PC端屏幕通常在13-27英寸,远超移动端的5-7英寸。这意味着UI布局可以从单列变为多列,充分利用横向空间。
- 输入方式:PC端以键盘和鼠标为主,触摸为辅。输入框可以更大,按钮可以更小(因为鼠标精度高于手指)。
- 窗口模式: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安全 →
医疗应用 → 教育应用 → 挑战机遇 → 总结展望
这条叙述线符合「技术演进 → 应用落地 → 挑战反思 → 未来展望」的经典论证结构。每一页的标题都自然地引向下一页,形成了清晰的信息流。
但我们也识别出了一些可改进之处:
- 过渡页缺失:在「医疗应用」和「教育应用」之间缺少一个行业应用的总览页,导致两个案例之间的跳跃感较强。
- 目录与内容不完全对应:目录中列出了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端适配不仅是布局调整,更是使用场景的转变:
- 双屏模式:在PC端,用户可能在主屏上编辑演示大纲,在副屏上预览PPT效果。这需要「演示架构师」支持多窗口模式,将大纲编辑和预览分离到两个窗口。
- 拖拽排序:在PC端,用户可能希望拖拽Slide卡片来调整页面顺序。这需要实现拖拽交互,使用ArkUI的拖拽API。
- 批量编辑:在PC端,用户可能希望批量修改所有页面的视觉建议或字体样式。这需要增加批量编辑面板。
- 协作编辑:在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渲染等模式,均来源于实际项目中的工程实践。