diff --git "a/FA\346\250\241\345\236\213\344\270\255\345\215\241\347\211\207\347\232\204\345\237\272\346\234\254\347\224\250\346\263\225.md" "b/FA\346\250\241\345\236\213\344\270\255\345\215\241\347\211\207\347\232\204\345\237\272\346\234\254\347\224\250\346\263\225.md" new file mode 100644 index 0000000000000000000000000000000000000000..b07da8052a9987f14dac2a3f7877d6308ec4a803 --- /dev/null +++ "b/FA\346\250\241\345\236\213\344\270\255\345\215\241\347\211\207\347\232\204\345\237\272\346\234\254\347\224\250\346\263\225.md" @@ -0,0 +1,480 @@ +# 基于FA模型的卡片基本用法 + +## 卡片概述 + +卡片是一种界面展示形式,可以将应用的重要信息或操作前置到卡片,以达到服务直达,减少体验层级的目的。 + +卡片常用于嵌入到其他应用(当前只支持系统应用,例如Launcher)中作为其界面的一部分显示,并支持拉起页面,发送消息等基础的交互功能。 + +卡片的基本概念: + +- 卡片提供方:提供卡片显示内容原子化服务,控制卡片的显示内容、控件布局以及控件点击事件。 +- 卡片使用方:显示卡片内容的宿主应用,负责显示卡片,控制卡片在宿主中展示的位置。 +- 卡片管理服务:用于管理系统中所添加卡片的常驻代理服务,包括卡片对象的管理与使用,以及卡片周期性刷新等。 + +> 卡片使用方和提供方不要求常驻运行,在需要添加/删除/请求更新卡片时,卡片管理服务会拉起卡片提供方获取卡片信息。 +> +> 开发者仅需作为卡片提供方进行卡片内容的开发,卡片使用方和卡片管理服务由系统自动处理。 + + + +## 场景介绍 + +FA卡片开发,即基于[FA模型](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/ability/fa-brief.md)的卡片提供方开发,主要涉及如下功能逻辑: + +- 开发卡片生命周期回调函数LifecycleForm。 +- 创建卡片数据FormBindingData对象。 +- 通过FormProvider更新卡片。 +- 卡片页面开发。 + + + +## 接口说明 + +#### LifecycleForm + +> 该接口提供了卡片生命周期函数。 +> +> 在卡片提供方应用中的FormAbility.ts文件中继承FormExtension并实现这些卡片生命周期函数。 + +| 接口名 | 描述 | +| ------------------------------------------------------------ | -------------------------------------------- | +| onCreate(want: Want): formBindingData.FormBindingData | 卡片提供方接收创建卡片的通知接口。 | +| onCastToNormal(formId: string): void | 卡片提供方接收临时卡片转常态卡片的通知接口。 | +| onUpdate(formId: string): void | 卡片提供方接收更新卡片的通知接口。 | +| onVisibilityChange(newStatus: { [key: string]: number }): void | 卡片提供方接收修改可见性的通知接口。 | +| onEvent(formId: string, message: string): void | 卡片提供方接收处理卡片事件的通知接口。 | +| onDestroy(formId: string): void | 卡片提供方接收销毁卡片的通知接口。 | +| onAcquireFormState?(want: Want): formInfo.FormState | 卡片提供方接收查询卡片状态的通知接口。 | + + + +#### FormProvider + +> 卡片提供者,可以更新卡片信息、设置卡片下一次刷新时间。 + +| 接口名 | 描述 | +| ------------------------------------------------------------ | ------------------------------------------------- | +| setFormNextRefreshTime(formId: string, minute: number, callback: AsyncCallback): void; | 设置指定卡片的下一次更新时间。 | +| setFormNextRefreshTime(formId: string, minute: number): Promise; | 设置指定卡片的下一次更新时间,以promise方式返回。 | +| updateForm(formId: string, formBindingData: FormBindingData, callback: AsyncCallback): void; | 更新指定的卡片。 | +| updateForm(formId: string, formBindingData: FormBindingData): Promise; | 更新指定的卡片,以promise方式返回。 | + + + +## 卡片开发指导 + +### 创建卡片提供者 + +1. 打开DevEco 3.0.0.900新建一个FA模型、API8的项目 + + ![](http://image.huawei.com/tiny-lts/v1/images/e8b6683ee64439e5f362341bf7056a38_980x607.png) + +2. 选择一个module,此处以entry为例。选中entry文件夹,右键New-->Service Widget + + ![](http://image.huawei.com/tiny-lts/v1/images/4c7f02414c14603ca015bb7d75c53e7b_915x651.png) + +3. 任选一种卡片模板,输入卡片名称,选择卡片尺寸(部分卡片模板支撑选择多种尺寸),输入卡片Ability名称,默认FormAbility。 + + ![](http://image.huawei.com/tiny-lts/v1/images/a640bc1e6cd52bdce1c5f5de0a63fed3_979x605.png) + +4. 点击Finish,完成卡片的创建之后,会生成如下文件。 + + ![](http://image.huawei.com/tiny-lts/v1/images/9b9ff48da725564f17304132731ad4ac_930x758.png) + +5. 安装应用到设备上。 + + 在设备的桌面上长按应用图标,会显示卡片管理,点击卡片管理即可看到该应用支持的卡片,选择卡片添加到桌面。 + + + +### 卡片页面文件说明 + +> JS卡片页面通过hml+css+json开发 + +- index.hml文件:卡片的显示页面,在该页面中可以为组件设置onClick属性,其值对应到index.json文件的actions字段中 + +- index.css文件:存放index.hml页面中使用的的css样式 + +- index.json文件:存放卡片页面index.hml中的变量及事件。 + + 内部字段结构说明: + + - data:存放的是index.hml中使用到的变量 + + - actions: 存放的是index.hml中使用的事件,有两种类型:router和message。 + + > router类型事件:用于卡片提供方进行跳转,须相应配置abilityName属性用于存放目标Ability名称。 + > + > message类型事件:用于卡片与卡片提供方进行交互,会触发卡片生命周期中的`onEvent`方法。 + + 示例: + + ```typescript + "actions": { + "routerPage": { + "action": "router", + "abilityName": "ohos.samples.FormApplication.MainAbility", + "params": { + "message": "add detail" + } + }, + "onUpdateEvent": { + "action": "message", + "params": { + "name" : "onUpdateEvent", + "message": "add detail" + } + }, + } + ``` + + + +### 卡片配置 + +FA模型的卡片只需在项目的配置文件`config.json`中进行配置,分为js模块和ability模块两个部分。 + +- js模块,用于对应卡片的js相关资源,内部字段结构说明: + + | 属性名称 | 含义 | 数据类型 | 是否可缺省 | + | -------- | ------------------------------------------------------------ | -------- | ------------------------ | + | name | 表示JS Component的名字。该标签不可缺省,默认值为default。 | 字符串 | 否 | + | pages | 表示JS Component的页面用于列举JS Component中每个页面的路由信息[页面路径+页面名称]。该标签不可缺省,取值为数组,数组第一个元素代表JS FA首页。 | 数组 | 否 | + | window | 用于定义与显示窗口相关的配置。 | 对象 | 可缺省 | + | type | 表示JS应用的类型。取值范围如下: normal:标识该JS Component为应用实例。 form:标识该JS Component为卡片实例。 | 字符串 | 可缺省,缺省值为“normal” | + | mode | 定义JS组件的开发模式。 | 对象 | 可缺省,缺省值为空 | + + 配置示例如下: + + ```json + "js": [{ + "name": "widget", + "pages": ["pages/index/index"], + "window": { + "designWidth": 720, + "autoDesignWidth": true + }, + "type": "form" + }] + ``` + +- abilities模块,用于对应卡片的LifecycleForm,内部字段结构说明: + + | 属性名称 | 含义 | 数据类型 | 是否可缺省 | + | ------------------- | ------------------------------------------------------------ | ---------- | ------------------------ | + | name | 表示卡片的类名。字符串最大长度为127字节。 | 字符串 | 否 | + | description | 表示卡片的描述。取值可以是描述性内容,也可以是对描述性内容的资源索引,以支持多语言。字符串最大长度为255字节。 | 字符串 | 可缺省,缺省为空。 | + | isDefault | 表示该卡片是否为默认卡片,每个Ability有且只有一个默认卡片。 true:默认卡片。 false:非默认卡片。 | 布尔值 | 否 | + | type | 表示卡片的类型。取值范围如下: JS:JS卡片。 | 字符串 | 否 | + | colorMode | 表示卡片的主题样式,取值范围如下: auto:自适应。 dark:深色主题。 light:浅色主题。 | 字符串 | 可缺省,缺省值为“auto”。 | + | supportDimensions | 表示卡片支持的外观规格,取值范围: 1 * 2:表示1行2列的二宫格。 2 * 2:表示2行2列的四宫格。 2 * 4:表示2行4列的八宫格。 4 * 4:表示4行4列的十六宫格。 | 字符串数组 | 否 | + | defaultDimension | 表示卡片的默认外观规格,取值必须在该卡片supportDimensions配置的列表中。 | 字符串 | 否 | + | updateEnabled | 表示卡片是否支持周期性刷新,取值范围: true:表示支持周期性刷新,可以在定时刷新(updateDuration)和定点刷新(scheduledUpdateTime)两种方式任选其一,优先选择定时刷新。 false:表示不支持周期性刷新。 | 布尔类型 | 否 | + | scheduledUpdateTime | 表示卡片的定点刷新的时刻,采用24小时制,精确到分钟。 | 字符串 | 可缺省,缺省值为“0:0”。 | + | updateDuration | 表示卡片定时刷新的更新周期,单位为30分钟,取值为自然数。 当取值为0时,表示该参数不生效。 当取值为正整数N时,表示刷新周期为30*N分钟。 | 数值 | 可缺省,缺省值为“0”。 | + | formConfigAbility | 表示卡片的配置跳转链接,采用URI格式。 | 字符串 | 可缺省,缺省值为空。 | + | formVisibleNotify | 标识是否允许卡片使用卡片可见性通知。 | 字符串 | 可缺省,缺省值为空。 | + | jsComponentName | 表示JS卡片的Component名称。字符串最大长度为127字节。 | 字符串 | 否 | + | metaData | 表示卡片的自定义信息,包含customizeData数组标签。 | 对象 | 可缺省,缺省值为空。 | + | customizeData | 表示自定义的卡片信息。 | 对象数组 | 可缺省,缺省值为空。 | + + 配置示例如下: + + ```json + "abilities": [{ + "name": "FormAbility", + "description": "This is a FormAbility", + "formsEnabled": true, + "icon": "$media:icon", + "label": "$string:form_FormAbility_label", + "srcPath": "FormAbility", + "type": "service", + "srcLanguage": "ets", + "formsEnabled": true, + "forms": [{ + "colorMode": "auto", + "defaultDimension": "2*2", + "description": "This is a service widget.", + "formVisibleNotify": true, + "isDefault": true, + "jsComponentName": "widget", + "name": "widget", + "scheduledUpdateTime": "10:30", + "supportDimensions": ["2*2"], + "type": "JS", + "updateDuration": 1, + "updateEnabled": true + }] + }] + ``` + + + +### 页面拉起功能 + +1. 在index.hml页面设置点击事件`routerEvent`,其值对应index.json文件中actions字段中。 + + ```html + +
+
+ ``` + +2. 在index.json中的actions标签下定义`routerEvent`事件 + + > action字段填router,表明是跳转事件 + > abilityName填写要调转的Ability名, + > + > 在FA模型下,abilityName = config.json.package + config.json.abilities.ability.name,而不是bundleName + ability.name + + ```json + "actions": { + "routerPage": { + "action": "router", + "abilityName": "com.example.entry.MainAbility", + "params": { + "message": "add detail" + } + }, + } + ``` + + + + +### 数据交互功能 + +> 在index.hml页面中展示两个数据:temperature 和 time +> +> ```html +> {{ $t('strings.temperature') }}{{temperature}} ℃ +> {{ $t('strings.time') }} {{time}} +> ``` +> +> 数据 temperature 和 time 已在index.json中定义: +> +> ```json +> { +> "data": { +> "temperature": "0", +> "time": "00:00:00" +> } +> } +> ``` +> +> 可以通过以下方式来实现卡片的数据交互。 + + + +#### 手动刷新数据 + +> 通过调用message类型的事件触发卡片生命周期函数onEvent,在onEvent函数中可以获取到当前卡片实例的Id及传入的事件信息。 +> +> 在onEvent函数中根据事件名来进行不同的操作,当传入的是更新数据的事件名时,调用formProvider接口的updateForm方法来更新卡片数据。 + +![](http://image.huawei.com/tiny-lts/v1/images/90697a0fc35c97b1a2c110c8f41709d6_945x872.png) + +1. 在index.hml文件中创建按钮,绑定`onUpdateEvent`事件 + + ```html + + ``` + +2. 在index.json文件中声明`onUpdateEvent`事件,action类型为`message` + + ```json + { + "data": { + "temperature": "0", + "time": "00:00:00" + }, + "actions":{ + "onUpdateEvent": { + "action": "message", + "params": { + "name" : "onUpdateEvent", + "message": "add detail" + } + } + } + + } + ``` + +3. 在FormAbility.ts中的onEvent方法中,获取事件名onUpdateEvent,然后进行卡片数据更新操作。 + + - onUpdateEvent: 调用卡片页面数据刷新函数,刷新卡片数据一次 + - openRefresh: 设置定时器,每间隔1s调用一次卡片数据刷新函数来实现卡片页面数据持续刷新 + - closeRefresh: 清除定时器,关闭卡片页面数据持续刷新 + + ```typescript + import formBindingData from '@ohos.application.formBindingData'; + import formProvider from '@ohos.application.formProvider'; + + var timer : number = 0 + + //卡片页面数据刷新函数 + async function updateFormData(formId: string){ + let obj = { + "temperature" : getTemperature(formId, formInfo.updateCount).toString(), + "time" : getTime() + } + let formData = formBindingData.createFormBindingData(obj) + //通过formProvider接口来更新卡片实例的数据 + formProvider.updateForm(formId,formData).catch(err=>{ + Logger.error("updateOne err : " + JSON.stringify(err)) + }) + } + + onEvent(formId, message) { + console.log(`FormAbility onEvent, formId = ${formId}, message: ${JSON.stringify(message)}`); + let jsonParams = JSON.parse(message) + //获取事件名 + let eventName = jsonParams.params.name + + switch(eventName){ + + case "onUpdateEvent" : + updateFormData(formId); + break; + + case "openRefresh" : + let count = 1 + timer = setInterval(()=>{ + this.onUpdate(formId) + },1000) + break; + + case "closeRefresh" : + clearInterval(timer) + break; + + default : + console.log("(onEvent) formId :" + formId + " message : " + message ) + break; + } + } + ``` + + + +#### 定点刷新数据 + +在卡片配置文件`form_config.json`中可以配置`scheduledUpdateTime`属性来实现卡片定点刷新数据, + +`scheduledUpdateTime`表示卡片的定点刷新的时刻,采用24小时制,精确到分钟。 + +时间到达`scheduledUpdateTime`参数设置的时刻时,会触发卡片生命周期的`onUpdate`方法,在`onUpdate`方法中执行卡片数据更新操作。 + +示例: + +- form_config.json + + ```json + { + "forms": [ + { + //... + "scheduledUpdateTime": "11:32", + "updateDuration" : 0, + //... + } + ] + } + ``` + +- FormAbility.ts + + ```typescript + onUpdate(formId) { + console.log(`FormAbility onUpdate, formId: ${formId}`); + //卡片数据更新方法 + updateFormData(formId); + } + ``` + + + +#### 定时刷新数据 + +在卡片配置文件`form_config.json`中可以配置来实现卡片定时刷新数据, + +`updateDuration`属性表示卡片定时刷新的更新周期,单位为30分钟,取值为自然数(正整数或0)。 + +当取值为0时,表示该参数不生效。 + +当取值为正整数N时,表示刷新周期为30*N分钟,每隔30*N分钟会触发卡片生命周期的`onUpdate`方法,在`onUpdate`方法中执行卡片数据更新操作。 + +当取值为正整数N时,定点刷新数据不生效。 + + + +示例: + +- form_config.json + + ```json + { + "forms": [ + { + ... + "scheduledUpdateTime": "11:32", + "updateDuration" : 1, + ... + } + ] + } + ``` + +- FormAbility.ts + + ```typescript + onUpdate(formId) { + console.log(`FormAbility onUpdate, formId: ${formId}`); + //卡片数据更新方法 + updateFormData(formId); + } + ``` + + + +### 卡片信息持久化 + +> 因大部分卡片提供方都不是常驻服务,只有在需要使用时才会被拉起获取卡片信息,且卡片管理服务支持对卡片进行多实例管理,卡片ID对应实例ID。 +> +> 因此若卡片提供方支持对卡片数据进行配置,则需要对卡片的业务数据按照卡片ID进行持久化管理, +> +> 以便在后续获取、更新以及拉起时能获取到正确的卡片业务数据, +> +> 且需要适配onDestroy卡片销毁通知接口,在其中实现卡片实例数据的删除。 + +卡片根据业务数据是否需要持久化分为以下两类: + +- 常态卡片:卡片使用方会持久化的卡片; +- 临时卡片:卡片使用方不会持久化的卡片; + +卡片管理服务调用卡片提供者创建卡片时,默认创建的是临时卡片。如果需要将临时卡片转化为常态卡片,可参考轻量级数据存储,将卡片示例的业务数据进行存储调用。 + +```typescript +import dataStorage from '@ohos.data.storage'; + +async function storeFormInfo(formId: string, formName: string, tempFlag: boolean) { + let formInfo = { + "formName": formName, + "tempFlag": tempFlag, + "updateCount": 0 + }; + try { + const storage = await dataStorage.getStorage(DATA_STORAGE_PATH); + // put form info + await storage.put(formId, JSON.stringify(formInfo)); + Logger.log(`storeFormInfo, put form info successfully, formId: ${formId}`); + await storage.flush(); + } catch (err) { + Logger.error(`failed to storeFormInfo, err: ${JSON.stringify(err)}`); + } +} +``` + + diff --git a/FormDemoFA/.gitignore b/FormDemoFA/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..121b8a53cfeff43434ef9d6db7d1b85890110be2 --- /dev/null +++ b/FormDemoFA/.gitignore @@ -0,0 +1,12 @@ +node_modules +local.properties +.idea + +entry/.preview +entry/build +entry/package-lock.json + + +install.bat + +package-lock.json \ No newline at end of file diff --git a/FormDemoFA/build-profile.json5 b/FormDemoFA/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..76c720adac9b01397022acc52842250bef4288bf --- /dev/null +++ b/FormDemoFA/build-profile.json5 @@ -0,0 +1,40 @@ +{ + "app": { + "signingConfigs": [ + { + "name": "default", + "material": { + "certpath": "C:\\Users\\dwx1140490\\.ohos\\config\\openharmony\\auto_ohos.cer", + "storePassword": "000000189BB70C876CA9B8852F9547631CC1DACA0B07A17CB24BF66EC06765FE0152B64A462166F9", + "keyAlias": "debugKey", + "keyPassword": "0000001883F233F0A153E30883B2D9BB9953C100C92DB6BC6C5E8A85198DF18F4BB483706B55D292", + "profile": "C:\\Users\\dwx1140490\\.ohos\\config\\openharmony\\auto_ohos_default_ohos.test.formfa.p7b", + "signAlg": "SHA256withECDSA", + "storeFile": "C:\\Users\\dwx1140490\\.ohos\\config\\openharmony\\auto_ohos.p12" + } + } + ], + "compileSdkVersion": 8, + "compatibleSdkVersion": 8, + "products": [ + { + "name": "default", + "signingConfig": "default", + } + ] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/FormDemoFA/entry/build-profile.json5 b/FormDemoFA/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..ae58d1d0a70c602c9cfe1909b00dfec899ba1944 --- /dev/null +++ b/FormDemoFA/entry/build-profile.json5 @@ -0,0 +1,13 @@ +{ + "apiType": 'faMode', + "buildOption": { + }, + "targets": [ + { + "name": "default", + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/FormDemoFA/entry/hvigorfile.js b/FormDemoFA/entry/hvigorfile.js new file mode 100644 index 0000000000000000000000000000000000000000..bcec4c99653062cbf17702c40a2dd2a7b809b81a --- /dev/null +++ b/FormDemoFA/entry/hvigorfile.js @@ -0,0 +1,2 @@ +// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently. +module.exports = require('@ohos/hvigor-ohos-plugin').legacyHapTasks diff --git a/FormDemoFA/entry/package.json b/FormDemoFA/entry/package.json new file mode 100644 index 0000000000000000000000000000000000000000..c7685ac4e7c0d79df04c96744f0d8f22cb4a9025 --- /dev/null +++ b/FormDemoFA/entry/package.json @@ -0,0 +1,14 @@ +{ + "license": "ISC", + "devDependencies": {}, + "name": "entry", + "ohos": { + "org": "huawei", + "directoryLevel": "module", + "buildTool": "hvigor" + }, + "description": "example description", + "repository": {}, + "version": "1.0.0", + "dependencies": {} +} diff --git a/FormDemoFA/entry/src/main/config.json b/FormDemoFA/entry/src/main/config.json new file mode 100644 index 0000000000000000000000000000000000000000..8ab03e67ab9141ff8c729d985dcaabffb949bd0d --- /dev/null +++ b/FormDemoFA/entry/src/main/config.json @@ -0,0 +1,107 @@ +{ + "app": { + "vendor": "example", + "bundleName": "ohos.test.formfa", + "version": { + "code": 1000000, + "name": "1.0.0" + } + }, + "deviceConfig": {}, + "module": { + "mainAbility": ".MainAbility", + "deviceType": [ + "phone", + "tablet" + ], + "abilities": [ + { + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ], + "orientation": "unspecified", + "visible": true, + "srcPath": "MainAbility", + "name": ".MainAbility", + "srcLanguage": "ets", + "icon": "$media:icon", + "description": "$string:MainAbility_desc", + "formsEnabled": false, + "label": "$string:MainAbility_label", + "type": "page", + "launchType": "standard" + }, + { + "srcPath": "FormAbility", + "name": "FormAbility", + "icon": "$media:icon", + "srcLanguage": "ets", + "description": "$string:form_FormAbility_desc", + "formsEnabled": true, + "label": "$string:form_FormAbility_label", + "type": "service", + "forms": [ + { + "jsComponentName": "widget", + "isDefault": true, + "scheduledUpdateTime": "10:30", + "defaultDimension": "2*2", + "formVisibleNotify": true, + "name": "widget", + "description": "This is a service widget.", + "colorMode": "auto", + "type": "JS", + "supportDimensions": [ + "2*2","2*4" + ], + "updateEnabled": false, + "updateDuration": 1 + } + ] + } + ], + "distro": { + "moduleType": "entry", + "installationFree": false, + "deliveryWithInstall": true, + "moduleName": "entry" + }, + "package": "com.example.entry", + "srcPath": "", + "name": ".entry", + "js": [ + { + "mode": { + "syntax": "ets", + "type": "pageAbility" + }, + "pages": [ + "pages/index" + ], + "name": ".MainAbility", + "window": { + "designWidth": 720, + "autoDesignWidth": false + } + }, + { + "pages": [ + "pages/index/index" + ], + "name": "widget", + "window": { + "designWidth": 720, + "autoDesignWidth": true + }, + "type": "form" + } + ] + } +} \ No newline at end of file diff --git a/FormDemoFA/entry/src/main/ets/FormAbility/form.ts b/FormDemoFA/entry/src/main/ets/FormAbility/form.ts new file mode 100644 index 0000000000000000000000000000000000000000..462f650bce1191180461e3c55e343d7a24b552cd --- /dev/null +++ b/FormDemoFA/entry/src/main/ets/FormAbility/form.ts @@ -0,0 +1,210 @@ +import formBindingData from '@ohos.application.formBindingData'; +import formInfo from '@ohos.application.formInfo'; +import formProvider from '@ohos.application.formProvider'; +import dataStorage from '@ohos.data.storage'; + + +import hilog from '@ohos.hilog' + +import Logger from "../Logger" + +const LOGTAG : string = "DON_TALK" + +const DATA_STORAGE_PATH = "/data/storage/el2/base/haps/form_store"; +const FORM_PARAM_IDENTITY_KEY = "ohos.extra.param.key.form_identity"; +const FORM_PARAM_NAME_KEY = "ohos.extra.param.key.form_name"; +const FORM_PARAM_TEMPORARY_KEY = "ohos.extra.param.key.form_temporary"; +var timer : number = 0 + + +function getTemperature(formId: string, count: number) { + const DECIMAL: number = 10; + const parsedFormId: number = parseInt(formId, DECIMAL); + const BASE_TEMP_MOD: number = 20; + const baseTemperature: number = parsedFormId % BASE_TEMP_MOD; + const RANGE_TEMP_MOD: number = 20; + return baseTemperature + Math.abs(count % RANGE_TEMP_MOD - RANGE_TEMP_MOD / 2); +} + +function padZero(num: number) { + // trans num to string and pad 0 + if (num < 10) { + return `0${num}`; + } else { + return num.toString(); + } +} + +function getTime() { + const date = new Date(); + const hours = padZero(date.getHours()); + const minutes = padZero(date.getMinutes()); + const seconds = padZero(date.getSeconds()); + return `${hours}:${minutes}:${seconds}` +} + +async function storeFormInfo(formId: string, formName: string, tempFlag: boolean) { + let formInfo = { + "formName": formName, + "tempFlag": tempFlag, + "updateCount": 0 + }; + try { + const storage = await dataStorage.getStorage(DATA_STORAGE_PATH); + // put form info + await storage.put(formId, JSON.stringify(formInfo)); + Logger.info(`storeFormInfo, put form info successfully, formId: ${formId}`); + await storage.flush(); + } catch (err) { + Logger.error(`failed to storeFormInfo, err: ${JSON.stringify(err)}`); + } +} + +async function updateTempFormInfo(formId: string) { + let formInfoDefault = { + "formName": "", + "tempFlag": false, + "updateCount": 0 + }; + try { + const storage = await dataStorage.getStorage(DATA_STORAGE_PATH); + // get form info + const data = await storage.get(formId, JSON.stringify(formInfoDefault)); + Logger.info(`updateTempFormInfo, get form info successfully, formId: ${formId}`); + const formInfo = JSON.parse(data.toString()); + if (!formInfo.tempFlag) { + Logger.info(`updateTempFormInfo, formId: ${formId} is not temporary.`); + return; + } + + formInfo.tempFlag = false; + // update form info + await storage.put(formId, JSON.stringify(formInfo)); + Logger.info(`updateTempFormInfo, update form info successfully, formId: ${formId}`); + await storage.flush(); + } catch (err) { + Logger.error(`failed to updateTempFormInfo, err: ${JSON.stringify(err)}`); + } +} + +async function updateForm(formId: string) { + let formInfoDefault = { + "formName": "", + "tempFlag": false, + "updateCount": 0 + }; + try { + const storage = await dataStorage.getStorage(DATA_STORAGE_PATH); + // get form info + const data = await storage.get(formId, JSON.stringify(formInfoDefault)); + Logger.info(`updateForm, get form info successfully, formId: ${formId}`); + const formInfo = JSON.parse(data.toString()); + formInfo.updateCount = formInfo.updateCount + 1; + + let obj = { + "temperature": getTemperature(formId, formInfo.updateCount).toString(), + "time": getTime() + }; + let formData = formBindingData.createFormBindingData(obj); + formProvider.updateForm(formId, formData).catch((err) => { + Logger.error(`updateForm, err: ${JSON.stringify(err)}`); + }); + + // update form info + await storage.put(formId, JSON.stringify(formInfo)); + Logger.info(`updateForm, update form info successfully, formId: ${formId}`); + await storage.flush(); + } catch (err) { + Logger.error(`failed to updateForm, err: ${JSON.stringify(err)}`); + } +} + + +async function deleteFormInfo(formId: string) { + try { + const storage = await dataStorage.getStorage(DATA_STORAGE_PATH); + // del form info + await storage.delete(formId); + Logger.info(`deleteFormInfo, del form info successfully, formId: ${formId}`); + await storage.flush(); + } catch (err) { + Logger.error(`failed to deleteFormInfo, err: ${JSON.stringify(err)}`); + } +} + + +export default { + onCreate(want) { + Logger.info(`FormAbility onCreate, want: ${JSON.stringify(want)}`); + + // get form info + let formId = want.parameters[FORM_PARAM_IDENTITY_KEY]; + let formName = want.parameters[FORM_PARAM_NAME_KEY]; + let tempFlag = want.parameters[FORM_PARAM_TEMPORARY_KEY]; + storeFormInfo(formId, formName, tempFlag); + + let obj = { + "temperature": getTemperature(formId, 0).toString(), + "time": getTime() + }; + let formData = formBindingData.createFormBindingData(obj); + return formData; + }, + + onCastToNormal(formId) { + Logger.info(`FormAbility onCastToNormal, formId: ${formId}`); + updateTempFormInfo(formId); + }, + + onUpdate(formId) { + Logger.info(`FormAbility onUpdate, formId: ${formId}`); + updateForm(formId); + }, + + onVisibilityChange(newStatus) { + Logger.info(`FormAbility onVisibilityChange`); + }, + + onEvent(formId, message) { + Logger.info(`FormAbility onEvent, formId = ${formId}, message: ${JSON.stringify(message)}`); + + let jsonParams = JSON.parse(message) + let eventName = jsonParams.params.name + + switch(eventName){ + case "onUpdateEvent" : + Logger.info("onUpdateEvent start ") + updateTempFormInfo(formId) + break; + case "openRefresh" : + Logger.info("openRefresh started ") + + let count = 1 + timer = setInterval(()=>{ + Logger.info("231--- count : " + count++) + updateTempFormInfo(formId) + },1000) + Logger.info("openRefresh end timer : " + timer) + break; + case "closeRefresh" : + Logger.info("closeRefresh started : " + timer) + clearInterval(timer) + Logger.info("closeRefresh end timer : " + timer) + break; + default : + Logger.info("(onEvent) formId :" + formId + " message : " + message ) + break; + } + }, + + onDestroy(formId) { + Logger.info(`FormAbility onDestroy, formId = ${formId}`); + deleteFormInfo(formId); + // clearTimeout(timeout) + }, + + onAcquireFormState(want) { + Logger.info(`FormAbility onAcquireFormState`); + return formInfo.FormState.READY; + } +}; diff --git a/FormDemoFA/entry/src/main/ets/Logger.ts b/FormDemoFA/entry/src/main/ets/Logger.ts new file mode 100644 index 0000000000000000000000000000000000000000..b021c0af047f0ffa05d57946802a99f556c79280 --- /dev/null +++ b/FormDemoFA/entry/src/main/ets/Logger.ts @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import hilog from '@ohos.hilog'; + +const LOGTAG : string = "DON_TALK" + +class Logger { + constructor() {} + + public info(...args: any[]) { + hilog.info(0x0000,LOGTAG,' %s',args.join('')) + } + + public debug(...args: any[]) { + hilog.debug(0x0000,LOGTAG,' %s',args.join('')) + + } + + public warn(...args: any[]) { + hilog.warn(0x0000,LOGTAG,' %s',args.join('')) + } + + public error(...args: any[]) { + hilog.error(0x0000,LOGTAG,' %s',args.join('')) + } +} + +export default new Logger() diff --git a/FormDemoFA/entry/src/main/ets/MainAbility/app.ets b/FormDemoFA/entry/src/main/ets/MainAbility/app.ets new file mode 100644 index 0000000000000000000000000000000000000000..b7a0995c8e441cac86e21e06e7c9071664482b1c --- /dev/null +++ b/FormDemoFA/entry/src/main/ets/MainAbility/app.ets @@ -0,0 +1,8 @@ +export default { + onCreate() { + console.info('Application onCreate') + }, + onDestroy() { + console.info('Application onDestroy') + }, +} \ No newline at end of file diff --git a/FormDemoFA/entry/src/main/ets/MainAbility/pages/index.ets b/FormDemoFA/entry/src/main/ets/MainAbility/pages/index.ets new file mode 100644 index 0000000000000000000000000000000000000000..d6ca48cf43988cd6f270a026f0c1a88b7bc57123 --- /dev/null +++ b/FormDemoFA/entry/src/main/ets/MainAbility/pages/index.ets @@ -0,0 +1,17 @@ +@Entry +@Component +struct Index { + @State message: string = 'Hello World' + + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + } + .width('100%') + } + .height('100%') + } +} \ No newline at end of file diff --git a/FormDemoFA/entry/src/main/js/widget/common/landscape.jpg b/FormDemoFA/entry/src/main/js/widget/common/landscape.jpg new file mode 100644 index 0000000000000000000000000000000000000000..83f49c412599045c3a66d257004bffe4f26ae7be Binary files /dev/null and b/FormDemoFA/entry/src/main/js/widget/common/landscape.jpg differ diff --git a/FormDemoFA/entry/src/main/js/widget/i18n/en-US.json b/FormDemoFA/entry/src/main/js/widget/i18n/en-US.json new file mode 100644 index 0000000000000000000000000000000000000000..87bf765ee25396f182973db4f75f726b33097cd4 --- /dev/null +++ b/FormDemoFA/entry/src/main/js/widget/i18n/en-US.json @@ -0,0 +1,7 @@ +{ + "strings": { + "temperature": "Current Temperature: ", + "time": "Last Update Time: " + } +} + diff --git a/FormDemoFA/entry/src/main/js/widget/i18n/zh-CN.json b/FormDemoFA/entry/src/main/js/widget/i18n/zh-CN.json new file mode 100644 index 0000000000000000000000000000000000000000..063384f02736cd95aa8a0acb1d7a7e336e779a85 --- /dev/null +++ b/FormDemoFA/entry/src/main/js/widget/i18n/zh-CN.json @@ -0,0 +1,6 @@ +{ + "strings": { + "temperature": "当前温度: ", + "time": "更新时间: " + } +} \ No newline at end of file diff --git a/FormDemoFA/entry/src/main/js/widget/pages/index/index.css b/FormDemoFA/entry/src/main/js/widget/pages/index/index.css new file mode 100644 index 0000000000000000000000000000000000000000..93804e81d4266b9df11b0524be7f9c3c9199371f --- /dev/null +++ b/FormDemoFA/entry/src/main/js/widget/pages/index/index.css @@ -0,0 +1,44 @@ +.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; + width: 100%; + height: 100%; + padding: 12px; + background-size: cover; + background-image: url("/common/landscape.jpg"); +} + +.title { + font-size: 17fp; + font-weight: bold; + color: black; + text-overflow: ellipsis; + max-lines: 1; + margin-bottom: 10%; +} + +.button{ + margin-bottom: 10%; + margin-top: 10%; +} + +.detail_text { + font-size: 16px; + color: white; + opacity: 0.66; + text-overflow: ellipsis; + max-lines: 1; + margin-top: 10%; +} \ No newline at end of file diff --git a/FormDemoFA/entry/src/main/js/widget/pages/index/index.hml b/FormDemoFA/entry/src/main/js/widget/pages/index/index.hml new file mode 100644 index 0000000000000000000000000000000000000000..0d9d1ba0f23e7af049861146cd57d6afd34eab10 --- /dev/null +++ b/FormDemoFA/entry/src/main/js/widget/pages/index/index.hml @@ -0,0 +1,12 @@ +
+ +
+ {{ $t('strings.temperature') }}{{temperature}} ℃ + {{ $t('strings.time') }} {{time}} + + + + +
+
+
\ No newline at end of file diff --git a/FormDemoFA/entry/src/main/js/widget/pages/index/index.json b/FormDemoFA/entry/src/main/js/widget/pages/index/index.json new file mode 100644 index 0000000000000000000000000000000000000000..8a39dbba17a2c39cedc6543f2cc83b14a583ddf1 --- /dev/null +++ b/FormDemoFA/entry/src/main/js/widget/pages/index/index.json @@ -0,0 +1,42 @@ +{ + "data": { + "temperature": "0", + "time": "00:00:00" + }, + "actions": { + "routerPage": { + "action": "router", + "abilityName": "ohos.samples.FormApplication.MainAbility", + "params": { + "message": "add detail" + } + }, + "routerPageOne": { + "action" : "router", + "bundleName" : "com.test.fts", + "abilityName": "MainAbility", + "params" : { + "message": "add detail" + } + }, + "onUpdateEvent": { + "action": "message", + "params": { + "name" : "onUpdateEvent", + "message": "add detail" + } + }, + "openRefresh": { + "action": "message", + "params": { + "name" : "openRefresh" + } + }, + "closeRefresh": { + "action": "message", + "params": { + "name" : "closeRefresh" + } + } + } +} \ No newline at end of file diff --git a/FormDemoFA/entry/src/main/resources/base/element/string.json b/FormDemoFA/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..ec1c10409aa7f0005cb71427316a4b6b055b5076 --- /dev/null +++ b/FormDemoFA/entry/src/main/resources/base/element/string.json @@ -0,0 +1,24 @@ +{ + "string": [ + { + "name": "entry_desc", + "value": "description" + }, + { + "name": "MainAbility_desc", + "value": "description" + }, + { + "name": "MainAbility_label", + "value": "FormFA" + }, + { + "name": "form_FormAbility_desc", + "value": "form_description" + }, + { + "name": "form_FormAbility_label", + "value": "form_label" + } + ] +} \ No newline at end of file diff --git a/FormDemoFA/entry/src/main/resources/base/media/icon.png b/FormDemoFA/entry/src/main/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/FormDemoFA/entry/src/main/resources/base/media/icon.png differ diff --git a/FormDemoFA/entry/src/ohosTest/config.json b/FormDemoFA/entry/src/ohosTest/config.json new file mode 100644 index 0000000000000000000000000000000000000000..f658e8f77c9d7b480201e5ac656aed7ecbda7412 --- /dev/null +++ b/FormDemoFA/entry/src/ohosTest/config.json @@ -0,0 +1,68 @@ +{ + "app": { + "bundleName": "ohos.test.formfa", + "vendor": "example", + "version": { + "code": 1000000, + "name": "1.0.0" + } + }, + "deviceConfig": {}, + "module": { + "package": "com.example.entry_test", + "name": ".entry_test", + "mainAbility": ".TestAbility", + "srcPath": "", + "deviceType": [ + "phone", + "tablet" + ], + "distro": { + "deliveryWithInstall": true, + "moduleName": "entry_test", + "moduleType": "feature", + "installationFree": false + }, + "abilities": [ + { + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ], + "orientation": "unspecified", + "visible": true, + "srcPath": "TestAbility", + "name": ".TestAbility", + "srcLanguage": "ets", + "icon": "$media:icon", + "description": "$string:description_TestAbility", + "formsEnabled": false, + "label": "$string:entry_TestAbility", + "type": "page", + "launchType": "standard" + } + ], + "js": [ + { + "mode": { + "syntax": "ets", + "type": "pageAbility" + }, + "pages": [ + "pages/index" + ], + "name": ".TestAbility", + "window": { + "designWidth": 720, + "autoDesignWidth": false + } + } + ] + } +} \ No newline at end of file diff --git a/FormDemoFA/entry/src/ohosTest/ets/TestAbility/app.ets b/FormDemoFA/entry/src/ohosTest/ets/TestAbility/app.ets new file mode 100644 index 0000000000000000000000000000000000000000..4db82cf120fbec47c43b3086571011383464e10a --- /dev/null +++ b/FormDemoFA/entry/src/ohosTest/ets/TestAbility/app.ets @@ -0,0 +1,18 @@ +import AbilityDelegatorRegistry from '@ohos.application.abilityDelegatorRegistry' +import { Hypium } from 'hypium/index' +import testsuite from '../test/List.test' + +export default { + onCreate() { + console.info('Application onCreate') + var abilityDelegator: any + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() + var abilityDelegatorArguments: any + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments() + console.info('start run testcase!!!') + Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite) + }, + onDestroy() { + console.info('Application onDestroy') + }, +} \ No newline at end of file diff --git a/FormDemoFA/entry/src/ohosTest/ets/TestAbility/pages/index.ets b/FormDemoFA/entry/src/ohosTest/ets/TestAbility/pages/index.ets new file mode 100644 index 0000000000000000000000000000000000000000..539eb9ae7b7cb0870b26b1a69d20fb977b55291d --- /dev/null +++ b/FormDemoFA/entry/src/ohosTest/ets/TestAbility/pages/index.ets @@ -0,0 +1,35 @@ +import router from '@system.router'; + +@Entry +@Component +struct Index { + aboutToAppear() { + console.info('TestAbility index aboutToAppear') + } + + @State message: string = 'Hello World' + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + Button() { + Text('next page') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .width('35%') + .height('5%') + .onClick(()=>{ + }) + } + .width('100%') + } + .height('100%') + } + } \ No newline at end of file diff --git a/FormDemoFA/entry/src/ohosTest/ets/TestRunner/OpenHarmonyTestRunner.ts b/FormDemoFA/entry/src/ohosTest/ets/TestRunner/OpenHarmonyTestRunner.ts new file mode 100644 index 0000000000000000000000000000000000000000..ed3ba0df1ea2e0e53c5dfe5065292f2e657a3b5c --- /dev/null +++ b/FormDemoFA/entry/src/ohosTest/ets/TestRunner/OpenHarmonyTestRunner.ts @@ -0,0 +1,63 @@ +import TestRunner from '@ohos.application.testRunner' +import AbilityDelegatorRegistry from '@ohos.application.abilityDelegatorRegistry' + +var abilityDelegator = undefined +var abilityDelegatorArguments = undefined + +function translateParamsToString(parameters) { + const keySet = new Set([ + '-s class', '-s notClass', '-s suite', '-s itName', + '-s level', '-s testType', '-s size', '-s timeout', + '-s package' + ]) + let targetParams = ''; + for (const key in parameters) { + if (keySet.has(key)) { + targetParams += ' ' + key + ' ' + parameters[key] + } + } + return targetParams.trim() +} + +async function onAbilityCreateCallback() { + console.log('onAbilityCreateCallback'); +} + +async function addAbilityMonitorCallback(err: any) { + console.info('addAbilityMonitorCallback : ' + JSON.stringify(err)) +} + +export default class OpenHarmonyTestRunner implements TestRunner { + constructor() { + } + + onPrepare() { + console.info('OpenHarmonyTestRunner OnPrepare') + } + + onRun() { + console.log('OpenHarmonyTestRunner onRun run') + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments() + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() + + let lMonitor = { + abilityName: testAbilityName, + onAbilityCreate: onAbilityCreateCallback, + }; + var testAbilityName = abilityDelegatorArguments.parameters['-p'] + '.TestAbility' + abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback) + var cmd = 'aa start -d 0 -a ' + testAbilityName + ' -b ' + abilityDelegatorArguments.bundleName + cmd += ' '+translateParamsToString(abilityDelegatorArguments.parameters) + console.info('cmd : '+cmd) + abilityDelegator.executeShellCommand(cmd, + (err: any, d: any) => { + console.info('executeShellCommand : err : ' + JSON.stringify(err)); + console.info('executeShellCommand : data : ' + d.stdResult); + console.info('executeShellCommand : data : ' + d.exitCode); + }) + console.info('OpenHarmonyTestRunner onRun call abilityDelegator.getAppContext') + var context = abilityDelegator.getAppContext() + console.info('getAppContext : ' + JSON.stringify(context)) + console.info('OpenHarmonyTestRunner onRun end') + } +}; \ No newline at end of file diff --git a/FormDemoFA/entry/src/ohosTest/ets/test/Ability.test.ets b/FormDemoFA/entry/src/ohosTest/ets/test/Ability.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..1236e0ce6077de4c6a4dbc22c79b1298173c07ac --- /dev/null +++ b/FormDemoFA/entry/src/ohosTest/ets/test/Ability.test.ets @@ -0,0 +1,13 @@ +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'hypium/index' + +export default function abilityTest() { + describe('ActsAbilityTest', function () { + it('assertContain',0, function () { + console.info("it begin") + let a = 'abc' + let b = 'b' + expect(a).assertContain(b) + expect(a).assertEqual(a) + }) + }) +} \ No newline at end of file diff --git a/FormDemoFA/entry/src/ohosTest/ets/test/List.test.ets b/FormDemoFA/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..d766fe249dfc3ada636f27e64d9b64451ce32c93 --- /dev/null +++ b/FormDemoFA/entry/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,5 @@ +import abilityTest from './Ability.test' + +export default function testsuite() { + abilityTest() +} \ No newline at end of file diff --git a/FormDemoFA/entry/src/ohosTest/resources/base/element/string.json b/FormDemoFA/entry/src/ohosTest/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..a0901cfced5abc1cb836b55896884b769adc7175 --- /dev/null +++ b/FormDemoFA/entry/src/ohosTest/resources/base/element/string.json @@ -0,0 +1,12 @@ +{ + "string": [ + { + "name": "description_TestAbility", + "value": "eTS_Empty Ability" + }, + { + "name": "entry_TestAbility", + "value": "entry_TestAbility" + } + ] +} \ No newline at end of file diff --git a/FormDemoFA/entry/src/ohosTest/resources/base/media/icon.png b/FormDemoFA/entry/src/ohosTest/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/FormDemoFA/entry/src/ohosTest/resources/base/media/icon.png differ diff --git a/FormDemoFA/hvigorfile.js b/FormDemoFA/hvigorfile.js new file mode 100644 index 0000000000000000000000000000000000000000..cff9f0dfcf8cb00cca34e7f50d61380cf5496868 --- /dev/null +++ b/FormDemoFA/hvigorfile.js @@ -0,0 +1,2 @@ +// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently. +module.exports = require('@ohos/hvigor-ohos-plugin').legacyAppTasks \ No newline at end of file diff --git a/FormDemoFA/package.json b/FormDemoFA/package.json new file mode 100644 index 0000000000000000000000000000000000000000..e1c9cd96e317e4e2ff887e39b1fc966a6b50df62 --- /dev/null +++ b/FormDemoFA/package.json @@ -0,0 +1,18 @@ +{ + "license":"ISC", + "devDependencies":{}, + "name":"formfa", + "ohos":{ + "org":"huawei", + "directoryLevel":"project", + "buildTool":"hvigor" + }, + "description":"example description", + "repository":{}, + "version":"1.0.0", + "dependencies":{ + "@ohos/hvigor-ohos-plugin":"1.0.6", + "hypium":"^1.0.0", + "@ohos/hvigor":"1.0.6" + } +} \ No newline at end of file diff --git a/README.md b/README.md index a4bcfd896c399f17c5b25fa0059d903d888176d4..51820e9c6183cae45ed9293a816667a1d234f9ad 100644 --- a/README.md +++ b/README.md @@ -4,14 +4,20 @@ 本仓主要存放OpenHarmony卡片相关文档、示例代码,旨在为开发者提供更好的卡片开发入门环境。 ## 目录 -├── [FormExtAbility](./FormExtAbility)                             #Stage模型下的卡片开发示例代码 +├── [FormDemoFA](./FormDemoFA)                              #FA模型下的卡片开发示例代码 +├── [FormExtAbility](./FormExtAbility)                             #Stage模型下的卡片开发示例代码 +├── [FA模型中卡片的基本用法](./FA模型中卡片的基本用法.md) ├── [Stage模型中卡片的基本用法](./Stage模型中卡片的基本用法.md) ## 说明 +### FormDemoFA +该示例代码实现了FA模型下卡片的基本功能:页面跳转、手动刷新数据、定时刷新数据功能。 +将该应用安装到设备上,在设备桌面长按该应用图标,弹出卡片管理,点击卡片管理进入卡片选择页面。 + ### FormExtAbility -该示例代码实现了卡片的基本功能:页面跳转、手动刷新数据、定时刷新数据功能。 +该示例代码实现了Stage模型下卡片的基本功能:页面跳转、手动刷新数据、定时刷新数据功能。 将该应用安装到设备上,在设备桌面长按该应用图标,弹出卡片管理,点击卡片管理进入卡片选择页面。 diff --git "a/Stage\346\250\241\345\236\213\344\270\255\345\215\241\347\211\207\347\232\204\345\237\272\346\234\254\347\224\250\346\263\225.md" "b/Stage\346\250\241\345\236\213\344\270\255\345\215\241\347\211\207\347\232\204\345\237\272\346\234\254\347\224\250\346\263\225.md" index d523c31b9ab66f631b765d66be1a01e2549a069c..01901d37055d0feeb83a9cf2a3e59bd8cddfa258 100644 --- "a/Stage\346\250\241\345\236\213\344\270\255\345\215\241\347\211\207\347\232\204\345\237\272\346\234\254\347\224\250\346\263\225.md" +++ "b/Stage\346\250\241\345\236\213\344\270\255\345\215\241\347\211\207\347\232\204\345\237\272\346\234\254\347\224\250\346\263\225.md" @@ -500,46 +500,3 @@ async function storeFormInfo(formId: string, formName: string, tempFlag: boolean } } ``` - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -