Skip to content
Back to skills

Hmos Form Kit Js Widget Development

ASecurity

开发JS卡片提供方(Stage模型),支持卡片生命周期管理、数据持久化、数据交互、页面开发(HML+CSS+JSON)及事件处理,适用于卡片创建、更新、删除场景,最大支持10秒生命周期

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 22, 2026
developmenttypescriptapiperformance

Works with

  • cli
  • api

Security analysis

A100/100

Pro scans all 9 files and shows the line behind each finding

Scanned September 22, 2026

npx -y skills add IsKenKenYa/skills --skill hmos-form-kit-js-widget-development --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Hmos Form Kit Js Widget Development?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Hmos Form Kit Js Widget Development
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/iskenkenya-hmos-form-kit-js-widget-development/badge)](https://www.skillsdirectory.com/skills/iskenkenya-hmos-form-kit-js-widget-development)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: hmos-form-kit-js-widget-development
description: 开发JS卡片提供方(Stage模型),支持卡片生命周期管理、数据持久化、数据交互、页面开发(HML+CSS+JSON)及事件处理,适用于卡片创建、更新、删除场景,最大支持10秒生命周期
---

# JS卡片开发指导(Stage模型)技能

## 功能描述

本技能提供基于Stage模型的JS卡片提供方开发能力,实现完整的卡片生命周期管理。主要功能包括:

- **生命周期管理**:实现FormExtensionAbility的生命周期回调(创建、更新、删除、可见性变更、事件处理)
- **数据持久化**:卡片信息的存储与管理,支持常态卡片和临时卡片的数据维护
- **数据交互**:通过formBindingData创建卡片数据,使用formProvider更新卡片显示
- **页面开发**:使用类Web范式(HML+CSS+JSON)开发卡片页面布局和样式
- **事件处理**:支持router事件(跳转UIAbility)和message事件(自定义点击事件)

**适用范围**:
- 卡片提供方应用开发
- Stage模型(API version 9及以上)
- 支持多种卡片尺寸(1×1、1×2、2×2、2×4、2×3、3×3、4×4、6×4)
- 最大生命周期限制:创建后10秒内无操作将被清理

**典型场景**:
- 创建桌面卡片应用
- 开发天气、日程、音乐播放器等卡片
- 实现卡片定时/定点刷新
- 处理卡片点击事件跳转

## 使用场景

### 触发词
- "开发JS卡片" - 创建JS卡片提供方应用
- "卡片生命周期" - 实现FormExtensionAbility生命周期接口
- "卡片数据更新" - 使用formProvider更新卡片显示内容
- "卡片事件处理" - 实现卡片点击事件(router/message)
- "卡片持久化" - 存储和管理卡片实例数据
- "Stage模型卡片" - 基于Stage模型的卡片开发

### 能做
- 创建和配置FormExtensionAbility卡片扩展类
- 实现卡片生命周期回调(onAddForm、onUpdateForm、onRemoveForm等)
- 持久化卡片信息(使用preferences轻量级数据存储)
- 创建FormBindingData对象并更新卡片数据
- 开发HML+CSS+JSON卡片页面布局
- 实现卡片router和message事件处理
- 配置卡片profile文件(尺寸、刷新策略等)
- 处理卡片可见性变更和临时卡片转换

### 绝不做
- 不支持FA模型卡片开发(仅支持Stage模型)
- 不实现卡片使用方功能(仅提供卡片提供方开发)
- 不处理超出10秒生命周期限制的长时间任务(FormExtensionAbility不能常驻后台)
- 不引用不支持模块(@ohos.ability.particleAbility、音频、相机、媒体、后台任务管理等)
- 不处理超过限制的图片资源(API version 20:最多20张图片/10MB数据;API version 19:最多5张图片/每张2MB)

### 补充
- FormExtensionAbility创建后10秒内无操作将被清理,无法处理长时间任务
- 卡片数据必须按照卡片ID进行持久化管理,支持多实例
- 临时卡片需要特殊处理(清理长时间未删除数据、转换为常态卡片)
- 卡片页面使用类Web范式(HML+CSS+JSON),不支持ArkTS语法
- 卡片事件分为router事件(跳转UIAbility)和message事件(自定义处理)
- 卡片配置文件必须在module.json5中声明metadata元信息

## 调用规范和规则

### 输入约束
- **API版本**:最低API version 9
- **模型约束**:仅支持Stage模型
- **卡片尺寸**:支持1×1、1×2、2×2、2×4、2×3、3×3、4×4、6×4(2×3和3×3仅支持手表设备,1×1仅支持锁屏)
- **数据大小**:
  - API version 20+:刷新数据总大小不超过10MB,图片不超过20张
  - API version 19:图片最多5张,每张限制2MB
- **刷新时间**:setFormNextRefreshTime最小值5分钟
- **文件格式**:卡片页面必须使用HML+CSS+JSON格式

### 执行约束
- **生命周期限制**:FormExtensionAbility创建后10秒内无操作将被清理
- **操作频次**:避免频繁更新卡片(遵循配置的刷新策略)
- **持久化路径**:使用/el2/base/haps/目录存储卡片信息
- **异步操作**:所有formProvider接口必须使用Promise或AsyncCallback异步调用
- **错误处理**:必须捕获BusinessError并处理错误码

### 内容约束
- **禁止引用模块**:
  - @ohos.ability.particleAbility
  - @ohos.multimedia.audio
  - @ohos.multimedia.camera
  - @ohos.multimedia.media
  - @ohos.resourceschedule.backgroundTaskManager
- **禁止高危操作**:
  - FormExtensionAbility中执行长时间任务
  - 硬编码敏感信息(卡片ID、formName等)
  - 直接操作文件系统(使用preferences进行数据持久化)
- **禁止遗漏处理**:
  - 临时卡片清理逻辑
  - 卡片数据完整性校验
  - 错误码处理(16500050、16500060、16500100、16501000等)

### 降级约束
- **生命周期超时**:10秒内无法完成操作时,记录日志并返回默认数据
- **持久化失败**:preferences操作失败时,使用内存临时存储并记录错误
- **更新失败**:formProvider.updateForm失败时,记录错误码并尝试重试(最多3次)
- **图片加载失败**:图片资源超出限制时,显示占位图或降级为纯文本卡片
- **网络请求失败**:无法获取最新数据时,使用本地缓存数据更新卡片

## 调用流程和步骤

### 步骤1:准备阶段(创建FormExtensionAbility)

**前置校验**:
1. 确认项目使用Stage模型(检查module.json5中type字段)
2. 确认API版本≥9(检查build-profile.json5中compatibleSdkVersion)
3. 确认已安装必要依赖(@kit.FormKit、@kit.AbilityKit、@kit.ArkData)

**导入模块**:
```typescript
// entry/src/main/ets/jscardformability/JsCardFormAbility.ets
import { common, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { formBindingData, FormExtensionAbility, formProvider } from '@kit.FormKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { preferences } from '@kit.ArkData';
```

**参数准备**:
```typescript
const TAG: string = 'JsCardFormAbility';
const DATA_STORAGE_PATH: string = '/data/storage/el2/base/haps/form_store';
const DOMAIN_NUMBER: number = 0xFF00;
```

### 步骤2:实现卡片生命周期回调

**示例代码**:
```typescript
// entry/src/main/ets/jscardformability/JsCardFormAbility.ets

// 持久化卡片信息
let storeFormInfo = async (formId: string, formName: string, tempFlag: boolean, context: common.FormExtensionContext): Promise<void> => {
  let formInfo: Record<string, string | boolean | number> = {
    'formName': formName,
    'tempFlag': tempFlag,
    'updateCount': 0
  };
  try {
    const storage: preferences.Preferences = await preferences.getPreferences(context, DATA_STORAGE_PATH);
    await storage.put(formId, JSON.stringify(formInfo));
    hilog.info(DOMAIN_NUMBER, TAG, `storeFormInfo success, formId: ${formId}`);
    await storage.flush();
  } catch (err) {
    hilog.error(DOMAIN_NUMBER, TAG, `storeFormInfo failed, err: ${JSON.stringify(err as BusinessError)}`);
  }
}

// 删除卡片信息
let deleteFormInfo = async (formId: string, context: common.FormExtensionContext): Promise<void> => {
  try {
    const storage: preferences.Preferences = await preferences.getPreferences(context, DATA_STORAGE_PATH);
    await storage.delete(formId);
    hilog.info(DOMAIN_NUMBER, TAG, `deleteFormInfo success, formId: ${formId}`);
    await storage.flush();
  } catch (err) {
    hilog.error(DOMAIN_NUMBER, TAG, `deleteFormInfo failed, err: ${JSON.stringify(err as BusinessError)}`);
  }
};

export default class JsCardFormAbility extends FormExtensionAbility {
  // 创建卡片回调
  onAddForm(want: Want): formBindingData.FormBindingData {
    hilog.info(DOMAIN_NUMBER, TAG, '[JsCardFormAbility] onAddForm');
    if (want.parameters) {
      let formId = JSON.stringify(want.parameters['ohos.extra.param.key.form_identity']);
      let formName = JSON.stringify(want.parameters['ohos.extra.param.key.form_name']);
      let tempFlag = want.parameters['ohos.extra.param.key.form_temporary'] as boolean;
      storeFormInfo(formId, formName, tempFlag, this.context);
    }
    let obj: Record<string, string> = {
      'title': 'titleOnCreate',
      'detail': 'detailOnCreate'
    };
    let formData: formBindingData.FormBindingData = formBindingData.createFormBindingData(obj);
    return formData;
  }

  // 删除卡片回调
  onRemoveForm(formId: string): void {
    hilog.info(DOMAIN_NUMBER, TAG, '[JsCardFormAbility] onRemoveForm');
    deleteFormInfo(formId, this.context);
  }

  // 更新卡片回调
  onUpdateForm(formId: string): void {
    hilog.info(DOMAIN_NUMBER, TAG, '[JsCardFormAbility] onUpdateForm');
    let obj: Record<string, string> = {
      'title': 'titleOnUpdate',
      'detail': 'detailOnUpdate'
    };
    let formData: formBindingData.FormBindingData = formBindingData.createFormBindingData(obj);
    formProvider.updateForm(formId, formData).catch((error: BusinessError) => {
      hilog.info(DOMAIN_NUMBER, TAG, `updateForm error: ${JSON.stringify(error)}`);
    });
  }

  // 卡片事件回调
  onFormEvent(formId: string, message: string): void {
    hilog.info(DOMAIN_NUMBER, TAG, '[JsCardFormAbility] onFormEvent');
    let msg: Record<string, string> = JSON.parse(message);
    if (msg.detail === 'message detail') {
      hilog.info(DOMAIN_NUMBER, TAG, `message info: ${msg.detail}`);
    }
  }
}
```

### 步骤3:配置卡片配置文件

**module.json5配置**:
```json
{
  "module": {
    "extensionAbilities": [
      {
        "name": "JsCardFormAbility",
        "srcEntry": "./ets/jscardformability/JsCardFormAbility.ets",
        "description": "$string:JSCardFormAbility_desc",
        "label": "$string:JSCardFormAbility_label",
        "type": "form",
        "metadata": [
          {
            "name": "ohos.extension.form",
            "resource": "$profile:form_jscard_config"
          }
        ]
      }
    ]
  }
}
```

**卡片profile配置文件(form_jscard_config.json)**:
```json
{
  "forms": [
    {
      "name": "WidgetJS",
      "description": "$string:JSCardEntryAbility_desc",
      "src": "./js/WidgetJS/pages/index/index",
      "window": {
        "designWidth": 720,
        "autoDesignWidth": true
      },
      "isDefault": true,
      "updateEnabled": true,
      "scheduledUpdateTime": "10:30",
      "updateDuration": 1,
      "defaultDimension": "2*2",
      "supportDimensions": ["2*2"]
    }
  ]
}
```

### 步骤4:开发卡片页面(HML+CSS+JSON)

**HML文件(index.hml)**:
```html
<div class="container">
  <stack>
    <div class="container-img">
      <image src="/common/widget.png" class="bg-img"></image>
    </div>
    <div class="container-inner">
      <text class="title">{{title}}</text>
      <text class="detail_text" onclick="routerEvent">{{detail}}</text>
    </div>
  </stack>
</div>
```

**CSS文件(index.css)**:
```css
.container {
  flex-direction: column;
  justify-content: center;
  align-items: center;
}
.bg-img {
  flex-shrink: 0;
  height: 100%;
}
.container-inner {
  flex-direction: column;
  justify-content: flex-end;
  align-items: flex-start;
  height: 100%;
  width: 100%;
  padding: 12px;
}
.title {
  font-size: 19px;
  font-weight: bold;
  color: white;
  text-overflow: ellipsis;
  max-lines: 1;
}
.detail_text {
  font-size: 16px;
  color: white;
  opacity: 0.66;
  text-overflow: ellipsis;
  max-lines: 1;
  margin-top: 6px;
}
```

**JSON文件(index.json)**:
```json
{
  "data": {
    "title": "TitleDefault",
    "detail": "TextDefault"
  },
  "actions": {
    "routerEvent": {
      "action": "router",
      "abilityName": "EntryAbility",
      "params": {
        "message": "add detail"
      }
    }
  }
}
```

### 步骤5:处理卡片事件

**router事件(跳转UIAbility)**:
```typescript
// 在UIAbility中接收router事件参数
// entry/src/main/ets/entryability/EntryAbility.ets
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';

const TAG: string = 'EntryAbility';
const DOMAIN_NUMBER: number = 0xFF00;

export default class EntryAbility extends UIAbility {
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    if (want?.parameters?.params) {
      let params: Record<string, Object> = JSON.parse(JSON.stringify(want.parameters.params));
      if (params.info === 'router info') {
        hilog.info(DOMAIN_NUMBER, TAG, `router info: ${params.info}`);
      }
      if (params.message === 'router message') {
        hilog.info(DOMAIN_NUMBER, TAG, `router message: ${params.message}`);
      }
    }
  }
}
```

**message事件(自定义处理)**:
```typescript
// 在FormExtensionAbility中接收message事件
onFormEvent(formId: string, message: string): void {
  let msg: Record<string, string> = JSON.parse(message);
  if (msg.detail === 'message detail') {
    hilog.info(DOMAIN_NUMBER, TAG, `message info: ${msg.detail}`);
  }
}
```

### 步骤6:错误处理

```typescript
// 捕获BusinessError并处理错误码
try {
  await formProvider.updateForm(formId, formData);
} catch (error) {
  const businessError = error as BusinessError;
  switch (businessError.code) {
    case 16500050:
      hilog.error(DOMAIN_NUMBER, TAG, 'IPC connection error');
      break;
    case 16500060:
      hilog.error(DOMAIN_NUMBER, TAG, 'Service connection error');
      break;
    case 16500100:
      hilog.error(DOMAIN_NUMBER, TAG, 'Failed to obtain configuration information');
      break;
    case 16501000:
      hilog.error(DOMAIN_NUMBER, TAG, 'Internal functional error');
      break;
    case 16501001:
      hilog.error(DOMAIN_NUMBER, TAG, 'Form ID does not exist');
      break;
    case 16501003:
      hilog.error(DOMAIN_NUMBER, TAG, 'Form cannot be operated by current application');
      break;
    default:
      hilog.error(DOMAIN_NUMBER, TAG, `Unknown error: ${businessError.message}`);
  }
}
```

### 步骤7:降级处理

```typescript
// 数据持久化失败的降级处理
let fallbackStorage: Map<string, string> = new Map();

let storeFormInfoWithFallback = async (formId: string, formName: string, tempFlag: boolean, context: common.FormExtensionContext): Promise<void> => {
  try {
    const storage: preferences.Preferences = await preferences.getPreferences(context, DATA_STORAGE_PATH);
    await storage.put(formId, JSON.stringify({ formName, tempFlag, updateCount: 0 }));
    await storage.flush();
  } catch (err) {
    hilog.error(DOMAIN_NUMBER, TAG, `Preferences failed, using memory fallback`);
    fallbackStorage.set(formId, JSON.stringify({ formName, tempFlag, updateCount: 0 }));
  }
}

// 卡片更新失败的降级处理
let updateFormWithRetry = async (formId: string, formData: formBindingData.FormBindingData, maxRetries: number = 3): Promise<void> => {
  for (let i = 0; i < maxRetries; i++) {
    try {
      await formProvider.updateForm(formId, formData);
      hilog.info(DOMAIN_NUMBER, TAG, `updateForm success on attempt ${i + 1}`);
      return;
    } catch (error) {
      hilog.error(DOMAIN_NUMBER, TAG, `updateForm failed on attempt ${i + 1}: ${JSON.stringify(error as BusinessError)}`);
      if (i === maxRetries - 1) {
        hilog.error(DOMAIN_NUMBER, TAG, 'Max retries reached, using cached data');
      }
    }
  }
}
```

## 错误码说明

| 错误码 | 说明 | 解决方法 |
|-------|------|---------|
| 401 | 参数错误(必填参数未指定、参数类型错误、参数校验失败) | 检查参数类型和取值范围,确保必填参数已提供 |
| 16500050 | IPC连接错误 | 检查FormExtensionAbility是否正常运行,避免引用不支持模块 |
| 16500060 | 服务连接错误 | 检查系统服务状态,重启应用或设备 |
| 16500100 | 无法获取配置信息 | 检查module.json5和form_config.json配置文件是否正确 |
| 16501000 | 内部功能错误 | 检查代码逻辑,避免在FormExtensionAbility中执行长时间任务 |
| 16501001 | 卡片ID不存在 | 检查formId是否正确,确保卡片实例已创建 |
| 16501002 | 卡片数量超过上限 | 减少卡片实例数量,清理已销毁的卡片数据 |
| 16501003 | 卡片无法被当前应用操作 | 检查应用权限和卡片归属关系 |
| 16501011 | 卡片不支持此操作 | 检查卡片类型和操作类型是否匹配 |

## 编译和修复问题

### 依赖声明
```json
{
  "dependencies": {
    "@kit.FormKit": "^9.0.0",
    "@kit.AbilityKit": "^9.0.0",
    "@kit.ArkData": "^9.0.0",
    "@kit.BasicServicesKit": "^9.0.0",
    "@kit.PerformanceAnalysisKit": "^9.0.0"
  }
}
```

### 环境要求
- HarmonyOS SDK:最低API version 9
- DevEco Studio:最新版本(推荐使用DevEco Studio服务卡片模板)
- 模型约束:仅支持Stage模型

### 常见编译问题

**问题1:FormExtensionAbility引用不支持模块**
```
Error: Cannot import '@ohos.multimedia.audio' in FormExtensionAbility
```
**解决方法**:移除不支持模块的引用,仅使用FormKit、AbilityKit、ArkData、BasicServicesKit、PerformanceAnalysisKit

**问题2:卡片配置文件路径错误**
```
Error: Failed to load form_config.json
```
**解决方法**:确保form_config.json放在resources/base/profile/目录下,metadata中resource字段格式为$profile:form_jscard_config

**问题3:卡片页面文件找不到**
```
Error: Cannot find './js/WidgetJS/pages/index/index'
```
**解决方法**:确保HML/CSS/JSON文件路径与form_config.json中src字段一致,使用相对路径

**问题4:生命周期超时**
```
Error: FormExtensionAbility cleaned after 10 seconds
```
**解决方法**:避免在生命周期回调中执行长时间任务,使用异步操作并快速返回结果

## 常见问题与解决方法

### Q1:如何正确持久化卡片信息?
**原因**:卡片提供方不是常驻服务,需要持久化卡片数据以便后续获取和更新
**解决方法**:
- 使用preferences轻量级数据存储
- 按照卡片ID(formId)进行数据存储
- 存储卡片名称(formName)、临时标记(tempFlag)、更新次数(updateCount)等关键信息
- 使用/el2/base/haps/目录作为存储路径

### Q2:如何处理临时卡片和常态卡片?
**原因**:临时卡片不会持久化,需要特殊处理清理逻辑和转换逻辑
**解决方法**:
- 在onAddForm中根据tempFlag字段区分临时卡片和常态卡片
- 实现临时卡片清理逻辑(定时清理长时间未删除的临时卡片数据)
- 在onCastToNormalForm中处理临时卡片转换为常态卡片的逻辑
- 防止已转换的临时卡片被误删

### Q3:如何实现卡片定时/定点刷新?
**原因**:卡片支持周期性刷新,需要配置刷新策略
**解决方法**:
- 在form_config.json中配置updateEnabled为true
- 配置scheduledUpdateTime(定点刷新,24小时制)或updateDuration(定时刷新,单位30分钟)
- updateDuration优先级高于scheduledUpdateTime
- 在onUpdateForm中实现数据获取和更新逻辑

### Q4:如何处理卡片点击事件?
**原因**:卡片需要响应用户点击操作,跳转UIAbility或执行自定义逻辑
**解决方法**:
- 在JSON文件中配置actions字段
- router事件:设置action为"router",指定abilityName和params
- message事件:设置action为"message",传递自定义参数
- 在UIAbility的onCreate中接收router事件参数(want.parameters.params)
- 在FormExtensionAbility的onFormEvent中接收message事件参数(message字段)

### Q5:如何处理卡片数据嵌套更新?
**原因**:FormBindingData支持多级嵌套数据,但更新时需要传递完整数据
**解决方法**:
- 在创建卡片时定义完整的数据结构(包含所有嵌套字段)
- 更新卡片时传递完整的嵌套数据,不能只传递单个字段
- 示例:更新teacher.name时,需要传递完整的teacher对象(name + course)

### Q6:FormExtensionAbility生命周期限制如何应对?
**原因**:FormExtensionAbility创建后10秒内无操作将被清理,无法执行长时间任务
**解决方法**:
- 避免在生命周期回调中执行网络请求、文件读写等长时间操作
- 使用异步操作快速返回结果
- 将长时间任务放在UIAbility或其他组件中执行
- 使用定时刷新机制(scheduledUpdateTime或updateDuration)定期更新卡片

## 输出结果报告

执行完成后输出以下信息:

```json
{
  "status": "success",
  "cardType": "JS Widget (Stage Model)",
  "apiUsed": [
    "FormExtensionAbility.onAddForm",
    "FormExtensionAbility.onUpdateForm",
    "FormExtensionAbility.onRemoveForm",
    "FormExtensionAbility.onFormEvent",
    "formBindingData.createFormBindingData",
    "formProvider.updateForm",
    "preferences.getPreferences",
    "preferences.put",
    "preferences.delete"
  ],
  "cardConfig": {
    "formName": "WidgetJS",
    "defaultDimension": "2*2",
    "supportDimensions": ["2*2"],
    "updateEnabled": true,
    "scheduledUpdateTime": "10:30",
    "updateDuration": 1
  },
  "cardFeatures": [
    "卡片生命周期管理",
    "数据持久化",
    "数据交互",
    "HML+CSS+JSON页面开发",
    "router和message事件处理"
  ]
}
```

## 参考文档

- [JS卡片开发指导(Stage模型)](references/js-ui-widget-development.md)
- [FormExtensionAbility API参考](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-app-form-formextensionability)
- [formProvider API参考](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-app-form-formprovider)
- [formBindingData API参考](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-app-form-formbindingdata)
- [Stage模型概述](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/stage-model-development-overview)
- [配置module.json5](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/module-configuration-file)
- [应用数据持久化概述](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/app-data-persistence-overview)

## 完整示例代码

- [FormExtensionAbility完整示例](assets/JsCardFormAbility.ets)
- [卡片配置文件示例](assets/form_jscard_config.json)
- [module.json5配置示例](assets/module.json5)
- [卡片HML页面示例](assets/index.hml)
- [卡片CSS样式示例](assets/index.css)
- [卡片JSON数据示例](assets/index.json)
- [UIAbility接收事件示例](assets/EntryAbility.ets)

## 测试用例

### 正向测试用例
- [创建JS卡片成功](tests/test_positive.js):验证onAddForm返回正确的FormBindingData
- [更新卡片数据成功](tests/test_positive.js):验证onUpdateForm正确更新卡片显示
- [处理router事件成功](tests/test_positive.js):验证点击卡片跳转UIAbility
- [处理message事件成功](tests/test_positive.js):验证点击卡片触发自定义事件
- [持久化卡片数据成功](tests/test_positive.js):验证preferences正确存储卡片信息

### 边界测试用例
- [卡片生命周期10秒限制](tests/test_boundary.js):验证超过10秒FormExtensionAbility被清理
- [最大图片数量限制](tests/test_boundary.js):验证超过20张图片(API version 20)或5张图片(API version 19)显示异常
- [最大数据大小限制](tests/test_boundary.js):验证超过10MB数据(API version 20)刷新失败
- [最小刷新时间限制](tests/test_boundary.js):验证setFormNextRefreshTime小于5分钟返回错误
- [多级嵌套数据更新](tests/test_boundary.js):验证部分嵌套字段更新导致数据丢失

### 异常测试用例
- [引用不支持模块](tests/test_exception.js):验证引用音频、相机等模块导致程序异常退出
- [卡片ID不存在](tests/test_exception.js):验证使用无效formId返回16501001错误码
- [持久化路径错误](tests/test_exception.js):验证使用错误路径导致preferences.getPreferences失败
- [卡片配置文件缺失](tests/test_exception.js):验证form_config.json不存在返回16500100错误码
- [卡片数量超限](tests/test_exception.js):验证超过最大卡片数量返回16501002错误码

Files in this skill

  • SUB_SKILL.md23.7 KB
  • assets/EntryAbility.ets1.8 KB
  • assets/JsCardFormAbility.ets7 KB
  • assets/form_jscard_config.json730 B
  • assets/index.css1 KB
  • assets/index.hml531 B
  • assets/index.json500 B
  • assets/module.json5742 B

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…