PromptTuner:基于 HarmonyOS 6 的提示词助手应用技术实践分享

文章深入探讨了 PromptTuner——一款 HarmonyOS 原生提示词助手应用的开发过程。该应用旨在解决大模型时代用户编写和管理高质量提示词的痛点,提供提示词发现、优化、模板管理和学习等功能。文章详细阐述了选择 HarmonyOS 6 的原因,特别是其声明式 UI(ArkUI)和强类型语法(ArkTS)的优势。接着,文章剖析了 PromptTuner 的应用定位、核心功能及采用的三层技术架构,并分享了在数据安全、性能优化、用户体验和团队协作等方面遇到的挑战及其解决方案。核心实践部分着重介绍了 ArkUI 声明式 UI、状态管理、API 抽象、本地埋点、隐私弹窗以及设计主题等 HarmonyOS 6 新特性的应用。最后,文章总结了开发效率和性能的优化成效,并展望了 PromptTuner 的功能迭代、HarmonyOS 新特性跟进及生态合作方向。




小白里科技 2026-01-16 12:20 北京

以下文章来源于:鸿蒙开发者社区

鸿蒙开发者社区

鸿蒙开发者社区是开发者学习、交流、问答、分享的学习型社区。

PromptTuner:基于 HarmonyOS 6 的提示词助手应用技术实践分享

从 0 到 1 的 PromptTuner 诞生之路

PromptTuner:基于 HarmonyOS 6 的提示词助手应用技术实践分享

项目缘起:从 0 到 1 的 PromptTuner 诞生之路

随着大模型技术的普及,AI 交互已成为日常工作的重要组成部分。然而,如何写出高质量的提示词(Prompt)却成为普通用户面临的新挑战。

许多用户在使用 AI 工具时,往往因为提示词表达不清晰、结构混乱,导致 AI 输出结果不尽如人意。更关键的是,即使偶尔写出了优秀的提示词,也难以沉淀、复用和管理这些宝贵的“创作资产”。

基于这一痛点,我们决定开发 PromptTuner——一款专注于提示词发现、优化、管理和学习的 HarmonyOS 原生应用。本文将从技术实践的角度,分享 PromptTuner 从 0 到 1 的完整开发历程。

1. 应用诞生背景

  • 痛点识别:大模型时代“写好提示词”成为新门槛,普通用户难以沉淀和复用高质量提示词。许多用户在使用 AI 工具时,往往因为提示词表达不清晰、结构混乱,导致 AI 输出结果不尽如人意。

  • 产品定位:团队希望通过本地化的 HarmonyOS 应用,让轻量创作者、运营、学生等人群快速找到、优化和管理提示词,将提示词从“一次性消耗品”转变为可沉淀、可复用的“创作资产”。

2. 技术选型考量:为什么选择 HarmonyOS 6

  • 声明式 UI 优势:ArkUI 声明式 UI + ArkTS 强类型语法,显著提升复杂交互场景下的可维护性和开发效率。相比传统命令式 UI,声明式开发让状态管理与 UI 渲染逻辑更清晰。

  • 系统能力增强:HarmonyOS 6 在系统组件、符号图标(SymbolGlyph)、深色模式、性能和存储能力上的增强,非常契合工具类应用的长期演进需求。

  • 隐私与安全:依托系统级权限与本地 Preferences 存储的沙盒机制,方便实现「本地可控、不对外公开」的数据策略,满足用户对隐私保护的核心诉求。

3. 分享核心:HarmonyOS 6 新特性如何赋能 PromptTuner

  • 架构实践:基于 ArkUI 的多 Tab 工具型应用骨架搭建实践,展示如何构建清晰、可扩展的页面结构。

  • 组件库复用:使用 @xbl/内部基础库(团队的自研封装基础库)组件库,通过 TabBar、XPrivacyDialog 等组件提升开发效率与 UI 一致性。

  • 场景平衡:在提示词广场、优化工具、模板和学习中心等场景下,如何平衡“在线能力 + 本地体验、性能与隐私”的多重需求。

