init
这个提交包含在:
当前提交
6ef4ef6d27
6
.gitignore
vendored
普通文件
6
.gitignore
vendored
普通文件
@ -0,0 +1,6 @@
|
|||||||
|
/node_modules
|
||||||
|
/oh_modules
|
||||||
|
/.preview
|
||||||
|
/build
|
||||||
|
/.cxx
|
||||||
|
/.test
|
||||||
5
BuildProfile.ets
普通文件
5
BuildProfile.ets
普通文件
@ -0,0 +1,5 @@
|
|||||||
|
export default class BuildProfile {
|
||||||
|
static readonly HAR_VERSION = '1.0.2';
|
||||||
|
static readonly BUILD_MODE_NAME = 'debug';
|
||||||
|
static readonly DEBUG = true;
|
||||||
|
}
|
||||||
9
CHANGELOG.md
普通文件
9
CHANGELOG.md
普通文件
@ -0,0 +1,9 @@
|
|||||||
|
# [v1.0.0] 2024.04.23
|
||||||
|
|
||||||
|
------
|
||||||
|
|
||||||
|
> - 网络请求
|
||||||
|
> - 正则验证
|
||||||
|
> - 基础工具
|
||||||
|
> - 统一弹窗
|
||||||
|
> - 存储管理
|
||||||
40
Index.ets
普通文件
40
Index.ets
普通文件
@ -0,0 +1,40 @@
|
|||||||
|
/**
|
||||||
|
* 常用工具
|
||||||
|
*/
|
||||||
|
export { ToolsHelper } from './src/main/ets/utils/ToolsHelper'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 存储相关
|
||||||
|
*/
|
||||||
|
export { AppStorageHelper } from './src/main/ets/utils/AppStorageHelper'
|
||||||
|
|
||||||
|
export { PreferencesHelper } from './src/main/ets/utils/PreferencesHelper'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 正则相关
|
||||||
|
*/
|
||||||
|
export { ValidatorHelper } from './src/main/ets/utils/ValidatorHelper'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网络请求
|
||||||
|
*/
|
||||||
|
export { HttpHelper } from './src/main/ets/http/HttpHelper'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打开H5页面
|
||||||
|
*/
|
||||||
|
export { XWebHelper } from './src/main/ets/utils/XWebHelper'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 列表选择弹窗
|
||||||
|
*/
|
||||||
|
export { XDialogList } from './src/main/ets/dialog/XDialogList'
|
||||||
|
export { XDialogCommon } from './src/main/ets/dialog/XDialogCommon'
|
||||||
|
|
||||||
|
export { XDialogController } from './src/main/ets/dialog/XDialogController'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 窗口管理
|
||||||
|
*/
|
||||||
|
export { WindowHelper } from './src/main/ets/utils/WindowHelper'
|
||||||
|
|
||||||
15
LICENSE
普通文件
15
LICENSE
普通文件
@ -0,0 +1,15 @@
|
|||||||
|
Mozilla Public License Version 2.0
|
||||||
|
|
||||||
|
1. Definitions
|
||||||
|
2. Scope
|
||||||
|
3. Grant of License
|
||||||
|
4. Restrictions
|
||||||
|
5. Original Code
|
||||||
|
6. Modifications
|
||||||
|
7. Required Notices
|
||||||
|
8. Disclaimer of Warranty
|
||||||
|
9. Limitation of Liability
|
||||||
|
10. Termination
|
||||||
|
11. Jurisdiction
|
||||||
|
12. Miscellaneous
|
||||||
|
|
||||||
229
README.md
普通文件
229
README.md
普通文件
@ -0,0 +1,229 @@
|
|||||||
|
# 基础开发工具包
|
||||||
|
```shell
|
||||||
|
ohpm install @szyx/sdk_base
|
||||||
|
```
|
||||||
|
|
||||||
|
## 1.[utils](./src/main/ets/utils)
|
||||||
|
|
||||||
|
### 1.1.[AppStorageHelper](./src/main/ets/utils/AppStorageHelper.ets)
|
||||||
|
> 缓存工具类,运行时存储,应用停止运行后清空
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { AppStorageHelper } from '@szyx/sdk_base/Index'
|
||||||
|
|
||||||
|
// 存储string数据
|
||||||
|
AppStorageHelper.save(StorageKeys.CLIENT_ID, d)
|
||||||
|
|
||||||
|
// 获取存储的strign数据
|
||||||
|
let d = AppStorageHelper.get(StorageKeys.CLIENT_ID)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1.2.[PreferencesHelper](./src/main/ets/utils/PreferencesHelper.ets)
|
||||||
|
> 永久存储类,应用停止后也不会清空
|
||||||
|
> 需要验证,更新应用会不会被清理
|
||||||
|
> 可存储类型 `number | string | boolean | Array<number> | Array<string> | Array<boolean> | Uint8Array`
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { PreferencesHelper } from '@szyx/sdk_base/Index'
|
||||||
|
// 存储数据
|
||||||
|
PreferencesHelper.put(StorageKeys.CLIENT_ID, value)
|
||||||
|
|
||||||
|
// 获取存储的数据
|
||||||
|
PreferencesHelper.get(StorageKeys.CLIENT_ID).then(res => {
|
||||||
|
console.log('>>>>>', res)
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1.3.[ToolsHelper](./src/main/ets/utils/ToolsHelper.ets)
|
||||||
|
> 常用方法工具栏
|
||||||
|
> 基础方法
|
||||||
|
#### 1.3.1.弹出Toast提示
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { ToolsHelper } from '@szyx/sdk_base';
|
||||||
|
|
||||||
|
ToolsHelper.showMessage('Hello Word!')
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1.4.[ValidatorHelper](./src/main/ets/utils/ValidatorHelper.ets)
|
||||||
|
> 常用正则
|
||||||
|
|
||||||
|
#### 1.4.1.验证手机号
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { ValidatorHelper } from '@szyx/sdk_base';
|
||||||
|
ValidatorHelper.isPhone('13800000000')
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1.5.[XWebHelper](./src/main/ets/utils/XWebHelper.ets)
|
||||||
|
> 打开webview页面
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { XWebHelper } from '@szyx/sdk_base';
|
||||||
|
// 必须先引入,否则无法跳转
|
||||||
|
const XWebview = import('../pages/XWebview');
|
||||||
|
|
||||||
|
XWebHelper.openWeb({
|
||||||
|
url: 'https://www.baidu.com',
|
||||||
|
title: '百度一下',
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## 2.[Dialog](./src/main/ets/dialog)
|
||||||
|
### 2.1.弹出list选中弹窗
|
||||||
|
```typescript
|
||||||
|
import { XDialogController } from '../dialog/XDialogController';
|
||||||
|
import { XDialogList } from '../dialog/XDialogList';
|
||||||
|
|
||||||
|
@Component
|
||||||
|
struct MyView {
|
||||||
|
// 控制器,控制开关
|
||||||
|
dialogController: XDialogController = {} as XDialogController
|
||||||
|
|
||||||
|
build() {
|
||||||
|
Column() {
|
||||||
|
Button({ buttonStyle: ButtonStyleMode.TEXTUAL }) {
|
||||||
|
Image($r('sys.media.ohos_ic_public_more'))
|
||||||
|
.width(26).height(26)
|
||||||
|
}.width(65)
|
||||||
|
.onClick(() => {
|
||||||
|
if (this.dialogController != null) {
|
||||||
|
this.dialogController.open()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
XDialogList({
|
||||||
|
// 控制器
|
||||||
|
controller: this.dialogController,
|
||||||
|
// 标题(可选)
|
||||||
|
title: '选择您的操作',
|
||||||
|
// 选择内容列表
|
||||||
|
values: ['刷新', '浏览器打开', '分享', '复制地址'],
|
||||||
|
// 用户选择事件
|
||||||
|
onSelected: (index: number, value: string) => {
|
||||||
|
ToolsHelper.showMessage(`用户选择了第${index}个,内容为:${value}`)
|
||||||
|
},
|
||||||
|
// 用户取消事件
|
||||||
|
onCancel: () => {
|
||||||
|
ToolsHelper.showMessage('用户取消操作')
|
||||||
|
},
|
||||||
|
// 是否可取消(点击空白处,或者物理返回键)
|
||||||
|
autoCancel: true
|
||||||
|
})
|
||||||
|
|
||||||
|
}.width('100%').height('100%')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
## 3.[网络请求](./src/main/ets/http/HttpHelper.ts)
|
||||||
|
> 使用室建议二次封装
|
||||||
|
>
|
||||||
|
> 参数定义
|
||||||
|
> ```typescript
|
||||||
|
> /**
|
||||||
|
> *
|
||||||
|
> * @param url url地址
|
||||||
|
> * @param data 请求参数
|
||||||
|
> * @param headers 请求头
|
||||||
|
> * @param apiNo 请求标识,取消请求或者去重使用|考虑做自动重试使用
|
||||||
|
> * @returns
|
||||||
|
> */
|
||||||
|
> ```
|
||||||
|
|
||||||
|
### 3.1.get请求
|
||||||
|
```typescript
|
||||||
|
|
||||||
|
HttpHelper.get()
|
||||||
|
.get<HttpResult<T>>(url.url.startsWith('http') ? url.url : GlobalValue.getInstance().envUrl + url.url,
|
||||||
|
data ? JSON.stringify(data) : undefined, {
|
||||||
|
userId: GlobalValue.getInstance().userId,
|
||||||
|
clientId: GlobalValue.getInstance().getClientId(),
|
||||||
|
version: ConstantValue.VERSION,
|
||||||
|
deviceType: '01',
|
||||||
|
timeStamp: timeStamp + '',
|
||||||
|
sign: sign,
|
||||||
|
phoneModel: 'sign',
|
||||||
|
phoneVersion: 'sign',
|
||||||
|
phoneBrand: 'HarmonyOS'
|
||||||
|
}, url.apiNo)
|
||||||
|
.then((res: HttpResult<T>) => {
|
||||||
|
if (res.status === '0') {
|
||||||
|
resolve(res.data as T)
|
||||||
|
} else {
|
||||||
|
reject(new Error(res.message))
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
.catch((error: Error) => {
|
||||||
|
reject(error)
|
||||||
|
})
|
||||||
|
```
|
||||||
|
### 3.2.postJson
|
||||||
|
```typescript
|
||||||
|
|
||||||
|
HttpHelper.get()
|
||||||
|
.post<HttpResult<T>>(url.url.startsWith('http') ? url.url : GlobalValue.getInstance().envUrl + url.url,
|
||||||
|
data ? JSON.stringify(data) : undefined, {
|
||||||
|
userId: GlobalValue.getInstance().userId,
|
||||||
|
clientId: GlobalValue.getInstance().getClientId(),
|
||||||
|
version: ConstantValue.VERSION,
|
||||||
|
deviceType: '01',
|
||||||
|
timeStamp: timeStamp + '',
|
||||||
|
sign: sign,
|
||||||
|
phoneModel: 'sign',
|
||||||
|
phoneVersion: 'sign',
|
||||||
|
phoneBrand: 'HarmonyOS'
|
||||||
|
}, url.apiNo)
|
||||||
|
.then((res: HttpResult<T>) => {
|
||||||
|
if (res.status === '0') {
|
||||||
|
resolve(res.data as T)
|
||||||
|
} else {
|
||||||
|
reject(new Error(res.message))
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
.catch((error: Error) => {
|
||||||
|
reject(error)
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# **** 常见问题
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
211
UTILS.md
普通文件
211
UTILS.md
普通文件
@ -0,0 +1,211 @@
|
|||||||
|
- # [@State装饰器:组件内状态](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-state-0000001774279614)
|
||||||
|
> @State装饰的变量,或称为状态变量,一旦变量拥有了状态属性,就和自定义组件的渲染绑定起来。当状态改变时,UI会发生对应的渲染改变。
|
||||||
|
>
|
||||||
|
> 在状态变量相关装饰器中,@State是最基础的,使变量拥有状态属性的装饰器,它也是大部分状态变量的数据源。
|
||||||
|
|
||||||
|
> @State装饰的变量,与声明式范式中的其他被装饰变量一样,是私有的,只能从组件内部访问,在声明时必须指定其类型和本地初始化。初始化也可选择使用命名参数机制从父组件完成初始化。
|
||||||
|
>
|
||||||
|
> @State装饰的变量拥有以下特点:
|
||||||
|
>
|
||||||
|
> @State装饰的变量与子组件中的@Prop装饰变量之间建立单向数据同步,与@Link、@ObjectLink装饰变量之间建立双向数据同步。
|
||||||
|
>
|
||||||
|
> @State装饰的变量生命周期与其所属自定义组件的生命周期相同。
|
||||||
|
>
|
||||||
|
|
||||||
|
- # [@Prop装饰器:父子单向同步](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-prop-0000001774119942)
|
||||||
|
> @Prop装饰的变量可以和父组件建立单向的同步关系。@Prop装饰的变量是可变的,但是变化不会同步回其父组件。
|
||||||
|
|
||||||
|
>@Prop装饰的变量和父组件建立单向的同步关系:
|
||||||
|
>
|
||||||
|
>@Prop变量允许在本地修改,但修改后的变化不会同步回父组件。
|
||||||
|
>
|
||||||
|
>当数据源更改时,@Prop装饰的变量都会更新,并且会覆盖本地所有更改。因此,数值的同步是父组件到子组件(所属组件),子组件数值的变化不会同步到父组件。
|
||||||
|
>
|
||||||
|
- # [@Link装饰器:父子双向同步](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-link-0000001820999565)
|
||||||
|
|
||||||
|
> 子组件中被@Link装饰的变量与其父组件中对应的数据源建立双向数据绑定。
|
||||||
|
>
|
||||||
|
> @Link装饰的变量与其父组件中的数据源共享相同的值。
|
||||||
|
>
|
||||||
|
> @Link装饰器不能在@Entry装饰的自定义组件中使用。
|
||||||
|
|
||||||
|
- # [@Provide装饰器和@Consume装饰器:与后代组件双向同步](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-provide-and-consume-0000001820879589)
|
||||||
|
|
||||||
|
> @Provide和@Consume,应用于与后代组件的双向数据同步,应用于状态数据在多个层级之间传递的场景。不同于上文提到的父子组件之间通过命名参数机制传递,@Provide和@Consume摆脱参数传递机制的束缚,实现跨层级传递。
|
||||||
|
>
|
||||||
|
> 其中@Provide装饰的变量是在祖先组件中,可以理解为被“提供”给后代的状态变量。@Consume装饰的变量是在后代组件中,去“消费(绑定)”祖先组件提供的变量。
|
||||||
|
|
||||||
|
> @Provide/@Consume装饰的状态变量有以下特性:
|
||||||
|
>
|
||||||
|
> @Provide装饰的状态变量自动对其所有后代组件可用,即该变量被“provide”给他的后代组件。由此可见,@Provide的方便之处在于,开发者不需要多次在组件之间传递变量。
|
||||||
|
>
|
||||||
|
> 后代通过使用@Consume去获取@Provide提供的变量,建立在@Provide和@Consume之间的双向数据同步,与@State/@Link不同的是,前者可以在多层级的父子组件之间传递。
|
||||||
|
>
|
||||||
|
> @Provide和@Consume可以通过相同的变量名或者相同的变量别名绑定,建议类型相同,否则会发生类型隐式转换,从而导致应用行为异常。
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 通过相同的变量名绑定
|
||||||
|
@Provide a: number = 0;
|
||||||
|
@Consume a: number;
|
||||||
|
|
||||||
|
// 通过相同的变量别名绑定
|
||||||
|
@Provide('a') b: number = 0;
|
||||||
|
@Consume('a') c: number;
|
||||||
|
@Provide和@Consume通过相同的变量名或者相同的变量别名绑定时,@Provide装饰的变量和@Consume装饰的变量是一对多的关系。不允许在同一个自定义组件内,包括其子组件中声明多个同名或者同别名的@Provide装饰的变量,@Provide的属性名或别名需要唯一且确定,如果声明多个同名或者同别名的@Provide装饰的变量,会发生运行时报错。
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
- # [@Observed装饰器和@ObjectLink装饰器:嵌套类对象属性变化](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-observed-and-objectlink-0000001774279618)
|
||||||
|
> 上文所述的装饰器仅能观察到第一层的变化,但是在实际应用开发中,应用会根据开发需要,封装自己的数据模型。对于多层嵌套的情况,比如二维数组,或者数组项class,或者class的属性是class,他们的第二层的属性变化是无法观察到的。这就引出了@Observed/@ObjectLink装饰器。
|
||||||
|
|
||||||
|
> @ObjectLink和@Observed类装饰器用于在涉及嵌套对象或数组的场景中进行双向数据同步:
|
||||||
|
>
|
||||||
|
> 被@Observed装饰的类,可以被观察到属性的变化;
|
||||||
|
>
|
||||||
|
> 子组件中@ObjectLink装饰器装饰的状态变量用于接收@Observed装饰的类的实例,和父组件中对应的状态变量建立双向数据绑定。这个实例可以是数组中的被@Observed装饰的项,或者是class object中的属性,这个属性同样也需要被@Observed装饰。
|
||||||
|
>
|
||||||
|
> 单独使用@Observed是没有任何作用的,需要搭配@ObjectLink或者@Prop使用。
|
||||||
|
|
||||||
|
> 使用@Observed装饰class会改变class原始的原型链,@Observed和其他类装饰器装饰同一个class可能会带来问题。
|
||||||
|
>
|
||||||
|
> @ObjectLink装饰器不能在@Entry装饰的自定义组件中使用。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- # [@Watch装饰器:状态变量更改通知](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-watch-0000001774119954)
|
||||||
|
> @Watch应用于对状态变量的监听。如果开发者需要关注某个状态变量的值是否改变,可以使用@Watch为状态变量设置回调函数。
|
||||||
|
|
||||||
|
> @Watch用于监听状态变量的变化,当状态变量变化时,@Watch的回调方法将被调用。@Watch在ArkUI框架内部判断数值有无更新使用的是严格相等(===),遵循严格相等规范。当在严格相等为false的情况下,就会触发@Watch的回调。
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
@Component
|
||||||
|
struct TotalView {
|
||||||
|
@Prop @Watch('onCountUpdated') count: number = 0;
|
||||||
|
@State total: number = 0;
|
||||||
|
// @Watch 回调
|
||||||
|
onCountUpdated(propName: string): void {
|
||||||
|
this.total += this.count;
|
||||||
|
}
|
||||||
|
|
||||||
|
build() {
|
||||||
|
Text(`Total: ${this.total}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entry
|
||||||
|
@Component
|
||||||
|
struct CountModifier {
|
||||||
|
@State count: number = 0;
|
||||||
|
|
||||||
|
build() {
|
||||||
|
Column() {
|
||||||
|
Button('add to basket')
|
||||||
|
.onClick(() => {
|
||||||
|
this.count++
|
||||||
|
})
|
||||||
|
TotalView({ count: this.count })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- # [$$语法:内置组件双向同步](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-two-way-sync-0000001820999577)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// xxx.ets
|
||||||
|
@Entry
|
||||||
|
@Component
|
||||||
|
struct TextInputExample {
|
||||||
|
@State text: string = ''
|
||||||
|
controller: TextInputController = new TextInputController()
|
||||||
|
|
||||||
|
build() {
|
||||||
|
Column({ space: 20 }) {
|
||||||
|
Text(this.text)
|
||||||
|
TextInput({ text: $$this.text, placeholder: 'input your word...', controller: this.controller })
|
||||||
|
.placeholderColor(Color.Grey)
|
||||||
|
.placeholderFont({ size: 14, weight: 400 })
|
||||||
|
.caretColor(Color.Blue)
|
||||||
|
.width(300)
|
||||||
|
}.width('100%').height('100%').justifyContent(FlexAlign.Center)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- # [@Track装饰器:class对象属性级更新](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-track-0000001820879601)
|
||||||
|
|
||||||
|
> @Track应用于class对象的属性级更新。@Track装饰的属性变化时,只会触发该属性关联的UI更新。
|
||||||
|
|
||||||
|
> @Track是class对象的属性装饰器。当一个class对象是状态变量时,@Track装饰的属性发生变化,只会触发该属性关联的UI更新;而未被标记的属性不能在UI中使用。
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
class LogTrack {
|
||||||
|
@Track str1: string;
|
||||||
|
@Track str2: string;
|
||||||
|
|
||||||
|
constructor(str1: string) {
|
||||||
|
this.str1 = str1;
|
||||||
|
this.str2 = 'World';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LogNotTrack {
|
||||||
|
str1: string;
|
||||||
|
str2: string;
|
||||||
|
|
||||||
|
constructor(str1: string) {
|
||||||
|
this.str1 = str1;
|
||||||
|
this.str2 = '世界';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entry
|
||||||
|
@Component
|
||||||
|
struct AddLog {
|
||||||
|
@State logTrack: LogTrack = new LogTrack('Hello');
|
||||||
|
@State logNotTrack: LogNotTrack = new LogNotTrack('你好');
|
||||||
|
|
||||||
|
isRender(index: number) {
|
||||||
|
console.log(`Text ${index} is rendered`);
|
||||||
|
return 50;
|
||||||
|
}
|
||||||
|
|
||||||
|
build() {
|
||||||
|
Row() {
|
||||||
|
Column() {
|
||||||
|
Text(this.logTrack.str1) // UINode1
|
||||||
|
.fontSize(this.isRender(1))
|
||||||
|
.fontWeight(FontWeight.Bold)
|
||||||
|
Text(this.logTrack.str2) // UINode2
|
||||||
|
.fontSize(this.isRender(2))
|
||||||
|
.fontWeight(FontWeight.Bold)
|
||||||
|
Button('change logTrack.str1')
|
||||||
|
.onClick(() => {
|
||||||
|
this.logTrack.str1 = 'Bye';
|
||||||
|
})
|
||||||
|
Text(this.logNotTrack.str1) // UINode3
|
||||||
|
.fontSize(this.isRender(3))
|
||||||
|
.fontWeight(FontWeight.Bold)
|
||||||
|
Text(this.logNotTrack.str2) // UINode4
|
||||||
|
.fontSize(this.isRender(4))
|
||||||
|
.fontWeight(FontWeight.Bold)
|
||||||
|
Button('change logNotTrack.str1')
|
||||||
|
.onClick(() => {
|
||||||
|
this.logNotTrack.str1 = '再见';
|
||||||
|
})
|
||||||
|
}
|
||||||
|
.width('100%')
|
||||||
|
}
|
||||||
|
.height('100%')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
44
build-profile.json5
普通文件
44
build-profile.json5
普通文件
@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"apiType": "stageMode",
|
||||||
|
"buildOption": {
|
||||||
|
},
|
||||||
|
"buildOptionSet": [
|
||||||
|
{
|
||||||
|
"name": "release",
|
||||||
|
"arkOptions": {
|
||||||
|
"obfuscation": {
|
||||||
|
"ruleOptions": {
|
||||||
|
"enable": true,
|
||||||
|
"files": [
|
||||||
|
"./obfuscation-rules.txt"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"consumerFiles": [
|
||||||
|
"./consumer-rules.txt"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "release2",
|
||||||
|
"arkOptions": {
|
||||||
|
"obfuscation": {
|
||||||
|
"ruleOptions": {
|
||||||
|
"enable": true,
|
||||||
|
"files": [
|
||||||
|
"./obfuscation-rules.txt"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"consumerFiles": [
|
||||||
|
"./consumer-rules.txt"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"name": "default"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
0
consumer-rules.txt
普通文件
0
consumer-rules.txt
普通文件
6
hvigorfile.ts
普通文件
6
hvigorfile.ts
普通文件
@ -0,0 +1,6 @@
|
|||||||
|
import { harTasks } from '@ohos/hvigor-ohos-plugin';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
system: harTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
|
||||||
|
plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
|
||||||
|
}
|
||||||
1
obfuscation-rules.txt
普通文件
1
obfuscation-rules.txt
普通文件
@ -0,0 +1 @@
|
|||||||
|
-remove-log
|
||||||
10
oh-package.json5
普通文件
10
oh-package.json5
普通文件
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"name": "@szyx/sdk_base",
|
||||||
|
"version": "1.0.2",
|
||||||
|
"description": "数字医信公司,鸿蒙app开发基础工具。",
|
||||||
|
"main": "Index.ets",
|
||||||
|
"author": "xuqm",
|
||||||
|
"license": "Mozilla-2.0",
|
||||||
|
"repository": "",
|
||||||
|
"dependencies": {}
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
@CustomDialog
|
||||||
|
export struct XDialogCommon {
|
||||||
|
controller: CustomDialogController
|
||||||
|
@BuilderParam dialogContent: () => void
|
||||||
|
|
||||||
|
build() {
|
||||||
|
this.dialogContent()
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
export interface XDialogController {
|
||||||
|
open: () => void
|
||||||
|
close: () => void
|
||||||
|
}
|
||||||
@ -0,0 +1,82 @@
|
|||||||
|
import { XDialogCommon } from './XDialogCommon'
|
||||||
|
import { XDialogController } from './XDialogController'
|
||||||
|
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Component
|
||||||
|
export struct XDialogList {
|
||||||
|
controller: XDialogController | null = null
|
||||||
|
onSelected: (index: number, value: string) => void = (index: number, value: string) => {
|
||||||
|
}
|
||||||
|
onCancel?: () => void = undefined
|
||||||
|
title?: string = undefined
|
||||||
|
values?: Array<string> | Array<object> = undefined
|
||||||
|
autoCancel?: boolean = false
|
||||||
|
private dialogController: CustomDialogController | null = null
|
||||||
|
|
||||||
|
build() {
|
||||||
|
this.buildContent()
|
||||||
|
}
|
||||||
|
|
||||||
|
aboutToAppear(): void {
|
||||||
|
|
||||||
|
this.dialogController = new CustomDialogController({
|
||||||
|
builder: XDialogCommon({
|
||||||
|
dialogContent: () => {
|
||||||
|
this.buildContent()
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
alignment: DialogAlignment.Center,
|
||||||
|
autoCancel: this.autoCancel ?? false,
|
||||||
|
cancel: () => {
|
||||||
|
this.onCancel && this.onCancel()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (this.controller) {
|
||||||
|
this.controller.open = () => {
|
||||||
|
this.dialogController?.open()
|
||||||
|
}
|
||||||
|
this.controller.close = () => {
|
||||||
|
this.dialogController?.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Builder
|
||||||
|
buildContent() {
|
||||||
|
Column() {
|
||||||
|
Text(this.title)
|
||||||
|
.fontSize(13)
|
||||||
|
.textAlign(TextAlign.Center)
|
||||||
|
.width('60%')
|
||||||
|
.maxLines(2)
|
||||||
|
.ellipsisMode(EllipsisMode.END)
|
||||||
|
.textOverflow({
|
||||||
|
overflow: TextOverflow.Ellipsis
|
||||||
|
})
|
||||||
|
.visibility(this.title ? Visibility.Visible : Visibility.None)
|
||||||
|
List({ space: 20, initialIndex: 0 }) {
|
||||||
|
ForEach(this.values ?? [], (item: string, index: number) => {
|
||||||
|
ListItem() {
|
||||||
|
Text(item)
|
||||||
|
.width('100%')
|
||||||
|
.fontSize(16)
|
||||||
|
.textAlign(TextAlign.Center)
|
||||||
|
.onClick(() => {
|
||||||
|
this.onSelected(index, item)
|
||||||
|
this.dialogController?.close()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, (item: string) => item)
|
||||||
|
}
|
||||||
|
.listDirection(Axis.Vertical) // 排列方向
|
||||||
|
.scrollBar(BarState.Off)
|
||||||
|
.friction(0.6)
|
||||||
|
.divider({ strokeWidth: 1, color: 0xEEEEEE, startMargin: 20, endMargin: 20 }) // 每行之间的分界线
|
||||||
|
.edgeEffect(EdgeEffect.Spring) // 边缘效果设置为Spring
|
||||||
|
.width('100%')
|
||||||
|
.height(this.values === undefined ? '20%' : this.values?.length < 8 ? `${this.values?.length / 16 * 100}%` : '50%')
|
||||||
|
.margin({ top: 20 })
|
||||||
|
}.padding({ top: 20, bottom: 20, left: 20, right: 20 })
|
||||||
|
}
|
||||||
|
}
|
||||||
189
src/main/ets/http/HttpHelper.ts
普通文件
189
src/main/ets/http/HttpHelper.ts
普通文件
@ -0,0 +1,189 @@
|
|||||||
|
import { ArrayList, HashMap } from '@kit.ArkTS';
|
||||||
|
import http from '@ohos.net.http';
|
||||||
|
|
||||||
|
|
||||||
|
export class HttpHelper {
|
||||||
|
private static instance: HttpHelper | null = null
|
||||||
|
|
||||||
|
// 单例模式
|
||||||
|
static get() {
|
||||||
|
// 判断系统是否已经有单例了
|
||||||
|
if (HttpHelper.instance === null) {
|
||||||
|
HttpHelper.instance = new HttpHelper()
|
||||||
|
}
|
||||||
|
return HttpHelper.instance
|
||||||
|
}
|
||||||
|
|
||||||
|
//请求中队列
|
||||||
|
private httpHandlerList = new HashMap<string, http.HttpRequest>();
|
||||||
|
// 并发白名单,这个名单里面的api,重复请求不会取消
|
||||||
|
private concurrentList = new ArrayList<string>();
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.httpHandlerList = new HashMap<string, http.HttpRequest>();
|
||||||
|
this.concurrentList.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加并发白名单
|
||||||
|
* @param apiNo
|
||||||
|
*/
|
||||||
|
public addConcurrent(apiNo: string) {
|
||||||
|
if (this.concurrentList.getIndexOf(apiNo) === -1) {
|
||||||
|
this.concurrentList.add(apiNo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public removeConcurrent(apiNo: string) {
|
||||||
|
if (this.concurrentList.getIndexOf(apiNo) !== -1) {
|
||||||
|
this.concurrentList.remove(apiNo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* postJson请求
|
||||||
|
* @param url url地址
|
||||||
|
* @param data 请求参数
|
||||||
|
* @param headers
|
||||||
|
* @param apiNo 请求标识,取消请求或者去重使用|考虑做自动重试使用
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
public post<T>(url: string, data: string | undefined, headers?: Object, apiNo?: string): Promise<T> {
|
||||||
|
|
||||||
|
return new Promise<T>((resolve, reject) => {
|
||||||
|
|
||||||
|
if (this.concurrentList.getIndexOf(apiNo ?? url) === -1 && this.httpHandlerList.hasKey(apiNo ?? url)) {
|
||||||
|
this.httpHandlerList.get(apiNo ?? url).destroy()
|
||||||
|
this.httpHandlerList.remove(apiNo ?? url)
|
||||||
|
}
|
||||||
|
let httpRequest = http.createHttp();
|
||||||
|
|
||||||
|
if (this.concurrentList.getIndexOf(apiNo ?? url) === -1) {
|
||||||
|
this.httpHandlerList.set(apiNo ?? url, httpRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
const header = {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"Accept": "application/json",
|
||||||
|
...headers
|
||||||
|
}
|
||||||
|
console.log('>>>>>', '接口请求', JSON.stringify(header))
|
||||||
|
console.log('>>>>>', '接口请求', data)
|
||||||
|
console.log('>>>>>', '接口请求', url)
|
||||||
|
|
||||||
|
httpRequest.request(url, {
|
||||||
|
method: http.RequestMethod.POST,
|
||||||
|
connectTimeout: 60000,
|
||||||
|
readTimeout: 60000,
|
||||||
|
header: header,
|
||||||
|
extraData: data
|
||||||
|
})
|
||||||
|
.then((data: http.HttpResponse) => {
|
||||||
|
console.info('=====>' + 'Result:' + data.result as string);
|
||||||
|
console.info('=====>' + 'code:' + data.responseCode);
|
||||||
|
// console.info('=====>' + 'type:' + JSON.stringify(data.resultType));
|
||||||
|
// console.info('=====>' + 'header:' + JSON.stringify(data.header));
|
||||||
|
// console.info('=====>' + 'cookies:' + data.cookies); // 自API version 8开始支持cookie
|
||||||
|
// console.info('=====>' + 'header.content-Type:' + JSON.stringify(data.header));
|
||||||
|
// console.info('=====>' + 'header.Status-Line:' + JSON.stringify(data.header));
|
||||||
|
|
||||||
|
if (this.httpHandlerList.hasKey(apiNo ?? url)) {
|
||||||
|
this.httpHandlerList.remove(apiNo ?? url)
|
||||||
|
}
|
||||||
|
if (data.responseCode === 200) {
|
||||||
|
resolve(JSON.parse(data.result as string) as T)
|
||||||
|
} else {
|
||||||
|
reject('服务异常')
|
||||||
|
}
|
||||||
|
}).catch((err: Error) => {
|
||||||
|
if (this.httpHandlerList.hasKey(apiNo ?? url)) {
|
||||||
|
this.httpHandlerList.remove(apiNo ?? url)
|
||||||
|
}
|
||||||
|
if (err.message === 'Failed writing received data to disk/application') {
|
||||||
|
reject('cancel')
|
||||||
|
} else
|
||||||
|
reject(err)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get请求
|
||||||
|
* @param url url地址
|
||||||
|
* @param data 请求参数
|
||||||
|
* @param headers
|
||||||
|
* @param apiNo 请求标识,取消请求或者去重使用|考虑做自动重试使用
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
public get<T>(url: string, data: string | undefined, headers?: Object, apiNo?: string): Promise<T> {
|
||||||
|
|
||||||
|
return new Promise<T>((resolve, reject) => {
|
||||||
|
|
||||||
|
if (this.concurrentList.getIndexOf(apiNo ?? url) === -1 && this.httpHandlerList.hasKey(apiNo ?? url)) {
|
||||||
|
this.httpHandlerList.get(apiNo ?? url).destroy()
|
||||||
|
this.httpHandlerList.remove(apiNo ?? url)
|
||||||
|
}
|
||||||
|
let httpRequest = http.createHttp();
|
||||||
|
|
||||||
|
if (this.concurrentList.getIndexOf(apiNo ?? url) === -1) {
|
||||||
|
this.httpHandlerList.set(apiNo ?? url, httpRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
const header = {
|
||||||
|
// "Content-Type": "application/json",
|
||||||
|
// "Accept": "application/json",
|
||||||
|
...headers
|
||||||
|
}
|
||||||
|
// console.log('>>>>>', '接口请求', JSON.stringify(header))
|
||||||
|
// console.log('>>>>>', '接口请求', data)
|
||||||
|
// console.log('>>>>>', '接口请求', url)
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
url = `${url}?`
|
||||||
|
const json = JSON.parse(data)
|
||||||
|
for (let jsonKey in json) {
|
||||||
|
const value = json[jsonKey]
|
||||||
|
if (value) {
|
||||||
|
url = `${url}${jsonKey}=${json[jsonKey]}&`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
url = url.slice(0, url.length - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
httpRequest.request(url, {
|
||||||
|
method: http.RequestMethod.GET,
|
||||||
|
connectTimeout: 60000,
|
||||||
|
readTimeout: 60000,
|
||||||
|
header: header,
|
||||||
|
})
|
||||||
|
.then((data: http.HttpResponse) => {
|
||||||
|
console.info('=====>' + 'Result:' + data.result as string);
|
||||||
|
console.info('=====>' + 'code:' + data.responseCode);
|
||||||
|
// console.info('=====>' + 'type:' + JSON.stringify(data.resultType));
|
||||||
|
// console.info('=====>' + 'header:' + JSON.stringify(data.header));
|
||||||
|
// console.info('=====>' + 'cookies:' + data.cookies); // 自API version 8开始支持cookie
|
||||||
|
// console.info('=====>' + 'header.content-Type:' + JSON.stringify(data.header));
|
||||||
|
// console.info('=====>' + 'header.Status-Line:' + JSON.stringify(data.header));
|
||||||
|
|
||||||
|
if (this.httpHandlerList.hasKey(apiNo ?? url)) {
|
||||||
|
this.httpHandlerList.remove(apiNo ?? url)
|
||||||
|
}
|
||||||
|
if (data.responseCode === 200) {
|
||||||
|
resolve(JSON.parse(data.result as string) as T)
|
||||||
|
} else {
|
||||||
|
reject('服务异常')
|
||||||
|
}
|
||||||
|
}).catch((err: Error) => {
|
||||||
|
if (this.httpHandlerList.hasKey(apiNo ?? url)) {
|
||||||
|
this.httpHandlerList.remove(apiNo ?? url)
|
||||||
|
}
|
||||||
|
if (err.message === 'Failed writing received data to disk/application') {
|
||||||
|
reject('cancel')
|
||||||
|
} else
|
||||||
|
reject(err)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
233
src/main/ets/pages/XWebview.ets
普通文件
233
src/main/ets/pages/XWebview.ets
普通文件
@ -0,0 +1,233 @@
|
|||||||
|
import web_webview from '@ohos.web.webview';
|
||||||
|
import { router } from '@kit.ArkUI';
|
||||||
|
import { XDialogController } from '../dialog/XDialogController';
|
||||||
|
import { XDialogList } from '../dialog/XDialogList';
|
||||||
|
import { picker } from '@kit.CoreFileKit';
|
||||||
|
import { BusinessError } from '@kit.BasicServicesKit';
|
||||||
|
import { ToolsHelper } from '../utils/ToolsHelper';
|
||||||
|
import { XWebParams } from '../utils/XWebHelper';
|
||||||
|
|
||||||
|
@Entry({ routeName: 'XWebview' })
|
||||||
|
@Preview
|
||||||
|
@Component
|
||||||
|
export struct XWebview {
|
||||||
|
// 手机号
|
||||||
|
@State url: string = (router.getParams() as XWebParams).url
|
||||||
|
@State title?: string = (router.getParams() as XWebParams).title
|
||||||
|
@State errorInfo: string | null = null
|
||||||
|
@State progress: number = 0
|
||||||
|
controller: web_webview.WebviewController = new web_webview.WebviewController();
|
||||||
|
dialogController: XDialogController = {} as XDialogController
|
||||||
|
|
||||||
|
aboutToAppear(): void {
|
||||||
|
}
|
||||||
|
|
||||||
|
aboutToDisappear(): void {
|
||||||
|
}
|
||||||
|
|
||||||
|
onBackPress(): boolean | void {
|
||||||
|
if (this.controller.accessBackward()) {
|
||||||
|
this.controller.backward()
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
build() {
|
||||||
|
Column() {
|
||||||
|
|
||||||
|
Row() {
|
||||||
|
Row() {
|
||||||
|
Button({ buttonStyle: ButtonStyleMode.TEXTUAL }) {
|
||||||
|
Image($r('sys.media.ohos_ic_back'))
|
||||||
|
.width(26).height(26)
|
||||||
|
}.onClick(() => {
|
||||||
|
this.onBackPress()
|
||||||
|
})
|
||||||
|
|
||||||
|
Button({ buttonStyle: ButtonStyleMode.TEXTUAL }) {
|
||||||
|
Image($r('sys.media.ohos_ic_public_close'))
|
||||||
|
.width(26).height(26)
|
||||||
|
}.margin({ left: 12 })
|
||||||
|
.onClick(() => {
|
||||||
|
router.back()
|
||||||
|
})
|
||||||
|
}.width(65)
|
||||||
|
|
||||||
|
Text(this.title)
|
||||||
|
.maxLines(1)
|
||||||
|
.fontColor('#222222')
|
||||||
|
.fontSize(18)
|
||||||
|
.textAlign(TextAlign.Center)
|
||||||
|
.width('50%')
|
||||||
|
.ellipsisMode(EllipsisMode.END)
|
||||||
|
.textOverflow({
|
||||||
|
overflow: TextOverflow.Ellipsis
|
||||||
|
})
|
||||||
|
|
||||||
|
Button({ buttonStyle: ButtonStyleMode.TEXTUAL }) {
|
||||||
|
Image($r('sys.media.ohos_ic_public_more'))
|
||||||
|
.width(26).height(26)
|
||||||
|
}.width(65)
|
||||||
|
.onClick(() => {
|
||||||
|
if (this.dialogController != null) {
|
||||||
|
this.dialogController.open()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
.width('100%')
|
||||||
|
.height(45)
|
||||||
|
.justifyContent(FlexAlign.SpaceBetween)
|
||||||
|
.padding({ left: 15, right: 15 })
|
||||||
|
|
||||||
|
Divider().height(2).color(0xCCCCCC)
|
||||||
|
Progress({ value: this.progress, type: ProgressType.Linear })
|
||||||
|
.visibility(this.progress > 95 || this.progress == 0 ? Visibility.None : Visibility.Visible)
|
||||||
|
.width('100%')
|
||||||
|
|
||||||
|
Web({ src: this.url, controller: this.controller })
|
||||||
|
.width('100%')
|
||||||
|
.height('100%')
|
||||||
|
.visibility(this.errorInfo == null ? Visibility.Visible : Visibility.None)
|
||||||
|
.mixedMode(MixedMode.All)//允许加载HTTP和HTTPS混合内容
|
||||||
|
.zoomAccess(false)//不支持手势进行缩放
|
||||||
|
.mediaPlayGestureAccess(false)//有声视频播放不需要用户手动点击
|
||||||
|
.cacheMode(CacheMode.Default)//设置缓存模式
|
||||||
|
.onConfirm((event) => { // 自定义Confirm弹窗
|
||||||
|
if (event) {
|
||||||
|
console.log("event.url:" + event.url)
|
||||||
|
console.log("event.message:" + event.message)
|
||||||
|
AlertDialog.show({
|
||||||
|
title: '提示',
|
||||||
|
message: event.message,
|
||||||
|
primaryButton: {
|
||||||
|
value: '取消',
|
||||||
|
action: () => {
|
||||||
|
event.result.handleCancel()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
secondaryButton: {
|
||||||
|
value: '确定',
|
||||||
|
action: () => {
|
||||||
|
event.result.handleConfirm()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cancel: () => {
|
||||||
|
event.result.handleCancel()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
.onAlert((event) => { // 自定义Alert弹窗
|
||||||
|
if (event) {
|
||||||
|
console.log("event.url:" + event.url)
|
||||||
|
console.log("event.message:" + event.message)
|
||||||
|
AlertDialog.show({
|
||||||
|
title: '提示',
|
||||||
|
message: event.message,
|
||||||
|
secondaryButton: {
|
||||||
|
value: '确定',
|
||||||
|
action: () => {
|
||||||
|
event.result.handleConfirm()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
.onDownloadStart((event) => { // 下载文件
|
||||||
|
if (event) {
|
||||||
|
console.log('url:' + event.url)
|
||||||
|
console.log('userAgent:' + event.userAgent)
|
||||||
|
console.log('contentDisposition:' + event.contentDisposition)
|
||||||
|
console.log('contentLength:' + event.contentLength)
|
||||||
|
console.log('mimetype:' + event.mimetype)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.onErrorReceive((event) => { // 加载失败
|
||||||
|
if (this.progress > 65) return
|
||||||
|
if (event) {
|
||||||
|
this.errorInfo = `错误码:${event.error.getErrorCode()}\n${event.error.getErrorInfo()}`
|
||||||
|
} else {
|
||||||
|
this.errorInfo = '错误码:-1\n未知错误'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.onHttpErrorReceive((event) => { // 加载失败
|
||||||
|
if (this.progress > 65) return
|
||||||
|
if (event) {
|
||||||
|
this.errorInfo = `错误码:${event.response.getResponseCode()}\n${event.response.getReasonMessage()}`
|
||||||
|
} else {
|
||||||
|
this.errorInfo = '错误码:-1\n未知错误'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.onProgressChange((event) => { // 加载进度
|
||||||
|
if (event) {
|
||||||
|
console.log('newProgress:' + event.newProgress)
|
||||||
|
this.progress = event.newProgress
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.onTitleReceive((event) => {
|
||||||
|
// 如果没有传输title,则从H5获取title赋值
|
||||||
|
if (event && !this.title) {
|
||||||
|
this.title = event.title
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.onShowFileSelector((event) => { // 选择文件
|
||||||
|
console.log('MyFileUploader onShowFileSelector invoked')
|
||||||
|
const documentSelectOptions = new picker.DocumentSelectOptions();
|
||||||
|
let uri: string | null = null;
|
||||||
|
const documentViewPicker = new picker.DocumentViewPicker();
|
||||||
|
documentViewPicker.select(documentSelectOptions).then((documentSelectResult) => {
|
||||||
|
uri = documentSelectResult[0];
|
||||||
|
console.info('documentViewPicker.select to file succeed and uri is:' + uri);
|
||||||
|
if (event) {
|
||||||
|
event.result.handleFileList([uri]);
|
||||||
|
}
|
||||||
|
}).catch((err: BusinessError) => {
|
||||||
|
if (event) {
|
||||||
|
event.result.handleFileList([])
|
||||||
|
}
|
||||||
|
ToolsHelper.showMessage(`Invoke documentViewPicker.select failed, code is ${err.code}, message is ${err.message}`)
|
||||||
|
console.error(`Invoke documentViewPicker.select failed, code is ${err.code}, message is ${err.message}`);
|
||||||
|
})
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
Column() {
|
||||||
|
Text(this.errorInfo)
|
||||||
|
Button('点击重试')
|
||||||
|
.onClick(() => {
|
||||||
|
this.controller.refresh()
|
||||||
|
this.errorInfo = null
|
||||||
|
this.progress = 0
|
||||||
|
})
|
||||||
|
.margin({ top: 30 })
|
||||||
|
}
|
||||||
|
.visibility(this.errorInfo == null ? Visibility.None : Visibility.Visible)
|
||||||
|
.width('100%')
|
||||||
|
.height('100%')
|
||||||
|
.justifyContent(FlexAlign.Center)
|
||||||
|
.padding({ bottom: 80 })
|
||||||
|
|
||||||
|
XDialogList({
|
||||||
|
// 控制器
|
||||||
|
controller: this.dialogController,
|
||||||
|
// 标题(可选)
|
||||||
|
title: '选择您的操作',
|
||||||
|
// 选择内容列表
|
||||||
|
values: ['刷新', '浏览器打开', '分享', '复制地址'],
|
||||||
|
// 用户选择事件
|
||||||
|
onSelected: (index: number, value: string) => {
|
||||||
|
ToolsHelper.showMessage(`用户选择了第${index}个,内容为:${value}`)
|
||||||
|
},
|
||||||
|
// 用户取消事件
|
||||||
|
onCancel: () => {
|
||||||
|
ToolsHelper.showMessage('用户取消操作')
|
||||||
|
},
|
||||||
|
// 是否可取消(点击空白处,或者物理返回键)
|
||||||
|
autoCancel: true
|
||||||
|
})
|
||||||
|
|
||||||
|
}.width('100%').height('100%')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
/**
|
||||||
|
* 永久化存储,存储在本地文件
|
||||||
|
*/
|
||||||
|
export class AppStorageHelper {
|
||||||
|
/**
|
||||||
|
* 缓存string
|
||||||
|
* @param key
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
public static save(key: string, value: string|undefined) {
|
||||||
|
PersistentStorage.persistProp(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取已缓存的string
|
||||||
|
* @param key
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
public static get(key: string):string|undefined {
|
||||||
|
return AppStorage.get<string>(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
import preferences from '@ohos.data.preferences';
|
||||||
|
|
||||||
|
export class PreferencesHelper {
|
||||||
|
public static async put(key: string, value: preferences.ValueType|undefined) {
|
||||||
|
|
||||||
|
const pref = await preferences.getPreferences(getContext(), 'PreferencesHelper')
|
||||||
|
// 写入数据
|
||||||
|
await pref.put(key, value)
|
||||||
|
// 刷盘
|
||||||
|
await pref.flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async get(key: string): Promise<preferences.ValueType> {
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
|
||||||
|
const pref = await preferences.getPreferences(getContext(), 'PreferencesHelper')
|
||||||
|
pref.get(key, undefined).then((r1: preferences.ValueType) => {
|
||||||
|
resolve(r1)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
200
src/main/ets/utils/ToolsHelper.ets
普通文件
200
src/main/ets/utils/ToolsHelper.ets
普通文件
@ -0,0 +1,200 @@
|
|||||||
|
import promptAction from '@ohos.promptAction';
|
||||||
|
import { Resource } from 'GlobalResource';
|
||||||
|
import { BusinessError } from '@kit.BasicServicesKit';
|
||||||
|
import { HashMap } from '@kit.ArkTS';
|
||||||
|
|
||||||
|
export interface Btn {
|
||||||
|
text?: string | Resource;
|
||||||
|
color?: string | Resource;
|
||||||
|
onClick: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AlertOptions {
|
||||||
|
title?: string
|
||||||
|
msg?: string
|
||||||
|
action: Btn
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ConfirmOptions {
|
||||||
|
title?: string
|
||||||
|
msg?: string
|
||||||
|
confirm: Btn
|
||||||
|
cancel: Btn
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ListOptions<T> {
|
||||||
|
title?: string
|
||||||
|
cancel?: Btn
|
||||||
|
values: Array<T>
|
||||||
|
onSelected: (index: number, value: T) => void
|
||||||
|
onError?: (msg: string) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ListItem {
|
||||||
|
content: string
|
||||||
|
}
|
||||||
|
|
||||||
|
@Builder
|
||||||
|
function customDialogBuilder<T>(option: ListOptions<T>, dialogId: number) {
|
||||||
|
|
||||||
|
Column() {
|
||||||
|
Text(option.title)
|
||||||
|
.fontSize(13)
|
||||||
|
.textAlign(TextAlign.Center)
|
||||||
|
.width('60%')
|
||||||
|
.maxLines(2)
|
||||||
|
.ellipsisMode(EllipsisMode.END)
|
||||||
|
.textOverflow({
|
||||||
|
overflow: TextOverflow.Ellipsis
|
||||||
|
})
|
||||||
|
.visibility(option.title ? Visibility.Visible : Visibility.None)
|
||||||
|
List({ space: 20, initialIndex: 0 }) {
|
||||||
|
ForEach(option.values, (item: T, index: number) => {
|
||||||
|
ListItem() {
|
||||||
|
Text(typeof item === "string" ? item : (item as ListItem).content)
|
||||||
|
.width('100%')
|
||||||
|
.fontSize(16)
|
||||||
|
.textAlign(TextAlign.Center)
|
||||||
|
.onClick(() => {
|
||||||
|
if (ToolsHelper.mapDialog.get(dialogId)) {
|
||||||
|
promptAction.closeCustomDialog(ToolsHelper.mapDialog.get(dialogId))
|
||||||
|
ToolsHelper.mapDialog.remove(dialogId)
|
||||||
|
}
|
||||||
|
option.onSelected(index, item)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, (item: string) => item)
|
||||||
|
}
|
||||||
|
.listDirection(Axis.Vertical) // 排列方向
|
||||||
|
.scrollBar(BarState.Off)
|
||||||
|
.friction(0.6)
|
||||||
|
.divider({ strokeWidth: 1, color: 0xEEEEEE, startMargin: 20, endMargin: 20 }) // 每行之间的分界线
|
||||||
|
.edgeEffect(EdgeEffect.Spring) // 边缘效果设置为Spring
|
||||||
|
.width('100%')
|
||||||
|
.height(option.values.length < 8 ? `${option.values.length / 16 * 100}%` : '50%')
|
||||||
|
.margin({ top: 20 })
|
||||||
|
}.padding({ top: 20, bottom: 20, left: 20, right: 20 })
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 常用方法
|
||||||
|
*/
|
||||||
|
export class ToolsHelper {
|
||||||
|
/**
|
||||||
|
* 弹出Toast
|
||||||
|
* @param msg
|
||||||
|
*/
|
||||||
|
static showMessage(msg: string) {
|
||||||
|
console.info(msg);
|
||||||
|
promptAction.showToast({
|
||||||
|
message: msg,
|
||||||
|
duration: 1500
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**kio9
|
||||||
|
* 弹出Alert弹窗
|
||||||
|
* @param options
|
||||||
|
*/
|
||||||
|
static showAlertDialog(options: AlertOptions) {
|
||||||
|
try {
|
||||||
|
promptAction.showDialog({
|
||||||
|
alignment: 1,
|
||||||
|
title: options.title,
|
||||||
|
message: options.msg,
|
||||||
|
buttons: [{
|
||||||
|
text: options.action.text ?? "确定",
|
||||||
|
color: options.action.color ?? "#000000",
|
||||||
|
}]
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
options.action.onClick()
|
||||||
|
})
|
||||||
|
.catch((err: Error) => {
|
||||||
|
ToolsHelper.showMessage(err.message)
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
let message = (error as BusinessError).message
|
||||||
|
ToolsHelper.showMessage(message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 弹出Confirm弹窗
|
||||||
|
* @param options
|
||||||
|
*/
|
||||||
|
static showConfirmDialog(options: ConfirmOptions) {
|
||||||
|
try {
|
||||||
|
promptAction.showDialog({
|
||||||
|
alignment: 1,
|
||||||
|
title: options.title,
|
||||||
|
message: options.msg,
|
||||||
|
buttons: [{
|
||||||
|
text: options.confirm.text ?? "确定",
|
||||||
|
color: options.confirm.color ?? "#000000",
|
||||||
|
}, {
|
||||||
|
text: options.cancel.text ?? "取消",
|
||||||
|
color: options.cancel.color ?? "#666666",
|
||||||
|
}]
|
||||||
|
})
|
||||||
|
.then((data) => {
|
||||||
|
if (data.index === 0) {
|
||||||
|
options.confirm.onClick()
|
||||||
|
} else {
|
||||||
|
options.cancel.onClick()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err: Error) => {
|
||||||
|
ToolsHelper.showMessage(err.message)
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
let message = (error as BusinessError).message
|
||||||
|
ToolsHelper.showMessage(message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static mapDialog = new HashMap<number, number>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 弹出List弹窗
|
||||||
|
* @param options values 如果是非string列表的话,需要存在content字段
|
||||||
|
*/
|
||||||
|
static showListDialog<T = string>(options: ListOptions<T>, p: object) {
|
||||||
|
|
||||||
|
let isSuccess: Array<number> = []
|
||||||
|
options.values.forEach((item, index) => {
|
||||||
|
if (typeof item !== 'string') {
|
||||||
|
if (!(item as ListItem).content) {
|
||||||
|
isSuccess.push(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (isSuccess.length > 0) {
|
||||||
|
options.onError && options.onError(`第(${isSuccess.join("、")})个数据中,没有content字段。`)
|
||||||
|
} else {
|
||||||
|
const dialogTag = new Date().getTime()
|
||||||
|
promptAction.openCustomDialog({
|
||||||
|
alignment: 1,
|
||||||
|
builder: customDialogBuilder.bind(p, options, dialogTag)
|
||||||
|
}).then((dialogId: number) => {
|
||||||
|
ToolsHelper.mapDialog.set(dialogTag, dialogId)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 弹出自定义弹窗
|
||||||
|
* @param alignment 弹窗在竖直方向上的对齐方式
|
||||||
|
*/
|
||||||
|
static showCustomDialog(b: CustomBuilder, alignment?: DialogAlignment) {
|
||||||
|
const dialogTag = new Date().getTime()
|
||||||
|
promptAction.openCustomDialog({
|
||||||
|
alignment: alignment ?? DialogAlignment.Center,
|
||||||
|
builder: b
|
||||||
|
}).then((dialogId: number) => {
|
||||||
|
ToolsHelper.mapDialog.set(dialogTag, dialogId)
|
||||||
|
}).catch((error: Error) => {
|
||||||
|
console.log('>>>>>', JSON.stringify(error))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* 常用正则验证
|
||||||
|
*/
|
||||||
|
export class ValidatorHelper {
|
||||||
|
/**
|
||||||
|
* 是否为手机号
|
||||||
|
* @param phone
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
public static isPhone(phone: string) {
|
||||||
|
let regexp: RegExp = new RegExp('^1[0-9]{10}$');
|
||||||
|
return regexp.test(phone)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,93 @@
|
|||||||
|
import { display, window } from '@kit.ArkUI';
|
||||||
|
import { common } from '@kit.AbilityKit';
|
||||||
|
|
||||||
|
|
||||||
|
export class WindowHelper {
|
||||||
|
/**
|
||||||
|
* 缓存窗体,关闭时需要
|
||||||
|
* 同时只能出现一个窗口,所以只做一个缓存就可以
|
||||||
|
*/
|
||||||
|
private static cacheWindow: window.Window | null = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据参数创建窗口
|
||||||
|
* @param options
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
static async open(options: WinOptions): Promise<void> {
|
||||||
|
if (WindowHelper.cacheWindow) {
|
||||||
|
options.callBack && options.callBack(-1, '窗口已存在')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!options) {
|
||||||
|
options = new WinOptions();
|
||||||
|
}
|
||||||
|
if (!options.name) {
|
||||||
|
options.name = 'window';
|
||||||
|
}
|
||||||
|
if (options.windowType == undefined) {
|
||||||
|
options.windowType = window.WindowType.TYPE_DIALOG;
|
||||||
|
}
|
||||||
|
if (!options.bgColor) {
|
||||||
|
options.bgColor = '#33606266';
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
//创建窗口
|
||||||
|
let windowClass = await window.createWindow({
|
||||||
|
name: options.name,
|
||||||
|
windowType: options.windowType,
|
||||||
|
ctx: getContext() as common.UIAbilityContext
|
||||||
|
});
|
||||||
|
//将窗口缓存
|
||||||
|
WindowHelper.cacheWindow = windowClass;
|
||||||
|
await windowClass.setUIContent(options.router);
|
||||||
|
//获取屏幕四大角
|
||||||
|
let d = display.getDefaultDisplaySync();
|
||||||
|
//设置窗口大小
|
||||||
|
await windowClass.resize(d.width, d.height);
|
||||||
|
// 设置窗口背景颜色
|
||||||
|
windowClass.setWindowBackgroundColor(options.bgColor);
|
||||||
|
//显示窗口
|
||||||
|
await windowClass.showWindow();
|
||||||
|
} catch (exception) {
|
||||||
|
options.callBack && options.callBack(-1, '创建窗口失败,原因为:' + JSON.stringify(exception))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭窗口
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
static async close(): Promise<void> {
|
||||||
|
if (WindowHelper.cacheWindow) {
|
||||||
|
await WindowHelper.cacheWindow.destroyWindow();
|
||||||
|
WindowHelper.cacheWindow = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 窗口入参对象
|
||||||
|
*/
|
||||||
|
class WinOptions {
|
||||||
|
/**
|
||||||
|
* 窗口名称 默认window
|
||||||
|
*/
|
||||||
|
name?: string;
|
||||||
|
/**
|
||||||
|
* 窗口类型 默认TYPE_DIALOG
|
||||||
|
*/
|
||||||
|
windowType?: window.WindowType;
|
||||||
|
/**
|
||||||
|
*窗口要显示的路由 如:pages/Welcome需要在main_pages.json中声明
|
||||||
|
*/
|
||||||
|
router: string = '';
|
||||||
|
/**
|
||||||
|
* 窗口背景颜色,默认#33606266
|
||||||
|
*/
|
||||||
|
bgColor?: string;
|
||||||
|
/**
|
||||||
|
* 窗口创建回调函数
|
||||||
|
*/
|
||||||
|
callBack?: (code: number, msg: string) => void;
|
||||||
|
}
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
import { router } from '@kit.ArkUI';
|
||||||
|
import { BusinessError } from '@kit.BasicServicesKit';
|
||||||
|
import { ToolsHelper } from './ToolsHelper';
|
||||||
|
|
||||||
|
const XWebview = import('../pages/XWebview');
|
||||||
|
|
||||||
|
|
||||||
|
export interface XWebParams {
|
||||||
|
url: string
|
||||||
|
title?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export class XWebHelper {
|
||||||
|
/**
|
||||||
|
* 打开web页面,加载h5
|
||||||
|
* @param params
|
||||||
|
*/
|
||||||
|
public static openWeb(params: XWebParams) {
|
||||||
|
|
||||||
|
router.pushNamedRoute({
|
||||||
|
name: 'XWebview',
|
||||||
|
params: params
|
||||||
|
}, router.RouterMode.Single).then(() => {
|
||||||
|
console.info('Succeeded in jumping to the XWebview page.')
|
||||||
|
|
||||||
|
}).catch((err: BusinessError) => {
|
||||||
|
console.error(`Failed to jump to the second page.Code is ${err.code}, message is ${err.message}`)
|
||||||
|
ToolsHelper.showMessage(`Failed to jump to the second page.Code is ${err.code}, message is ${err.message}`)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
11
src/main/module.json5
普通文件
11
src/main/module.json5
普通文件
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"module": {
|
||||||
|
"name": "basic",
|
||||||
|
"type": "har",
|
||||||
|
"deviceTypes": [
|
||||||
|
"default",
|
||||||
|
"tablet",
|
||||||
|
"2in1"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"string": [
|
||||||
|
{
|
||||||
|
"name": "page_show",
|
||||||
|
"value": "page from package"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "permission_internet",
|
||||||
|
"value": "需要使用网络权限连接网络"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "permission_device",
|
||||||
|
"value": "需要获取设备唯一码"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
二进制文件未显示。
|
之后 宽度: | 高度: | 大小: 922 B |
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"string": [
|
||||||
|
{
|
||||||
|
"name": "page_show",
|
||||||
|
"value": "page from package"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "permission_internet",
|
||||||
|
"value": "需要使用网络权限连接网络"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "permission_device",
|
||||||
|
"value": "需要获取设备唯一码"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"string": [
|
||||||
|
{
|
||||||
|
"name": "page_show",
|
||||||
|
"value": "page from package"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "permission_internet",
|
||||||
|
"value": "需要使用网络权限连接网络"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "permission_device",
|
||||||
|
"value": "需要获取设备唯一码"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
5
src/test/List.test.ets
普通文件
5
src/test/List.test.ets
普通文件
@ -0,0 +1,5 @@
|
|||||||
|
import localUnitTest from './LocalUnit.test';
|
||||||
|
|
||||||
|
export default function testsuite() {
|
||||||
|
localUnitTest();
|
||||||
|
}
|
||||||
33
src/test/LocalUnit.test.ets
普通文件
33
src/test/LocalUnit.test.ets
普通文件
@ -0,0 +1,33 @@
|
|||||||
|
import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium';
|
||||||
|
|
||||||
|
export default function localUnitTest() {
|
||||||
|
describe('localUnitTest',() => {
|
||||||
|
// Defines a test suite. Two parameters are supported: test suite name and test suite function.
|
||||||
|
beforeAll(() => {
|
||||||
|
// Presets an action, which is performed only once before all test cases of the test suite start.
|
||||||
|
// This API supports only one parameter: preset action function.
|
||||||
|
});
|
||||||
|
beforeEach(() => {
|
||||||
|
// Presets an action, which is performed before each unit test case starts.
|
||||||
|
// The number of execution times is the same as the number of test cases defined by **it**.
|
||||||
|
// This API supports only one parameter: preset action function.
|
||||||
|
});
|
||||||
|
afterEach(() => {
|
||||||
|
// Presets a clear action, which is performed after each unit test case ends.
|
||||||
|
// The number of execution times is the same as the number of test cases defined by **it**.
|
||||||
|
// This API supports only one parameter: clear action function.
|
||||||
|
});
|
||||||
|
afterAll(() => {
|
||||||
|
// Presets a clear action, which is performed after all test cases of the test suite end.
|
||||||
|
// This API supports only one parameter: clear action function.
|
||||||
|
});
|
||||||
|
it('assertContain', 0, () => {
|
||||||
|
// Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
|
||||||
|
let a = 'abc';
|
||||||
|
let b = 'b';
|
||||||
|
// Defines a variety of assertion methods, which are used to declare expected boolean conditions.
|
||||||
|
expect(a).assertContain(b);
|
||||||
|
expect(a).assertEqual(a);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
正在加载...
在新工单中引用
屏蔽一个用户