HarmonyOS ArkTS API 24+ 实战:实现模板选择与应用

发布时间:2026/8/1 7:59:05

HarmonyOS ArkTS API 24+ 实战:实现模板选择与应用 前言版本比较完成后还要把应用对象选清楚建立了参数模板的数据边界明确了当前版本、候选版本、产品关联、应用机台和应用日志各自的责任。仅有模型还不能完成现场工作工程师还需要从模板列表选中一个模板进入详情页确认版本再选择目标机台并执行应用。本篇围绕当前工程已经实现的完整交互链路展开TemplateList展示模板摘要点击后把templateId传给入口页TemplateDetail回填已有机台、等待用户选择最后由DemoBusinessRepository.applyTemplate()完成状态修改和日志追加。重点不是把按钮写出来而是保证“选中了哪个模板、准备应用到哪台机台、应用后哪些字段改变”能够沿着一条可追踪的链路运行。一、先画出页面和数据的调用链当前链路可以拆成六个节点调机记录页点击“参数模板”。Index.ets打开TemplateList。模板列表渲染ParameterTemplate点击时传出template.id。Index.ets将 ID 装配到TemplateDetail。详情页把用户选择的机台 ID 保存到State selectedMachineId。确认按钮调用 Repository更新当前版本、状态、应用机台和日志。页面组件之间传递的是稳定 ID而不是整个模板对象。这样做的好处是详情页每次打开都从 Repository 读取最新对象列表和详情不会因为各自持有一份旧对象而出现状态分叉。二、调机页只负责打开模板列表DebugRecordList.ets对外暴露了打开模板的回调onOpenTemplates:()void(){};页面上的按钮只触发回调Button(参数模板).fontSize(12).fontColor(ThemeTokens.accent).backgroundColor(ThemeTokens.accentSoft).borderRadius(6).onClick(()this.onOpenTemplates())列表组件不直接操作detailKind也不直接创建TemplateList。它只表达“用户想进入模板列表”这一动作页面入口统一决定下一块内容。这样调机记录页不需要知道模板详情的路由细节后续替换成弹层、独立页面或异步加载时列表组件的职责仍然稳定。三、Index.ets 负责页面装配Index.ets将调机列表的回调装配为DebugRecordList({onOpenRecord:(recordId:string)this.openDetail(debug,recordId),onCreate:()this.openDetail(debug,new),onOpenTemplates:()this.openDetail(templateList,)})当detailKind为templateList时入口页渲染}elseif(this.detailKindtemplateList){TemplateList({onOpenTemplate:(templateId:string)this.openDetail(template,templateId)})}这里的空字符串只表示模板列表本身没有某个具体对象 ID用户点击列表项后真正的模板 ID 才会进入openDetail(template, templateId)。不要在打开列表时预先塞入一个模板 ID否则列表和详情的状态会混在一起。四、模板列表怎样保留选择对象TemplateList.ets通过回调把点击对象的 ID交给父级exportstruct TemplateList{onOpenTemplate:(templateId:string)void(){};build(){Scroll(){Column({space:14}){Text(参数模板)Text(比较候选版本确认后应用到指定机台并保留日志。)ForEach(demoBusinessRepository.loadTemplates(),(template:ParameterTemplate){Button(this.label(template)).onClick(()this.onOpenTemplate(template.id))},(template:ParameterTemplate)template.id)}}}}这里有两个容易被忽略的边界。第一ForEach的 key 是template.id列表更新时 ArkUI 能够继续识别同一模板。第二点击传递的是 ID详情页不会接收到一个脱离 Repository 的临时对象。列表摘要由产品名称、当前版本、候选版本和状态组成。它帮助工程师在进入详情前先判断是否点对了模板但不在列表上执行应用因为应用需要确认目标机台。五、详情页打开时先回填已应用机台TemplateDetail.ets的输入参数是templateId:string;onBack:()void(){};StateselectedMachineId:string;Statefeedback:string;组件出现时查找模板并把已有的应用机台回填到状态aboutToAppear():void{consttemplate:ParameterTemplate|undefineddemoBusinessRepository.templateById(this.templateId);if(template!undefined){this.selectedMachineIdtemplate.appliedMachineId;}}对于 C08 模板appliedMachineId初始是machine-001因此进入详情时默认选择 IM-120T-11对于没有应用记录的模板状态为空用户必须主动选择机台。回填已有选择和自动替用户确认是两回事代码只做回填不在页面打开时执行应用。六、先处理不存在的模板 ID页面有一个简单的存在性判断privateexists():boolean{returndemoBusinessRepository.templateById(this.templateId)!undefined;}构建时先判断exists()。如果模板不存在页面显示“未找到参数模板”和“返回模板列表”只有存在时才创建版本比较、机台列表和确认按钮。这种分支在演示数据中不一定经常触发但它很重要。列表传来的 ID 可能来自旧快照、外部深链接或已经删除的对象。错误状态应该让用户能够返回而不是用一组默认版本继续显示造成“应用了一个看起来合法但不存在的模板”的错觉。七、版本比较区域只读展示详情页将两个版本放在同一块信息区域Column({space:8}){Text(版本比较)Text(当前版本${this.current().currentVersion})Text(候选版本${this.current().candidateVersion})Text(候选参数来自已提交的调机记录应用前必须确认机台。)}当前版本和候选版本在本篇动作中是只读信息。用户的确认动作不是修改输入框中的版本字符串而是确认候选版本应用到某个机台。版本关系的修改集中放在 Repository避免页面显示文本和数据对象产生不同步。提示文案还建立了调机记录和模板的流程关系候选参数来自已提交的调机记录但候选来源没有在当前ParameterTemplate中展开成完整记录列表。文章只保留当前代码能够证明的关系不把这句提示扩展成自动生成模板或自动审批结论。八、机台选择状态保存的是 ID机台列表由 Repository 提供Text(选择应用机台)ForEach(demoBusinessRepository.loadMachines(),(machine:Machine){Button(this.machineLabel(machine.id)).fontColor(this.selectedMachineIdmachine.id?ThemeTokens.surface:ThemeTokens.textPrimary).backgroundColor(this.selectedMachineIdmachine.id?ThemeTokens.accent:ThemeTokens.surface).onClick(()this.selectedMachineIdmachine.id)},(machine:Machine)machine.id)选中状态通过颜色变化反映但真正保存的是machine.id。显示文案由machineLabel()生成privatemachineLabel(machineId:string):string{constmachine:Machine|undefineddemoBusinessRepository.machineById(machineId);returnmachineundefined?machineId:${machine.code}·${machine.name};}如果机器名称后来调整应用关联仍然使用稳定 ID如果机器查找失败页面至少保留原始 ID便于定位数据问题。不要把IM-120T-11 · 精密外壳注塑机这样的显示字符串反向解析成 ID。九、确认按钮只负责触发应用动作页面按钮绑定到apply()Button(确认应用候选版本).width(100%).height(44).fontColor(ThemeTokens.surface).backgroundColor(ThemeTokens.accent).onClick(()this.apply())按钮文字直接说明动作是“应用候选版本”不是“保存模板”。这能帮助用户区分编辑模板信息和执行版本变更。按钮的点击处理仍然只进入页面方法具体字段变化放到 Repository。十、应用前先检查机台是否为空apply()的第一道门禁是机台选择privateapply():void{if(this.selectedMachineId.length0){this.feedback请选择应用机台后再确认。;return;}constapplied:booleandemoBusinessRepository.applyTemplate(this.templateId,this.selectedMachineId);this.feedbackapplied?模板已应用应用日志已更新。:模板应用失败请返回列表重新选择。;}如果用户没有选择机台页面只更新反馈文本不进入 Repository。这个判断属于页面输入完整性校验即使页面漏掉这条判断Repository 仍然有machineId.length 0的保护但让错误在更靠近用户操作的地方出现反馈会更及时。十一、Repository 执行一次完整状态更新Repository 中的应用方法是applyTemplate(templateId:string,machineId:string):boolean{consttemplate:ParameterTemplate|undefinedthis.templateById(templateId);if(templateundefined||machineId.length0)returnfalse;template.currentVersiontemplate.candidateVersion;template.statusapplied;template.appliedMachineIdmachineId;template.applicationLog.push(${template.currentVersion}已应用至${machineId});this.notifyStateChanged();returntrue;}这段方法不是简单地给一个字段赋值。一次成功应用至少改变四项数据当前版本、状态、应用机台和日志。把它们放在同一个 Repository 方法里能够避免出现“当前版本已经改变但状态仍显示候选”这种半更新状态。notifyStateChanged()负责通知外层状态变化。当前入口页通过StorageLink(demoStateVersion)连接演示状态其他页面可以据此重新计算内容。应用动作不应该由详情页手工刷新多个页面状态通知是跨页面更新的统一入口。十二、应用日志是可观察的结果详情页在版本应用后显示反馈同时在“应用日志”区域渲染applicationLogColumn({space:6}){Text(应用日志)if(this.current().applicationLog.length0){Text(暂无应用记录)}ForEach(this.current().applicationLog,(entry:string){Text(entry).width(100%)},(entry:string)entry)}用户点击确认后应该同时观察三个结果反馈文字变成“模板已应用应用日志已更新”模板状态从候选版本变成已应用日志中出现目标机台。只看按钮点击没有意义应用动作的业务结果必须能在对象状态和历史记录中找到。当前日志是字符串数组日志 key 直接使用文字内容。演示数据中每次内容不同因此能够渲染生产系统若允许同一模板同一机台多次应用应使用独立日志 ID 和时间字段不能把日志文本本身当成稳定身份。十三、API 24 运行验证项目当前使用 API 26 Beta SDK 构建并在 API 24 模拟器观察运行。针对模板选择与应用测试路径如下点击底部“调机”。点击“参数模板”。在模板列表中打开“C08 密封盖”。查看当前版本v2.3和候选版本v2.4。选择IM-120T-11 · 精密外壳注塑机。点击“确认应用候选版本”。已有 M3 运行证据显示模板详情能够显示版本比较区域。机台按钮可以被选中选中项使用主题强调色。详情页能够显示“模板已应用应用日志已更新”。应用日志区域出现应用结果。页面没有跳转到错误模板也没有把机台显示文案当成保存 ID。这组证据支持当前演示实现的页面链路和内存状态更新不推导出数据库事务、网络重试或并发应用控制已经完成。十四、常见错误和定位顺序1. 点击模板后详情显示短横线先检查TemplateList回调传出的 ID再检查Index.openDetail(template, templateId)是否收到同一个值最后查看templateById()的查找结果。不要先改详情页默认版本。2. 选择机台后颜色没有变化检查selectedMachineId是否是State按钮比较的是否同一个机器 ID以及ForEach的 key 是否稳定。颜色是状态结果根因通常在状态写入或 ID 不一致。3. 点击确认后只出现成功文字成功文字由页面设置不能单独证明 Repository 修改完成。应同时检查currentVersion、status、appliedMachineId和applicationLog。4. 没选择机台却应用成功检查页面的空值门禁和 Repository 的空值门禁是否都还在。两个位置职责不同页面负责及时反馈Repository 负责保护数据层。5. 把“已应用”当成“模板永久生效”当前状态表示演示 Repository 中已经执行过应用动作不代表设备端已经完成下载、切换和生产验证。正式流程需要额外的设备回执和版本确认。十五、当前实现和生产实现的边界当前applyTemplate()是同步内存方法返回布尔值。生产实现通常还需要校验模板、产品、模具和机台是否匹配。校验操作者是否有应用候选版本的权限。防止同一候选版本被重复提交。保存操作者、时间、来源调机记录和设备回执。应用失败时保留失败原因并提供重试或回滚路径。处理多个终端同时应用同一模板时的版本冲突。这些内容属于后续工程边界。本篇只把当前代码已经实现的页面选择、状态变更和日志观察讲完整不把建议写成当前 App 的既成能力。十六、总结本篇完成了从模板选择到应用确认的完整链路调机记录页通过回调打开模板列表。模板列表用稳定 ID 进入对应详情。详情页展示当前版本和候选版本。用户选择目标机台状态保存为机台 ID。页面先拦截空机台输入Repository 再检查模板和机台边界。应用成功后同步更新版本、状态、机台和应用日志。API 24 运行证据核对了 C08 候选模板的选择与应用反馈。附录工程配置与版本说明为了便于读者复现本文中的代码片段和运行现象这里把当前文章系列对应的工程基线单独列出。本文所说的“当前工程”指e_notebook项目的 HarmonyOS ArkTS 客户端应用名称为“注塑工程师助手”主要用于脱敏演示机台档案、产品档案、调机记录、参数模板、异常闭环、生产批次和看板报表等业务路径。1. 应用与模块配置应用包名com.atan.enotebook。应用版本versionName为1.0.0versionCode为1000000。工程模型ArkTS / ArkUI Stage 模型。主模块entry模块类型为entry。入口 AbilityEntryAbility入口文件为entry/src/main/ets/entryability/EntryAbility.ets。主页面配置模块通过pages: $profile:main_pages读取页面列表。设备类型当前模块声明支持phone、tablet和2in1。安装方式deliveryWithInstall为trueinstallationFree为false属于随应用安装的普通 entry 模块。2. SDK 与 API 版本DevEco Studio 版本DevEco Studio Beta26.0.0.461。编译 SDKHarmonyOS SDK API 26 Beta1SDK 包版本为26.0.0.23。SDK 平台信息apiVersion为26platformVersion为26.0.0releaseType/stage为Beta1。targetSdkVersion26.0.0。compatibleSdkVersion6.1.1(24)。API 口径说明文章系列以 API 24 作为兼容目标进行表述当前工程实际由 API 26 Beta SDK 编译并在 API 24 模拟器上做过安装、启动和交互观察。因此文中的“API 24 运行观察”表示兼容目标环境下的模拟器验证结果不等同于使用 API 24 SDK 重新完成编译验证。3. 构建与运行工具开发工具 IDEDevEco Studio Beta安装目录指向D:/Program Files/Huawei/DevEco Studio Beta。SDK 路径D:/Program Files/Huawei/DevEco Studio Beta/sdk。构建系统Hvigor工程入口hvigorfile.ts使用ohos/hvigor-ohos-plugin的appTasks。Hvigor 执行配置开启 daemon、incremental、parallel 和 typeCheck日志级别为info。构建脚本本地build.ps1优先使用 DevEco Studio 自带的 JBR、Node.js、SDK 与 Hvigor避免系统环境变量中的 Java 或 Node.js 版本干扰构建结果。调试产物未配置签名时本地构建生成entry/build/default/outputs/default/entry-default-unsigned.hap。这类 unsigned HAP 只用于本地调试和模拟器验证正式发布前需要在 DevEco Studio 中补充签名配置。4. 本系列文章的验证边界本系列代码以脱敏演示数据为主Repository、Store、页面状态和组件边界都围绕本地演示闭环展开。已观察过的运行现象以文中对应截图、布局树和人工核对记录为准没有重新核对的页面不在单篇文章中扩大为完整结论。如果读者使用更新的 DevEco Studio、HarmonyOS SDK 或真机系统版本复现API 差异、控件行为和签名流程可能会发生变化。遇到差异时建议优先核对build-profile.json5、module.json5、SDK Manager 中安装的 API 版本以及当前设备或模拟器的系统 API 等级。附录 2项目目录结构与设计意图下面这份目录说明对应当前 DevEco Studio 中打开的harmonyos-app工程。截图里能看到的目录并不只是文件摆放习惯它反映了一个 ArkTS Stage 工程的分层方式应用级配置、业务模块、页面源码、资源文件、构建配置和过程归档分别放在不同位置方便后续排查问题时先判断“问题属于配置、页面、数据、状态、资源还是构建产物”。harmonyos-app/ ├── AppScope/ # 应用级配置与全局资源入口 │ ├── app.json5 # bundleName、版本号、图标、应用标签等应用级元信息 │ └── resources/ # 应用级图标、字符串和基础资源 ├── entry/ # 主业务模块当前 App 的主要页面和业务代码都在这里 │ ├── src/main/ets/ # ArkTS 源码根目录 │ │ ├── components/ # 可复用 ArkUI 组件如底部导航、数据状态面板 │ │ ├── entryability/ # Stage 模型入口 Ability负责应用启动入口 │ │ ├── features/ # 按业务域拆分的功能页面 │ │ │ ├── debug/ # 调机记录相关页面 │ │ │ ├── exceptions/ # 异常处置与闭环相关页面 │ │ │ ├── home/ # 首页看板与概览入口 │ │ │ ├── machines/ # 机台档案列表、详情和机台相关交互 │ │ │ ├── production/ # 生产批次、报工和结案门禁相关页面 │ │ │ ├── products/ # 产品档案、产品详情和关联信息 │ │ │ ├── reports/ # 周报、月报、班次报表和下钻入口 │ │ │ └── templates/ # 参数模板列表与详情 │ │ ├── models/ # 业务对象的数据结构如 Machine、Product、DebugRecord │ │ ├── pages/ # 页面容器与导航装配如 Index.ets │ │ ├── repositories/ # 脱敏演示数据、查询方法、快照持久化和数据重置边界 │ │ ├── stores/ # 页面路由、导航选择和共享状态规则 │ │ └── utils/ # 主题令牌、校验函数等通用工具 │ ├── src/main/resources/base/ # 模块级资源目录 │ │ ├── element/ # 字符串、颜色等基础资源声明 │ │ ├── media/ # 图标、启动图等媒体资源 │ │ └── profile/ # 页面 profile 配置如 main_pages.json │ ├── src/main/module.json5 # entry 模块配置声明 EntryAbility、设备类型和页面入口 │ ├── build-profile.json5 # 模块级构建目标、混淆和 target 配置 │ └── oh-package.json5 # entry 模块包信息与依赖声明 ├── hvigor/ # Hvigor 构建系统配置 │ └── hvigor-config.json5 # 构建执行参数如增量、并行和类型检查 ├── build-profile.json5 # 工程级 SDK、targetSdkVersion、compatibleSdkVersion 配置 ├── hvigorfile.ts # 工程级构建任务入口接入 appTasks ├── local.properties # 本机 SDK 路径配置 ├── oh-package.json5 # 工程级包信息与依赖声明 ├── build.ps1 # 本地构建脚本固定使用 DevEco Studio 自带工具链 ├── document_claude/ # 开发过程归档、测试记录和验证材料 ├── .hvigor/ # Hvigor 生成的缓存和构建记录不作为手写源码维护 ├── .idea/ # DevEco Studio / IntelliJ 工程配置不承载业务逻辑 └── entry/build/ # 构建输出目录HAP 和中间产物由构建流程生成1. 为什么应用级配置放在AppScopeAppScope负责应用整体身份而不是某个页面的业务逻辑。app.json5中的bundleName、versionName、versionCode、应用图标和应用标签会影响安装包身份、桌面展示和版本识别。把这类配置放在应用级目录可以避免业务页面为了改一个标题或图标而混入应用发布配置。在当前工程中AppScope更像“应用身份证”。它回答的是“这个 App 是谁、版本是多少、展示什么图标”而不是“机台列表怎么筛选、详情页怎么返回”。2. 为什么业务代码集中在entry/src/main/etsentry是当前工程的主业务模块src/main/ets是 ArkTS 源码根目录。截图里打开的MachineDetail.ets就位于features/machines下面说明机台详情页被归入“机台业务域”而不是随意放在全局页面目录中。这种组织方式的好处是定位明确机台问题优先看features/machines产品问题优先看features/products生产批次问题优先看features/production。当文章里讨论某个业务链路时读者也能从目录直接反推代码位置。3.components、features和pages的边界components放的是可复用组件例如底部导航、加载/空态/失败态面板。它们不应该直接知道“当前打开的是哪台机台”而是通过参数和回调服务于不同页面。features放的是业务域页面。每个子目录都围绕一个业务主题组织例如machines负责机台档案templates负责参数模板exceptions负责异常闭环。业务页面可以组合组件也可以读取模型和仓储但应尽量把本业务域的显示和交互留在本目录内。pages更偏页面容器和入口装配。当前Index.ets承担主页面状态切换、底部导航和详情路径分发等职责。它不应该塞满所有业务细节而是负责把用户当前所在位置、打开对象和页面分支组织起来。4.models、repositories和stores分别解决什么问题models定义数据形状例如机台、产品、调机记录、生产批次等对象有哪些字段。它让页面和仓储使用同一套类型语言避免每个页面临时拼对象。repositories定义数据来源和查询边界。当前工程使用脱敏演示数据和本地持久化快照因此仓储层负责“从哪里取数据、按什么 ID 查询、怎样重置演示数据”。页面不直接关心数据是内置数组、Preferences 快照还是后续真实接口。stores定义页面级或应用级状态规则例如当前导航项、路由分支、打开详情的类型和 ID。把状态规则从具体组件中抽出来可以减少“列表、详情、导航互相覆盖状态”的问题。5. 为什么资源放在resources/baseresources/base/element管字符串、颜色等声明resources/base/media管图标和图片resources/base/profile管页面 profile。它们和 ArkTS 页面代码分开是为了让“界面逻辑”和“静态资源”各自清晰。如果页面显示异常先判断是布局代码问题还是资源引用问题。比如图标不显示应优先检查media和资源引用页面无法进入应检查profile/main_pages.json和module.json5的页面声明颜色或字符串不符合预期则回到element下核对。6. 构建目录和生成目录不要手工维护.hvigor、entry/build和部分中间产物目录由构建系统生成主要用于缓存、编译记录、HAP 输出和临时文件。它们可以帮助排查构建结果但不应该作为手写业务代码维护。当前调试 HAP 位于entry/build/default/outputs/default/entry-default-unsigned.hap。这个路径说明构建已经产出安装包但它仍是 unsigned 调试产物正式发布前应回到 DevEco Studio 的签名配置和发布流程而不是直接修改build目录里的文件。

相关新闻