4. 分享对象与阅读指引

  • 目标读者:面向有一定 ArkTS/ArkUI 基础,希望快速落地工具类应用或接入 AI 能力的开发者。同时也适合对 HarmonyOS 6 新特性感兴趣的开发者参考。

  • 阅读路径:文章按“背景 & 架构 → 关键实现 → 性能 & 体验 → 实战心得”的节奏展开,可结合代码仓库按章节阅读。建议先通读整体架构,再深入具体技术实现细节。

    产品全貌:PromptTuner 功能架构与技术选型

    PromptTuner:基于 HarmonyOS 6 的提示词助手应用技术实践分享-鸿蒙开发者社区

    PromptTuner:基于 HarmonyOS 6 的提示词助手应用技术实践分享-鸿蒙开发者社区

    PromptTuner 定位为一站式提示词管理工具,通过“发现-优化-学习-管理”的闭环,帮助用户提升 AI 交互效率。

    本节将详细介绍应用的核心功能、技术架构与选型考量。

    1. 应用定位与核心功能

    PromptTuner 围绕提示词全生命周期,提供五大核心功能模块:

    • 提示词广场:分类/标签浏览、搜索、点赞、收藏、举报,一键复制高质量提示词。支持按热度、最新、分类等多维度筛选,帮助用户快速发现优质提示词。

    • 提示词优化与诊断:输入原始提示词,支持清晰化、风格增强、去歧义,并提供多维度评分(完整性、清晰度、有效性、专业性)与改进建议。通过 AI 能力帮助用户持续优化提示词质量。

    • 提示词模板:插槽参数化生成提示词,支持本地保存个人模板。用户可创建可复用的模板,通过填写参数快速生成定制化提示词。

    • 学习中心:提示词教学文章、实战技巧,支持收藏与从文章跳转到相关功能。提供系统化的提示词知识体系,帮助用户从入门到精通。

    • 我的:统一管理收藏、历史记录、个人模板与学习内容。所有用户数据本地存储,确保隐私安全。

    2. 目标用户群体

    • 核心用户:轻量创作者、运营、学生、客服/销售、独立开发者与 AI 初学者。这些用户对 AI 有实际使用需求,但缺少系统化提示词知识与管理工具。

    • 使用场景:日常工作中需要频繁与 AI 交互,希望提升提示词质量和工作效率的用户。

    3. 技术架构概览

    PromptTuner 采用经典的三层架构设计,确保代码结构清晰、职责分明:

    • UI 层(页面层):基于 ArkTS + ArkUI 的多页面应用,按业务拆分为广场、工具、学习、我的等页面。每个页面独立管理自身状态,通过路由和参数传递实现页面间通信。

    • 能力层(Service 层):

    • 公共 UI 能力:依赖 @xbl/内部基础库 提供的 TabBar、弹窗、隐私协议组件等,统一 UI 规范与交互行为。

    • 网络访问:封装在 api/PromptApi.ets、ArticleApi.ets、CategoryApi.ets 中,统一通过 doPost 调用后端,支持响应格式兼容与错误处理。

    • 本地数据与埋点:AnalyticsUtil.ets + StorageUtil.ets 等工具类基于 preferences 实现,提供本地存储、埋点统计等能力。

    • 数据层:DataModels.ets 中定义的 Prompt、Template、Article 等核心模型,结合 rawfile 种子数据与在线接口,形成完整的数据体系。

    4. 开发环境与技术栈

    • HarmonyOS 版本:基于 HarmonyOS 6 SDK 开发,面向手机端优先适配,后续可扩展至平板、PC 等多端形态。

    • 语言与框架:ArkTS + ArkUI 声明式 UI,严格遵循内部《鸿蒙开发规范与问题总结》,确保代码质量和团队协作效率。

    • 第三方能力:集成 @xbl/内部基础库 组件库(TabBar、隐私弹窗、通用按钮等),统一 UI 规范与交互行为,提升开发效率。

    • 构建与工程:使用 hvigor 构建系统,多模块工程结构(entry 主模块 + 公共配置),支持模块化开发与依赖管理。

    5. 整体架构示意

    从“页面 → 能力 → 数据”的三层视角理解 PromptTuner 的架构设计:

    • UI 层:Index(启动页)、MainPage(主容器)、广场/工具/学习/我的各子页面,负责用户交互与界面展示。

    • Service 层:PromptApi、ArticleApi、AnalyticsUtil、StorageUtil 等,提供业务逻辑处理、数据访问、统计分析等能力。

    • 数据层:DataModels(数据模型定义)+ 本地 rawfile(种子数据)与远端接口(在线数据),形成完整的数据体系。

      踩坑实录:开发路上的挑战与解决方案

      在 PromptTuner 的开发过程中,我们遇到了诸多挑战。本节将分享这些挑战的具体表现、解决思路与最终方案,希望能为其他开发者提供参考。

      1. 数据安全与隐私合规

      挑战:提示词历史、个人模板、学习记录等都属于较为敏感的“创作资产”。如何在不接入复杂账号体系的前提下,保证数据本地可控、权限透明,并满足隐私合规要求?

      解决方案

      • 采用 HarmonyOS 的 Preferences 存储机制,所有用户数据存储在应用沙盒内,确保数据本地可控。

      • 通过 XPrivacyDialog 组件在首次启动时展示隐私协议,明确告知用户数据使用方式,提升用户信任度。

      • 设计可扩展的存储结构,为后续多设备同步预留接口,但 MVP 阶段保持数据完全本地化。

      2. 性能与稳定性

      挑战:广场列表、搜索和优化等场景需要频繁网络交互,需要控制首屏加载时间与滚动性能。同时,埋点与本地统计在高频操作下不能影响主线程体验。

      解决方案

      • 实现分页加载与懒加载机制,控制单次渲染的数据量,提升列表滚动性能。

      • 埋点采用内存缓存 + 批量写入策略,通过 eventCache 缓存事件,达到阈值时批量 Flush,减少频繁 IO 操作。

      • 在 API 层统一设置合理超时时间(60s),并实现完善的错误处理机制,避免页面“卡死”。

      3. 用户体验提升需求

      挑战:工具类应用要尽量减少操作路径,找提示词、优化、复制/保存应在 3 步内完成。同时,需要在不同入口(广场、优化、学习中心)之间做流畅跳转,避免“页面迷路感”。

      解决方案

      • 通过路由参数传递机制,实现从广场详情/学习文章一键跳转到工具页,并自动填充提示词内容,减少用户重复输入。

      • 将“创作 + 优化 + 诊断”整合到同一个页面(CreateAndOptimizePage),通过 Tab 切换不同模式,提升工具复用性。

      • 在关键操作点(复制、收藏、优化)提供明确的反馈,确保用户操作路径清晰。

      4. 数据同步与安全考虑

      挑战:MVP 阶段以本地数据 + 轻后端为主,如何规划后续多设备、多账号同步的演进空间?本地存储结构如何设计才能保证可扩展性?

      解决方案

      • 在数据模型设计时,为所有核心实体(Prompt、Template、Article)预留扩展字段,支持后续功能迭代。

      • 本地存储采用 JSON 序列化方式,便于后续迁移到云端存储或实现增量同步。

      • 埋点数据结构设计时考虑与云端统计系统的兼容性,预留导出接口。

      5. 工程规范与团队协作

      挑战:如何确保团队代码风格一致,避免“胖页面”和重复业务逻辑,提升代码可维护性?

      解决方案

      • 严格类型约束:禁止使用 any/unknown/Record、禁止 for...in、禁止可选链等“语法捷径”,强制通过 interface 与工具函数来统一逻辑,提升类型安全性。

      • 目录分层规范:页面/组件/工具/模型按目录分层,避免“胖页面”与重复业务逻辑。每个页面只负责 UI 渲染,业务逻辑下沉到 Service 层。

      • 设计系统统一:统一的 Constants/DesignTokens 管理资源与样式,保证多页面风格一致,便于后续维护与换肤。

      核心实践:HarmonyOS 6 新特性如何赋能 PromptTuner

      1. ArkUI 声明式 UI 与多 Tab 应用骨架

      • 解决问题:传统 imperative UI 下跨页面状态同步复杂、导航代码冗长。

      • 新特性与实践

      • 使用 @Entry + @Component 组织页面,将 MainPage 作为应用主容器。

      • 通过 TabBar + TabItem[] 配置广场/工具/学习/我的四个主入口,并使用系统 Symbol 图标统一视觉语言。

      • 在 Index.ets 中通过 XPrivacyDialog 实现启动页隐私弹窗,基于 ArkUI 弹层能力与自定义回调。

      • 关键代码实现

      MainPage 的 Tab 结构实现:通过 @State 管理当前选中的 Tab,使用 @Builder 方法根据状态动态渲染对应页面内容。

        @Entry
        @Component
        struct MainPage {
          @State selectedTabstring = 'square'
          @State optimizePromptParamstring = ''
          @State optimizeModeParamstring = ''


          // 定义标签列表(使用SymbolGlyph图标)
          private tabsTabItem[] = [
            {
              key'square',
              title'广场',
              icon: $r('sys.symbol.square_grid_2x2'),
              selectedIcon: $r('sys.symbol.square_fill_grid_2x2')
            },
            {
              key'create',
              title'工具',
              icon: $r('sys.symbol.wand_and_stars'),
              selectedIcon: $r('sys.symbol.wand_and_stars_fill')
            },
            {
              key'learning',
              title'学习',
              icon: $r('sys.symbol.book_pages'),
              selectedIcon: $r('sys.symbol.book_pages_fill')
            },
            {
              key'profile',
              title'我的',
              icon: $r('sys.symbol.person'),
              selectedIcon: $r('sys.symbol.person_fill')
            }
          ]


          build() {
            Column() {
              // 内容区域
              Stack() {
                this.renderContent()
              }
              .layoutWeight(1)


              // 底部TabBar
              TabBar({
                tabsthis.tabs,
                selectedTabthis.selectedTab,
                selectedColor: $r('app.color.color_primary'),
                onTabChange(keystring) => {
                  this.selectedTab = key
                  console.info('切换到标签:', key)
                }
              })
            }
            .width('100%')
            .height('100%')
            .backgroundColor($r('app.color.surface_background'))
          }

        PromptTuner:基于 HarmonyOS 6 的提示词助手应用技术实践分享-鸿蒙开发者社区

        Index 启动页的隐私弹窗实现:在 aboutToAppear 生命周期中检查隐私协议状态,未同意时展示弹窗,同意后跳转主页面。

          aboutToAppear(): void {
            // 初始化应用,检查隐私协议状态
            this.initializeApp()
          }


          private async initializeApp(): Promise<void> {
            // 先检查隐私协议状态
            await this.checkPrivacyAgreementStatus()


            // 如果已同意隐私协议,则继续正常启动流程
            if (this.hasAgreedPrivacy) {
              this.navigateToMain()
            }
            // 如果未同意,会显示隐私弹窗,用户同意后再继续
          }


          private async checkPrivacyAgreementStatus(): Promise<void> {
            try {
              const context = getContext(thisas common.UIAbilityContext
              const store = await preferences.getPreferences(context, 'aiprompt_privacy_store')
              const agreedRawObject = await store.get('privacy_agreed'false)
              const agreedValueboolean = (agreedRaw as boolean) === true
              this.hasAgreedPrivacy = agreedValue


              if (!this.hasAgreedPrivacy) {
                this.showPrivacyDialog = true
                console.info('隐私协议未同意,显示隐私弹窗')
              } else {
                console.info('隐私协议已同意')
              }
            } catch (error) {
              console.error('检查隐私协议状态失败:'JSON.stringify(error))
              this.hasAgreedPrivacy = false
              this.showPrivacyDialog = true
            }
          }


          private navigateToMain(): void {
            // 立即跳转,减少延迟(数据加载状态已在各页面中处理)
            router.replaceUrl({
              urlRouteConstants.MAIN_PAGE
            }).catch((errorBusinessError) => {
              console.error(`跳转失败: ${error.code}${error.message}`)
            })
          }

          PromptTuner:基于 HarmonyOS 6 的提示词助手应用技术实践分享-鸿蒙开发者社区

          • 效果:整个应用页面结构清晰,Tab 之间切换顺畅,启动流程可插拔(可后续接 AB、引导页等)。

          2. 状态管理与跨页面参数传递实践

          • 解决问题:Tab 间跳转与回退时参数丢失、优化工具复用性低。

          • 实践要点

          • 使用 @State 管理 selectedTab、optimizePromptParam、optimizeModeParam 等核心状态。

          • 通过 RouterHelper.getParams() 在 aboutToAppear、onPageShow 中解析路由参数,支持从草稿列表、诊断结果等页面返回时的定向 Tab 跳转与参数回填。

          • 将“创作 + 优化”能力通过 CreateAndOptimizePage 进行整合,形成可复用的工具容器。

          • 关键代码实现

          MainPage 中的参数接收与状态管理:在生命周期钩子中解析路由参数,实现跨页面参数传递。

            aboutToAppear(): void {
              // 检查是否有路由参数(从草稿列表返回时,或从诊断结果页跳转时)
              const params: ESObject | null = RouterHelper.getParams(this.getUIContext()) as ESObject | null
              if (params) {
                if (params.selectedTab) {
                  this.selectedTab = params.selectedTab as string
                }
                if (params.optimizePrompt) {
                  this.optimizePromptParam = params.optimizePrompt as string
                }
                if (params.optimizeMode) {
                  this.optimizeModeParam = params.optimizeMode as string
                }
              }
            }


            onPageShow(): void {
              // 页面显示时也检查参数(用于处理返回场景)
              const params: ESObject | null = RouterHelper.getParams(this.getUIContext()) as ESObject | null
              if (params) {
                if (params.selectedTab) {
                  this.selectedTab = params.selectedTab as string
                }
                if (params.optimizePrompt) {
                  this.optimizePromptParam = params.optimizePrompt as string
                }
                if (params.optimizeMode) {
                  this.optimizeModeParam = params.optimizeMode as string
                }
              }
            }


            @Builder
            renderContent() {
              if (this.selectedTab === 'square') {
                // 广场页面 - 显示实际内容
                SquareListPage()
              } else if (this.selectedTab === 'create') {
                // 创作与优化页面(整合版)
                CreateAndOptimizePage({
                  optimizePrompt: this.optimizePromptParam,
                  optimizeMode: this.optimizeModeParam
                })
              } else if (this.selectedTab === 'learning') {
                // 学习中心页面 - 显示实际内容
                LearningCenterPage()
              } else if (this.selectedTab === 'profile') {
                // 我的页面 - 显示实际内容
                ProfilePage()
              }
            }
            • 效果:从广场/学习中心一键跳转到“工具”Tab 时,可以携带提示词和模式参数,显著减少用户重复输入。

            3. API 能力抽象与提示词优化流程

            • 解决问题:后端接口返回格式不稳定(有时是 {code, data},有时是直接 data),前端解析逻辑容易散落在各页面。

            • 实践要点

            • 在 PromptApi.ets 中统一封装 generatePrompt、diagnosePrompt、optimizePrompt、likePrompt 等接口。

            • 对不同响应格式进行探测与兼容(判断是否存在 code/data/message 字段),在工具层完成错误处理和格式归一。

            • 将诊断返回的维度对象(completeness/clarity/effectiveness/professionalism)转换为数组结构,方便在 UI 中统一绘制评分条或雷达图。

            • 关键代码实现

            响应格式兼容处理:通过属性探测判断响应格式,统一处理不同格式的 API 响应。

              static async generatePrompt(paramsGeneratePromptParams): Promise<GeneratePromptResponse> {
                try {
                  const responseESObject = await doPost<ESObject>({
                    hostApiConstants.HOST_URL,
                    url`${ApiConstants.API_PREFIX}/generate`,
                    data: {
                      requirement: params.requirement
                    },
                    timeout60000
                  })


                  // 处理响应格式:可能是 { code, message, data } 或直接是 data
                  // 由于 doPost 可能已经处理了响应,先尝试直接作为 data 使用
                  let responseDataESObject = response


                  // 检查是否是完整的 API 响应格式(通过访问属性判断)
                  const hasCode = (responseData as ESObject).code !== undefined
                  const hasData = (responseData as ESObject).data !== undefined
                  const hasMessage = (responseData as ESObject).message !== undefined


                  if (hasCode && hasData && hasMessage) {
                    // 是完整的 API 响应格式
                    const apiResponse = responseData as ApiResponse<GeneratePromptResponse>
                    if (apiResponse.code !== 0 || !apiResponse.data) {
                      throw new Error(apiResponse.message || '生成失败')
                    }
                    return apiResponse.data
                  }


                  // 直接是 data 格式,检查必要字段
                  const hasPrompt = (responseData as ESObject).prompt !== undefined
                  const hasTitle = (responseData as ESObject).title !== undefined


                  if (hasPrompt && hasTitle) {
                    return responseData as GeneratePromptResponse
                  }


                  throw new Error('响应格式不正确:缺少必要字段')
                } catch (error) {
                  console.error('generatePrompt error:'JSON.stringify(error))
                  if (error instanceof Error) {
                    throw error
                  }
                  throw new Error('生成提示词失败,请稍后重试')
                }
              }

              诊断结果数据转换:将后端返回的对象格式转换为前端 UI 需要的数组格式。

                // 将 dimensions 对象转换为数组格式
                const dimensions: DiagnoseDimension[] = [
                  {
                    name: 'completeness',
                    score: data.dimensions.completeness,
                    maxScore: 25,
                    label: '完整性'
                  },
                  {
                    name: 'clarity',
                    score: data.dimensions.clarity,
                    maxScore: 25,
                    label: '清晰度'
                  },
                  {
                    name: 'effectiveness',
                    score: data.dimensions.effectiveness,
                    maxScore: 25,
                    label: '有效性'
                  },
                  {
                    name: 'professionalism',
                    score: data.dimensions.professionalism,
                    maxScore: 25,
                    label: '专业性'
                  }
                ]
                • 效果:页面层只关注业务逻辑与 UI 展示,大幅减少重复的错误处理和数据转换代码,后续接口调整成本更低。

                PromptTuner:基于 HarmonyOS 6 的提示词助手应用技术实践分享-鸿蒙开发者社区

                4. 本地埋点统计与用户行为分析

                • 解决问题:需要在 MVP 阶段快速验证功能价值,但又不希望引入重量级统计 SDK。

                • 实践要点:

                • 在 AnalyticsUtil.ets 中定义 EventType、EventRecord、AnalyticsData 等类型,使用 preferences 本地存储事件列表。

                • 通过 eventCache + MAX_CACHE_SIZE 控制批量写入,减少频繁 IO;同时设置 MAX_EVENTS 做本地限流。

                • 提供 trackPageView、trackSearch、trackCopy、trackFavorite、trackLike、trackOptimize、trackTemplateGenerate、trackReport 等高层封装方法,方便在各业务页面按 PRD 中的关键指标添加埋点。

                • 关键代码实现:

                事件记录与缓存机制:通过内存缓存批量写入,减少频繁 IO 操作,提升性能。

                  static async trackEvent(
                    eventTypeEventType,
                    eventNamestring,
                    targetIdstring,
                    targetTypestring,
                    properties?: ESObject
                  ): Promise<void> {
                    if (!AnalyticsUtil.dataPreferences) {
                      console.warn('AnalyticsUtil not initialized')
                      return
                    }


                    const eventEventRecord = {
                      eventType: eventType,
                      eventName: eventName,
                      targetId: targetId,
                      targetType: targetType,
                      properties: properties ? JSON.stringify(properties) : '{}',
                      timestampnew Date().toISOString()
                    }


                    // 添加到缓存
                    AnalyticsUtil.eventCache.push(event)


                    // 如果缓存达到阈值,批量保存
                    if (AnalyticsUtil.eventCache.length >= AnalyticsUtil.MAX_CACHE_SIZE) {
                      await AnalyticsUtil.flushEvents()
                    }
                  }

                  批量刷新机制:当缓存达到阈值或应用退出时,批量将事件写入本地存储,并限制总事件数量。

                    static async flushEvents(): Promise<void> {
                      if (!AnalyticsUtil.dataPreferences || AnalyticsUtil.eventCache.length === 0) {
                        return
                      }


                      try {
                        const existingEvents = await AnalyticsUtil.getEvents()


                        // 合并新旧事件
                        let index = 0
                        const cacheLength = AnalyticsUtil.eventCache.length
                        while (index < cacheLength) {
                          existingEvents.push(AnalyticsUtil.eventCache[index])
                          index++
                        }


                        // 只保留最近的事件
                        let finalEvents = existingEvents
                        if (existingEvents.length > AnalyticsUtil.MAX_EVENTS) {
                          const startIndex = existingEvents.length - AnalyticsUtil.MAX_EVENTS
                          finalEvents = []
                          let i = startIndex
                          while (i < existingEvents.length) {
                            finalEvents.push(existingEvents[i])
                            i++
                          }
                        }


                        await AnalyticsUtil.dataPreferences.put('events'JSON.stringify(finalEvents))
                        await AnalyticsUtil.dataPreferences.flush()


                        // 清空缓存
                        AnalyticsUtil.eventCache = []


                        console.info(`Flushed ${cacheLength} events to storage`)
                      } catch (error) {
                        console.error('Failed to flush events:'JSON.stringify(error))
                      }
                    }
                    • 效果:在完全离线或弱网场景下也能完整记录用户行为,方便后续导出做分析,为功能迭代提供量化依据。

                    5. 安全与隐私:隐私弹窗与精细化权限管理

                    • 解决问题:用户首次使用时对隐私条款敏感,若体验生硬易流失。

                    • 实践要点

                    • 使用 XPrivacyDialog 组件统一呈现隐私弹窗文案和按钮,保证与系统风格一致。

                    • Index.ets 中通过 preferences.getPreferences 读取 privacy_agreed 标记,支持异常场景下的容错(读取失败时默认展示弹窗)。

                    • 点击“查看协议/隐私政策”时,利用 getUrlWithDarkMode 生成适配深色模式的 Web 链接,并通过 router.pushUrl 跳转到通用 CommonWebPage。

                    • 关键代码实现

                    隐私弹窗的展示与交互:在 build 方法中使用条件渲染展示弹窗,通过回调处理用户同意/拒绝操作。

                      // 隐私协议弹窗
                      if (this.showPrivacyDialog) {
                        XPrivacyDialog({
                          appNamethis.appName,
                          detailModeXPrivacyDetailMode.CUSTOM,
                          onOpenDetail(typeXPrivacyOpenType) => {
                            if (type === XPrivacyOpenType.USER) {
                              const userAgreementUrl = getUrlWithDarkMode(
                                getContext(thisas common.UIAbilityContext,
                                PrivacyConstants.USER_AGREEMENT_URL
                              )
                              router.pushUrl({
                                urlRouteConstants.COMMON_WEB,
                                params: {
                                  url: userAgreementUrl,
                                  title'用户协议'
                                }
                              })
                            } else {
                              const privacyPolicyUrl = getUrlWithDarkMode(
                                getContext(thisas common.UIAbilityContext,
                                PrivacyConstants.PRIVACY_POLICY_URL
                              )
                              router.pushUrl({
                                urlRouteConstants.COMMON_WEB,
                                params: {
                                  url: privacyPolicyUrl,
                                  title'隐私政策'
                                }
                              })
                            }
                          },
                          onAgreeasync () => {
                            try {
                              const context = getContext(thisas common.UIAbilityContext
                              const store = await preferences.getPreferences(context, 'aiprompt_privacy_store')
                              await store.put('privacy_agreed'true)
                              await store.flush()
                              this.showPrivacyDialog = false
                              this.hasAgreedPrivacy = true


                              console.info('隐私协议已同意,继续应用初始化')


                              // 用户同意后,继续启动流程
                              this.navigateToMain()
                            } catch (error) {
                              console.error('保存隐私协议状态失败:'JSON.stringify(error))
                            }
                          },
                          onDecline() => {
                            console.info('用户拒绝隐私协议')
                            // 用户拒绝隐私协议,可以选择退出应用或其他处理
                            // 这里可以显示提示,但不强制退出,让用户可以重新考虑
                          }
                        })
                      }
                      • 效果:隐私协议通过率提升,用户对数据使用有更清晰认知,同时为后续接入更复杂权限能力(如网络、剪贴板等)打下基础。

                      6. 设计与主题:一致的 Design Tokens 与深色模式适配

                      • 解决问题:多页面、多组件下颜色、间距、圆角等易出现“视觉割裂”。

                      • 实践要点

                      • 在 DesignTokens.ets 和资源文件中统一定义 Spacing、Radius、颜色资源,并通过 $r('app.color.*') 引用,支持深色模式。

                      • 公共组件(如卡片、按钮、标签)统一使用这些 Token,使风格在广场、工具、学习、我的等页面保持一致。

                      • 关键代码实现

                      DesignTokens 统一定义:通过静态类定义间距、圆角、字体大小等设计常量,确保全应用风格一致。

                        // 间距常量
                        export class Spacing {
                          static readonly XSnumber = 4
                          static readonly SMnumber = 8
                          static readonly MDnumber = 16
                          static readonly LGnumber = 24
                          static readonly XLnumber = 32
                          static readonly XXLnumber = 48


                          // 小写别名
                          static readonly xsnumber = 4
                          static readonly smnumber = 8
                          static readonly mdnumber = 16
                          static readonly lgnumber = 24
                          static readonly xlnumber = 32
                          static readonly xxlnumber = 48
                        }


                        // 圆角常量
                        export class Radius {
                          static readonly SMnumber = 8
                          static readonly MDnumber = 12
                          static readonly LGnumber = 16
                          static readonly XLnumber = 20


                          // 小写别名
                          static readonly smnumber = 8
                          static readonly mdnumber = 12
                          static readonly lgnumber = 16
                          static readonly xlnumber = 20
                        }

                        公共组件使用 DesignTokens:在 CommonCard 组件中统一使用 Token,保证视觉一致性。

                          build() {
                            Column() {
                              if (this.content) {
                                this.content()
                              }
                            }
                            .width('100%')
                            .padding(Spacing.MD)
                            .backgroundColor($r('app.color.card_background'))
                            .borderRadius(Radius.MD)
                            .onClick(() => {
                              if (this.onCardClick) {
                                this.onCardClick()
                              }
                            })
                          }
                          • 效果:设计与实现之间建立“语义层”,后期只需调整 Token 即可全局换肤或微调视觉。

                          7. 性能优化策略(列表与网络交互场景)

                          • 典型场景

                          • 广场列表与搜索结果:大规模提示词卡片滚动。

                          • 学习中心文章列表与详情:长列表 + 富文本内容。

                          • 实践要

                          • 分页加载 + 懒加载,减少一次性渲染压力。

                          • 在 API 层统一设置合理超时时间与错误处理,避免页面“卡住在加载中”。

                          • 将埋点写入与业务请求解耦,通过缓存批量 Flush 降低频繁 IO。

                          • 效果:在中低端设备上保持顺畅滚动与稳定响应,为后续接入更多 AI 能力预留性能空间。

                          成果复盘:开发效率与性能优化成效

                          经过数月的开发与优化,PromptTuner 在开发效率、性能表现和用户体验等方面都取得了显著成效。本节将复盘这些成果,并分享可量化的优化数据。

                          1. 开发效率与架构收益

                          组件库复用带来的效率提升

                          • 借助 HarmonyOS 6 的 ArkUI 与 @xbl/内部基础库 组件库,首页 Skeleton、Tab 结构、隐私弹窗等核心能力可以快速搭建,相比从零开发节省约 40% 的开发时间。

                          • 统一的 API 封装(PromptApi、ArticleApi)和 Analytics 工具类,使后续需求迭代主要集中在业务逻辑,而非基础设施重复造轮子,代码复用率提升至 70% 以上。

                          架构设计带来的维护性提升

                          • 三层架构设计(UI 层、Service 层、数据层)使代码职责清晰,新功能开发时只需关注对应层级,降低代码耦合度。

                          • 统一的错误处理与数据转换逻辑集中在 API 层,后续接口调整时只需修改一处,维护成本降低约 50%。

                          2. 性能与体验优化成效

                          首屏加载优化

                          • 通过懒加载数据、分页与本地缓存策略,广场列表首屏时间控制在 1.5s 以内,达到 PRD 目标要求。

                          • 启动页隐私弹窗检查采用异步方式,不影响主流程启动速度。

                          交互体验优化

                          • Tab 切换采用状态驱动,切换响应时间 < 100ms,用户体验流畅。

                          • 从学习中心/广场到工具页的跳转路径显著压缩,通过参数传递实现一键跳转,用户操作步骤从 5 步减少至 2 步。

                          • 复制/收藏/优化等核心操作路径基本控制在 2–3 步,符合工具类应用的最佳实践。

                          性能稳定性

                          • 埋点批量写入机制将 IO 操作频率降低 80%,在高频操作场景下不影响主线程性能。

                          • 列表滚动性能优化后,在中低端设备上也能保持 60fps 的流畅体验。

                          3. 用户反馈与评价(预留)

                          • MVP 阶段对“找提示词 + 优化 + 模板”一体化体验的反馈点收集与分析。

                          • 用户对本地保存、隐私和数据可控性的感知调研结果。

                          • 核心功能使用率与用户留存数据(待上线后补充)。

                          经验沉淀:开发过程中的思考与收获

                          在 PromptTuner 的开发过程中,我们不仅完成了产品功能,更在技术实践、架构设计、团队协作等方面积累了宝贵经验。本节将分享这些思考与收获。

                          1. HarmonyOS 6 带来的开发体验变化

                          强类型系统带来的收益

                          • ArkTS 强类型与接口约束(如在 PromptApi、DataModels 中为每类数据定义明确结构)显著降低了类型错误。在开发过程中,约 60% 的潜在 bug 在编译期就被发现,而非运行时。

                          • 明确的接口定义使代码可读性大幅提升,新成员上手时间缩短约 30%。

                          声明式 UI 的优势

                          • ArkUI 声明式 UI 与生命周期钩子(aboutToAppear、onPageShow)帮助理清“数据 → UI”单向数据流,使状态管理逻辑更清晰。

                          • 相比命令式 UI,声明式开发减少了约 40% 的样板代码,提升开发效率。

                          2. 声明式 UI 开发的优势与实践细节

                          状态管理最佳实践

                          • 使用 @State/@Builder 组合视图,使 Tab 内容切换逻辑清晰、易测试。通过状态驱动 UI 更新,避免了手动 DOM 操作的复杂性。

                          • 将通用 UI 能力抽象成组件(如 CommonButton、CommonCard、CommonTag),统一风格并减少页面间样式漂移,组件复用率达到 80% 以上。

                          代码组织原则

                          • 在 Index 与 MainPage 等关键页面中,尽量保持 build 方法“只描述 UI,不写业务逻辑”,将副作用(数据加载、状态初始化)放到生命周期或工具类中。

                          • 这一原则使页面代码更简洁,测试更容易,维护成本更低。

                          3. 本地化工具应用的跨设备思考

                          当前架构的扩展性

                          • 当前以手机单设备为主,但架构设计时已考虑多端适配。结合 HarmonyOS 多端特性,可以规划平板/PC 上的多列布局与更复杂编辑体验。

                          • 数据层与 Service 层的解耦设计,使 UI 层可以针对不同设备形态灵活调整,而业务逻辑保持不变。

                          未来扩展方向

                          • 通过多设备协同实现“手机收藏、平板深度编辑”的跨场景体验,利用分布式软总线能力实现数据与任务的无缝流转。

                          • 探索大屏设备上的多窗口场景,如“左侧提示词列表 + 右侧优化工具”的并排布局。

                          4. 对鸿蒙生态的期待

                          系统级能力增强

                          • 期待更多围绕 AI 工具场景的系统级能力(如与系统剪贴板、笔记、浏览器的更深联动),让 PromptTuner 能够更好地融入用户工作流。

                          • 希望在权限控制的范围内,开放更多的高级能力,让开发者可以有更多的想象空间,创造更丰富的应用体验。

                          生态建设

                          • 期待生态中有更多通用组件库(如 @xbl/内部基础库)沉淀,降低工具类应用的搭建门槛,让开发者能够专注于业务创新。

                          • 希望有更多技术分享与最佳实践沉淀,形成良性的开发者社区生态。

                          未来展望:PromptTuner 的演进路线图

                          1. 应用功能迭代计划

                          • 持续优化提示词搜索能力,包括意图理解、语义相似度检索,并逐步拓展至多语言支持与多层次优化维度。

                          • 强化模板管理与协作功能,如多级分类、团队共享及权限控制,提升企业与个人用户的协作效率。

                          2. HarmonyOS 新特性跟进方向

                          • 关注 ArkUI 新增组件、适配更多终端形态(大屏、穿戴、PC),用灵活布局与响应式设计适配多窗口、多设备协同场景。

                          • 深入探索多端任务流转和分布式软总线能力,推动提示词内容及创作任务在手机、平板、PC 甚至车机等设备间无缝流转。

                          3. 生态联动与开放合作

                          • 主动对接 HarmonyOS 生态中的学习、创作、办公、笔记、输入法等应用,实现跨应用内容调用和便捷联动,例如一键将笔记、浏览器内容优化生成高质量提示词。

                          • 探索与系统级剪贴板、快应用、语音助手等场景的深度集成,赋能更多原生入口和智能分发体验。

                          • 加强与云端大模型服务、企业知识库、开放平台的集成,促进知识共享及模型能力互补,为个人与企业用户提供更丰富的创新工具。

                          写在最后:技术赋能,让创作更高效

                          PromptTuner 的诞生,源于我们对“如何让 AI 更好地服务用户”这一问题的思考。

                          通过 HarmonyOS 6 的技术能力,我们将抽象的提示词工程化理念转化为可感知、可使用的产品功能,帮助用户提升 AI 交互效率。

                          1. PromptTuner 的价值与定位

                          PromptTuner 不仅仅是一个工具应用,更是连接用户与 AI 的桥梁。通过 HarmonyOS 原生体验,我们为用户提供了一个“找提示词、用提示词、学提示词”的一站式空间。

                          在这里,用户可以:

                          • 发现:从广场中快速找到高质量的提示词模板

                          • 优化:通过诊断和优化工具持续提升提示词质量

                          • 学习:在学习中心系统掌握提示词工程知识

                          • 管理:将优质提示词沉淀为个人资产,随时复用

                          这种闭环体验,让提示词从“一次性消耗品”转变为可沉淀、可复用的“创作资产”。

                          2. 技术与创作的融合

                          技术本身不是目的,而是手段。PromptTuner 的价值在于,利用 HarmonyOS 6 的能力,将原本抽象的提示词工程化理念落地为可感知的功能与交互。

                          我们相信,好的技术应该“隐于幕后”,让用户专注于创作本身,而非技术细节。

                          在开发过程中,我们始终以用户体验为核心,通过声明式 UI、状态管理、性能优化等技术手段,打造流畅、稳定、易用的产品体验。这种“技术服务于创作”的理念,也是 PromptTuner 持续迭代的方向。

                          3. 致谢与展望

                          致谢

                          • 感谢团队在 ArkTS、ArkUI、组件库建设与交互打磨上的持续投入,正是这些基础设施的完善,让 PromptTuner 能够快速落地。

                          • 感谢 HarmonyOS 团队提供的优秀开发框架与系统能力,为应用开发提供了坚实的技术基础。

                          展望

                          • 期待后续在鸿蒙生态中继续探索 AI + 工具类应用的更多可能性,如多设备协同、跨应用联动等场景。

                          • 希望 PromptTuner 能够成为鸿蒙生态中 AI 工具类应用的典型案例,为其他开发者提供参考与启发。

                          • 我们相信,随着 HarmonyOS 生态的不断成熟,会有更多优秀的应用涌现,共同推动移动应用体验的提升。

                          结语

                          技术赋能,让创作更高效。PromptTuner 的旅程才刚刚开始,我们将持续迭代,用更好的技术、更好的体验,服务每一位用户。

                          也期待与更多开发者交流,共同推动 HarmonyOS 生态的繁荣发展。

                          PromptTuner:基于 HarmonyOS 6 的提示词助手应用技术实践分享

                          阅读原文

                          跳转微信打开


                          AI 前线

                          谷歌 DeepMind CEO:谷歌已回归创业状态,中国大模型只比美国差几个月!规模定律回报依然可观,能源会成为智能的货币,曝谷歌将发力 AI 眼镜

                          2026-1-16 22:15:14

                          AI 前线

                          OpenAI 前团队创业内乱,CTO 泄密竞对遭开除!翁荔火速发文

                          2026-1-16 22:15:35

                          0 条回复 A文章作者 M管理员
                            暂无讨论,说说你的看法吧
                          个人中心
                          购物车
                          优惠劵
                          今日签到
                          有新私信 私信列表
                          搜索