Browse Source

init

master
徐勤民 4 months ago
commit
d7f391f3f1
66 changed files with 1906 additions and 0 deletions
  1. +11
    -0
      .gitignore
  2. +14
    -0
      AppScope/app.json5
  3. +8
    -0
      AppScope/resources/base/element/string.json
  4. BIN
      AppScope/resources/base/media/app_icon.png
  5. +5
    -0
      README.md
  6. +44
    -0
      build-profile.json5
  7. +6
    -0
      entry/.gitignore
  8. +28
    -0
      entry/build-profile.json5
  9. +6
    -0
      entry/hvigorfile.ts
  10. +18
    -0
      entry/obfuscation-rules.txt
  11. +26
    -0
      entry/oh-package-lock.json5
  12. +17
    -0
      entry/oh-package.json5
  13. +11
    -0
      entry/patch.json
  14. +41
    -0
      entry/src/main/ets/entryability/EntryAbility.ets
  15. +0
    -0
      entry/src/main/ets/pages/Home.ets
  16. +59
    -0
      entry/src/main/ets/pages/Index.ets
  17. +13
    -0
      entry/src/main/ets/pages/PageOne.ets
  18. +24
    -0
      entry/src/main/ets/pages/PageTwo.ets
  19. +199
    -0
      entry/src/main/ets/pages/cert/CertHome.ets
  20. +142
    -0
      entry/src/main/ets/pages/evn/ChangeEvnView.ets
  21. +89
    -0
      entry/src/main/ets/pages/setting/SettingView.ets
  22. +213
    -0
      entry/src/main/ets/pages/sign/Sign.ets
  23. +81
    -0
      entry/src/main/ets/pages/sign/SignForAuto.ets
  24. +129
    -0
      entry/src/main/ets/pages/sign/SignForPin.ets
  25. +69
    -0
      entry/src/main/ets/pages/sign/SignHome.ets
  26. +11
    -0
      entry/src/main/ets/pages/sign/SynedData.ets
  27. +12
    -0
      entry/src/main/ets/pages/sign/SynedModel.ets
  28. +12
    -0
      entry/src/main/ets/router/NavPathStackHelper.ets
  29. +23
    -0
      entry/src/main/ets/router/RouterBuilder.ets
  30. +14
    -0
      entry/src/main/ets/router/ViewMap.ts
  31. +40
    -0
      entry/src/main/module.json5
  32. +8
    -0
      entry/src/main/resources/base/element/color.json
  33. +16
    -0
      entry/src/main/resources/base/element/string.json
  34. BIN
      entry/src/main/resources/base/media/icon.png
  35. BIN
      entry/src/main/resources/base/media/icon_code_normal.png
  36. BIN
      entry/src/main/resources/base/media/icon_code_selected.png
  37. BIN
      entry/src/main/resources/base/media/icon_home_normal.png
  38. BIN
      entry/src/main/resources/base/media/icon_home_selected.png
  39. BIN
      entry/src/main/resources/base/media/icon_setting_Normal.png
  40. BIN
      entry/src/main/resources/base/media/icon_setting_selected.png
  41. BIN
      entry/src/main/resources/base/media/icon_sign_normal.png
  42. BIN
      entry/src/main/resources/base/media/icon_sign_selected.png
  43. BIN
      entry/src/main/resources/base/media/startIcon.png
  44. +5
    -0
      entry/src/main/resources/base/profile/main_pages.json
  45. +16
    -0
      entry/src/main/resources/en_US/element/string.json
  46. +16
    -0
      entry/src/main/resources/zh_CN/element/string.json
  47. +2
    -0
      entry/src/mock/mock-config.json5
  48. +35
    -0
      entry/src/ohosTest/ets/test/Ability.test.ets
  49. +5
    -0
      entry/src/ohosTest/ets/test/List.test.ets
  50. +48
    -0
      entry/src/ohosTest/ets/testability/TestAbility.ets
  51. +17
    -0
      entry/src/ohosTest/ets/testability/pages/Index.ets
  52. +90
    -0
      entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ets
  53. +38
    -0
      entry/src/ohosTest/module.json5
  54. +8
    -0
      entry/src/ohosTest/resources/base/element/color.json
  55. +16
    -0
      entry/src/ohosTest/resources/base/element/string.json
  56. BIN
      entry/src/ohosTest/resources/base/media/icon.png
  57. +5
    -0
      entry/src/ohosTest/resources/base/profile/test_pages.json
  58. +5
    -0
      entry/src/test/List.test.ets
  59. +33
    -0
      entry/src/test/LocalUnit.test.ets
  60. +22
    -0
      hvigor/hvigor-config.json5
  61. +2
    -0
      hvigor/hvigor-wrapper.js
  62. +6
    -0
      hvigorfile.ts
  63. +54
    -0
      hvigorw
  64. +54
    -0
      hvigorw.bat
  65. +25
    -0
      oh-package-lock.json5
  66. +15
    -0
      oh-package.json5

+ 11
- 0
.gitignore View File

@@ -0,0 +1,11 @@
/node_modules
/oh_modules
/local.properties
/.idea
**/build
/.hvigor
.cxx
/.clangd
/.clang-format
/.clang-tidy
**/.test

