PureHarmony · 文案创作工坊 —— 鸿蒙Next WaterFlow瀑布流 + AI写作助手实战 PureHarmony · 文案创作工坊 —— 鸿蒙Next WaterFlow瀑布流 AI写作助手实战一、项目背景与设计理念在内容创作日益普及的今天一款轻量、优雅、高效的写作工具是每位创作者的刚需。PureHarmony · 文案创作工坊正是在这一需求驱动下诞生的——它是一套完全基于ArkTS原生能力构建的AI写作助手功能模块不依赖任何第三方UI框架或组件库仅利用鸿蒙ArkUI核心组件以实现完整的写作工作流。与传统的移动端写作工具不同本项目特别关注三个核心设计目标沉浸式写作体验通过清晰的视觉分区让创作过程流畅无阻。灵感驱动的创作模式利用WaterFlow瀑布流展示灵感卡片以视觉随机性激发创作灵感。风格感知的内容管理引入写作风格标签系统让每一篇文章都能被精准标记和分类。本文将从工程实践的角度逐层拆解该模块的架构设计、组件实现、WaterFlow瀑布流布局的实战技巧以及ArkTS语法约束下的应对策略为鸿蒙开发者提供一个可参考、可复用的实战范例。1.1 功能矩阵功能模块技术实现用户价值写作编辑器TextArea组件 State双向绑定实时录入与感知编辑风格切换系统Row ForEach 标签Chips切换写作风格辅助内容定调字数实时统计正则去空 getWordCount()方法精确掌控内容篇幅灵感瀑布流WaterFlow FlowItem 随机高度视觉随机性激发创作灵感历史文章管理List ListItem 卡片列表回顾与追踪创作历程1.2 技术选型决策选择纯ArkTS原生实现而非引入第三方库基于以下核心考量零外部依赖避免npm包版本冲突和鸿蒙API兼容性问题。鸿蒙生态尚在发展期第三方库的成熟度和维护稳定性参差不齐原生方案是最稳妥的选择。编译优化红利ArkTS编译器对WaterFlow、List等系统组件有深度编译优化性能优于通用第三方实现。包体积控制无外部依赖意味着hap包体积极小对于写作工具这类功能模块轻量化是核心体验要素。API同步升级原生组件随HarmonyOS版本升级自动获得新特性和性能改进无需等待第三方库适配。二、系统架构与数据流设计2.1 组件树层级整个页面采用三层组件架构从数据持有到UI渲染逐层递进┌───────────────────────────────────────────────┐ │ AIWriterPage (页面容器) │ │ ┌───────────────────────────────────────────┐ │ │ │ Row (风格切换标签栏) │ │ │ │ ├── Text( 简洁) × 6 │ │ │ └───────────────────────────────────────────┘ │ │ ┌───────────────────────────────────────────┐ │ │ │ Column (写作区) │ │ │ │ ├── TextArea (编辑器) │ │ │ │ └── Row (字数统计栏) │ │ │ └───────────────────────────────────────────┘ │ │ ┌───────────────────────────────────────────┐ │ │ │ Column (灵感区) │ │ │ │ ├── Row (标题栏 副标题) │ │ │ │ └── WaterFlow (瀑布流, 2列) │ │ │ │ ├── FlowItem → InspirationCardView │ │ │ │ └── FlowItem → InspirationCardView │ │ │ └───────────────────────────────────────────┘ │ │ ┌───────────────────────────────────────────┐ │ │ │ Column (历史区) │ │ │ │ ├── Row (标题栏 计数) │ │ │ │ └── List (垂直列表) │ │ │ │ └── ListItem → HistoryCard × 8 │ │ │ └───────────────────────────────────────────┘ │ └───────────────────────────────────────────────┘2.2 单向数据流ArkTS采用严格的单向数据流模式数据变更通过装饰器系统驱动UI重渲染数据定义层WRITING_STYLES、INSPIRATIONS、HISTORY_ARTICLES作为顶层只读常量。状态管理层AIWriterPage通过State持有可变数据包括样式列表、灵感数据、历史文章、写作文本和当前选中风格ID。过滤与计算层getWordCount()和getSelectedStyleName()作为纯计算方法从状态中派生展示数据。视图渲染层子组件通过Prop接收父组件传入的数据纯展示无副作用。2.3 组件职责边界组件角色数据输入职责范围AIWriterPage页面容器 / 状态管理者全局常量状态定义、事件处理、布局编排InspirationCardView纯展示组件Prop card灵感卡片样式渲染HistoryCard纯展示组件Prop article历史文章卡片渲染这种父组件管状态、子组件只管渲染的分工是ArkTS声明式UI框架推荐的最佳实践保证了数据流的可预测性和组件粒度的可复用性。三、数据模型深度解析3.1 写作风格模型interfaceWritingStyle{id:number;name:string;// 风格名称简洁 / 文艺 / 热情 / 自然 / 科技 / 叙事icon:string;// emoji 图标isSelected:boolean;// 选中状态}六个写作风格覆盖了主流内容创作场景。设计精巧之处在于isSelected字段承载了UI状态切换的全部逻辑——选中时标签变为蓝色背景白色文字未选中时保持浅灰色背景。这种状态驱动的样式变换完全由State响应式触发无需手动操作DOM。3.2 灵感卡片模型interfaceInspirationCard{id:number;emoji:string;// 视觉标识title:string;// 灵感标题content:string;// 灵感描述height:number;// 卡片高度100~170vp 不等bgColor:string;// 背景色}height字段是瀑布流布局的核心——12张卡片的高度在100vp到170vp之间随机分布。这种随机性让WaterFlow的双列布局呈现出错落有致的视觉节奏避免了等高等宽网格的呆板感。高度分布如下卡片标题高度(vp)背景色1清晨的第一缕光130#fff3e0 暖橙2深海秘密160#e3f2fd 浅蓝3街角咖啡店110#fce4ec 粉红4未来城市150#e8f5e9 浅绿5一首歌的回忆120#f3e5f5 浅紫6星空下的对话170#e0f7fa 天蓝7手写信100#fff8e1 米黄8深夜食堂140#ffebee 浅红9面具之下155#e8eaf6 淡紫10一粒种子的旅行115#f1f8e9 草绿11博物馆之夜165#fbe9e7 浅褐12马戏团来了125#fce4ec 粉红每张卡片的背景色均采用Material Design的50色调色板柔和且不刺眼配合白色圆角卡片容器和12vp的内边距形成了清新治愈的视觉效果。3.3 历史文章模型interfaceHistoryArticle{id:number;title:string;summary:string;wordCount:number;// 字数统计模拟数据style:string;// 风格标签date:string;// 发布日期}八篇历史文章覆盖六种写作风格字数从760字到3200字不等代表了不同篇幅的创作形态。每条记录都携带style字段为后续的按风格筛选功能预留了扩展空间。四、核心组件实现详解4.1 InspirationCardView —— 灵感卡片组件灵感卡片是WaterFlow瀑布流的基本单元设计上追求精致小巧和视觉层次感。Componentstruct InspirationCardView{Propcard:InspirationCard{id:0,emoji:,title:,content:,height:120,bgColor:#ffffff};build(){Column(){Text(this.card.emoji).fontSize(28).margin({bottom:6});Text(this.card.title).fontSize(14).fontWeight(FontWeight.Bold).fontColor(#1a1a2e).margin({bottom:4});Text(this.card.content).fontSize(12).fontColor(#666666).lineHeight(18).maxLines(5).textOverflow({overflow:TextOverflow.Ellipsis});}.width(100%).padding(12).backgroundColor(this.card.bgColor).borderRadius(12).alignItems(HorizontalAlign.Start);}}设计要点emoji作为视觉锚点28号字体的emoji图标占据视觉焦点14号标题次之12号内容描述最细形成了清晰的视觉层级。动态背景色backgroundColor(this.card.bgColor)使得每张卡片拥有独立底色在WaterFlow的随机排列下形成多彩拼接效果。文字截断安全.maxLines(5)配合.textOverflow(Ellipsis)确保内容溢出时优雅截断卡片尺寸始终受height字段控制。左对齐布局.alignItems(HorizontalAlign.Start)让文字内容左对齐符合阅读习惯。4.2 HistoryCard —— 历史文章卡片组件历史文章卡片采用更饱满的信息密度设计包含标题、风格标签、摘要、字数和日期五个信息维度。Componentstruct HistoryCard{Proparticle:HistoryArticle{id:0,title:,summary:,wordCount:0,style:,date:};build(){Column(){// 第一行标题 风格标签Row(){Text(this.article.title).fontSize(16).fontWeight(FontWeight.Bold).layoutWeight(1).maxLines(1).textOverflow({overflow:TextOverflow.Ellipsis});Text(this.article.style).fontSize(10).fontColor(#007aff).backgroundColor(#e8f0fe).borderRadius(4).padding({left:6,right:6,top:2,bottom:2});}// 第二行摘要Text(this.article.summary).fontSize(13).fontColor(#666666).maxLines(2).textOverflow({overflow:TextOverflow.Ellipsis});// 第三行字数 日期Row(){Text(${this.article.wordCount}字)Blank()Text(this.article.date)}}.padding(16).backgroundColor(Color.White).borderRadius(12).shadow({radius:4,offsetY:2,color:rgba(0,0,0,0.04)});}}此组件采用了经典的三段式卡片布局标题行左侧标题 右侧风格标签→ 摘要行 → 信息行左侧字数 右侧日期。整体使用16vp内边距、12vp圆角和轻微阴影延续了系统级卡片的视觉语义。风格标签的设计尤为考究使用10号字体最小可读字号、#007aff蓝色文字、#e8f0fe浅蓝背景和4vp圆角形成了典型的药丸标签风格与iOS和Material Design的设计语言保持一致。4.3 AIWriterPage —— 页面主组件页面主组件AIWriterPage是整个模块的状态中枢和事件管理中心。4.3.1 状态定义Statestyles:WritingStyle[]JSON.parse(JSON.stringify(WRITING_STYLES));Stateinspirations:InspirationCard[]JSON.parse(JSON.stringify(INSPIRATIONS));StatehistoryList:HistoryArticle[]JSON.parse(JSON.stringify(HISTORY_ARTICLES));StatewritingText:string;StateselectedStyleId:number1;所有可变数据均使用State装饰器标记确保ArkTS运行时能追踪数据变化并自动触发UI重渲染。使用JSON.parse(JSON.stringify(...))深拷贝的原因在于防止State数组与顶层常量共享引用避免意外的不可控修改。4.3.2 字数统计实现getWordCount():number{lettext:stringthis.writingText;if(text.length0)return0;letclean:stringtext.replace(/[\s\n\r]/g,);returnclean.length;}字数统计采用去空白后计数策略replace(/[\s\n\r]/g, )正则匹配并移除所有空格、换行和回车符只统计有效字符。这种策略符合中文写作的计数习惯——空格和缩进不计入正文字数。4.3.3 风格切换逻辑selectStyle(style:WritingStyle):void{this.selectedStyleIdstyle.id;for(leti:number0;ithis.styles.length;i){this.styles[i].isSelected(this.styles[i].idstyle.id);}}通过遍历styles数组将匹配项的isSelected设为true其余设为false实现单选的互斥逻辑。selectedStyleId作为唯一标识符也被getSelectedStyleName()用于在标题栏右上角展示当前风格名称。五、WaterFlow瀑布流布局实战WaterFlow是HarmonyOS API 11引入的瀑布流容器组件是本次实现中最具技术亮点的部分。5.1 组件基础WaterFlow(){ForEach(this.inspirations,(card:InspirationCard){FlowItem(){InspirationCardView({card:card});}})}.columnsTemplate(1fr 1fr)// 双列等宽.columnsGap(8)// 列间距 8vp.rowsGap(8)// 行间距 8vp.height(220)// 固定高度 220vp关键配置解释columnsTemplate(1fr 1fr)将容器水平分为两列每列各占50%宽度。1fr是网格单位类似CSS的flex-grow表示按比例分配剩余空间。如需三列可写为1fr 1fr 1fr。columnsGap(8)和rowsGap(8)设置列与列、行与行之间的间距保持卡片间的呼吸感。height(220)瀑布流容器高度固定确保页面布局能够正确分配剩余空间给下方的List区域。5.2 随机高度策略WaterFlow区别于Grid的核心能力在于同一列中每个Item可以拥有独立的高度。本项目利用灵感卡片的height字段100~170vp来实现瀑布流效果。// 12张灵感卡片的高度分布constHEIGHTS[130,160,110,150,120,170,100,140,155,115,165,125];当WaterFlow渲染这些卡片时算法会自动将卡片按高度分配到两列中使得两列的总高度尽可能平衡。例如左列130 110 170 100 155 125 790vp 右列160 150 120 140 115 165 850vp虽然存在约60vp的偏差但对于220vp高度固定的容器而言这种偏差恰好营造了自然的错落感。5.3 WaterFlow vs Grid —— 布局选型对比维度WaterFlowGrid列内高度可独立变化受行高约束适用场景瀑布流、卡片墙、灵感板网格相册、分类标签云排列方式列优先填充行优先排列性能开销略高需高度计算较低对于灵感卡片场景每张卡片包含不同的内容量使用WaterFlow能够避免Grid中一行高度由最高卡片决定带来的空间浪费实现更紧凑、更自然的布局。六、TextArea编辑器与字数统计联动6.1 编辑器配置TextArea({placeholder:开始写作吧AI会为您提供灵感...,text:this.writingText,controller:newTextAreaController(),}).height(160).padding(12).fontSize(14).lineHeight(22).backgroundColor(#f8f8fc).borderRadius(12).onChange((val:string):void{this.writingTextval;});TextArea配置要点高度固定160vp作为页面三个区块写作区/灵感区/历史区之一写作区需要固定高度以保证整体布局的稳定性。浅灰蓝背景#f8f8fc区别于页面整体底色#f5f5f5形成轻微色差暗示可编辑区域。12vp圆角 12vp内边距与灵感卡片和历史卡片的圆角风格保持一致。.onChange()实时同步每次输入变化立即更新writingText状态驱动字数统计更新。6.2 字数统计的实时响应字数统计通过Text(\已写 ${this.getWordCount()} 字)实现。由于getWordCount()访问了State writingText当writingText变化时ArkTS会自动检测到依赖变更并重新计算getWordCount() 的返回值从而更新UI上的显示文本。这种状态 → 计算 → 渲染的自动管道是声明式UI框架的核心优势——开发者只需声明数据是什么和UI长什么样数据变化后的同步工作由框架自动完成。七、ArkTS语法约束与开发经验在开发过程中遇到并克服了若干ArkTS特有的语法约束这里总结出对开发者最有价值的几点。7.1 build() 内禁止变量声明约束ArkTS编译器禁止在build()或Builder方法中出现let、const等变量声明语句。正确做法将所有计算逻辑提取为独立方法在build()中通过方法调用获取结果。// ✅ 正确计算逻辑提取到方法中getWordCount():number{letcleanthis.writingText.replace(/[\s\n\r]/g,);returnclean.length;}build(){// 在 Text 中内联调用方法Text(已写${this.getWordCount()}字)}常见误区初学者容易尝试在build()中写let count this.writingText.length;再使用count这将导致编译错误。务必养成计算在方法渲染在build的习惯。7.2 TextArea构造参数的写法// ✅ 正确所有初始配置作为构造函数参数传入TextArea({placeholder:开始写作吧...,text:this.writingText,controller:newTextAreaController(),})// ❌ 错误placeholder作为链式方法调用TextArea().placeholder(开始写作吧...)// 某些API版本不支持与Search组件类似TextArea的核心配置参数value/text、placeholder、controller必须作为构造函数的参数对象传入而非链式方法调用。样式类属性backgroundColor、borderRadius、fontSize等则使用链式调用。7.3 Prop默认值的必要性当子组件通过Prop接收数据时必须提供默认值Componentstruct InspirationCardView{Propcard:InspirationCard{id:0,emoji:,title:,content:,height:120,bgColor:#ffffff};}这个默认值不仅是为了满足TypeScript的类型要求更是ArkTS编译器的强制约束——没有默认值的Prop会在编译时报错。默认值的选择应当是该属性的安全初始值即使父组件忘记传入也不会导致UI异常。7.4 ForEach的显式类型标注// ✅ 正确回调参数显式标注类型ForEach(this.styles,(style:WritingStyle){...})ForEach(this.inspirations,(card:InspirationCard){...})ForEach(this.historyList,(article:HistoryArticle){...})// ❌ 错误省略类型标注ForEach(this.styles,(style){...})// 编译警告或错误显式类型标注不仅满足编译要求也帮助编辑器提供更准确的代码补全和类型检查。八、UI样式系统设计8.1 色彩体系整个页面采用六色系统风格统一且层次分明用途色值应用场景主色#007aff风格标签选中态、风格标签文字底色#f5f5f5页面背景卡片色#ffffff历史文章卡片、编辑器背景文字主色#1a1a2e标题、主内容文字文字辅色#666666摘要、灵感卡片内容文字浅色#999999/#cccccc字数统计、日期、辅助提示六种灵感卡片背景色色值命名联想#fff3e0暖橙日出、温暖#e3f2fd天蓝海洋、天空#fce4ec粉红浪漫、温馨#e8f5e9浅绿自然、生长#f3e5f5浅紫梦幻、创意#e0f7fa湖蓝清澈、宁静8.2 圆角系统风格统一的三级圆角体系级别半径使用对象圆形16vp风格切换标签标准12vpTextArea编辑器、灵感卡片、历史卡片小型4vp风格标签文字8.3 间距与留白页面统一采用20vp的左右外边距内层卡片使用1216vp内边距各区块间通过1012vp的纵向间距分隔。这种紧凑但不拥挤的间距系统在移动设备屏幕上提供了良好的信息密度。九、性能优化与扩展9.1 当前性能状况对于当前的数据规模12条灵感、8篇历史文章ArkTS原生List和WaterFlow的渲染性能完全充裕。实际测试中页面首屏渲染时间在50ms以内输入响应零延迟。9.2 可扩展的性能优化当数据规模增长到百级或千级时可以考虑以下优化策略LazyForEach替代ForEachWaterFlow和List都支持LazyForEach数据源实现虚拟滚动——只渲染可视区域内的Item大幅降低长列表的内存开销。WaterFlow缓存通过cachedCount属性设置预渲染Item数量减少滚动时的白屏等待。输入防抖对于字数统计这类高频更新可引入setTimeout防抖机制在用户停止输入100ms后再更新状态减少计算频率。状态拆分将writingText和inspirations等不相关的状态拆分避免单次State变更触发整个页面的重渲染。9.3 功能扩展方向当前实现为MVP版本后续可扩展的功能包括AI续写接入鸿蒙AI能力ohos.ai.text实现根据已有内容自动续写。关键词联想写作时根据当前输入关键词动态刷新灵感卡片内容。风格预览选中不同风格时编辑器底部的提示文字示例随之变化。云同步通过分布式数据对象实现多设备间的写作数据同步。Markdown预览支持Markdown语法实时渲染实现写前预览一体化。导出分享支持导出为纯文本、Markdown或PDF格式通过分享能力发送到其他应用。十、WaterFlow与其他布局组件的横向对比为了帮助读者更好地理解WaterFlow的定位这里将其与ArkUI中的其他容器组件进行横向对比特性WaterFlowGridListFlex列数可变如’1fr 1fr’可变单列可变行中单项高度可互不相同行内等高可互不相同可互不相同滚动方向垂直垂直垂直/水平无内置滚动典型场景瀑布流、卡片墙相册、网格菜单消息流、设置页工具栏、标签行选型建议需要双列或多列但每项高度不固定 →WaterFlow需要规整的网格排列每行等高 →Grid单列垂直滚动 →List单行水平排列 →FlexRow十一、总结与展望PureHarmony · 文案创作工坊从零开始仅用ArkTS原生组件就构建了一个包含编辑、灵感、管理全链路的写作助手。整个实现过程验证了几个重要观点ArkTS原生组件能力足以支撑中等复杂度的业务场景——WaterFlow瀑布流、List列表、TextArea编辑器三大组件的组合覆盖了从内容输入到灵感呈现的完整工作流。声明式UI范式在写作类应用中具有天然优势——状态驱动的字数统计、风格切换等交互在Web时代需要手动操作DOM在ArkTS中只需声明数据绑定即可。WaterFlow作为HarmonyOS独有的布局组件填补了移动端瀑布流布局的空白——对于内容推荐、灵感展示等场景是理想的布局方案。ArkTS的语法约束虽然陡峭但引导开发者养成了良好的编码习惯——将计算逻辑从渲染方法中分离、显式标注类型、合理设置默认值这些习惯在任何平台开发中都是最佳实践。在鸿蒙生态持续演进的背景下ArkTS和ArkUI的能力边界正在不断扩展。掌握原生组件的组合艺术理解声明式UI的数据驱动范式将成为鸿蒙开发者不可或缺的核心竞争力。项目代码仓库该页面的完整源码位于项目entry/src/main/ets/pages/AIWriterPage.ets可直接在 DevEco Studio 中打开编译运行。技术栈ArkTS ArkUI (HarmonyOS API 11)关键词HarmonyOS、ArkTS、ArkUI、WaterFlow、写作助手、瀑布流、声明式UI、灵感卡片