@@ -0,0 +1,11 @@ | |||
/node_modules | |||
/oh_modules | |||
/local.properties | |||
/.idea | |||
**/build | |||
/.hvigor | |||
.cxx | |||
/.clangd | |||
/.clang-format | |||
/.clang-tidy | |||
**/.test |
@@ -0,0 +1,14 @@ | |||
{ | |||
"app": { | |||
"bundleName": "com.xuqinmin.hw.demo", | |||
// 开发商信息 | |||
"vendor": "徐勤民", | |||
"versionCode": 1, | |||
"versionName": "1.0.0", | |||
// 应用能够兼容的最低历史版本号 | |||
"minCompatibleVersionCode": 1, | |||
"icon": "$media:app_icon", | |||
"label": "$string:app_name", | |||
"description": "鸿蒙示例,各组件积累。" | |||
} | |||
} |
@@ -0,0 +1,8 @@ | |||
{ | |||
"string": [ | |||
{ | |||
"name": "app_name", | |||
"value": "鸿蒙示例" | |||
} | |||
] | |||
} |
@@ -0,0 +1,5 @@ | |||
# 问题记录 | |||
> Q: 预览失败,无报错信息,或者报错信息指定的位置,没有问题 | |||
> | |||
> A: 预览页面所在model下,查找 `.preview`文件夹,删除 |
@@ -0,0 +1,44 @@ | |||
{ | |||
"app": { | |||
"signingConfigs": [], | |||
"products": [ | |||
{ | |||
"name": "default", | |||
"signingConfig": "default", | |||
"compileSdkVersion": "4.1.0(11)", | |||
"compatibleSdkVersion": "4.1.0(11)", | |||
"runtimeOS": "HarmonyOS", | |||
} | |||
], | |||
"buildModeSet": [ | |||
{ | |||
"name": "debug", | |||
}, | |||
{ | |||
"name": "release" | |||
} | |||
] | |||
}, | |||
"modules": [ | |||
{ | |||
"name": "entry", | |||
"srcPath": "./entry", | |||
"targets": [ | |||
{ | |||
"name": "default", | |||
"applyToProducts": [ | |||
"default" | |||
] | |||
} | |||
] | |||
}, | |||
{ | |||
"name": "basic", | |||
"srcPath": "./basic" | |||
}, | |||
{ | |||
"name": "sdk_ywx", | |||
"srcPath": "./sdk_ywx" | |||
} | |||
] | |||
} |
@@ -0,0 +1,6 @@ | |||
/node_modules | |||
/oh_modules | |||
/.preview | |||
/build | |||
/.cxx | |||
/.test |
@@ -0,0 +1,28 @@ | |||
{ | |||
"apiType": "stageMode", | |||
"buildOption": { | |||
}, | |||
"buildOptionSet": [ | |||
{ | |||
"name": "release", | |||
"arkOptions": { | |||
"obfuscation": { | |||
"ruleOptions": { | |||
"enable": true, | |||
"files": [ | |||
"./obfuscation-rules.txt" | |||
] | |||
} | |||
} | |||
} | |||
}, | |||
], | |||
"targets": [ | |||
{ | |||
"name": "default" | |||
}, | |||
{ | |||
"name": "ohosTest", | |||
} | |||
] | |||
} |
@@ -0,0 +1,6 @@ | |||
import { hapTasks } from '@ohos/hvigor-ohos-plugin'; | |||
export default { | |||
system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ | |||
plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ | |||
} |
@@ -0,0 +1,18 @@ | |||
# Define project specific obfuscation rules here. | |||
# You can include the obfuscation configuration files in the current module's build-profile.json5. | |||
# | |||
# For more details, see | |||
# https://gitee.com/openharmony/arkcompiler_ets_frontend/blob/master/arkguard/README.md | |||
# Obfuscation options: | |||
# -disable-obfuscation: disable all obfuscations | |||
# -enable-property-obfuscation: obfuscate the property names | |||
# -enable-toplevel-obfuscation: obfuscate the names in the global scope | |||
# -compact: remove unnecessary blank spaces and all line feeds | |||
# -remove-log: remove all console.* statements | |||
# -print-namecache: print the name cache that contains the mapping from the old names to new names | |||
# -apply-namecache: reuse the given cache file | |||
# Keep options: | |||
# -keep-property-name: specifies property names that you want to keep | |||
# -keep-global-name: specifies names that you want to keep in the global scope |
@@ -0,0 +1,26 @@ | |||
{ | |||
"meta": { | |||
"stableOrder": false | |||
}, | |||
"lockfileVersion": 3, | |||
"ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.", | |||
"specifiers": { | |||
"@szyx/sdk_ywx@../sdk_ywx": "@szyx/sdk_ywx@../sdk_ywx", | |||
"@szyx/sdk_base@../basic": "@szyx/sdk_base@../basic" | |||
}, | |||
"packages": { | |||
"@szyx/sdk_ywx@../sdk_ywx": { | |||
"name": "@szyx/sdk_ywx", | |||
"resolved": "../sdk_ywx", | |||
"registryType": "local", | |||
"dependencies": { | |||
"@szyx/sdk_base": "file:../basic" | |||
} | |||
}, | |||
"@szyx/sdk_base@../basic": { | |||
"name": "@szyx/sdk_base", | |||
"resolved": "../basic", | |||
"registryType": "local" | |||
} | |||
} | |||
} |
@@ -0,0 +1,17 @@ | |||
{ | |||
"name": "entry", | |||
"version": "1.0.0", | |||
"description": "Please describe the basic information.", | |||
"main": "", | |||
"author": "", | |||
"license": "", | |||
"dependencies": { | |||
"@szyx/sdk_ywx": "file:../sdk_ywx", | |||
// "@szyx/sdk_ywx": "^1.0.4", | |||
"@szyx/sdk_base": "file:../basic", | |||
// "@szyx/sdk_base": "^1.0.2", | |||
// "@yunkss/eftool": "^1.1.8" | |||
}, | |||
"devDependencies": {}, | |||
"dynamicDependencies": {} | |||
} |
@@ -0,0 +1,11 @@ | |||
{ | |||
"app": { | |||
"bundleName": "com.xuqinmin.hw.demo", | |||
"patchVersionCode": 2000109, | |||
"versionCode": 1 | |||
}, | |||
"module": { | |||
"name": "entry", | |||
"type": "hotreload" | |||
} | |||
} |
@@ -0,0 +1,41 @@ | |||
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit'; | |||
import { hilog } from '@kit.PerformanceAnalysisKit'; | |||
import { window } from '@kit.ArkUI'; | |||
export default class EntryAbility extends UIAbility { | |||
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { | |||
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); | |||
} | |||
onDestroy(): void { | |||
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy'); | |||
} | |||
onWindowStageCreate(windowStage: window.WindowStage): void { | |||
// Main window is created, set main page for this ability | |||
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); | |||
windowStage.loadContent('pages/Index', (err, data) => { | |||
if (err.code) { | |||
hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); | |||
return; | |||
} | |||
hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? ''); | |||
}); | |||
} | |||
onWindowStageDestroy(): void { | |||
// Main window is destroyed, release UI related resources | |||
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); | |||
} | |||
onForeground(): void { | |||
// Ability has brought to foreground | |||
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); | |||
} | |||
onBackground(): void { | |||
// Ability has back to background | |||
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground'); | |||
} | |||
} |
@@ -0,0 +1,59 @@ | |||
import { CertHome } from './cert/CertHome' | |||
import { SettingView } from './setting/SettingView' | |||
import { RouterBuilder } from '../router/RouterBuilder' | |||
import { BJCASDK } from '@szyx/sdk_ywx/Index' | |||
import { SignHome } from './sign/SignHome' | |||
@Entry | |||
@Component | |||
struct Index { | |||
@Provide('pageInfos') pageInfos: NavPathStack = new NavPathStack() | |||
@State currentIndex: number = 0 | |||
@Builder | |||
tabBuilder(title: string, targetIndex: number, selectedImg: Resource, normalImg: Resource) { | |||
Column() { | |||
Image(this.currentIndex === targetIndex ? selectedImg : normalImg) | |||
.size({ width: 25, height: 25 }) | |||
Text(title) | |||
.fontColor(this.currentIndex === targetIndex ? '#d81e06' : '#8a8a8a') | |||
} | |||
.width('100%') | |||
.height(50) | |||
.justifyContent(FlexAlign.Center) | |||
} | |||
aboutToAppear(): void { | |||
BJCASDK.settingManager().init() | |||
} | |||
build() { | |||
Navigation(this.pageInfos) { | |||
Tabs({ barPosition: BarPosition.End }) { | |||
TabContent() { | |||
CertHome() | |||
} | |||
.tabBar(this.tabBuilder('证书', 0, $r('app.media.icon_home_selected'), $r('app.media.icon_home_normal'))) | |||
TabContent() { | |||
SignHome() | |||
} | |||
.tabBar(this.tabBuilder('签名', 1, $r('app.media.icon_sign_selected'), $r('app.media.icon_sign_normal'))) | |||
TabContent() { | |||
Text('1.0.1版本上线').fontSize(30) | |||
} | |||
.tabBar(this.tabBuilder('二维码', 2, $r('app.media.icon_code_selected'), $r('app.media.icon_code_normal'))) | |||
TabContent() { | |||
SettingView() | |||
} | |||
.tabBar(this.tabBuilder('设置', 3, $r('app.media.icon_setting_selected'), $r('app.media.icon_setting_Normal'))) | |||
}.scrollable(false).barMode(BarMode.Fixed).animationDuration(0) | |||
.onChange((index: number) => { | |||
this.currentIndex = index | |||
}) | |||
}.navDestination(RouterBuilder).hideTitleBar(true) | |||
} | |||
} |
@@ -0,0 +1,13 @@ | |||
// PageOne.ets | |||
@Entry | |||
@Component | |||
export struct PageOneTmp { | |||
build() { | |||
Button('pushPathByName', { stateEffect: true, type: ButtonType.Capsule }) | |||
.width('80%') | |||
.height(40) | |||
.margin(20) | |||
.onClick(() => { | |||
}) | |||
} | |||
} |
@@ -0,0 +1,24 @@ | |||
// PageTwo.ets | |||
export class Pages { | |||
names: string = "" | |||
values: NavPathStack | null = null | |||
} | |||
@Builder | |||
export function pageTwoTmp(info: Pages) { | |||
NavDestination() { | |||
Column() { | |||
Button('pushPathByName', { stateEffect: true, type: ButtonType.Capsule }) | |||
.width('80%') | |||
.height(40) | |||
.margin(20) | |||
.onClick(() => { | |||
(info.values as NavPathStack).pushPathByName('pageOne', null) | |||
}) | |||
}.width('100%').height('100%') | |||
}.title('pageTwo') | |||
.onBackPressed(() => { | |||
(info.values as NavPathStack).pop() | |||
return true | |||
}) | |||
} |
@@ -0,0 +1,199 @@ | |||
import promptAction from '@ohos.promptAction'; | |||
import { HttpHelper, ToolsHelper } from '@szyx/sdk_base'; | |||
import { BJCASDK } from '@szyx/sdk_ywx/Index'; | |||
import { BJCACallMsg } from '@szyx/sdk_ywx/src/main/ets/public/callBack/BJCACallMsg'; | |||
@Component | |||
@Preview | |||
export struct CertHome { | |||
@Consume('pageInfos') pageInfos: NavPathStack; | |||
private oldTime = 0 | |||
// 手机号 | |||
@State phone: string = '15731028102' | |||
@State draw: string | null = null | |||
build() { | |||
NavDestination() { | |||
Column() { | |||
Text('证书下载完成后即可签名') | |||
.margin({ top: 100 }) | |||
Row({ space: FlexAlign.SpaceBetween }) { | |||
TextInput({ | |||
placeholder: '证书下载需要填写手机号', | |||
text: $$this.phone, | |||
}) | |||
.width('70%') | |||
.maxLength(11) | |||
.fontSize(16) | |||
.placeholderFont({ size: 16 }) | |||
.type(InputType.PhoneNumber)/** | |||
* 正则表达式,限制输入内容,而不是格式验证 | |||
* 配置该参数后,上面的type会失效 | |||
*/ | |||
.inputFilter('[-0-9]', error => { | |||
ToolsHelper.showMessage(error) | |||
}) | |||
Button('证书下载', { stateEffect: true, type: ButtonType.Normal, buttonStyle: ButtonStyleMode.NORMAL }) | |||
.width('30%') | |||
.fontColor('#333333') | |||
.height(40) | |||
.onClick(() => { | |||
BJCASDK.certManager().certDown(this.phone, undefined, (result) => { | |||
ToolsHelper.showMessage(result.msg) | |||
}) | |||
}) | |||
} | |||
.width('100%') | |||
.alignItems(VerticalAlign.Center) | |||
.margin({ top: 50 }) | |||
Row() { | |||
Button('查看证书页面', { stateEffect: true, type: ButtonType.Normal, buttonStyle: ButtonStyleMode.NORMAL }) | |||
.width('40%') | |||
.fontColor('#333333') | |||
.height(40) | |||
.onClick(() => { | |||
if (BJCASDK.certManager().existsCert(this.phone)) { | |||
BJCASDK.certManager().showCertPage(this.phone, (result) => { | |||
ToolsHelper.showMessage(result.msg) | |||
}) | |||
} else { | |||
ToolsHelper.showMessage("证书不存在,请先下证。") | |||
} | |||
}) | |||
Button('查看用户信息', { stateEffect: true, type: ButtonType.Normal, buttonStyle: ButtonStyleMode.NORMAL }) | |||
.width('40%') | |||
.height(40) | |||
.fontColor('#333333') | |||
.onClick(() => { | |||
if (BJCASDK.certManager().existsCert(this.phone)) { | |||
BJCASDK.certManager().getUserInfo(this.phone, res => { | |||
ToolsHelper.showMessage(JSON.stringify(res)) | |||
}) | |||
} else { | |||
ToolsHelper.showMessage("证书不存在,请先下证。") | |||
} | |||
}) | |||
}.margin({ top: 20 }) | |||
.width('100%') | |||
.justifyContent(FlexAlign.SpaceAround) | |||
Grid() { | |||
GridItem() { | |||
Button('密码重置', { stateEffect: true, type: ButtonType.Normal, buttonStyle: ButtonStyleMode.NORMAL }) | |||
.height(40) | |||
.fontColor('#333333') | |||
.width('100%') | |||
.onClick(() => { | |||
BJCASDK.certManager().certResetPin(undefined, res => { | |||
if (res !== BJCACallMsg.SUCCESS) { | |||
ToolsHelper.showMessage(JSON.stringify(res)) | |||
} | |||
}) | |||
}) | |||
} | |||
GridItem() { | |||
Button('证书更新', { stateEffect: true, type: ButtonType.Normal, buttonStyle: ButtonStyleMode.NORMAL }) | |||
.height(40) | |||
.fontColor('#333333') | |||
.width('100%') | |||
.onClick(() => { | |||
BJCASDK.certManager().certUpdate(this.phone, undefined, res => { | |||
if (res !== BJCACallMsg.SUCCESS) { | |||
ToolsHelper.showMessage(JSON.stringify(res)) | |||
} | |||
}) | |||
}) | |||
} | |||
GridItem() { | |||
Button('存在本地证书', { stateEffect: true, type: ButtonType.Normal, buttonStyle: ButtonStyleMode.NORMAL }) | |||
.height(40) | |||
.fontColor('#333333') | |||
.width('100%') | |||
.onClick(() => { | |||
ToolsHelper.showMessage(BJCASDK.certManager().existsCert(this.phone) ? "证书存在" : "证书不存在") | |||
}) | |||
} | |||
GridItem() { | |||
Button('清除本地证书', { stateEffect: true, type: ButtonType.Normal, buttonStyle: ButtonStyleMode.NORMAL }) | |||
.height(40) | |||
.fontColor('#333333') | |||
.width('100%') | |||
.onClick(() => { | |||
BJCASDK.certManager().certClear() | |||
}) | |||
} | |||
} | |||
.margin({ top: 20 }) | |||
.width('100%') | |||
.columnsGap(10) | |||
.height(100) | |||
.rowsTemplate('1fr 1fr') | |||
.columnsTemplate('1fr 1fr') | |||
Text('用户可以修改个人的手写签名图片') | |||
.margin({ top: 20 }) | |||
Row() { | |||
Button('查看个人签章图片', { | |||
stateEffect: true, | |||
type: ButtonType.Normal, | |||
buttonStyle: ButtonStyleMode.NORMAL | |||
}) | |||
.width('40%') | |||
.fontColor('#333333') | |||
.height(40) | |||
.onClick(() => { | |||
BJCASDK.certManager().drawStamp(this.phone, res => { | |||
if (res.code === BJCACallMsg.SUCCESS.code && res.data) { | |||
this.draw = res.data | |||
} else { | |||
ToolsHelper.showMessage("未设置签名图片") | |||
} | |||
}) | |||
}) | |||
Button('修改个人签章图片', { | |||
stateEffect: true, | |||
type: ButtonType.Normal, | |||
buttonStyle: ButtonStyleMode.NORMAL | |||
}) | |||
.width('40%') | |||
.height(40) | |||
.fontColor('#333333') | |||
.onClick(() => { | |||
ToolsHelper.showMessage('hello world1') | |||
}) | |||
}.margin({ top: 10 }) | |||
.width('100%') | |||
.justifyContent(FlexAlign.SpaceAround) | |||
Image(`data:image/png;base64,${this.draw}`) | |||
.width(300) | |||
.height(200) | |||
.margin({ top: 15 }) | |||
.objectFit(ImageFit.Contain) | |||
.visibility(this.draw ? Visibility.Visible : Visibility.None) | |||
} | |||
}.padding({ left: 15, right: 15 }).hideTitleBar(true) | |||
.onBackPressed(() => { | |||
const currentTime = new Date().getTime() | |||
if (currentTime - this.oldTime > 1500) { | |||
promptAction.showToast({ | |||
message: '双击退出', | |||
duration: 2000 | |||
}); | |||
this.oldTime = currentTime | |||
return false | |||
} | |||
return true | |||
}) | |||
} | |||
} |
@@ -0,0 +1,142 @@ | |||
import { ToolsHelper } from '@szyx/sdk_base/Index'; | |||
import { BJCASDK, EnvEnum } from '@szyx/sdk_ywx'; | |||
import { AlertDialog } from '@ohos.arkui.advanced.Dialog'; | |||
@Component | |||
@Preview | |||
export struct ChangeEvnView { | |||
@Consume('pageInfos') pageInfos: NavPathStack | |||
// 环境信息 | |||
@State envType: EnvEnum = BJCASDK.settingManager().getServerEnvType() | |||
// 环境地址 | |||
@State envUrl: String = BJCASDK.settingManager().getServerEnvUrl() | |||
// 是否清理证书 | |||
@State clean: boolean = true | |||
// 切换确认 | |||
dialogControllerConfirm: CustomDialogController = new CustomDialogController({ | |||
builder: AlertDialog({ | |||
content: '确定需要切换环境吗?', | |||
primaryButton: { | |||
value: '取消', | |||
action: () => { | |||
}, | |||
}, | |||
secondaryButton: { | |||
value: '确认', | |||
fontColor: $r('sys.color.ohos_id_color_warning'), | |||
action: () => { | |||
BJCASDK.settingManager().setServerEnvType(this.envType) | |||
this.pageInfos.pop() | |||
} | |||
}, | |||
}), | |||
autoCancel: true, | |||
customStyle: true, | |||
alignment: DialogAlignment.Center | |||
}) | |||
build() { | |||
NavDestination() { | |||
Column() { | |||
Row() { | |||
Text(`当前环境地址:${this.envType}\n${this.envUrl}`).margin({ left: 5 }) | |||
}.width('100%') | |||
Row() { | |||
Radio({ value: 'Radio1', group: 'evnGroup' }) | |||
.height(20) | |||
.width(20) | |||
.onChange((isChecked: boolean) => { | |||
if (isChecked) { | |||
this.envType = EnvEnum.DEV | |||
this.envUrl = BJCASDK.settingManager().getUrlByEnvType(EnvEnum.DEV) | |||
} | |||
}).checked(this.envType == EnvEnum.DEV) | |||
Text('开发环境').margin({ left: 5 }).onClick(() => { | |||
this.envType = EnvEnum.DEV | |||
this.envUrl = BJCASDK.settingManager().getUrlByEnvType(EnvEnum.DEV) | |||
}) | |||
}.width('100%').margin({ top: 15 }) | |||
Row() { | |||
Radio({ value: 'Radio2', group: 'evnGroup' }) | |||
.height(20) | |||
.width(20) | |||
.onChange((isChecked: boolean) => { | |||
if (isChecked) { | |||
this.envType = EnvEnum.TEST | |||
this.envUrl = BJCASDK.settingManager().getUrlByEnvType(EnvEnum.TEST) | |||
} | |||
}).checked(this.envType == EnvEnum.TEST) | |||
Text('测试环境').margin({ left: 5 }).onClick(() => { | |||
this.envType = EnvEnum.TEST | |||
this.envUrl = BJCASDK.settingManager().getUrlByEnvType(EnvEnum.TEST) | |||
}) | |||
}.width('100%').margin({ top: 5 }) | |||
Row() { | |||
Radio({ value: 'Radio3', group: 'evnGroup' }) | |||
.height(20) | |||
.width(20) | |||
.onChange((isChecked: boolean) => { | |||
if (isChecked) { | |||
this.envType = EnvEnum.INTEGRATE | |||
this.envUrl = BJCASDK.settingManager().getUrlByEnvType(EnvEnum.INTEGRATE) | |||
} | |||
}).checked(this.envType == EnvEnum.INTEGRATE) | |||
Text('集成环境').margin({ left: 5 }).onClick(() => { | |||
this.envType = EnvEnum.INTEGRATE | |||
this.envUrl = BJCASDK.settingManager().getUrlByEnvType(EnvEnum.INTEGRATE) | |||
}) | |||
}.width('100%').margin({ top: 5 }) | |||
Row() { | |||
Radio({ value: 'Radio3', group: 'evnGroup' }) | |||
.height(20) | |||
.width(20) | |||
.onChange((isChecked: boolean) => { | |||
if (isChecked) { | |||
this.envType = EnvEnum.PUBLIC | |||
this.envUrl = BJCASDK.settingManager().getUrlByEnvType(EnvEnum.PUBLIC) | |||
} | |||
}).checked(this.envType == EnvEnum.PUBLIC) | |||
Text('运营环境').margin({ left: 5 }).onClick(() => { | |||
this.envType = EnvEnum.PUBLIC | |||
this.envUrl = BJCASDK.settingManager().getUrlByEnvType(EnvEnum.PUBLIC) | |||
}) | |||
}.width('100%').margin({ top: 5 }) | |||
Row() { | |||
Toggle({ type: ToggleType.Checkbox, isOn: this.clean }) | |||
Text('清空本地数据').margin({ left: 5 }) | |||
}.width('100%').margin({ top: 10 }) | |||
Row() { | |||
Button('取消', { type: ButtonType.Normal, stateEffect: true }) | |||
.borderRadius(8) | |||
.backgroundColor(0x317aff) | |||
.width(90) | |||
.height(40) | |||
.onClick(() => { | |||
this.pageInfos.pop() | |||
}) | |||
Button('确定', { type: ButtonType.Normal, stateEffect: true }) | |||
.borderRadius(8) | |||
.backgroundColor(0x317aff) | |||
.width(90) | |||
.height(40) | |||
.onClick(() => { | |||
if (BJCASDK.settingManager().getServerEnvType() == this.envType) { | |||
ToolsHelper.showMessage('环境没有变更!') | |||
return | |||
} | |||
this.dialogControllerConfirm.open() | |||
}) | |||
}.width('100%').margin({ top: 20 }).justifyContent(FlexAlign.SpaceAround) | |||
}.width('100%').height('100%').padding(20) | |||
}.title('切换sdk环境') | |||
} | |||
} |
@@ -0,0 +1,89 @@ | |||
import { ToolsHelper } from '@szyx/sdk_base'; | |||
import { BJCASDK } from '@szyx/sdk_ywx'; | |||
@Component | |||
@Preview | |||
export struct SettingView { | |||
@Consume('pageInfos') pageInfos: NavPathStack | |||
// 环境地址 | |||
@State clientId: string | undefined = BJCASDK.settingManager().getClientId() | |||
@State clientIdEdit: string | undefined = '2015112716143758' | |||
build() { | |||
NavDestination() { | |||
Column() { | |||
Row() { | |||
Text(`当前厂商ID:${this.clientId}`).margin({ left: 5 }) | |||
}.width('100%') | |||
Row({ space: FlexAlign.SpaceBetween }) { | |||
TextInput({ | |||
placeholder: '输入厂商ID', | |||
text: $$this.clientIdEdit, | |||
}) | |||
.width('70%') | |||
.fontSize(16) | |||
.placeholderFont({ size: 16 }) | |||
.type(InputType.PhoneNumber) | |||
Button('确认', { stateEffect: true, type: ButtonType.Normal, buttonStyle: ButtonStyleMode.NORMAL }) | |||
.width('30%') | |||
.fontColor('#333333') | |||
.height(40) | |||
.onClick(() => { | |||
if (!this.clientIdEdit) { | |||
ToolsHelper.showMessage('请输入厂商ID') | |||
return | |||
} | |||
BJCASDK.settingManager().setClientId(this.clientIdEdit) | |||
this.clientId = BJCASDK.settingManager().getClientId() | |||
}) | |||
} | |||
.width('80%') | |||
.alignItems(VerticalAlign.Center) | |||
.margin({ top: 10 }) | |||
Button('获取当前版本号', { stateEffect: true, type: ButtonType.Normal, buttonStyle: ButtonStyleMode.NORMAL }) | |||
.width('80%') | |||
.fontColor('#333333') | |||
.height(40) | |||
.onClick(() => { | |||
ToolsHelper.showMessage(BJCASDK.settingManager().getVersion()) | |||
}) | |||
.margin({ top: 60 }) | |||
Button('切换环境', { stateEffect: true, type: ButtonType.Normal, buttonStyle: ButtonStyleMode.NORMAL }) | |||
.width('80%') | |||
.fontColor('#333333') | |||
.height(40) | |||
.onClick(() => { | |||
this.pageInfos.pushPathByName('ChangeEvnView', undefined) | |||
}) | |||
.margin({ top: 10 }) | |||
Button('设置语言-中文', { stateEffect: true, type: ButtonType.Normal, buttonStyle: ButtonStyleMode.NORMAL }) | |||
.width('80%') | |||
.fontColor('#333333') | |||
.height(40) | |||
.onClick(() => { | |||
ToolsHelper.showMessage('hello world1') | |||
}) | |||
.margin({ top: 30 }) | |||
Button('设置语言-英文', { stateEffect: true, type: ButtonType.Normal, buttonStyle: ButtonStyleMode.NORMAL }) | |||
.width('80%') | |||
.fontColor('#333333') | |||
.height(40) | |||
.onClick(() => { | |||
ToolsHelper.showMessage('hello world1') | |||
}) | |||
.margin({ top: 10 }) | |||
Button('显示pin码输入框', { stateEffect: true, type: ButtonType.Normal, buttonStyle: ButtonStyleMode.NORMAL }) | |||
.width('80%') | |||
.fontColor('#333333') | |||
.height(40) | |||
.onClick(() => { | |||
ToolsHelper.showMessage('hello world1') | |||
}) | |||
.margin({ top: 10 }) | |||
} | |||
}.padding({ left: 15, right: 15, top: 100 }).hideTitleBar(true) | |||
} | |||
} |
@@ -0,0 +1,213 @@ | |||
import { HttpHelper, ToolsHelper } from '@szyx/sdk_base/Index' | |||
import { BJCASDK, PinDialog } from '@szyx/sdk_ywx/Index' | |||
import { SynedModel } from './SynedModel' | |||
@Component | |||
@Preview | |||
export struct Sign { | |||
@Consume('pageInfos') pageInfos: NavPathStack | |||
@State mDoctorId: string | null = '130427199604025922' | |||
@State mNum: string = '1' | |||
@State mListUniqueId: string[] = [] | |||
@State mSynedNum: number = 0 | |||
@State uniqueId: string | null = null | |||
@State needSignNow: boolean = false | |||
private signRequest() { | |||
this.needSignNow = false | |||
BJCASDK.signManager().signWithFirmId(this.mListUniqueId, (res) => { | |||
ToolsHelper.showMessage(JSON.stringify(res)) | |||
}) | |||
} | |||
private shouldSynAgain() { | |||
this.mSynedNum += 1 | |||
if (this.mSynedNum < Number.parseInt(this.mNum)) { | |||
this.synUnSignData() | |||
} else { | |||
ToolsHelper.showMessage('处方同步完成') | |||
if (this.needSignNow) { | |||
this.signRequest() | |||
} | |||
} | |||
} | |||
private synUnSignData() { | |||
HttpHelper.get() | |||
.get<SynedModel>(BJCASDK.settingManager() | |||
.getServerEnvUrl() + `AppOAuthDemo/synSdkRecipeInfoForBatch?clientId=${BJCASDK.settingManager() | |||
.getClientId()!}&doctorId=${this.mDoctorId}`, undefined) | |||
.then(res => { | |||
console.log('---->', JSON.stringify(res)) | |||
if (res.status === '0') { | |||
this.mListUniqueId.push(res.data.uniqueId) | |||
} | |||
this.shouldSynAgain() | |||
}).catch(() => { | |||
ToolsHelper.showMessage(`同步第 ${this.mSynedNum + 1} 条处方失败!`) | |||
this.shouldSynAgain() | |||
}) | |||
} | |||
build() { | |||
NavDestination() { | |||
Column() { | |||
Text('第一步,模拟应用厂商将多条待签数据同步到医网信获取待签名数据的唯一标识uniqueId。') | |||
.margin({ top: 20 }) | |||
.fontSize(16) | |||
.fontColor('#666666') | |||
Row() { | |||
Text('医师证号:') | |||
.fontSize(16) | |||
.fontColor('#666666') | |||
TextInput({ | |||
placeholder: '请输入医师证号', | |||
text: $$this.mDoctorId, | |||
}) | |||
.margin({ left: 5 }) | |||
.layoutWeight(1) | |||
}.alignItems(VerticalAlign.Center) | |||
.margin({ top: 10 }) | |||
.width('100%') | |||
Row() { | |||
Button('1.批量获取待签数据:', { | |||
stateEffect: true, | |||
type: ButtonType.Normal, | |||
buttonStyle: ButtonStyleMode.NORMAL | |||
}) | |||
.fontSize(16) | |||
.fontColor('#666666') | |||
.enabled(this.mSynedNum === 0 || this.mSynedNum === this.mListUniqueId.length) | |||
.onClick(() => { | |||
if (!this.mDoctorId) { | |||
ToolsHelper.showMessage('医师证号不能为空') | |||
return | |||
} | |||
if (!this.mNum || Number.parseInt(this.mNum) < 1 || Number.parseInt(this.mNum) > 100) { | |||
ToolsHelper.showMessage('需要批量签名数量不能小于1,不能大于100') | |||
return | |||
} | |||
this.mListUniqueId = [] | |||
this.mSynedNum = 0 | |||
this.needSignNow = false | |||
this.synUnSignData() | |||
}) | |||
TextInput({ | |||
text: $$this.mNum, | |||
}) | |||
.enabled(this.mSynedNum === 0 || this.mSynedNum === this.mListUniqueId.length) | |||
.margin({ left: 5 }) | |||
.width(60) | |||
.maxLength(3) | |||
.type(InputType.Number) | |||
Text('条') | |||
.fontSize(16) | |||
.fontColor('#666666') | |||
.textAlign(TextAlign.Center) | |||
.margin({ left: 3 }) | |||
}.alignItems(VerticalAlign.Center) | |||
.width('100%') | |||
.margin({ top: 10 }) | |||
Text(`已同步 ${this.mListUniqueId.length}/${this.mNum} 条待签数据`) | |||
.fontSize(14) | |||
.fontColor('#666666') | |||
.textAlign(TextAlign.Center) | |||
.width('100%') | |||
.margin({ top: 10 }) | |||
Text(`当前待签名数据总量为: ${this.mListUniqueId.length}`) | |||
.fontSize(14) | |||
.fontColor('#666666') | |||
.textAlign(TextAlign.Center) | |||
.width('100%') | |||
.margin({ top: 5 }) | |||
Text('第二步,调用医网信接口进行签名,参数为厂商标识(clientId)和医网信待签数据唯一标识(uniqueId)的List列表(不大于100条)') | |||
.margin({ top: 30 }) | |||
.fontSize(16) | |||
.fontColor('#666666') | |||
Button(this.mSynedNum >= Number.parseInt(this.mNum) ? '2.签名' : '请耐心等待批量同步待签数据', { | |||
stateEffect: true, | |||
type: ButtonType.Normal, | |||
buttonStyle: ButtonStyleMode.NORMAL, | |||
}) | |||
.enabled(this.mSynedNum >= Number.parseInt(this.mNum)) | |||
.fontSize(16) | |||
.width('100%') | |||
.fontColor('#666666') | |||
.margin({ top: 10 }) | |||
.onClick(() => { | |||
this.signRequest() | |||
}) | |||
Button(this.mSynedNum === 0 ? '立即签名(同步后立即签名)' : '正在同步处方数据', { | |||
stateEffect: true, | |||
type: ButtonType.Normal, | |||
buttonStyle: ButtonStyleMode.NORMAL | |||
}) | |||
.fontSize(16) | |||
.width('100%') | |||
.fontColor('#666666') | |||
.margin({ top: 10 }) | |||
.enabled(this.mSynedNum === 0) | |||
.onClick(() => { | |||
if (!this.mDoctorId) { | |||
ToolsHelper.showMessage('医师证号不能为空') | |||
return | |||
} | |||
if (!this.mNum || Number.parseInt(this.mNum) < 1) { | |||
ToolsHelper.showMessage('需要批量签名数量不能小于1,不能大于100') | |||
return | |||
} | |||
this.mListUniqueId = [] | |||
this.mSynedNum = 0 | |||
this.needSignNow = true | |||
this.synUnSignData() | |||
}) | |||
Row() { | |||
TextInput({ | |||
text: $$this.uniqueId, | |||
placeholder: '请输入待签uniqueId' | |||
}) | |||
.margin({ left: 5 }) | |||
.width(180) | |||
.type(InputType.NUMBER_DECIMAL) | |||
Button('添加uniqueId', { | |||
stateEffect: true, | |||
type: ButtonType.Normal, | |||
buttonStyle: ButtonStyleMode.NORMAL | |||
}) | |||
.fontSize(16) | |||
.layoutWeight(1) | |||
.margin({ left: 3 }) | |||
.fontColor('#666666') | |||
.onClick(() => { | |||
if (this.uniqueId) { | |||
this.mListUniqueId.push(this.uniqueId) | |||
this.uniqueId = null | |||
} | |||
}) | |||
}.alignItems(VerticalAlign.Center) | |||
.width('100%') | |||
.margin({ top: 40 }) | |||
Button('手动签名', { | |||
stateEffect: true, | |||
type: ButtonType.Normal, | |||
buttonStyle: ButtonStyleMode.NORMAL | |||
}) | |||
.fontSize(16) | |||
.width('100%') | |||
.fontColor('#666666') | |||
.margin({ top: 10 }) | |||
.onClick(() => { | |||
this.signRequest() | |||
}) | |||
PinDialog({ | |||
controller: BJCASDK.signManager().dialogController | |||
}) | |||
}.width('100%').height('100%').padding(20) | |||
}.title('医师sdk签名演示') | |||
} | |||
} |
@@ -0,0 +1,81 @@ | |||
import { ToolsHelper } from '@szyx/sdk_base/Index' | |||
import { BJCASDK, PinDialog } from '@szyx/sdk_ywx/Index' | |||
@Component | |||
@Preview | |||
export struct SignForAuto { | |||
@State sysTag: string | null = null | |||
build() { | |||
NavDestination() { | |||
Column() { | |||
Row() { | |||
Text('系统标识名称') | |||
.fontSize(16) | |||
.fontColor('#666666') | |||
TextInput({ | |||
text: $$this.sysTag, | |||
placeholder: '开启自动签标识' | |||
}) | |||
.margin({ left: 5 }) | |||
.width(160) | |||
}.alignItems(VerticalAlign.Center) | |||
.width('100%') | |||
.margin({ top: 10 }) | |||
Row() { | |||
Button('获取自动签信息', { | |||
stateEffect: true, | |||
type: ButtonType.Normal, | |||
buttonStyle: ButtonStyleMode.NORMAL, | |||
}) | |||
.fontSize(16) | |||
.fontColor('#666666') | |||
.onClick(() => { | |||
BJCASDK.signManager().getSignAutoInfo((res) => { | |||
ToolsHelper.showMessage(JSON.stringify(res)) | |||
}) | |||
}) | |||
Button('开启自动签名', { | |||
stateEffect: true, | |||
type: ButtonType.Normal, | |||
buttonStyle: ButtonStyleMode.NORMAL, | |||
}) | |||
.fontSize(16) | |||
.fontColor('#666666') | |||
.margin({ left: 10 }) | |||
.onClick(() => { | |||
if (!this.sysTag) { | |||
ToolsHelper.showMessage('请输入系统标识') | |||
return | |||
} | |||
BJCASDK.signManager().signForSignAuto(this.sysTag, (res) => { | |||
ToolsHelper.showMessage(JSON.stringify(res)) | |||
}) | |||
}) | |||
}.alignItems(VerticalAlign.Center) | |||
.width('100%') | |||
.margin({ top: 15 }) | |||
Button('关闭自动签名', { | |||
stateEffect: true, | |||
type: ButtonType.Normal, | |||
buttonStyle: ButtonStyleMode.NORMAL, | |||
}) | |||
.fontSize(16) | |||
.fontColor('#666666') | |||
.margin({ top: 10 }) | |||
.onClick(() => { | |||
BJCASDK.signManager().stopSignAuto(this.sysTag ?? undefined, (res) => { | |||
ToolsHelper.showMessage(JSON.stringify(res)) | |||
}) | |||
}) | |||
PinDialog({ | |||
controller: BJCASDK.signManager().dialogController | |||
}) | |||
}.width('100%').height('100%').padding(20) | |||
}.title('医师sdk自动签名演示') | |||
} | |||
} |
@@ -0,0 +1,129 @@ | |||
import { ToolsHelper } from '@szyx/sdk_base/Index' | |||
import { BJCASDK, PinDialog } from '@szyx/sdk_ywx/Index' | |||
@Component | |||
@Preview | |||
export struct SignForPin { | |||
@State mNum: string = '1' | |||
build() { | |||
NavDestination() { | |||
Column() { | |||
Text('此页面的接口是为了让用户在签名过程中无需输入证书签名密码,如果不使用可以忽略。') | |||
.margin({ top: 20 }) | |||
.fontSize(16) | |||
.fontColor('#666666') | |||
Text('1.开启免密签名后,在开启时间内用户签名无需输入密码') | |||
.margin({ top: 80 }) | |||
.fontSize(16) | |||
.fontColor('#666666') | |||
Row() { | |||
Text('免密时间1-60天:') | |||
.fontSize(16) | |||
.fontColor('#666666') | |||
TextInput({ | |||
text: $$this.mNum, | |||
placeholder: '天数' | |||
}) | |||
.margin({ left: 5 }) | |||
.width(60) | |||
.maxLength(3) | |||
.type(InputType.Number) | |||
Button('开启免密', { | |||
stateEffect: true, | |||
type: ButtonType.Normal, | |||
buttonStyle: ButtonStyleMode.NORMAL, | |||
}) | |||
.fontSize(16) | |||
.margin({ left: 5 }) | |||
.fontColor('#666666') | |||
.onClick(() => { | |||
BJCASDK.signManager().keepPin(Number.parseInt(this.mNum), (res) => { | |||
ToolsHelper.showMessage(JSON.stringify(res)) | |||
}) | |||
}) | |||
}.alignItems(VerticalAlign.Center) | |||
.width('100%') | |||
.margin({ top: 10 }) | |||
Row() { | |||
Button('判断免密状态', { | |||
stateEffect: true, | |||
type: ButtonType.Normal, | |||
buttonStyle: ButtonStyleMode.NORMAL, | |||
}) | |||
.fontSize(16) | |||
.fontColor('#666666') | |||
.onClick(() => { | |||
ToolsHelper.showMessage(BJCASDK.signManager().isPinExempt() ? '已开启' : '未开启') | |||
}) | |||
Button('取消免密', { | |||
stateEffect: true, | |||
type: ButtonType.Normal, | |||
buttonStyle: ButtonStyleMode.NORMAL, | |||
}) | |||
.fontSize(16) | |||
.fontColor('#666666') | |||
.margin({ left: 10 }) | |||
.onClick(() => { | |||
BJCASDK.signManager().clearPin(() => { | |||
ToolsHelper.showMessage('免密签名已关闭') | |||
}) | |||
}) | |||
}.alignItems(VerticalAlign.Center) | |||
.width('100%') | |||
.margin({ top: 10 }) | |||
Text('---以下功能,1.0.1版本开始支持---') | |||
.margin({ top: 80 }) | |||
.fontSize(13) | |||
.fontColor('#999999') | |||
Text('2.开启指纹签名后,在开启状态内用户可以通过指纹验证来进行签名,当免密开启时无效') | |||
.margin({ top: 10 }) | |||
.fontSize(16) | |||
.fontColor('#666666') | |||
Row() { | |||
Button('指纹签名状态', { | |||
stateEffect: true, | |||
type: ButtonType.Normal, | |||
buttonStyle: ButtonStyleMode.NORMAL, | |||
}) | |||
.fontSize(16) | |||
.fontColor('#666666') | |||
.onClick(() => { | |||
}) | |||
Button('开启指纹签名', { | |||
stateEffect: true, | |||
type: ButtonType.Normal, | |||
buttonStyle: ButtonStyleMode.NORMAL, | |||
}) | |||
.fontSize(16) | |||
.fontColor('#666666') | |||
.margin({ left: 10 }) | |||
.onClick(() => { | |||
}) | |||
}.alignItems(VerticalAlign.Center) | |||
.width('100%') | |||
.margin({ top: 10 }) | |||
Button('关闭指纹签名', { | |||
stateEffect: true, | |||
type: ButtonType.Normal, | |||
buttonStyle: ButtonStyleMode.NORMAL, | |||
}) | |||
.fontSize(16) | |||
.fontColor('#666666') | |||
.margin({ top: 5 }) | |||
.onClick(() => { | |||
}) | |||
PinDialog({ | |||
controller: BJCASDK.signManager().dialogController | |||
}) | |||
}.width('100%').height('100%').padding(20) | |||
}.title('医师sdk免密签名演示') | |||
} | |||
} |
@@ -0,0 +1,69 @@ | |||
import promptAction from '@ohos.promptAction'; | |||
import { ToolsHelper } from '@szyx/sdk_base/Index'; | |||
import { BJCASDK } from '@szyx/sdk_ywx/Index'; | |||
@Component | |||
@Preview | |||
export struct SignHome { | |||
@Consume('pageInfos') pageInfos: NavPathStack; | |||
private oldTime = 0 | |||
build() { | |||
NavDestination() { | |||
Column() { | |||
Button('签名', { stateEffect: true, type: ButtonType.Normal, buttonStyle: ButtonStyleMode.NORMAL }) | |||
.width('40%') | |||
.fontColor('#333333') | |||
.height(40) | |||
.onClick(() => { | |||
if (BJCASDK.certManager().existsCert()) { | |||
this.pageInfos.pushPathByName('Sign', undefined) | |||
} else { | |||
ToolsHelper.showMessage("证书不存在,请先下证。") | |||
} | |||
}) | |||
Button('自动签', { stateEffect: true, type: ButtonType.Normal, buttonStyle: ButtonStyleMode.NORMAL }) | |||
.width('40%') | |||
.fontColor('#333333') | |||
.height(40) | |||
.margin({ top: 40 }) | |||
.onClick(() => { | |||
if (BJCASDK.certManager().existsCert()) { | |||
this.pageInfos.pushPathByName('SignForAuto', undefined) | |||
} else { | |||
ToolsHelper.showMessage("证书不存在,请先下证。") | |||
} | |||
}) | |||
Button('免密签名', { stateEffect: true, type: ButtonType.Normal, buttonStyle: ButtonStyleMode.NORMAL }) | |||
.width('40%') | |||
.fontColor('#333333') | |||
.height(40) | |||
.margin({ top: 40 }) | |||
.onClick(() => { | |||
if (BJCASDK.certManager().existsCert()) { | |||
this.pageInfos.pushPathByName('SignForPin', undefined) | |||
} else { | |||
ToolsHelper.showMessage("证书不存在,请先下证。") | |||
} | |||
}) | |||
} | |||
.width('100%') | |||
.height("100%") | |||
.padding(20) | |||
.backgroundColor("#ffffff") | |||
}.padding({ left: 15, right: 15 }).hideTitleBar(true) | |||
.onBackPressed(() => { | |||
const currentTime = new Date().getTime() | |||
if (currentTime - this.oldTime > 1500) { | |||
promptAction.showToast({ | |||
message: '双击退出', | |||
duration: 2000 | |||
}); | |||
this.oldTime = currentTime | |||
return false | |||
} | |||
return true | |||
}) | |||
} | |||
} |
@@ -0,0 +1,11 @@ | |||
export class SynedData { | |||
doctorId: string | |||
clientId: string | |||
constructor(doctorId: string, clientId: string) { | |||
this.doctorId = doctorId | |||
this.clientId = clientId | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
export interface Data { | |||
selfSign: boolean; | |||
checkSelfToken: boolean; | |||
uniqueId: string; | |||
timeStampSignData: string; | |||
} | |||
export interface SynedModel { | |||
data: Data; | |||
message: string; | |||
status: string; | |||
} |
@@ -0,0 +1,12 @@ | |||
import { RouterParam } from './ViewMap'; | |||
/** | |||
* 导航辅助方法 | |||
*/ | |||
export class NavPathStackHelper { | |||
static pushPathByName(pageInfos: NavPathStack, param: RouterParam) { | |||
console.log('-------------------------------',JSON.stringify(pageInfos)) | |||
pageInfos.pushPathByName('ChangeEvnView', undefined) | |||
} | |||
} |
@@ -0,0 +1,23 @@ | |||
import { ChangeEvnView } from '../pages/evn/ChangeEvnView' | |||
import { PageOneTmp } from '../pages/PageOne' | |||
import { Sign } from '../pages/sign/Sign' | |||
import { SignForAuto } from '../pages/sign/SignForAuto' | |||
import { SignForPin } from '../pages/sign/SignForPin' | |||
@Builder | |||
export function RouterBuilder(name: string) { | |||
if (name === 'pageOne') { | |||
PageOneTmp() | |||
} else if (name === 'pageTwo') { | |||
// pageTwoTmp() | |||
} else if (name === 'ChangeEvnView') { | |||
ChangeEvnView() | |||
} else if (name === 'Sign') { | |||
Sign() | |||
} else if (name === 'SignForAuto') { | |||
SignForAuto() | |||
} else if (name === 'SignForPin') { | |||
SignForPin() | |||
} | |||
} |
@@ -0,0 +1,14 @@ | |||
/** | |||
* 页面名称和参数定义 | |||
*/ | |||
type RouterMap = { | |||
ChangeEvnView: undefined | |||
}; | |||
export type RouterParam = { | |||
[Key in keyof RouterMap]: { | |||
name: Key; | |||
param: RouterMap[Key]; | |||
}; | |||
}[keyof RouterMap]; |
@@ -0,0 +1,40 @@ | |||
{ | |||
"module": { | |||
"name": "entry", | |||
"type": "entry", | |||
"description": "$string:module_desc", | |||
"mainElement": "EntryAbility", | |||
"deviceTypes": [ | |||
"phone", | |||
], | |||
"deliveryWithInstall": true, | |||
"installationFree": false, | |||
"pages": "$profile:main_pages", | |||
"abilities": [ | |||
{ | |||
"name": "EntryAbility", | |||
"srcEntry": "./ets/entryability/EntryAbility.ets", | |||
"description": "$string:EntryAbility_desc", | |||
"icon": "$media:icon", | |||
"label": "$string:EntryAbility_label", | |||
"startWindowIcon": "$media:startIcon", | |||
"startWindowBackground": "$color:start_window_background", | |||
"exported": true, | |||
"skills": [ | |||
{ | |||
"entities": [ | |||
"entity.system.home" | |||
], | |||
"actions": [ | |||
"action.system.home" | |||
] | |||
} | |||
] | |||
} | |||
], | |||
"requestPermissions": [ | |||
{"name": "ohos.permission.INTERNET", | |||
"reason": "$string:permission_internet"} | |||
] | |||
} | |||
} |
@@ -0,0 +1,8 @@ | |||
{ | |||
"color": [ | |||
{ | |||
"name": "start_window_background", | |||
"value": "#FFFFFF" | |||
} | |||
] | |||
} |
@@ -0,0 +1,16 @@ | |||
{ | |||
"string": [ | |||
{ | |||
"name": "module_desc", | |||
"value": "module description" | |||
}, | |||
{ | |||
"name": "EntryAbility_desc", | |||
"value": "description" | |||
}, | |||
{ | |||
"name": "EntryAbility_label", | |||
"value": "label" | |||
} | |||
] | |||
} |
@@ -0,0 +1,5 @@ | |||
{ | |||
"src": [ | |||
"pages/Index" | |||
] | |||
} |
@@ -0,0 +1,16 @@ | |||
{ | |||
"string": [ | |||
{ | |||
"name": "module_desc", | |||
"value": "module description" | |||
}, | |||
{ | |||
"name": "EntryAbility_desc", | |||
"value": "description" | |||
}, | |||
{ | |||
"name": "EntryAbility_label", | |||
"value": "label" | |||
} | |||
] | |||
} |
@@ -0,0 +1,16 @@ | |||
{ | |||
"string": [ | |||
{ | |||
"name": "module_desc", | |||
"value": "模块描述" | |||
}, | |||
{ | |||
"name": "EntryAbility_desc", | |||
"value": "description" | |||
}, | |||
{ | |||
"name": "EntryAbility_label", | |||
"value": "label" | |||
} | |||
] | |||
} |
@@ -0,0 +1,2 @@ | |||
{ | |||
} |
@@ -0,0 +1,35 @@ | |||
import { hilog } from '@kit.PerformanceAnalysisKit'; | |||
import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; | |||
export default function abilityTest() { | |||
describe('ActsAbilityTest', () => { | |||
// 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. | |||
hilog.info(0x0000, 'testTag', '%{public}s', 'it begin'); | |||
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); | |||
}) | |||
}) | |||
} |
@@ -0,0 +1,5 @@ | |||
import abilityTest from './Ability.test'; | |||
export default function testsuite() { | |||
abilityTest(); | |||
} |
@@ -0,0 +1,48 @@ | |||
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit'; | |||
import { abilityDelegatorRegistry } from '@kit.TestKit'; | |||
import { hilog } from '@kit.PerformanceAnalysisKit'; | |||
import { window } from '@kit.ArkUI'; | |||
import { Hypium } from '@ohos/hypium'; | |||
import testsuite from '../test/List.test'; | |||
export default class TestAbility extends UIAbility { | |||
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) { | |||
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onCreate'); | |||
hilog.info(0x0000, 'testTag', '%{public}s', 'want param:' + JSON.stringify(want) ?? ''); | |||
hilog.info(0x0000, 'testTag', '%{public}s', 'launchParam:' + JSON.stringify(launchParam) ?? ''); | |||
let abilityDelegator: abilityDelegatorRegistry.AbilityDelegator; | |||
abilityDelegator = abilityDelegatorRegistry.getAbilityDelegator(); | |||
let abilityDelegatorArguments: abilityDelegatorRegistry.AbilityDelegatorArgs; | |||
abilityDelegatorArguments = abilityDelegatorRegistry.getArguments(); | |||
hilog.info(0x0000, 'testTag', '%{public}s', 'start run testcase!!!'); | |||
Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite); | |||
} | |||
onDestroy() { | |||
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onDestroy'); | |||
} | |||
onWindowStageCreate(windowStage: window.WindowStage) { | |||
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageCreate'); | |||
windowStage.loadContent('testability/pages/Index', (err, data) => { | |||
if (err.code) { | |||
hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); | |||
return; | |||
} | |||
hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', | |||
JSON.stringify(data) ?? ''); | |||
}); | |||
} | |||
onWindowStageDestroy() { | |||
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageDestroy'); | |||
} | |||
onForeground() { | |||
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onForeground'); | |||
} | |||
onBackground() { | |||
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onBackground'); | |||
} | |||
} |
@@ -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%') | |||
} | |||
} |
@@ -0,0 +1,90 @@ | |||
import { abilityDelegatorRegistry, TestRunner } from '@kit.TestKit'; | |||
import { UIAbility, Want } from '@kit.AbilityKit'; | |||
import { BusinessError } from '@kit.BasicServicesKit'; | |||
import { hilog } from '@kit.PerformanceAnalysisKit'; | |||
import { resourceManager } from '@kit.LocalizationKit'; | |||
import { util } from '@kit.ArkTS'; | |||
let abilityDelegator: abilityDelegatorRegistry.AbilityDelegator; | |||
let abilityDelegatorArguments: abilityDelegatorRegistry.AbilityDelegatorArgs; | |||
let jsonPath: string = 'mock/mock-config.json'; | |||
let tag: string = 'testTag'; | |||
async function onAbilityCreateCallback(data: UIAbility) { | |||
hilog.info(0x0000, 'testTag', 'onAbilityCreateCallback, data: ${}', JSON.stringify(data)); | |||
} | |||
async function addAbilityMonitorCallback(err: BusinessError) { | |||
hilog.info(0x0000, 'testTag', 'addAbilityMonitorCallback : %{public}s', JSON.stringify(err) ?? ''); | |||
} | |||
export default class OpenHarmonyTestRunner implements TestRunner { | |||
constructor() { | |||
} | |||
onPrepare() { | |||
hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner OnPrepare'); | |||
} | |||
async onRun() { | |||
let tag = 'testTag'; | |||
hilog.info(0x0000, tag, '%{public}s', 'OpenHarmonyTestRunner onRun run'); | |||
abilityDelegatorArguments = abilityDelegatorRegistry.getArguments() | |||
abilityDelegator = abilityDelegatorRegistry.getAbilityDelegator() | |||
let moduleName = abilityDelegatorArguments.parameters['-m']; | |||
let context = abilityDelegator.getAppContext().getApplicationContext().createModuleContext(moduleName); | |||
let mResourceManager = context.resourceManager; | |||
await checkMock(abilityDelegator, mResourceManager); | |||
const bundleName = abilityDelegatorArguments.bundleName; | |||
const testAbilityName: string = 'TestAbility'; | |||
let lMonitor: abilityDelegatorRegistry.AbilityMonitor = { | |||
abilityName: testAbilityName, | |||
onAbilityCreate: onAbilityCreateCallback, | |||
moduleName: moduleName | |||
}; | |||
abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback) | |||
const want: Want = { | |||
bundleName: bundleName, | |||
abilityName: testAbilityName, | |||
moduleName: moduleName | |||
}; | |||
abilityDelegator.startAbility(want, (err: BusinessError, data: void) => { | |||
hilog.info(0x0000, tag, 'startAbility : err : %{public}s', JSON.stringify(err) ?? ''); | |||
hilog.info(0x0000, tag, 'startAbility : data : %{public}s', JSON.stringify(data) ?? ''); | |||
}) | |||
hilog.info(0x0000, tag, '%{public}s', 'OpenHarmonyTestRunner onRun end'); | |||
} | |||
} | |||
async function checkMock(abilityDelegator: abilityDelegatorRegistry.AbilityDelegator, resourceManager: resourceManager.ResourceManager) { | |||
let rawFile: Uint8Array; | |||
try { | |||
rawFile = resourceManager.getRawFileContentSync(jsonPath); | |||
hilog.info(0x0000, tag, 'MockList file exists'); | |||
let mockStr: string = util.TextDecoder.create("utf-8", { ignoreBOM: true }).decodeWithStream(rawFile); | |||
let mockMap: Record<string, string> = getMockList(mockStr); | |||
try { | |||
abilityDelegator.setMockList(mockMap) | |||
} catch (error) { | |||
let code = (error as BusinessError).code; | |||
let message = (error as BusinessError).message; | |||
hilog.error(0x0000, tag, `abilityDelegator.setMockList failed, error code: ${code}, message: ${message}.`); | |||
} | |||
} catch (error) { | |||
let code = (error as BusinessError).code; | |||
let message = (error as BusinessError).message; | |||
hilog.error(0x0000, tag, `ResourceManager:callback getRawFileContent failed, error code: ${code}, message: ${message}.`); | |||
} | |||
} | |||
function getMockList(jsonStr: string) { | |||
let jsonObj: Record<string, Object> = JSON.parse(jsonStr); | |||
let map: Map<string, object> = new Map<string, object>(Object.entries(jsonObj)); | |||
let mockList: Record<string, string> = {}; | |||
map.forEach((value: object, key: string) => { | |||
let realValue: string = value['source'].toString(); | |||
mockList[key] = realValue; | |||
}); | |||
hilog.info(0x0000, tag, '%{public}s', 'mock-json value:' + JSON.stringify(mockList) ?? ''); | |||
return mockList; | |||
} |
@@ -0,0 +1,38 @@ | |||
{ | |||
"module": { | |||
"name": "entry_test", | |||
"type": "feature", | |||
"description": "$string:module_test_desc", | |||
"mainElement": "TestAbility", | |||
"deviceTypes": [ | |||
"phone", | |||
"tablet", | |||
"2in1" | |||
], | |||
"deliveryWithInstall": true, | |||
"installationFree": false, | |||
"pages": "$profile:test_pages", | |||
"abilities": [ | |||
{ | |||
"name": "TestAbility", | |||
"srcEntry": "./ets/testability/TestAbility.ets", | |||
"description": "$string:TestAbility_desc", | |||
"icon": "$media:icon", | |||
"label": "$string:TestAbility_label", | |||
"exported": true, | |||
"startWindowIcon": "$media:icon", | |||
"startWindowBackground": "$color:start_window_background", | |||
"skills": [ | |||
{ | |||
"actions": [ | |||
"action.system.home" | |||
], | |||
"entities": [ | |||
"entity.system.home" | |||
] | |||
} | |||
] | |||
} | |||
] | |||
} | |||
} |
@@ -0,0 +1,8 @@ | |||
{ | |||
"color": [ | |||
{ | |||
"name": "start_window_background", | |||
"value": "#FFFFFF" | |||
} | |||
] | |||
} |
@@ -0,0 +1,16 @@ | |||
{ | |||
"string": [ | |||
{ | |||
"name": "module_test_desc", | |||
"value": "test ability description" | |||
}, | |||
{ | |||
"name": "TestAbility_desc", | |||
"value": "the test ability" | |||
}, | |||
{ | |||
"name": "TestAbility_label", | |||
"value": "test label" | |||
} | |||
] | |||
} |
@@ -0,0 +1,5 @@ | |||
{ | |||
"src": [ | |||
"testability/pages/Index" | |||
] | |||
} |
@@ -0,0 +1,5 @@ | |||
import localUnitTest from './LocalUnit.test'; | |||
export default function testsuite() { | |||
localUnitTest(); | |||
} |
@@ -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); | |||
}); | |||
}); | |||
} |
@@ -0,0 +1,22 @@ | |||
{ | |||
"hvigorVersion": "4.1.2", | |||
"dependencies": { | |||
"@ohos/hvigor-ohos-plugin": "4.1.2" | |||
}, | |||
"execution": { | |||
// "analyze": "default", /* Define the build analyze mode. Value: [ "default" | "verbose" | false ]. Default: "default" */ | |||
// "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */ | |||
// "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */ | |||
// "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */ | |||
// "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */ | |||
}, | |||
"logging": { | |||
// "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ | |||
}, | |||
"debugging": { | |||
// "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */ | |||
}, | |||
"nodeOptions": { | |||
// "maxOldSpaceSize": 4096 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process */ | |||
} | |||
} |
@@ -0,0 +1,6 @@ | |||
import { appTasks } from '@ohos/hvigor-ohos-plugin'; | |||
export default { | |||
system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ | |||
plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ | |||
} |
@@ -0,0 +1,54 @@ | |||
#!/bin/bash | |||
# ---------------------------------------------------------------------------- | |||
# Hvigor startup script, version 1.0.0 | |||
# | |||
# Required ENV vars: | |||
# ------------------ | |||
# NODE_HOME - location of a Node home dir | |||
# or | |||
# Add /usr/local/nodejs/bin to the PATH environment variable | |||
# ---------------------------------------------------------------------------- | |||
HVIGOR_APP_HOME="`pwd -P`" | |||
HVIGOR_WRAPPER_SCRIPT=${HVIGOR_APP_HOME}/hvigor/hvigor-wrapper.js | |||
#NODE_OPTS="--max-old-space-size=4096" | |||
fail() { | |||
echo "$*" | |||
exit 1 | |||
} | |||
set_executable_node() { | |||
EXECUTABLE_NODE="${NODE_HOME}/bin/node" | |||
if [ -x "$EXECUTABLE_NODE" ]; then | |||
return | |||
fi | |||
EXECUTABLE_NODE="${NODE_HOME}/node" | |||
if [ -x "$EXECUTABLE_NODE" ]; then | |||
return | |||
fi | |||
fail "ERROR: NODE_HOME is set to an invalid directory,check $NODE_HOME\n\nPlease set NODE_HOME in your environment to the location where your nodejs installed" | |||
} | |||
# Determine node to start hvigor wrapper script | |||
if [ -n "${NODE_HOME}" ]; then | |||
set_executable_node | |||
else | |||
EXECUTABLE_NODE="node" | |||
command -v ${EXECUTABLE_NODE} &> /dev/null || fail "ERROR: NODE_HOME not set and 'node' command not found" | |||
fi | |||
# Check hvigor wrapper script | |||
if [ ! -r "$HVIGOR_WRAPPER_SCRIPT" ]; then | |||
fail "ERROR: Couldn't find hvigor/hvigor-wrapper.js in ${HVIGOR_APP_HOME}" | |||
fi | |||
if [ -z "${NODE_OPTS}" ]; then | |||
NODE_OPTS="--" | |||
fi | |||
# start hvigor-wrapper script | |||
exec "${EXECUTABLE_NODE}" "${NODE_OPTS}" \ | |||
"${HVIGOR_WRAPPER_SCRIPT}" "$@" |
@@ -0,0 +1,54 @@ | |||
@rem | |||
@rem ---------------------------------------------------------------------------- | |||
@rem Hvigor startup script for Windows, version 1.0.0 | |||
@rem | |||
@rem Required ENV vars: | |||
@rem ------------------ | |||
@rem NODE_HOME - location of a Node home dir | |||
@rem or | |||
@rem Add %NODE_HOME%/bin to the PATH environment variable | |||
@rem ---------------------------------------------------------------------------- | |||
@rem | |||
@echo off | |||
@rem Set local scope for the variables with windows NT shell | |||
if "%OS%"=="Windows_NT" setlocal | |||
set DIRNAME=%~dp0 | |||
if "%DIRNAME%" == "" set DIRNAME=. | |||
set APP_BASE_NAME=%~n0 | |||
set APP_HOME=%DIRNAME% | |||
set WRAPPER_MODULE_PATH=%APP_HOME%\hvigor\hvigor-wrapper.js | |||
set NODE_EXE=node.exe | |||
@rem set NODE_OPTS="--max-old-space-size=4096" | |||
@rem Resolve any "." and ".." in APP_HOME to make it shorter. | |||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi | |||
if not defined NODE_OPTS set NODE_OPTS="--" | |||
@rem Find node.exe | |||
if defined NODE_HOME ( | |||
set NODE_HOME=%NODE_HOME:"=% | |||
set NODE_EXE_PATH=%NODE_HOME%/%NODE_EXE% | |||
) | |||
%NODE_EXE% --version >NUL 2>&1 | |||
if "%ERRORLEVEL%" == "0" ( | |||
"%NODE_EXE%" "%NODE_OPTS%" "%WRAPPER_MODULE_PATH%" %* | |||
) else if exist "%NODE_EXE_PATH%" ( | |||
"%NODE_EXE%" "%NODE_OPTS%" "%WRAPPER_MODULE_PATH%" %* | |||
) else ( | |||
echo. | |||
echo ERROR: NODE_HOME is not set and no 'node' command could be found in your PATH. | |||
echo. | |||
echo Please set the NODE_HOME variable in your environment to match the | |||
echo location of your NodeJs installation. | |||
) | |||
if "%ERRORLEVEL%" == "0" ( | |||
if "%OS%" == "Windows_NT" endlocal | |||
) else ( | |||
exit /b %ERRORLEVEL% | |||
) |
@@ -0,0 +1,25 @@ | |||
{ | |||
"meta": { | |||
"stableOrder": false | |||
}, | |||
"lockfileVersion": 3, | |||
"ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.", | |||
"specifiers": { | |||
"@ohos/hypium@1.0.15": "@ohos/hypium@1.0.15", | |||
"@ohos/hamock@^1.0.0": "@ohos/hamock@1.0.0" | |||
}, | |||
"packages": { | |||
"@ohos/hypium@1.0.15": { | |||
"name": "@ohos/hypium", | |||
"integrity": "sha512-AhkuYX2l/IzrVARV/hKRGsJDQPtZ5bygr6Q1N2M9W15kBllNYL3khQ0dNvJwh/CIGoEPMDVcME9q6MhFGccqkw==", | |||
"resolved": "https://repo.harmonyos.com/ohpm/@ohos/hypium/-/hypium-1.0.15.har", | |||
"registryType": "ohpm" | |||
}, | |||
"@ohos/hamock@1.0.0": { | |||
"name": "@ohos/hamock", | |||
"integrity": "sha512-K6lDPYc6VkKe6ZBNQa9aoG+ZZMiwqfcR/7yAVFSUGIuOAhPvCJAo9+t1fZnpe0dBRBPxj2bxPPbKh69VuyAtDg==", | |||
"resolved": "https://repo.harmonyos.com/ohpm/@ohos/hamock/-/hamock-1.0.0.har", | |||
"registryType": "ohpm" | |||
} | |||
} | |||
} |
@@ -0,0 +1,15 @@ | |||
{ | |||
"name": "hwdwmo", | |||
"version": "1.0.0", | |||
"description": "Please describe the basic information.", | |||
"main": "", | |||
"author": "", | |||
"license": "", | |||
"dependencies": { | |||
"@ohos/hamock": "^1.0.0" | |||
}, | |||
"devDependencies": { | |||
"@ohos/hypium": "1.0.15" | |||
}, | |||
"dynamicDependencies": {} | |||
} |