【化学实验室|12】HarmonyOS ArkTS 桌面学习卡片实战:用 FormExtensionAbility 展示每日学习入口 桌面学习卡片的价值不是把应用首页缩小后放到桌面而是把“今天学什么”和“点一下去哪里”前置。用户不需要先打开应用、切换学习标签、找到每日一题再判断是否完成卡片应该直接给出当日任务并把一次点击送到对应页面。本文基于化学实验室 1.0.5的真实 HarmonyOS ArkTS 源码拆解DailyStudyFormAbility.ets、DailyStudyCard.ets、form_config.json、module.json5和EntryAbility.ets。当前工程已经声明FormExtensionAbility支持2*2与2*4配置了 08:00 刷新并用FormLink携带source: daily_study_card拉起EntryAbility。表面链路完整继续沿数据和路由逐步检查却能发现三个关键断点。第一扩展能力通过buildFormData()创建了标题、任务和提示但卡片页面把同样的文案全部写死没有读取绑定数据因此onUpdateForm()即使成功也看不出任何变化。第二更新回调每次返回的仍是同一组静态字符串08:00 或周期更新都不会产生“今日”差异。第三FormLink传入的source没有在EntryAbility的冷启动或热启动生命周期中被消费应用最终仍加载pages/Index的首页标签。本文的核心判断是桌面卡片不是一张会跳转的海报而是一条由数据契约、刷新时机、卡片快照和启动路由共同组成的服务直达链路。只实现其中一个环节用户就会看到“刷新了但没变化”或“点击了却还要自己找入口”。本文唯一校验标记CHEM-LAB-ONE12-DAILY-STUDY-FORM-CLOSURE-20260730本文将完成这些工程问题的拆解还原当前卡片从配置发现到系统更新的真实链路。让FormBindingData成为卡片页面的唯一数据来源。用日期键、任务 ID、完成态和目标路由构造稳定契约。设计冷启动与热启动都能消费的卡片跳转参数。区分2*2与2*4的信息密度而不是简单拉伸。明确刷新策略、失败回退、实例清理和日志边界。给出可复现的真机测试矩阵与故障定位顺序。一、先理解卡片提供方与卡片使用方在当前场景中化学实验室是卡片提供方系统桌面是卡片使用方。应用负责声明卡片、生成数据、实现 UI 和处理交互桌面负责添加、展示、删除和触发系统调度。官方 Form Kit 术语将静态 ArkTS 卡片描述为适合 UI 相对固定、交互简单的场景卡片渲染完成后宿主使用最后一帧快照并释放运行资源。对于“每天展示一个学习任务、点击进入应用”的需求这种形态是合理的没有必要为了一个入口升级为长期运行的复杂动态卡片。这里的“静态”不等于“永远不更新”。提供方仍可以在添加和更新回调中生成新的绑定数据再由系统刷新卡片快照。二、当前工程的四个声明位置卡片能被系统发现至少依赖四处一致配置module.json5声明类型为form的DailyStudyFormAbility。扩展能力通过metadata引用$profile:form_config。form_config.json声明DailyStudyCard的页面、尺寸和更新配置。src指向./ets/widget/pages/DailyStudyCard.ets。当前module.json5的关键配置为extensionAbilities: [ { name: DailyStudyFormAbility, srcEntry: ./ets/formability/DailyStudyFormAbility.ets, label: $string:daily_study_form_label, description: $string:daily_study_form_desc, type: form, metadata: [ { name: ohos.extension.form, resource: $profile:form_config } ] } ]这一层已经正确建立了“系统配置 - 扩展能力 - 卡片描述文件”的引用关系。后续排障时只有系统完全看不到卡片才优先检查这些声明如果卡片能添加但内容不更新应转向数据绑定链路。三、form_config.json 决定系统怎样看待卡片当前配置支持2*2和2*4默认尺寸是2*2{ name: DailyStudyCard, src: ./ets/widget/pages/DailyStudyCard.ets, uiSyntax: arkts, colorMode: auto, updateEnabled: true, scheduledUpdateTime: 08:00, updateDuration: 1, defaultDimension: 2*2, supportDimensions: [2*2, 2*4] }这里应重点验证三件事。第一支持尺寸必须有真实布局适配。第二colorMode: auto只有在页面使用可随模式变化的资源时才有意义。第三定点和周期更新字段应根据项目目标 SDK 的官方说明选用并在真机验证不应只因为模板生成了两个字段就同时保留。每日学习任务通常不需要高频刷新。若内容只在日期变化或用户完成任务后改变可以采用“每日定点 业务事件主动更新”的组合避免无意义周期唤醒。四、当前扩展能力的生命周期实现DailyStudyFormAbility已覆盖创建、更新和删除export default class DailyStudyFormAbility extends FormExtensionAbility { onAddForm(want: Want): formBindingData.FormBindingData { return buildFormData() } onUpdateForm(formId: string): void { formProvider.updateForm(formId, buildFormData()).catch((err: Error) { hilog.error(DOMAIN, DailyStudyForm, update form failed: %{public}s, err.message) }) } onRemoveForm(formId: string): void { hilog.info(DOMAIN, DailyStudyForm, onRemoveForm: %{public}s, formId) } }生命周期框架本身没有缺失。真正的问题是buildFormData()返回什么、卡片页面是否读取它以及点击后应用是否消费路由参数。五、数据提供方与卡片 UI 目前各写了一份文案扩展能力构造了interface DailyStudyFormData { title: string subtitle: string task: string tip: string }但DailyStudyCard.ets又直接写了“今日化学学习”“完成一道化学题”等同样文本。两份内容暂时一样容易让开发者误以为绑定成功只要把task改成另一个值再更新就会发现卡片没有变化。这是一类典型的“假闭环”提供方生成了数据更新 API 也返回成功但渲染页根本没有消费。判断刷新是否有效必须以桌面实际快照变化为准不能只看updateForm()Promise 成功。六、把绑定字段接入 ArkTS 卡片页面卡片页面应为绑定字段提供状态入口默认值只用于数据尚未就绪时的可控展示Entry Component struct DailyStudyCard { StorageProp(title) title: string 今日化学学习 StorageProp(subtitle) subtitle: string 准备今天的学习任务 StorageProp(taskTitle) taskTitle: string 打开应用查看任务 StorageProp(statusText) statusText: string 待开始 StorageProp(targetRoute) targetRoute: string daily_quiz build() { // Text(this.title)、Text(this.taskTitle) 等从绑定字段渲染 } }字段名称必须与createFormBindingData()中的对象键完全一致。默认值不承担每日业务逻辑只保证异常情况下卡片不出现空白。七、重新定义每日学习卡片的数据契约仅有四段展示文本不足以支持去重、更新、跳转和完成态。建议把数据契约扩展为export interface DailyStudyFormData { schemaVersion: number dateKey: string taskId: string taskType: quiz | reading | experiment_review title: string subtitle: string taskTitle: string statusText: string completed: boolean targetRoute: string }schemaVersion用于未来兼容字段变化dateKey判断是否跨日taskId保证内容身份稳定taskType决定图标和目标页面completed决定视觉状态。卡片 UI 不再根据中文文案猜业务状态。八、数据生成不能散落在 FormExtensionAbility 中扩展能力应管理生命周期业务数据由仓库或服务提供export interface DailyStudyTask { id: string dateKey: string type: quiz | reading | experiment_review title: string completed: boolean targetRoute: string } export class DailyStudyRepository { async getTask(dateKey: string): PromiseDailyStudyTask { // 从项目现有本地数据服务读取失败时返回受控默认任务 return this.buildFallbackTask(dateKey) } }如果卡片数据来自本地持久化仓库应使用扩展能力可用的上下文初始化存储。不要让卡片页面直接访问应用页面的内存状态因为卡片渲染与应用 UI 不是同一个页面生命周期。九、创建卡片时要记录实例维度一个用户可能同时添加多个卡片实例且尺寸不同。onAddForm(want)中的参数可以用于识别实例与维度解析时应做类型保护不要直接假设字段一定存在interface FormRequestInfo { formId: string dimension: number } function readFormRequest(want: Want): FormRequestInfo { const params want.parameters const formId String(params?.[ohos.extra.param.key.form_identity] ?? ) const rawDimension Number(params?.[ohos.extra.param.key.form_dimension] ?? 0) return { formId, dimension: Number.isFinite(rawDimension) ? rawDimension : 0 } }具体系统参数键和可用 API 应以项目目标 SDK 的 Form Kit 文档为准。示例的重点是系统输入先规范化再进入业务逻辑日志和持久化只保存确实需要的字段。十、不要把完整 want.parameters 作为公开日志当前代码把JSON.stringify(want.parameters)以%{public}s输出。现阶段参数主要是卡片元数据但未来一旦加入用户选择、任务 ID 或来源信息完整公开日志会扩大泄露范围。更稳的日志只记录排障所需字段hilog.info( DOMAIN, DailyStudyForm, add form, id%{public}s, dimension%{public}d, request.formId, request.dimension )任务标题、学习记录和用户内容不应写入公开日志。错误日志记录错误码与受控消息不输出整个对象。十一、构造数据时要让日期和任务真正变化可把“当前日期 - 今日任务 - 卡片契约”集中在一个构造器中function toFormData(task: DailyStudyTask): DailyStudyFormData { return { schemaVersion: 1, dateKey: task.dateKey, taskId: task.id, taskType: task.type, title: 今日化学学习, subtitle: task.completed ? 今日任务已完成 : 每天前进一小步, taskTitle: task.title, statusText: task.completed ? 已完成 : 待完成, completed: task.completed, targetRoute: task.targetRoute } }同一天的同一个任务应生成稳定taskId避免每次更新都变成新任务跨日后dateKey和任务身份才更新。十二、更新流程要有加载失败回退onUpdateForm()返回void内部可以启动异步更新但必须在 Promise 链中收口错误onUpdateForm(formId: string): void { this.refreshForm(formId).catch((error: Error) { hilog.error( DOMAIN, DailyStudyForm, refresh failed, id%{public}s, reason%{public}s, formId, error.message ) }) } private async refreshForm(formId: string): Promisevoid { const dateKey this.clock.todayKey() const task await this.repository.getTask(dateKey) const binding formBindingData.createFormBindingData(toFormData(task)) await formProvider.updateForm(formId, binding) }这里把时钟也抽成依赖是为了在测试中固定日期验证跨日更新而不等待第二天。十三、每日卡片应该选择什么刷新策略当前配置同时存在scheduledUpdateTime: 08:00与updateDuration: 1。不同 API 版本对更新字段的约束和调度行为需要按目标 SDK 官方文档确认工程上不应依赖未验证的组合。对于化学学习卡片可以定义清楚的业务策略每天早上刷新当天任务。用户完成题目或阅读后主动更新完成态。应用升级或数据版本变化时重建契约。无需为了静态任务每隔短时间重复刷新。系统调度不是精确定时器测试时应允许延迟业务正确性不能依赖“08:00 整秒一定回调”。十四、完成任务后如何主动刷新卡片当用户在应用内完成每日一题业务层应先保存完成记录再通知卡片更新。不要让答题页直接拼装卡片字段可以调用统一服务export class DailyStudyCardUpdater { async refresh(formIds: string[]): Promisevoid { const task await this.repository.getTask(this.clock.todayKey()) const data formBindingData.createFormBindingData(toFormData(task)) for (const formId of formIds) { await formProvider.updateForm(formId, data) } } }如果项目不需要保存实例 ID就采用 Form Kit 针对当前版本提供的查询或更新方案若保存实例 ID必须在删除回调中清理失效记录。十五、onRemoveForm 是否需要清理取决于是否保存实例状态当前onRemoveForm()只记录日志。在完全无状态的卡片中这足够一旦为不同卡片保存尺寸、任务偏好或实例 ID就必须删除对应数据onRemoveForm(formId: string): void { this.formInstanceRepository.remove(formId).catch((error: Error) { hilog.error(DOMAIN, DailyStudyForm, remove instance failed: %{public}s, error.message) }) }删除回调应幂等记录已经不存在时也视为成功避免系统重复通知造成异常。十六、当前 FormLink 只证明能拉起应用卡片页面把整个内容包在FormLink中FormLink({ action: router, abilityName: EntryAbility, params: { source: daily_study_card } }) { // card content }它能够携带来源参数拉起EntryAbility但“拉起应用”和“直达学习任务”不是同一件事。当前EntryAbility.onCreate()没有读取want.parameters也没有onNewWant()随后固定加载pages/Index。卡片点击因此只完成了链路前半段。十七、为跳转定义稳定参数不能只传 source建议传递最小、可验证的启动契约export interface DailyStudyLaunchParams { source: daily_study_card target: daily_quiz | reading | experiment_review taskId: string dateKey: string }source用于统计和回退target决定页面taskId定位内容dateKey防止用户点击昨天的快照后误打开今天的另一条任务。卡片不传完整题目正文避免参数过大和数据过期。十八、冷启动与热启动必须分别处理应用未运行时参数从onCreate(want, ...)进入应用已在前台或后台时新的启动请求可能进入onNewWant(want, ...)。两条生命周期都应调用同一个规范化函数private acceptLaunchWant(want: Want): void { const launch DailyStudyLaunchParser.parse(want.parameters) if (launch undefined) { return } AppStorage.setOrCreateDailyStudyLaunchParams(pendingDailyLaunch, launch) } onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { this.acceptLaunchWant(want) // 其余初始化 } onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void { this.acceptLaunchWant(want) }具体生命周期签名以项目当前 SDK 类型定义为准。核心是冷、热启动共享解析逻辑避免一种场景能直达、另一种只回首页。十九、页面加载与数据初始化存在竞态当前EntryAbility.onCreate()异步执行DataStore.init()onWindowStageCreate()直接加载pages/Index。如果卡片目标页依赖存储路由消费可能早于数据初始化完成。可以让启动协调器保存两个条件页面已就绪、数据已就绪。只有两者都满足时才消费pendingDailyLaunchinterface StartupState { contentReady: boolean dataReady: boolean } private tryDispatchPendingLaunch(): void { if (!this.startupState.contentReady || !this.startupState.dataReady) return this.launchCoordinator.dispatchPending() }如果任务读取失败回退到学习首页并显示可恢复提示不能留下白屏或无响应点击。二十、Index 页需要接住学习标签与二级页面目标当前Index.ets的currentIndex默认为 0学习标签是索引 2。最小改造是先让启动协调器切换到学习标签再由页面路由进入DailyQuizPageStorageLink(requestedTabIndex) requestedTabIndex: number 0 aboutToAppear(): void { this.currentIndex this.requestedTabIndex this.tabController.changeIndex(this.requestedTabIndex) }二级页面跳转应继续走项目已有路由方式。若路由失败或目标任务已过期停留在学习标签而不是返回空白页。二十一、旧卡片快照必须有过期处理用户可能在第二天 08:00 刷新前点击昨天卡片。应用收到dateKey后应与当前日期比较if (launch.dateKey ! this.clock.todayKey()) { return { target: learning_home, message: 卡片内容已更新请查看今天的学习任务 } }这比盲目使用taskId更安全。页面可以随后触发一次卡片刷新让桌面快照尽快与当天内容一致。二十二、2×2 与 2×4 不应该共用同一信息密度当前配置声明两个尺寸但只有一个卡片页面布局。它可以被拉伸却没有利用2*4的额外空间。建议保持同一数据契约按尺寸设计两种信息层级尺寸必须显示可选显示2×2标题、今日任务、完成态、打开按钮一行简短副标题2×42×2 全部内容学习连续天数、预计用时、下一任务尺寸适配不是把字号放大。2×2 要保证最长任务名省略后仍能看懂2×4 则利用宽度提供一个额外决策信息点。二十三、卡片 UI 要从硬编码颜色迁移到资源DailyStudyCard.ets直接使用#0052D9、#047481、#FFFFFF等颜色同时配置了colorMode: auto。如果没有深浅色资源映射“auto”不会自动让硬编码渐变和文字达到合理对比。卡片资源至少应区分背景起止色、主文字、次文字、状态标签、按钮背景和完成态。文字在渐变最亮和最暗位置都要可读系统深色模式、不同壁纸和桌面缩放下都需要截图验证。二十四、点击区域要明确且不制造误触当前整个卡片都是FormLink适合只有一个动作的静态入口。但卡片内部又绘制了“学习”和“打开”两个视觉按钮用户可能误以为它们有不同功能。如果卡片只有一个目标保留整卡点击同时把视觉按钮统一成一个明确动作如果 2×4 未来出现多个入口应分别定义交互区域并确保参数目标不同。交互设计不能比实际能力更复杂。二十五、卡片数据的空态、错误态和完成态卡片没有普通页面那么多空间但仍需要三类受控状态export type CardContentState ready | completed | fallbackready显示任务与“去完成”。completed显示已完成和次日提示不重复催促。fallback数据读取失败时显示“打开应用继续学习”仍保留安全入口。不要在卡片上展示技术错误码。错误码进入日志用户看到的是可执行的回退动作。二十六、职责拆分后的整体结构推荐的依赖方向是FormExtensionAbility - DailyStudyCardService - DailyStudyRepository - FormDataMapper - FormProviderAdapter DailyStudyCard UI - FormBindingData fields - FormLink launch contract EntryAbility - LaunchParser - StartupCoordinator - Index / target page扩展能力不拼业务文案卡片 UI 不查持久化入口 Ability 不理解题目数据。每一层只处理一种变化原因。二十七、对构造器做纯函数测试toFormData()不依赖系统上下文最适合先写单元测试const task: DailyStudyTask { id: quiz-20260717, dateKey: 2026-07-17, type: quiz, title: 完成一道酸碱平衡题, completed: false, targetRoute: daily_quiz } const data toFormData(task) expect(data.taskId).assertEqual(quiz-20260717) expect(data.statusText).assertEqual(待完成) expect(data.targetRoute).assertEqual(daily_quiz)还要验证完成态、空标题回退、超长标题截断策略和未知任务类型。纯函数测试失败时不必启动桌面卡片环境。二十八、用适配器测试更新失败直接调用系统formProvider不易制造异常可以封装窄接口export interface FormUpdater { update(formId: string, data: DailyStudyFormData): Promisevoid } export class SystemFormUpdater implements FormUpdater { async update(formId: string, data: DailyStudyFormData): Promisevoid { const binding formBindingData.createFormBindingData(data) await formProvider.updateForm(formId, binding) } }测试替身可以模拟实例不存在、数据加载失败和连续两次更新。服务层应记录失败但不崩溃也不能把一个实例失败误判成所有实例失败。二十九、冷启动与热启动测试矩阵场景前置状态预期结果冷启动点击应用未运行初始化完成后进入每日一题热启动点击应用停在实验室标签切换学习标签并进入目标页旧日期点击卡片 dateKey 为昨天回退学习首页并提示内容更新未知 target参数被篡改或版本过旧忽略目标安全进入学习首页数据初始化失败本地仓库不可用不白屏展示可重试提示重复点击连续点击同一卡片不叠加重复目标页如果只验证冷启动应用已在运行时的onNewWant漏洞很容易带到发布版本。三十、卡片显示测试矩阵检查项2×22×4普通任务标题与动作完整增加辅助信息超长任务单行省略且主动作可见最多两行不挤压按钮完成态明确“已完成”展示下一步建议数据失败回退文案和入口回退文案和入口深色模式文字、渐变、状态标签可读同左大字体不重叠、不截断核心动作信息按优先级收缩还要在手机、平板和 2in1 的桌面环境中验证实际卡片支持情况。应用声明支持这些设备不代表桌面卡片布局自动适配完成。三十一、常见故障一系统完全找不到卡片按下面顺序检查module.json5是否声明type: form。srcEntry路径与类文件是否一致。metadata 是否引用正确 profile。form_config.json的name、src和uiSyntax是否有效。卡片页面是否成功编译进包。安装的是不是包含最新配置的构建产物。此时不要先改业务数据因为系统尚未走到数据阶段。三十二、常见故障二updateForm 成功但界面不变先把绑定字段临时改成可辨识值例如标题追加日期。若桌面仍不变检查卡片页面是否用StorageProp或当前 SDK 对应绑定方式读取同名键。createFormBindingData()是否包含该字段。更新的formId是否对应桌面上的实例。桌面宿主是否已接收新快照。是否实际上仍在看旧的另一个卡片实例。当前项目首先应修复第 1 项因为卡片页面仍使用硬编码文本。三十三、常见故障三点击卡片只回首页确认FormLink的abilityName能匹配EntryAbility后继续检查onCreate是否读取启动参数。热启动时是否实现onNewWant。参数是否在页面加载前被覆盖。Index是否消费标签切换请求。目标页路由是否在main_pages.json中存在。当前DailyQuizPage已在main_pages.json中主要缺口是参数接收和启动协调。三十四、常见故障四08:00 没有准时刷新系统卡片更新受版本、调度策略、设备状态和配置约束影响不应当作精确闹钟。排查时记录实际回调时间确认updateEnabled与目标 SDK 配置有效并在业务完成事件后主动更新。若每日内容必须在首次查看时正确卡片点击进入应用后还应重新校验当前日期不能把正确性完全押在系统定点刷新上。三十五、真机验收清单安装新包后能在桌面卡片列表找到“今日化学学习”。添加 2×2 与 2×4 两种实例布局均无重叠。首次添加时绑定数据与当日任务一致。修改今日任务并触发更新后桌面文案发生变化。完成任务后卡片变成已完成态。冷启动点击直达对应学习页。应用已运行时再次点击仍能直达。删除一个实例后其实例记录被清理且其他实例不受影响。重启设备后卡片不白屏点击仍有安全回退。浅色、深色、大字体和不同壁纸下均可读。三十六、分阶段落地更容易定位问题第一阶段只把FormBindingData接入卡片页面用一个可辨识日期字段证明数据闭环。第二阶段接入每日任务仓库和完成态。第三阶段定义启动契约分别打通冷、热启动。第四阶段完成 2×2、2×4 和主题适配。第五阶段补主动刷新、实例清理和真机回归。每阶段只改变一个验证点看到卡片变化、看到任务变化、看到页面直达、看到尺寸适配、看到完成态同步。这样一旦失败可以立刻定位到对应层。三十七、完成标准应该写成可观察结果这张卡片的验收不是“代码里有FormExtensionAbility”而是系统能发现并添加卡片。卡片显示的是绑定数据不是页面硬编码副本。日期或完成态变化后桌面快照能被更新。点击参数在冷启动和热启动都被消费。目标无效或数据失败时安全回退到学习首页。2×2 与 2×4 都提供清晰、不过载的信息。三十八、官方资料与版本核对入口本文结合项目真实源码与当前工程结构给出改造方案。Form Kit 配置字段、生命周期签名和交互能力会随 API 版本演进落地时应以项目目标 SDK 的华为官方文档为准Form Kit 术语与卡片角色Form Kit 产品与能力入口HarmonyOS 开发文档中心特别是更新策略、系统参数键和onNewWant的准确签名应在 DevEco Studio 当前 SDK 类型提示中再次确认并通过真机回调日志验证。三十九、源码事实与建议实现的边界为了避免把设计方案写成已经上线的能力下面将当前仓库可以复核的 Form Kit 实现与建议演进明确分开。观察维度当前源码事实建议实现扩展能力DailyStudyFormAbility继承FormExtensionAbility实现添加、更新和移除回调保留系统生命周期入口把数据构建委托给可测试的每日任务服务初始数据buildFormData()返回标题、副标题、任务和提示四个固定字符串使用日期键、任务 ID、完成态、目标路由和版本字段构建稳定契约更新行为onUpdateForm调用formProvider.updateForm但每次仍生成同一组静态字符串更新时读取真实任务状态失败时保留最近有效快照并记录可定位日志卡片 UIDailyStudyCard.ets中标题、副标题和任务文案全部硬编码从FormBindingData读取字段避免提供方数据与 UI 副本分叉点击行为FormLink使用router动作目标为EntryAbility参数只有source: daily_study_card增加受控目标路由与任务 ID并对未知目标做白名单回退冷启动EntryAbility.onCreate接收Want但当前没有消费卡片source在初始化完成后解析启动契约并把一次性导航意图交给页面路由层热启动当前EntryAbility没有实现卡片参数的onNewWant消费路径按目标 SDK 的准确签名补热启动处理避免应用已运行时点击失效首屏加载onWindowStageCreate固定加载pages/Index继续加载稳定首屏再由明确的导航状态直达目标或安全回退尺寸与更新配置支持2*2、2*4默认2*2启用更新并配置 08:00 与周期参数为两个尺寸定义不同信息密度并在目标 SDK 与真机上验证实际调度语义主题策略卡片配置使用colorMode: auto页面本身采用固定渐变与白色文字验证深浅色、壁纸、大字体与快照对比度必要时提供资源化主题本文提出的每日任务仓库、版本化DailyStudyFormData、日期键、完成态同步、尺寸分级布局、冷/热启动统一消费器和主动刷新策略都是建议实现当前源码尚未集成。本次精修没有执行 DevEco Studio 构建、卡片安装添加、08:00 调度、设备重启或真机点击直达测试因此不能据此声称卡片数据闭环和服务直达已经修复相关配置字段与生命周期签名还必须以项目目标 SDK 类型和真机日志为准。总结化学实验室现有桌面卡片已经完成了声明、扩展能力、卡片页面和FormLink的基础搭建最值得修复的不是视觉细节而是两条没有闭环的链路FormBindingData没有进入 UIFormLink参数没有进入业务页面。更新回调反复提交静态文案、两个尺寸共用同一信息密度也让“每日学习入口”的产品价值没有真正体现。把每日任务建模为带日期键、任务 ID、完成态和目标路由的稳定契约再让 Form 扩展、卡片页面和启动路由共同消费这份契约才能得到可信的服务直达体验。卡片显示什么、何时更新、点击去哪、失败如何回退都必须能被真机观察和测试而不是只在配置文件里看起来完整。AI 辅助声明本文由 AI 辅助完成源码梳理、结构校对与配图设计技术结论均以文中列出的本地 ArkTS 源码为依据并由作者复核后发布。