+ 14
- 0
AppScope/app.json5 View File

@@ -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": "鸿蒙示例,各组件积累。"
}
}

+ 8
- 0
AppScope/resources/base/element/string.json View File

@@ -0,0 +1,8 @@
{
"string": [
{
"name": "app_name",
"value": "鸿蒙示例"
}
]
}

BIN
AppScope/resources/base/media/app_icon.png View File

Before After
Width: 41  |  Height: 41  |  Size: 2.0KB

+ 5
- 0
README.md View File

@@ -0,0 +1,5 @@
# 问题记录

> Q: 预览失败,无报错信息,或者报错信息指定的位置,没有问题
>
> A: 预览页面所在model下,查找 `.preview`文件夹,删除

+ 44
- 0
build-profile.json5 View File

@@ -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"
}
]
}

+ 6
- 0
entry/.gitignore View File

@@ -0,0 +1,6 @@
/node_modules
/oh_modules
/.preview
/build
/.cxx
/.test

+ 28
- 0
entry/build-profile.json5 View File

@@ -0,0 +1,28 @@
{
"apiType": "stageMode",
"buildOption": {
},
"buildOptionSet": [
{
"name": "release",
"arkOptions": {
"obfuscation": {
"ruleOptions": {
"enable": true,
"files": [
"./obfuscation-rules.txt"
]
}
}
}
},
],
"targets": [
{
"name": "default"
},
{
"name": "ohosTest",
}
]
}

+ 6
- 0
entry/hvigorfile.ts View File

@@ -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. */
}

+ 18
- 0
entry/obfuscation-rules.txt View File

@@ -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

+ 26
- 0
entry/oh-package-lock.json5 View File

@@ -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"
}
}
}

+ 17
- 0
entry/oh-package.json5 View File

@@ -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": {}
}

+ 11
- 0
entry/patch.json View File

@@ -0,0 +1,11 @@
{
"app": {
"bundleName": "com.xuqinmin.hw.demo",
"patchVersionCode": 2000109,
"versionCode": 1
},
"module": {
"name": "entry",
"type": "hotreload"
}
}

+ 41
- 0
entry/src/main/ets/entryability/EntryAbility.ets View File

@@ -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
entry/src/main/ets/pages/Home.ets View File


+ 59
- 0
entry/src/main/ets/pages/Index.ets View File

@@ -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)
}
}

+ 13
- 0
entry/src/main/ets/pages/PageOne.ets View File

@@ -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(() => {
})
}
}

+ 24
- 0
entry/src/main/ets/pages/PageTwo.ets View File

@@ -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
})
}

+ 199
- 0
entry/src/main/ets/pages/cert/CertHome.ets View File

@@ -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
})
}
}

+ 142
- 0
entry/src/main/ets/pages/evn/ChangeEvnView.ets View File

@@ -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环境')
}
}

+ 89
- 0
entry/src/main/ets/pages/setting/SettingView.ets View File

@@ -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)
}
}

+ 213
- 0
entry/src/main/ets/pages/sign/Sign.ets View File

@@ -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签名演示')
}
}

+ 81
- 0
entry/src/main/ets/pages/sign/SignForAuto.ets View File

@@ -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自动签名演示')
}
}

+ 129
- 0
entry/src/main/ets/pages/sign/SignForPin.ets View File

@@ -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免密签名演示')
}
}

+ 69
- 0
entry/src/main/ets/pages/sign/SignHome.ets View File

@@ -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
})
}
}

+ 11
- 0
entry/src/main/ets/pages/sign/SynedData.ets View File

@@ -0,0 +1,11 @@
export class SynedData {
doctorId: string
clientId: string

constructor(doctorId: string, clientId: string) {
this.doctorId = doctorId
this.clientId = clientId
}


}

+ 12
- 0
entry/src/main/ets/pages/sign/SynedModel.ets View File

@@ -0,0 +1,12 @@
export interface Data {
selfSign: boolean;
checkSelfToken: boolean;
uniqueId: string;
timeStampSignData: string;
}

export interface SynedModel {
data: Data;
message: string;
status: string;
}

+ 12
- 0
entry/src/main/ets/router/NavPathStackHelper.ets View File

@@ -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)
}
}

+ 23
- 0
entry/src/main/ets/router/RouterBuilder.ets View File

@@ -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()
}
}

+ 14
- 0
entry/src/main/ets/router/ViewMap.ts View File

@@ -0,0 +1,14 @@
/**
* 页面名称和参数定义
*/
type RouterMap = {
ChangeEvnView: undefined
};


export type RouterParam = {
[Key in keyof RouterMap]: {
name: Key;
param: RouterMap[Key];
};
}[keyof RouterMap];

+ 40
- 0
entry/src/main/module.json5 View File

@@ -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"}
]
}
}

+ 8
- 0
entry/src/main/resources/base/element/color.json View File

@@ -0,0 +1,8 @@
{
"color": [
{
"name": "start_window_background",
"value": "#FFFFFF"
}
]
}

+ 16
- 0
entry/src/main/resources/base/element/string.json View File

@@ -0,0 +1,16 @@
{
"string": [
{
"name": "module_desc",
"value": "module description"
},
{
"name": "EntryAbility_desc",
"value": "description"
},
{
"name": "EntryAbility_label",
"value": "label"
}
]
}

BIN
entry/src/main/resources/base/media/icon.png View File

Before After
Width: 41  |  Height: 41  |  Size: 2.0KB

BIN
entry/src/main/resources/base/media/icon_code_normal.png View File

Before After
Width: 64  |  Height: 64  |  Size: 978B

BIN
entry/src/main/resources/base/media/icon_code_selected.png View File

Before After
Width: 64  |  Height: 64  |  Size: 1012B

BIN
entry/src/main/resources/base/media/icon_home_normal.png View File

Before After
Width: 64  |  Height: 64  |  Size: 791B

BIN
entry/src/main/resources/base/media/icon_home_selected.png View File

Before After
Width: 64  |  Height: 64  |  Size: 823B

BIN
entry/src/main/resources/base/media/icon_setting_Normal.png View File

Before After
Width: 64  |  Height: 64  |  Size: 1.5KB

BIN
entry/src/main/resources/base/media/icon_setting_selected.png View File

Before After
Width: 64  |  Height: 64  |  Size: 1.5KB

BIN
entry/src/main/resources/base/media/icon_sign_normal.png View File

Before After
Width: 64  |  Height: 64  |  Size: 1.2KB

BIN
entry/src/main/resources/base/media/icon_sign_selected.png View File

Before After
Width: 64  |  Height: 64  |  Size: 1.2KB

BIN
entry/src/main/resources/base/media/startIcon.png View File

Before After
Width: 144  |  Height: 144  |  Size: 4.2KB

+ 5
- 0
entry/src/main/resources/base/profile/main_pages.json View File

@@ -0,0 +1,5 @@
{
"src": [
"pages/Index"
]
}

+ 16
- 0
entry/src/main/resources/en_US/element/string.json View File

@@ -0,0 +1,16 @@
{
"string": [
{
"name": "module_desc",
"value": "module description"
},
{
"name": "EntryAbility_desc",
"value": "description"
},
{
"name": "EntryAbility_label",
"value": "label"
}
]
}

+ 16
- 0
entry/src/main/resources/zh_CN/element/string.json View File

@@ -0,0 +1,16 @@
{
"string": [
{
"name": "module_desc",
"value": "模块描述"
},
{
"name": "EntryAbility_desc",
"value": "description"
},
{
"name": "EntryAbility_label",
"value": "label"
}
]
}

+ 2
- 0
entry/src/mock/mock-config.json5 View File

@@ -0,0 +1,2 @@
{
}

+ 35
- 0
entry/src/ohosTest/ets/test/Ability.test.ets View File

@@ -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);
})
})
}

+ 5
- 0
entry/src/ohosTest/ets/test/List.test.ets View File

@@ -0,0 +1,5 @@
import abilityTest from './Ability.test';

export default function testsuite() {
abilityTest();
}

+ 48
- 0
entry/src/ohosTest/ets/testability/TestAbility.ets View File

@@ -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');
}
}

+ 17
- 0
entry/src/ohosTest/ets/testability/pages/Index.ets View File

@@ -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%')
}
}

+ 90
- 0
entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ets View File

@@ -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;
}

+ 38
- 0
entry/src/ohosTest/module.json5 View File

@@ -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"
]
}
]
}
]
}
}

+ 8
- 0
entry/src/ohosTest/resources/base/element/color.json View File

@@ -0,0 +1,8 @@
{
"color": [
{
"name": "start_window_background",
"value": "#FFFFFF"
}
]
}

+ 16
- 0
entry/src/ohosTest/resources/base/element/string.json View File

@@ -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"
}
]
}

BIN
entry/src/ohosTest/resources/base/media/icon.png View File

Before After
Width: 41  |  Height: 41  |  Size: 2.0KB

+ 5
- 0
entry/src/ohosTest/resources/base/profile/test_pages.json View File

@@ -0,0 +1,5 @@
{
"src": [
"testability/pages/Index"
]
}

+ 5
- 0
entry/src/test/List.test.ets View File

@@ -0,0 +1,5 @@
import localUnitTest from './LocalUnit.test';

export default function testsuite() {
localUnitTest();
}

+ 33
- 0
entry/src/test/LocalUnit.test.ets View File

@@ -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);
});
});
}

+ 22
- 0
hvigor/hvigor-config.json5 View File

@@ -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 */
}
}

+ 2
- 0
hvigor/hvigor-wrapper.js
File diff suppressed because it is too large
View File


+ 6
- 0
hvigorfile.ts View File

@@ -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. */
}

+ 54
- 0
hvigorw View File

@@ -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}" "$@"

+ 54
- 0
hvigorw.bat View File

@@ -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%
)

+ 25
- 0
oh-package-lock.json5 View File

@@ -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"
}
}
}

+ 15
- 0
oh-package.json5 View File

@@ -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": {}
}

Loading…
Cancel
Save