fanmingyou3_wd

添加wdRouter模块,

添加wdJsBridge,wdWebComponent模块
Showing 75 changed files with 1795 additions and 60 deletions
@@ -47,6 +47,18 @@ @@ -47,6 +47,18 @@
47 ] 47 ]
48 }, 48 },
49 { 49 {
  50 + "name": "wdConstant",
  51 + "srcPath": "./wdConstant",
  52 + "targets": [
  53 + {
  54 + "name": "default",
  55 + "applyToProducts": [
  56 + "default"
  57 + ]
  58 + }
  59 + ]
  60 + },
  61 + {
50 "name": "wdKit", 62 "name": "wdKit",
51 "srcPath": "./wdKit", 63 "srcPath": "./wdKit",
52 "targets": [ 64 "targets": [
@@ -83,8 +95,8 @@ @@ -83,8 +95,8 @@
83 ] 95 ]
84 }, 96 },
85 { 97 {
86 - "name": "wdConstant",  
87 - "srcPath": "./wdConstant", 98 + "name": "wdNetwork",
  99 + "srcPath": "./wdNetwork",
88 "targets": [ 100 "targets": [
89 { 101 {
90 "name": "default", 102 "name": "default",
@@ -95,8 +107,24 @@ @@ -95,8 +107,24 @@
95 ] 107 ]
96 }, 108 },
97 { 109 {
98 - "name": "wdNetwork",  
99 - "srcPath": "./wdNetwork", 110 + "name": "wdRouter",
  111 + "srcPath": "./wdRouter",
  112 + "targets": [
  113 + {
  114 + "name": "default",
  115 + "applyToProducts": [
  116 + "default"
  117 + ]
  118 + }
  119 + ]
  120 + },
  121 + {
  122 + "name": "wdJsBridge",
  123 + "srcPath": "./wdJsBridge"
  124 + },
  125 + {
  126 + "name": "wdWebComponent",
  127 + "srcPath": "./wdWebComponent",
100 "targets": [ 128 "targets": [
101 { 129 {
102 "name": "default", 130 "name": "default",
@@ -10,7 +10,9 @@ @@ -10,7 +10,9 @@
10 "wdComponent": "file:../wdComponent", 10 "wdComponent": "file:../wdComponent",
11 "wdConstant": "file:../wdConstant", 11 "wdConstant": "file:../wdConstant",
12 "wdKit": "file:../wdKit", 12 "wdKit": "file:../wdKit",
  13 + "wdWebComponent": "file:../wdWebComponent",
13 "wdBean": "file:../wdBean", 14 "wdBean": "file:../wdBean",
  15 + "wdRouter": "file:../wdRouter",
14 "wdNetwork": "file:../wdNetwork" 16 "wdNetwork": "file:../wdNetwork"
15 } 17 }
16 } 18 }
@@ -3,10 +3,12 @@ import hilog from '@ohos.hilog'; @@ -3,10 +3,12 @@ import hilog from '@ohos.hilog';
3 import UIAbility from '@ohos.app.ability.UIAbility'; 3 import UIAbility from '@ohos.app.ability.UIAbility';
4 import Want from '@ohos.app.ability.Want'; 4 import Want from '@ohos.app.ability.Want';
5 import window from '@ohos.window'; 5 import window from '@ohos.window';
  6 +import { registerRouter } from 'wdRouter';
6 7
7 export default class EntryAbility extends UIAbility { 8 export default class EntryAbility extends UIAbility {
8 onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { 9 onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
9 hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); 10 hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
  11 + registerRouter();
10 } 12 }
11 13
12 onDestroy(): void { 14 onDestroy(): void {
  1 +import router from '@ohos.router';
  2 +import { Action } from 'wdBean';
  3 +import { Logger } from 'wdKit';
  4 +import { WdWebComponent } from 'wdWebComponent';
  5 +
  6 +const TAG = 'DefaultWebPage';
  7 +
  8 +@Entry
  9 +@Component
  10 +struct DefaultWebPage {
  11 + private url?: string;
  12 + @State reload: number = 0;
  13 +
  14 + aboutToAppear() {
  15 + let action: Action = router.getParams() as Action
  16 + if (action) {
  17 + this.url = action.params?.url
  18 + }
  19 + }
  20 +
  21 + onPageShow() {
  22 + Logger.info(TAG, `DefaultWebPage# onPageShow:::refresh`);
  23 + this.reload = ++this.reload
  24 + }
  25 +
  26 + onPageHide() {
  27 + this.reload = 0
  28 + }
  29 +
  30 + build() {
  31 + Column() {
  32 + WdWebComponent({
  33 + webUrl: this.url,
  34 + backVisibility: true,
  35 + reload: this.reload
  36 + })
  37 + }
  38 + }
  39 +}
1 { 1 {
2 "src": [ 2 "src": [
3 - "pages/Index" 3 + "pages/Index",
  4 + "pages/web/DefaultWebPage"
4 ] 5 ]
5 } 6 }
@@ -26,6 +26,10 @@ export { ItemDTO } from './src/main/ets/bean/ItemDTO'; @@ -26,6 +26,10 @@ export { ItemDTO } from './src/main/ets/bean/ItemDTO';
26 export { ItemBean } from './src/main/ets/bean/ItemBean'; 26 export { ItemBean } from './src/main/ets/bean/ItemBean';
27 27
28 // component 28 // component
  29 +export { Action } from './src/main/ets/bean/programme/Action'
  30 +
  31 +export { Params } from './src/main/ets/bean/programme/Params'
  32 +
29 export { LabelBean } from './src/main/ets/bean/component/extra/LabelBean'; 33 export { LabelBean } from './src/main/ets/bean/component/extra/LabelBean';
30 34
31 export { LabelDTO } from './src/main/ets/bean/component/extra/LabelDTO'; 35 export { LabelDTO } from './src/main/ets/bean/component/extra/LabelDTO';
  1 +import { Params } from './Params';
  2 +
1 // 事件对象 3 // 事件对象
2 export interface Action { 4 export interface Action {
3 type: string; 5 type: string;
4 name?: string; // 行为的名称,目前值与type相同,暂不启用 6 name?: string; // 行为的名称,目前值与type相同,暂不启用
5 - // params?: Params; // 参数集合 7 + params?: Params; // 参数集合
6 } 8 }
  1 +import { ExtraDTO } from '../component/extra/ExtraDTO';
  2 +
  3 +export interface Params {
  4 + pageID: string;
  5 + contentID?: string;
  6 + path?: string;
  7 + url?: string;
  8 + extra?: ExtraDTO; // 跳转时额外需要带的参数:map<String,String> 即仅有一层的json
  9 + detailPageType?:number; // 详情页类型
  10 +}
@@ -9,6 +9,7 @@ @@ -9,6 +9,7 @@
9 "dependencies": { 9 "dependencies": {
10 "wdConstant": "file:../wdConstant", 10 "wdConstant": "file:../wdConstant",
11 "wdKit": "file:../wdKit", 11 "wdKit": "file:../wdKit",
12 - "wdBean": "file:../wdBean" 12 + "wdBean": "file:../wdBean",
  13 + "wdRouter": "file:../wdRouter"
13 } 14 }
14 } 15 }
1 -import { ContentDTO, ScreenType } from 'wdBean';  
2 -import { CommonConstants } from 'wdConstant'; 1 +import { Action, ContentDTO, Params, ScreenType } from 'wdBean';
  2 +import { CommonConstants, ConfigConstants } from 'wdConstant';
3 import { Logger } from 'wdKit'; 3 import { Logger } from 'wdKit';
4 import { CompUtils } from '../utils/CompUtils'; 4 import { CompUtils } from '../utils/CompUtils';
  5 +import { WDRouterRule } from 'wdRouter';
5 6
6 const TAG: string = 'CardView'; 7 const TAG: string = 'CardView';
7 8
@@ -70,6 +71,13 @@ export struct CarouselLayout01CardView { @@ -70,6 +71,13 @@ export struct CarouselLayout01CardView {
70 .hoverEffect(HoverEffect.Scale) 71 .hoverEffect(HoverEffect.Scale)
71 .onClick((event: ClickEvent) => { 72 .onClick((event: ClickEvent) => {
72 Logger.info(TAG, `BannerComponent onClick event index: ${this.index}`); 73 Logger.info(TAG, `BannerComponent onClick event index: ${this.index}`);
  74 + let taskAction: Action = {
  75 + type: 'JUMP_H5_BY_WEB_VIEW',
  76 + params: {
  77 + url: ConfigConstants.DETAIL_URL
  78 + } as Params,
  79 + };
  80 + WDRouterRule.jumpWithAction(taskAction)
73 }) 81 })
74 } 82 }
75 } 83 }
@@ -143,6 +151,13 @@ export struct SingleColumn01CardView { @@ -143,6 +151,13 @@ export struct SingleColumn01CardView {
143 .hoverEffect(HoverEffect.Scale) 151 .hoverEffect(HoverEffect.Scale)
144 .onClick((event: ClickEvent) => { 152 .onClick((event: ClickEvent) => {
145 Logger.info(TAG, `SingleColumn01CardView onClick event index: ${this.index}`); 153 Logger.info(TAG, `SingleColumn01CardView onClick event index: ${this.index}`);
  154 + let taskAction: Action = {
  155 + type: 'JUMP_H5_BY_WEB_VIEW',
  156 + params: {
  157 + url: ConfigConstants.DETAIL_URL
  158 + } as Params,
  159 + };
  160 + WDRouterRule.jumpWithAction(taskAction)
146 }) 161 })
147 } 162 }
148 } 163 }
@@ -258,6 +273,13 @@ export struct SingleColumn02CardView { @@ -258,6 +273,13 @@ export struct SingleColumn02CardView {
258 .hoverEffect(HoverEffect.Scale) 273 .hoverEffect(HoverEffect.Scale)
259 .onClick((event: ClickEvent) => { 274 .onClick((event: ClickEvent) => {
260 Logger.info(TAG, `SingleColumn02CardView onClick event index: ${this.index}`); 275 Logger.info(TAG, `SingleColumn02CardView onClick event index: ${this.index}`);
  276 + let taskAction: Action = {
  277 + type: 'JUMP_H5_BY_WEB_VIEW',
  278 + params: {
  279 + url: ConfigConstants.DETAIL_URL
  280 + } as Params,
  281 + };
  282 + WDRouterRule.jumpWithAction(taskAction)
261 }) 283 })
262 } 284 }
263 } 285 }
@@ -356,6 +378,13 @@ export struct MasonryLayout01CardView { @@ -356,6 +378,13 @@ export struct MasonryLayout01CardView {
356 .hoverEffect(HoverEffect.Scale) 378 .hoverEffect(HoverEffect.Scale)
357 .onClick((event: ClickEvent) => { 379 .onClick((event: ClickEvent) => {
358 Logger.info(TAG, `MasonryLayout01CardView onClick event index: ${this.index}`); 380 Logger.info(TAG, `MasonryLayout01CardView onClick event index: ${this.index}`);
  381 + let taskAction: Action = {
  382 + type: 'JUMP_H5_BY_WEB_VIEW',
  383 + params: {
  384 + url: ConfigConstants.DETAIL_URL
  385 + } as Params,
  386 + };
  387 + WDRouterRule.jumpWithAction(taskAction)
359 }) 388 })
360 } 389 }
361 } 390 }
1 -import { ContentDTO } from 'wdBean';  
2 -import { CommonConstants } from 'wdConstant'; 1 +import { Action, ContentDTO, Params } from 'wdBean';
  2 +import { CommonConstants, ConfigConstants } from 'wdConstant';
  3 +import { Logger } from 'wdKit';
  4 +import { WDRouterRule } from 'wdRouter';
3 5
4 6
5 const TAG = 'GridLayout01Component'; 7 const TAG = 'GridLayout01Component';
@@ -13,7 +15,7 @@ const TAG = 'GridLayout01Component'; @@ -13,7 +15,7 @@ const TAG = 'GridLayout01Component';
13 export struct GridLayout01Component { 15 export struct GridLayout01Component {
14 @StorageLink('currentBreakpoint') currentBreakpoint: string = 'xs'; 16 @StorageLink('currentBreakpoint') currentBreakpoint: string = 'xs';
15 @State dataList?: ContentDTO[] = undefined 17 @State dataList?: ContentDTO[] = undefined
16 - @State adapterBeanList?:ContentDTO[] = [] 18 + @State adapterBeanList?: ContentDTO[] = []
17 19
18 aboutToAppear() { 20 aboutToAppear() {
19 this.buildAdapterBeanList(this.currentBreakpoint) 21 this.buildAdapterBeanList(this.currentBreakpoint)
@@ -49,12 +51,12 @@ export struct GridLayout01Component { @@ -49,12 +51,12 @@ export struct GridLayout01Component {
49 switch (currentBreakpoint) { 51 switch (currentBreakpoint) {
50 case 'xs': // break; // pass through 52 case 'xs': // break; // pass through
51 case 'sm': 53 case 'sm':
52 - divisor = 2; 54 + divisor = 2;
53 break; 55 break;
54 case 'md': // break; // pass through 56 case 'md': // break; // pass through
55 case 'lg': // break; // pass through 57 case 'lg': // break; // pass through
56 default: 58 default:
57 - divisor = 4; 59 + divisor = 4;
58 break; 60 break;
59 } 61 }
60 this.adapterBeanList = [] // 重置 62 this.adapterBeanList = [] // 重置
@@ -74,28 +76,36 @@ export struct GridLayout01Component { @@ -74,28 +76,36 @@ export struct GridLayout01Component {
74 } 76 }
75 77
76 @Builder 78 @Builder
77 - buildItemTopImgBottomTxt01(item: ContentDTO, index: number){  
78 - Column(){  
79 - Image(item.hImageUrl)  
80 - .width('100%')  
81 - .aspectRatio(16 / 9)  
82 - .borderRadius($r("app.float.image_border_radius"))  
83 - .objectFit(ImageFit.Cover) 79 + buildItemTopImgBottomTxt01(item: ContentDTO, index: number) {
  80 + Column() {
  81 + Image(item.hImageUrl)
  82 + .width('100%')
  83 + .aspectRatio(16 / 9)
  84 + .borderRadius($r("app.float.image_border_radius"))
  85 + .objectFit(ImageFit.Cover)
84 86
85 - Text(item.title)  
86 - .width('100%')  
87 - .margin({ top: 4, left: 6, right: 6 })  
88 - .fontWeight(FontWeight.Normal)  
89 - .textAlign(TextAlign.Start)  
90 - .fontSize($r('app.float.font_size_14'))  
91 - .fontColor($r('app.color.color_333333'))  
92 - .maxLines(2)  
93 - .textOverflow({ overflow: TextOverflow.Ellipsis }) 87 + Text(item.title)
  88 + .width('100%')
  89 + .margin({ top: 4, left: 6, right: 6 })
  90 + .fontWeight(FontWeight.Normal)
  91 + .textAlign(TextAlign.Start)
  92 + .fontSize($r('app.float.font_size_14'))
  93 + .fontColor($r('app.color.color_333333'))
  94 + .maxLines(2)
  95 + .textOverflow({ overflow: TextOverflow.Ellipsis })
94 } 96 }
95 .backgroundColor(Color.White) 97 .backgroundColor(Color.White)
96 .hoverEffect(HoverEffect.Scale) 98 .hoverEffect(HoverEffect.Scale)
97 .alignItems(HorizontalAlign.Start) 99 .alignItems(HorizontalAlign.Start)
98 -  
99 - 100 + .onClick((event: ClickEvent) => {
  101 + Logger.info(TAG, `buildItemTopImgBottomTxt01 onClick event index: ${index}`);
  102 + let taskAction: Action = {
  103 + type: 'JUMP_H5_BY_WEB_VIEW',
  104 + params: {
  105 + url: ConfigConstants.DETAIL_URL
  106 + } as Params,
  107 + };
  108 + WDRouterRule.jumpWithAction(taskAction)
  109 + })
100 } 110 }
101 } 111 }
1 -import { ContentDTO } from 'wdBean'; 1 +import { Action, ContentDTO, Params } from 'wdBean';
  2 +import { ConfigConstants } from 'wdConstant';
  3 +import { Logger } from 'wdKit';
  4 +import { WDRouterRule } from 'wdRouter';
2 5
3 6
4 const TAG = 'SingleRow03Component'; 7 const TAG = 'SingleRow03Component';
@@ -16,7 +19,7 @@ export struct SingleRow03Component { @@ -16,7 +19,7 @@ export struct SingleRow03Component {
16 List( {space: 2.5}){ 19 List( {space: 2.5}){
17 ForEach(this.dataList, (item : ContentDTO, index?: number) =>{ 20 ForEach(this.dataList, (item : ContentDTO, index?: number) =>{
18 ListItem(){ 21 ListItem(){
19 - this.contentItem(item) 22 + this.contentItem(item, index)
20 } 23 }
21 24
22 } , (item: ContentDTO) => JSON.stringify(item)) 25 } , (item: ContentDTO) => JSON.stringify(item))
@@ -29,7 +32,7 @@ export struct SingleRow03Component { @@ -29,7 +32,7 @@ export struct SingleRow03Component {
29 } 32 }
30 33
31 @Builder 34 @Builder
32 - contentItem(item: ContentDTO){ 35 + contentItem(item: ContentDTO, index?: number){
33 Column(){ 36 Column(){
34 RelativeContainer() { 37 RelativeContainer() {
35 Image(item.coverUrl) 38 Image(item.coverUrl)
@@ -97,7 +100,15 @@ export struct SingleRow03Component { @@ -97,7 +100,15 @@ export struct SingleRow03Component {
97 .height($r('app.float.single_row_03_item_height')) 100 .height($r('app.float.single_row_03_item_height'))
98 .backgroundColor(Color.White) 101 .backgroundColor(Color.White)
99 .alignItems(HorizontalAlign.Start) 102 .alignItems(HorizontalAlign.Start)
100 -  
101 - 103 + .onClick((event: ClickEvent) => {
  104 + Logger.info(TAG, `contentItem onClick event index: ${index}`);
  105 + let taskAction: Action = {
  106 + type: 'JUMP_H5_BY_WEB_VIEW',
  107 + params: {
  108 + url: ConfigConstants.DETAIL_URL
  109 + } as Params,
  110 + };
  111 + WDRouterRule.jumpWithAction(taskAction)
  112 + })
102 } 113 }
103 } 114 }
@@ -7,13 +7,11 @@ export class ConfigConstants { @@ -7,13 +7,11 @@ export class ConfigConstants {
7 * 7 *
8 */ 8 */
9 static readonly appId: string = ""; 9 static readonly appId: string = "";
10 -  
11 /** 10 /**
12 * 终端id/terminalId 11 * 终端id/terminalId
13 * 12 *
14 */ 13 */
15 static readonly terminalId: string = "android"; 14 static readonly terminalId: string = "android";
16 -  
17 /** 15 /**
18 * 36_渠道编码(sappType) 16 * 36_渠道编码(sappType)
19 * 17 *
@@ -22,34 +20,27 @@ export class ConfigConstants { @@ -22,34 +20,27 @@ export class ConfigConstants {
22 static readonly appType: string = "3"; // 手机客户端App(安卓) 20 static readonly appType: string = "3"; // 手机客户端App(安卓)
23 21
24 static readonly clientType: string = ""; 22 static readonly clientType: string = "";
25 -  
26 /** 23 /**
27 * SourceID 24 * SourceID
28 * 25 *
29 */ 26 */
30 static readonly sourceId: string = ""; 27 static readonly sourceId: string = "";
31 -  
32 /** 28 /**
33 * 产品渠道应用对照关系: 29 * 产品渠道应用对照关系:
34 */ 30 */
35 static readonly appCode: string = ""; 31 static readonly appCode: string = "";
36 -  
37 /** 32 /**
38 * 基线代码和客户端应用版本号规范 33 * 基线代码和客户端应用版本号规范
39 */ 34 */
40 static readonly ptvCode: string = ""; 35 static readonly ptvCode: string = "";
41 -  
42 -  
43 /** 36 /**
44 * 省份code/province(02->上海) 37 * 省份code/province(02->上海)
45 */ 38 */
46 static readonly province: string = "02"; 39 static readonly province: string = "02";
47 -  
48 /** 40 /**
49 * 正在播放的节目ID 41 * 正在播放的节目ID
50 */ 42 */
51 - static playingContentId?: string = null  
52 - 43 + static playingContentId?: string = undefined
53 /** 44 /**
54 * 设备Id/deviceId 45 * 设备Id/deviceId
55 * 设备Id或者能标识请求端的唯一标识 46 * 设备Id或者能标识请求端的唯一标识
@@ -59,12 +50,10 @@ export class ConfigConstants { @@ -59,12 +50,10 @@ export class ConfigConstants {
59 * base url VOD 50 * base url VOD
60 */ 51 */
61 static readonly BASE_URL_VOD: string = ""; 52 static readonly BASE_URL_VOD: string = "";
62 -  
63 /** 53 /**
64 * base url Live 54 * base url Live
65 */ 55 */
66 static readonly BASE_URL_LIVE: string = ""; 56 static readonly BASE_URL_LIVE: string = "";
67 -  
68 /** 57 /**
69 * 获取用户信息的服务器 58 * 获取用户信息的服务器
70 */ 59 */
@@ -77,4 +66,8 @@ export class ConfigConstants { @@ -77,4 +66,8 @@ export class ConfigConstants {
77 * 电视台(直播)列表路径 66 * 电视台(直播)列表路径
78 */ 67 */
79 static readonly LIVE_TV_PATH: string = "/live/v2/tv-data"; 68 static readonly LIVE_TV_PATH: string = "/live/v2/tv-data";
  69 + /**
  70 + * 临时的详情URL
  71 + */
  72 + static readonly DETAIL_URL = "https://pd-people-uat.pdnews.cn/h/contentTop/110?hiddenTopNavigation=true"
80 } 73 }
  1 +/node_modules
  2 +/oh_modules
  3 +/.preview
  4 +/build
  5 +/.cxx
  6 +/.test
  1 +export { BridgeWebViewControl } from './src/main/ets/core/BridgeWebViewControl'
  2 +
  3 +export { BridgeHandler } from './src/main/ets/core/BridgeHandler'
  4 +
  5 +export { Callback } from './src/main/ets/core/BridgeHandler'
  6 +
  7 +export { BridgeUtil } from './src/main/ets/utils/BridgeUtil'
  1 +{
  2 + "apiType": "stageMode",
  3 + "buildOption": {
  4 + "arkOptions": {
  5 + // "apPath": "./modules.ap" /* Profile used for profile-guided optimization (PGO), a compiler optimization technique to improve app runtime performance. */
  6 + }
  7 + },
  8 + "buildOptionSet": [
  9 + {
  10 + "name": "release",
  11 + "arkOptions": {
  12 + "obfuscation": {
  13 + "ruleOptions": {
  14 + "enable": true,
  15 + "files": [
  16 + "./obfuscation-rules.txt"
  17 + ]
  18 + }
  19 + }
  20 + }
  21 + },
  22 + ],
  23 + "targets": [
  24 + {
  25 + "name": "default"
  26 + }
  27 + ]
  28 +}
  1 +import { harTasks } from '@ohos/hvigor-ohos-plugin';
  2 +
  3 +export default {
  4 + system: harTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
  5 + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
  6 +}
  1 +# Define project specific obfuscation rules here.
  2 +# You can include the obfuscation configuration files in the current module's build-profile.json5.
  3 +#
  4 +# For more details, see
  5 +# https://gitee.com/openharmony/arkcompiler_ets_frontend/blob/master/arkguard/README.md
  6 +
  7 +# Obfuscation options:
  8 +# -disable-obfuscation: disable all obfuscations
  9 +# -enable-property-obfuscation: obfuscate the property names
  10 +# -enable-toplevel-obfuscation: obfuscate the names in the global scope
  11 +# -compact: remove unnecessary blank spaces and all line feeds
  12 +# -remove-log: remove all console.* statements
  13 +# -print-namecache: print the name cache that contains the mapping from the old names to new names
  14 +# -apply-namecache: reuse the given cache file
  15 +
  16 +# Keep options:
  17 +# -keep-property-name: specifies property names that you want to keep
  18 +# -keep-global-name: specifies names that you want to keep in the global scope
  1 +{
  2 + "license": "Apache-2.0",
  3 + "devDependencies": {},
  4 + "author": "",
  5 + "name": "wdjsbridge",
  6 + "description": "Please describe the basic information.",
  7 + "main": "Index.ets",
  8 + "version": "1.0.0",
  9 + "dependencies": {}
  10 +}
  1 +// 事件对象,同wdBean的Action
  2 +export interface Action {
  3 + type: string;
  4 + // params?: Params; // 参数集合
  5 +}
  1 +import { StringUtils } from '../utils/StringUtils';
  2 +
  3 +/**
  4 + * 消息Message
  5 + */
  6 +export class CallBackMessage {
  7 + callbackId: string = ""; //callbackId
  8 + responseId: string = ""; //responseId
  9 + responseData: string = ""; //responseData
  10 + data?: string; //data of message
  11 + handlerName: string = ""; //name of handler
  12 +
  13 + /**
  14 + * TODO 待验证
  15 + * @returns
  16 + */
  17 + toJson(): string {
  18 + let cloneObject:object = JSON.parse(JSON.stringify(this))
  19 + return StringUtils.escapeDoubleQuotes(JSON.stringify(cloneObject))
  20 + }
  21 +
  22 + /**
  23 + * TODO 待验证
  24 + * @param jsonStr
  25 + * @returns
  26 + */
  27 + toList(jsonStr: string): Array<CallBackMessage> {
  28 + return JSON.parse(jsonStr)
  29 + }
  30 +}
  1 +import { Action } from './Action';
  2 +
  3 +/**
  4 + * 消息Message
  5 + */
  6 +export class Message {
  7 + callbackId: string = ""; //callbackId
  8 + responseId: string = ""; //responseId
  9 + responseData: string = ""; //responseData
  10 + data?: Action; //data of message
  11 + handlerName: string = ""; //name of handler
  12 +
  13 + /**
  14 + * TODO 待验证
  15 + * @returns
  16 + */
  17 + toJson(): string {
  18 + let jsonString: string = JSON.stringify(this)
  19 + return jsonString
  20 + }
  21 +
  22 + /**
  23 + * TODO 待验证
  24 + * @param jsonStr
  25 + * @returns
  26 + */
  27 + toList(jsonStr: string): Array<Message> {
  28 + return JSON.parse(jsonStr)
  29 + }
  30 +}
  1 +import { Action } from '../bean/Action'
  2 +
  3 +/**
  4 + * 注册回调接口
  5 + */
  6 +export type Callback = (data: string) => void
  7 +
  8 +export interface BridgeHandler {
  9 + handle: (data: Action, f: Callback) => void
  10 +}
  11 +
  12 +export class DefaultBridgeHandler implements BridgeHandler {
  13 + handle(data: Action, f: Callback) {
  14 + //1,2.3
  15 + f("DefaultHandler response data")
  16 + }
  17 +}
  1 +import webview from '@ohos.web.webview';
  2 +import HashMap from '@ohos.util.HashMap';
  3 +import { BridgeHandler, DefaultBridgeHandler, Callback } from './BridgeHandler';
  4 +import { BridgeUtil } from '../utils/BridgeUtil';
  5 +import { Message } from '../bean/Message';
  6 +import { CallBackMessage } from '../bean/CallBackMessage';
  7 +import { StringUtils } from '../utils/StringUtils';
  8 +
  9 +const TAG = 'BridgeWebViewControl';
  10 +
  11 +export class BridgeWebViewControl extends webview.WebviewController {
  12 + /**
  13 + *
  14 + */
  15 + private responseCallbacks: HashMap<string, Callback> = new HashMap<string, Callback>()
  16 + /**
  17 + *
  18 + */
  19 + private messageHandlers: HashMap<string, BridgeHandler> = new HashMap()
  20 + /**
  21 + * 页面加载前,不能处理消息
  22 + */
  23 + private uniqueId = 0;
  24 +
  25 + registerHandler(handlerName: string, handler: BridgeHandler) {
  26 + if (handler != null) {
  27 + this.messageHandlers.set(handlerName, handler)
  28 + }
  29 + }
  30 +
  31 + unregisterHandler(handlerName: string) {
  32 + if (handlerName != null) {
  33 + this.messageHandlers.remove(handlerName);
  34 + }
  35 + }
  36 +
  37 + /**
  38 + * @param url
  39 + * @param returnCallback
  40 + */
  41 + loadUrlCustom(url: string, returnCallback: Callback) {
  42 + this.loadUrl(url)
  43 + this.responseCallbacks.set(BridgeUtil.parseFunctionName(url), returnCallback);
  44 + }
  45 +
  46 + /**
  47 + * 刷新消息
  48 + */
  49 + flushMessageQueue() {
  50 + this.loadUrlCustom(BridgeUtil.JS_FETCH_QUEUE_FROM_JAVA, (data: string) => {
  51 + let list: Array<Message> = JSON.parse(data)
  52 + if (list == null || list.length == 0) {
  53 + return
  54 + }
  55 + list.forEach(value => {
  56 + let responseId: string = value.responseId
  57 + // 是否是response CallBackFunction,收到消息,
  58 + if (StringUtils.isNotEmpty(responseId)) {
  59 + let call: Callback = this.responseCallbacks.get(responseId)
  60 + let responseData: string = value.responseData;
  61 + if (StringUtils.isEmpty(responseData) || call === undefined) {
  62 + return
  63 + }
  64 + call(responseData)
  65 + this.responseCallbacks.remove(responseId)
  66 + } else {
  67 + let responseFunction: Callback;
  68 + let callbackId: string = value.callbackId
  69 + if (StringUtils.isNotEmpty(callbackId)) {
  70 + responseFunction = (data: string) => {
  71 + let msg: CallBackMessage = new CallBackMessage()
  72 + msg.responseId = callbackId
  73 + msg.responseData = data
  74 + this.queueMessage(msg)
  75 + }
  76 + } else {
  77 + responseFunction = (data: string) => {
  78 + //TODO 更换log输出方式
  79 + // Logger.info(TAG, `default response:: ${data}`);
  80 + }
  81 + }
  82 + let handle: BridgeHandler
  83 + if (StringUtils.isNotEmpty(value.handlerName)) {
  84 + handle = this.messageHandlers.get(value.handlerName)
  85 + } else {
  86 + handle = new DefaultBridgeHandler()
  87 + }
  88 + if (handle != undefined && value.data != undefined) {
  89 + handle.handle(value.data, responseFunction)
  90 + }
  91 + }
  92 + })
  93 +
  94 + })
  95 +
  96 + }
  97 +
  98 + private queueMessage(msg: CallBackMessage) {
  99 + // //TODO
  100 + this.dispatchMessage(msg);
  101 + // }
  102 + }
  103 +
  104 + /**
  105 + * 消息分发,最终执行js方法
  106 + * @param msg
  107 + */
  108 + private dispatchMessage(msg: CallBackMessage) {
  109 + let messageJson: string = msg.toJson()
  110 + // messageJson = messageJson.replace("%7B", encodeURIComponent("%7B"));
  111 + // messageJson = messageJson.replace("%7D", encodeURIComponent("%7D"));
  112 + // messageJson = messageJson.replace("%22", encodeURIComponent("%22"));
  113 +
  114 + let javascriptCommand: string = StringUtils.formatStringForJS(BridgeUtil.JS_HANDLE_MESSAGE_FROM_JAVA, messageJson);
  115 + this.runJavaScript(javascriptCommand)
  116 + }
  117 +
  118 + /**
  119 + * native 主动调用JSBridge方法
  120 + * @param msg
  121 + */
  122 + callHandle(handlerName: string, data: string, callBack: Callback) {
  123 + this.doSend(handlerName, data, callBack)
  124 + }
  125 +
  126 + private doSend(handlerName: string, data: string, callBack: Callback) {
  127 + let msg: CallBackMessage = new CallBackMessage()
  128 + if (StringUtils.isNotEmpty(data)) {
  129 + // msg.data = data
  130 + }
  131 + if (StringUtils.isNotEmpty(handlerName)) {
  132 + msg.handlerName = handlerName
  133 + }
  134 + if (callBack != undefined) {
  135 + let callbackId: string = StringUtils.formatStringForJS(BridgeUtil.CALLBACK_ID_FORMAT, ++this.uniqueId + (BridgeUtil.UNDERLINE_STR + new Date().getTime()));
  136 + this.responseCallbacks.set(callbackId, callBack)
  137 + msg.callbackId = callbackId
  138 + }
  139 + this.queueMessage(msg);
  140 + }
  141 +
  142 + handlerReturnData(url: string) {
  143 + let functionName: string = BridgeUtil.getFunctionFromReturnUrl(url);
  144 + let callback = this.responseCallbacks.get(functionName);
  145 + let data: string = BridgeUtil.getDataFromReturnUrl(url);
  146 + if (callback != undefined) {
  147 + callback(data)
  148 + this.responseCallbacks.remove(functionName)
  149 + }
  150 + }
  151 +
  152 + //TODO
  153 + clean() {
  154 + this.responseCallbacks.clear()
  155 + this.messageHandlers.clear()
  156 + this.uniqueId = 0
  157 + }
  158 +}
  159 +
  160 +
  161 +
  1 +import webview from '@ohos.web.webview';
  2 +import { ResourceManager } from './ResourceManager';
  3 +
  4 +export class BridgeUtil {
  5 + static readonly YY_OVERRIDE_SCHEMA = "yy://";
  6 + static readonly YY_RETURN_DATA = BridgeUtil.YY_OVERRIDE_SCHEMA + "return/";
  7 + static readonly YY_FETCH_QUEUE = BridgeUtil.YY_RETURN_DATA + "_fetchQueue/";
  8 + static readonly EMPTY_STR = "";
  9 + static readonly UNDERLINE_STR = "_";
  10 + static readonly SPLIT_MARK = "/";
  11 + static readonly CALLBACK_ID_FORMAT = "JAVA_CB_%s";
  12 + static readonly JS_HANDLE_MESSAGE_FROM_JAVA = "javascript:WebViewJavascriptBridge._handleMessageFromNative('%s');";
  13 + static readonly JS_FETCH_QUEUE_FROM_JAVA = "javascript:WebViewJavascriptBridge._fetchQueue();";
  14 + static readonly JAVASCRIPT_STR = "javascript:";
  15 +
  16 + // 例子 javascript:WebViewJavascriptBridge._fetchQueue(); --> _fetchQueue
  17 + static parseFunctionName(jsUrl: string): string {
  18 + return jsUrl.replace("javascript:WebViewJavascriptBridge.", "").replace("();", "");
  19 + }
  20 +
  21 + static getDataFromReturnUrl(url: string): string {
  22 + if (url.startsWith(BridgeUtil.YY_FETCH_QUEUE)) {
  23 + // return = [{"responseId":"JAVA_CB_2_3957","responseData":"Javascript Says Right back aka!"}]
  24 + return url.replace(BridgeUtil.YY_FETCH_QUEUE, BridgeUtil.EMPTY_STR);
  25 + }
  26 + // temp = _fetchQueue/[{"responseId":"JAVA_CB_2_3957","responseData":"Javascript Says Right back aka!"}]
  27 + let temp = url.replace(BridgeUtil.YY_RETURN_DATA, BridgeUtil.EMPTY_STR);
  28 + let functionAndData = temp.split(BridgeUtil.SPLIT_MARK);
  29 + if (functionAndData.length < 2) {
  30 + return ""
  31 + }
  32 + let result = ""
  33 + functionAndData.forEach((value) => {
  34 + result = result + value
  35 + });
  36 + return result
  37 +
  38 + }
  39 +
  40 + /**
  41 + * TODO
  42 + */
  43 + static releaseWebView() {
  44 +
  45 + }
  46 +
  47 + // 获取到传递信息的方法
  48 + // url = yy://return/_fetchQueue/[{"responseId":"JAVA_CB_1_360","responseData":"Javascript Says Right back aka!"}]
  49 + static getFunctionFromReturnUrl(url: string): string {
  50 + let temp = url.replace(BridgeUtil.YY_RETURN_DATA, BridgeUtil.EMPTY_STR);
  51 + let functionAndData = temp.split(BridgeUtil.SPLIT_MARK);
  52 + if (functionAndData.length >= 1) {
  53 + // functionAndData[0] = _fetchQueue
  54 + return functionAndData[0];
  55 + }
  56 + return ""
  57 + }
  58 +
  59 + /**
  60 + * 这里只是加载lib包中assets中的 WebViewJavascriptBridge.js
  61 + * @param controller
  62 + * @param path 路径
  63 + */
  64 + static webViewLoadLocalJs(context: Context, controller: webview.WebviewController) {
  65 + ResourceManager.getResourcesText(context, "WebViewJavascriptBridge.js").then((str) => {
  66 + //执行js注入
  67 + controller.runJavaScriptExt('javascript:' + str).then((msg) => {
  68 + console.log("Js注入结果:" + msg.getString());
  69 + })
  70 + })
  71 + }
  72 +
  73 +}
  1 +import buffer from '@ohos.buffer';
  2 +
  3 +export class ResourceManager {
  4 + /**
  5 + * 获取资源字符串内容
  6 + * @param context
  7 + * @param filename
  8 + * @returns
  9 + */
  10 + static getResourcesText(context: Context, filename: string): Promise<string> {
  11 + return new Promise<string>((success, error) => {
  12 + context.resourceManager.getRawFileContent(filename).then((content: Uint8Array) => {
  13 + if (!content) {
  14 + error("file is empty");
  15 + return
  16 + }
  17 + let result = buffer.from(content).toString("utf8");
  18 + if (result) {
  19 + success(result);
  20 + } else {
  21 + error("parse resources file result is empty");
  22 + }
  23 + }).catch((err: Error) => {
  24 + error(err);
  25 + })
  26 + })
  27 + }
  28 +}
  1 +/**
  2 + * StringUtils class.
  3 + */
  4 +export class StringUtils {
  5 +
  6 + /**
  7 + * Check obj is not empty.
  8 + *
  9 + * @param {object} obj
  10 + * @return {boolean} true(not empty)
  11 + */
  12 + static isNotEmpty(obj: any): boolean {
  13 + // return (obj && obj !== '');
  14 + // 或
  15 + return (obj !== undefined && obj !== null && obj !== '');
  16 + }
  17 +
  18 +
  19 + static isEmpty(...params: any): boolean {
  20 + if (params.length === 0) {
  21 + return true;
  22 + }
  23 + for (const param of params) {
  24 + if (!param) { // param === undefined || param === null || param === '';
  25 + return true;
  26 + }
  27 + }
  28 + return false;
  29 + }
  30 +
  31 +
  32 + static formatStringForJS(template: string, ...args: any[]): string {
  33 + let formattedString = template;
  34 + for (const arg of args) {
  35 + formattedString = formattedString.replace(/%s/, arg.toString());
  36 + }
  37 + return formattedString;
  38 + }
  39 +
  40 +
  41 + static escapeDoubleQuotes(obj:any): any {
  42 + if (typeof obj === 'string') {
  43 + return obj.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
  44 + } else if (typeof obj === 'object') {
  45 + for (let key in obj) {
  46 + if (obj.hasOwnProperty(key)) {
  47 + obj[key] = StringUtils.escapeDoubleQuotes(obj[key]);
  48 + }
  49 + }
  50 + }
  51 + return obj;
  52 + }
  53 +
  54 +}
  55 +// export default new StringUtils();
  1 +{
  2 + "module": {
  3 + "name": "wdJsBridge",
  4 + "type": "har",
  5 + "description": "$string:shared_desc",
  6 + "deviceTypes": [
  7 + "phone",
  8 + "tablet",
  9 + "2in1"
  10 + ]
  11 + }
  12 +}
  1 +{
  2 + "color": [
  3 + {
  4 + "name": "white",
  5 + "value": "#FFFFFF"
  6 + }
  7 + ]
  8 +}
  1 +{
  2 + "string": [
  3 + {
  4 + "name": "shared_desc",
  5 + "value": "description"
  6 + }
  7 + ]
  8 +}
  1 +//notation: js file can only use this kind of comments
  2 +//since comments will cause error when use in webview.loadurl,
  3 +//comments will be remove by java use regexp
  4 +(function() {
  5 + if (window.WebViewJavascriptBridge) {
  6 + return;
  7 + }
  8 +
  9 + var messagingIframe;
  10 + var bizMessagingIframe;
  11 + var sendMessageQueue = [];
  12 + var receiveMessageQueue = [];
  13 + var messageHandlers = {};
  14 +
  15 + var CUSTOM_PROTOCOL_SCHEME = 'yy';
  16 + var QUEUE_HAS_MESSAGE = '__QUEUE_MESSAGE__/';
  17 +
  18 + var responseCallbacks = {};
  19 + var uniqueId = 1;
  20 +
  21 + // 创建消息index队列iframe
  22 + function _createQueueReadyIframe(doc) {
  23 + messagingIframe = doc.createElement('iframe');
  24 + messagingIframe.style.display = 'none';
  25 + doc.documentElement.appendChild(messagingIframe);
  26 + }
  27 + //创建消息体队列iframe
  28 + function _createQueueReadyIframe4biz(doc) {
  29 + bizMessagingIframe = doc.createElement('iframe');
  30 + bizMessagingIframe.style.display = 'none';
  31 + doc.documentElement.appendChild(bizMessagingIframe);
  32 + }
  33 + //set default messageHandler 初始化默认的消息线程
  34 + function init(messageHandler) {
  35 + if (WebViewJavascriptBridge._messageHandler) {
  36 + throw new Error('WebViewJavascriptBridge.init called twice');
  37 + }
  38 + WebViewJavascriptBridge._messageHandler = messageHandler;
  39 + var receivedMessages = receiveMessageQueue;
  40 + receiveMessageQueue = null;
  41 + for (var i = 0; i < receivedMessages.length; i++) {
  42 + _dispatchMessageFromNative(receivedMessages[i]);
  43 + }
  44 + }
  45 +
  46 + // 发送
  47 + function send(data, responseCallback) {
  48 + _doSend({
  49 + data: data
  50 + }, responseCallback);
  51 + }
  52 +
  53 + // 注册线程 往数组里面添加值
  54 + function registerHandler(handlerName, handler) {
  55 + messageHandlers[handlerName] = handler;
  56 + }
  57 + // 调用线程
  58 + function callHandler(handlerName, data, responseCallback) {
  59 + _doSend({
  60 + handlerName: handlerName,
  61 + data: data
  62 + }, responseCallback);
  63 + }
  64 +
  65 + //sendMessage add message, 触发native处理 sendMessage
  66 + function _doSend(message, responseCallback) {
  67 + if (responseCallback) {
  68 + var callbackId = 'cb_' + (uniqueId++) + '_' + new Date().getTime();
  69 + responseCallbacks[callbackId] = responseCallback;
  70 + message.callbackId = callbackId;
  71 + }
  72 +
  73 + sendMessageQueue.push(message);
  74 + messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://' + QUEUE_HAS_MESSAGE;
  75 + }
  76 +
  77 + // 提供给native调用,该函数作用:获取sendMessageQueue返回给native,由于android不能直接获取返回的内容,所以使用url shouldOverrideUrlLoading 的方式返回内容
  78 + function _fetchQueue() {
  79 + var messageQueueString = JSON.stringify(sendMessageQueue);
  80 + sendMessageQueue = [];
  81 + //android can't read directly the return data, so we can reload iframe src to communicate with java
  82 + if (messageQueueString !== '[]') {
  83 + bizMessagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://return/_fetchQueue/' + encodeURIComponent(messageQueueString);
  84 + }
  85 + }
  86 +
  87 + //提供给native使用,
  88 + function _dispatchMessageFromNative(messageJSON) {
  89 + setTimeout(function() {
  90 + var message = JSON.parse(messageJSON);
  91 + var responseCallback;
  92 + //java call finished, now need to call js callback function
  93 + if (message.responseId) {
  94 + responseCallback = responseCallbacks[message.responseId];
  95 + if (!responseCallback) {
  96 + return;
  97 + }
  98 + responseCallback(message.responseData);
  99 + delete responseCallbacks[message.responseId];
  100 + } else {
  101 + //直接发送
  102 + if (message.callbackId) {
  103 + var callbackResponseId = message.callbackId;
  104 + responseCallback = function(responseData) {
  105 + _doSend({
  106 + responseId: callbackResponseId,
  107 + responseData: responseData
  108 + });
  109 + };
  110 + }
  111 +
  112 + var handler = WebViewJavascriptBridge._messageHandler;
  113 + if (message.handlerName) {
  114 + handler = messageHandlers[message.handlerName];
  115 + }
  116 + //查找指定handler
  117 + try {
  118 + handler(message.data, responseCallback);
  119 + } catch (exception) {
  120 + if (typeof console != 'undefined') {
  121 + console.log("WebViewJavascriptBridge: WARNING: javascript handler threw.", message, exception);
  122 + }
  123 + }
  124 + }
  125 + });
  126 + }
  127 +
  128 + //提供给native调用,receiveMessageQueue 在会在页面加载完后赋值为null,所以
  129 + function _handleMessageFromNative(messageJSON) {
  130 + //console.log(messageJSON);
  131 + if (receiveMessageQueue) {
  132 + receiveMessageQueue.push(messageJSON);
  133 + }
  134 + _dispatchMessageFromNative(messageJSON);
  135 +
  136 + }
  137 +
  138 + var WebViewJavascriptBridge = window.WebViewJavascriptBridge = {
  139 + init: init,
  140 + send: send,
  141 + registerHandler: registerHandler,
  142 + callHandler: callHandler,
  143 + _fetchQueue: _fetchQueue,
  144 + _handleMessageFromNative: _handleMessageFromNative
  145 + };
  146 +
  147 + var doc = document;
  148 + _createQueueReadyIframe(doc);
  149 + _createQueueReadyIframe4biz(doc);
  150 + var readyEvent = doc.createEvent('Events');
  151 + readyEvent.initEvent('WebViewJavascriptBridgeReady');
  152 + readyEvent.bridge = WebViewJavascriptBridge;
  153 + doc.dispatchEvent(readyEvent);
  154 +})();
  1 +//notation: js file can only use this kind of comments
  2 +//since comments will cause error when use in webview.loadurl,
  3 +//comments will be remove by java use regexp
  4 +(function() {
  5 + if (window.WebViewJavascriptBridge) {
  6 + return;
  7 + }
  8 +
  9 + var messagingIframe;
  10 + var bizMessagingIframe;
  11 + var sendMessageQueue = [];
  12 + var receiveMessageQueue = [];
  13 + var messageHandlers = {};
  14 +
  15 + var CUSTOM_PROTOCOL_SCHEME = 'yy';
  16 + var QUEUE_HAS_MESSAGE = '__QUEUE_MESSAGE__/';
  17 +
  18 + var responseCallbacks = {};
  19 + var uniqueId = 1;
  20 +
  21 + // 创建消息index队列iframe
  22 + function _createQueueReadyIframe(doc) {
  23 + messagingIframe = doc.createElement('iframe');
  24 + messagingIframe.style.display = 'none';
  25 + doc.documentElement.appendChild(messagingIframe);
  26 + }
  27 + //创建消息体队列iframe
  28 + function _createQueueReadyIframe4biz(doc) {
  29 + bizMessagingIframe = doc.createElement('iframe');
  30 + bizMessagingIframe.style.display = 'none';
  31 + doc.documentElement.appendChild(bizMessagingIframe);
  32 + }
  33 + //set default messageHandler 初始化默认的消息线程
  34 + function init(messageHandler) {
  35 + if (WebViewJavascriptBridge._messageHandler) {
  36 + throw new Error('WebViewJavascriptBridge.init called twice');
  37 + }
  38 + WebViewJavascriptBridge._messageHandler = messageHandler;
  39 + var receivedMessages = receiveMessageQueue;
  40 + receiveMessageQueue = null;
  41 + for (var i = 0; i < receivedMessages.length; i++) {
  42 + _dispatchMessageFromNative(receivedMessages[i]);
  43 + }
  44 + }
  45 +
  46 + // 发送
  47 + function send(data, responseCallback) {
  48 + _doSend({
  49 + data: data
  50 + }, responseCallback);
  51 + }
  52 +
  53 + // 注册线程 往数组里面添加值
  54 + function registerHandler(handlerName, handler) {
  55 + messageHandlers[handlerName] = handler;
  56 + }
  57 + // 调用线程
  58 + function callHandler(handlerName, data, responseCallback) {
  59 + _doSend({
  60 + handlerName: handlerName,
  61 + data: data
  62 + }, responseCallback);
  63 + }
  64 +
  65 + //sendMessage add message, 触发native处理 sendMessage
  66 + function _doSend(message, responseCallback) {
  67 + if (responseCallback) {
  68 + var callbackId = 'cb_' + (uniqueId++) + '_' + new Date().getTime();
  69 + responseCallbacks[callbackId] = responseCallback;
  70 + message.callbackId = callbackId;
  71 + }
  72 +
  73 + sendMessageQueue.push(message);
  74 + messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://' + QUEUE_HAS_MESSAGE;
  75 + }
  76 +
  77 + // 提供给native调用,该函数作用:获取sendMessageQueue返回给native,由于android不能直接获取返回的内容,所以使用url shouldOverrideUrlLoading 的方式返回内容
  78 + function _fetchQueue() {
  79 + var messageQueueString = JSON.stringify(sendMessageQueue);
  80 + sendMessageQueue = [];
  81 + //android can't read directly the return data, so we can reload iframe src to communicate with java
  82 + if (messageQueueString !== '[]') {
  83 + bizMessagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://return/_fetchQueue/' + encodeURIComponent(messageQueueString);
  84 + }
  85 + }
  86 +
  87 + //提供给native使用,
  88 + function _dispatchMessageFromNative(messageJSON) {
  89 + setTimeout(function() {
  90 + var message = JSON.parse(messageJSON);
  91 + var responseCallback;
  92 + //java call finished, now need to call js callback function
  93 + if (message.responseId) {
  94 + responseCallback = responseCallbacks[message.responseId];
  95 + if (!responseCallback) {
  96 + return;
  97 + }
  98 + responseCallback(message.responseData);
  99 + delete responseCallbacks[message.responseId];
  100 + } else {
  101 + //直接发送
  102 + if (message.callbackId) {
  103 + var callbackResponseId = message.callbackId;
  104 + responseCallback = function(responseData) {
  105 + _doSend({
  106 + responseId: callbackResponseId,
  107 + responseData: responseData
  108 + });
  109 + };
  110 + }
  111 +
  112 + var handler = WebViewJavascriptBridge._messageHandler;
  113 + if (message.handlerName) {
  114 + handler = messageHandlers[message.handlerName];
  115 + }
  116 + //查找指定handler
  117 + try {
  118 + handler(message.data, responseCallback);
  119 + } catch (exception) {
  120 + if (typeof console != 'undefined') {
  121 + console.log("WebViewJavascriptBridge: WARNING: javascript handler threw.", message, exception);
  122 + }
  123 + }
  124 + }
  125 + });
  126 + }
  127 +
  128 + //提供给native调用,receiveMessageQueue 在会在页面加载完后赋值为null,所以
  129 + function _handleMessageFromNative(messageJSON) {
  130 + //console.log(messageJSON);
  131 + if (receiveMessageQueue) {
  132 + receiveMessageQueue.push(messageJSON);
  133 + }
  134 + _dispatchMessageFromNative(messageJSON);
  135 +
  136 + }
  137 +
  138 + var WebViewJavascriptBridge = window.WebViewJavascriptBridge = {
  139 + init: init,
  140 + send: send,
  141 + registerHandler: registerHandler,
  142 + callHandler: callHandler,
  143 + _fetchQueue: _fetchQueue,
  144 + _handleMessageFromNative: _handleMessageFromNative
  145 + };
  146 +
  147 + var doc = document;
  148 + _createQueueReadyIframe(doc);
  149 + _createQueueReadyIframe4biz(doc);
  150 + var readyEvent = doc.createEvent('Events');
  151 + readyEvent.initEvent('WebViewJavascriptBridgeReady');
  152 + readyEvent.bridge = WebViewJavascriptBridge;
  153 + doc.dispatchEvent(readyEvent);
  154 +})();
  1 +import localUnitTest from './LocalUnit.test';
  2 +
  3 +export default function testsuite() {
  4 + localUnitTest();
  5 +}
  1 +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium';
  2 +
  3 +export default function localUnitTest() {
  4 + describe('localUnitTest',() => {
  5 + // Defines a test suite. Two parameters are supported: test suite name and test suite function.
  6 + beforeAll(() => {
  7 + // Presets an action, which is performed only once before all test cases of the test suite start.
  8 + // This API supports only one parameter: preset action function.
  9 + });
  10 + beforeEach(() => {
  11 + // Presets an action, which is performed before each unit test case starts.
  12 + // The number of execution times is the same as the number of test cases defined by **it**.
  13 + // This API supports only one parameter: preset action function.
  14 + });
  15 + afterEach(() => {
  16 + // Presets a clear action, which is performed after each unit test case ends.
  17 + // The number of execution times is the same as the number of test cases defined by **it**.
  18 + // This API supports only one parameter: clear action function.
  19 + });
  20 + afterAll(() => {
  21 + // Presets a clear action, which is performed after all test cases of the test suite end.
  22 + // This API supports only one parameter: clear action function.
  23 + });
  24 + it('assertContain', 0, () => {
  25 + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
  26 + let a = 'abc';
  27 + let b = 'b';
  28 + // Defines a variety of assertion methods, which are used to declare expected boolean conditions.
  29 + expect(a).assertContain(b);
  30 + expect(a).assertEqual(a);
  31 + });
  32 + });
  33 +}
@@ -13,3 +13,5 @@ export { BasicDataSource } from './src/main/ets/utils/BasicDataSource'; @@ -13,3 +13,5 @@ export { BasicDataSource } from './src/main/ets/utils/BasicDataSource';
13 export { LazyDataSource } from './src/main/ets/utils/LazyDataSource' 13 export { LazyDataSource } from './src/main/ets/utils/LazyDataSource'
14 14
15 export { BreakpointSystem, BreakPointType } from './src/main/ets/utils/BreakPointSystem'; 15 export { BreakpointSystem, BreakPointType } from './src/main/ets/utils/BreakPointSystem';
  16 +
  17 +export { ToastUtils } from './src/main/ets/utils/ToastUtils';
1 -import common from '@ohos.app.ability.common';  
2 import bundleManager from '@ohos.bundle.bundleManager'; 1 import bundleManager from '@ohos.bundle.bundleManager';
  2 +import common from '@ohos.app.ability.common';
  3 +import { Logger } from './Logger';
3 4
4 const TAG: string = 'AppUtils'; 5 const TAG: string = 'AppUtils';
5 6
@@ -34,6 +35,7 @@ export class AppUtils { @@ -34,6 +35,7 @@ export class AppUtils {
34 let bundleInfo = bundleManager.getBundleInfoForSelfSync(bundleManager.BundleFlag.GET_BUNDLE_INFO_DEFAULT) 35 let bundleInfo = bundleManager.getBundleInfoForSelfSync(bundleManager.BundleFlag.GET_BUNDLE_INFO_DEFAULT)
35 return bundleInfo?.versionName 36 return bundleInfo?.versionName
36 } catch (e) { 37 } catch (e) {
  38 + Logger.warn(TAG, 'get app version error:' + e?.message);
37 } 39 }
38 return ""; 40 return "";
39 } 41 }
@@ -43,13 +45,13 @@ export class AppUtils { @@ -43,13 +45,13 @@ export class AppUtils {
43 * @returns 应用版本编码 45 * @returns 应用版本编码
44 */ 46 */
45 static getAppVersionCode(): string { 47 static getAppVersionCode(): string {
46 - return "2600010700"  
47 - // try {  
48 - // let bundleInfo = bundleManager.getBundleInfoForSelfSync(bundleManager.BundleFlag.GET_BUNDLE_INFO_DEFAULT)  
49 - // return bundleInfo?.versionCode  
50 - // } catch (e) {  
51 - // Logger.warn(TAG, 'get app version error:' + e?.message);  
52 - // }  
53 - // return 0; 48 + try {
  49 + let bundleInfo = bundleManager.getBundleInfoForSelfSync(bundleManager.BundleFlag.GET_BUNDLE_INFO_DEFAULT)
  50 + return bundleInfo?.versionCode + ""
  51 + } catch (e) {
  52 + Logger.warn(TAG, 'get app version error:' + e?.message);
  53 + }
  54 + return '';
54 } 55 }
55 } 56 }
  57 +
  1 +import prompt from '@ohos.promptAction'
  2 +
  3 +export class ToastUtils {
  4 + private static longToastTime: number = 3000
  5 + private static shortToastTime: number = 1000
  6 +
  7 + static showToast(message: ResourceStr, duration: number) {
  8 + prompt.showToast({ message: message, duration: duration })
  9 + }
  10 +
  11 + static shortToast(message: ResourceStr) {
  12 + ToastUtils.showToast(message, ToastUtils.shortToastTime)
  13 + }
  14 +
  15 + static longToast(message: ResourceStr) {
  16 + ToastUtils.showToast(message, ToastUtils.longToastTime)
  17 + }
  18 +}
  19 +
  20 +// export default new ToastUtils()
  1 +/node_modules
  2 +/oh_modules
  3 +/.preview
  4 +/build
  5 +/.cxx
  6 +/.test
@@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
7 "main": "Index.ets", 7 "main": "Index.ets",
8 "version": "1.0.0", 8 "version": "1.0.0",
9 "dependencies": { 9 "dependencies": {
10 - "@ohos/axios": "^2.1.1",  
11 - "wdKit": "file:../wdKit" 10 + "wdKit": "file:../wdKit",
  11 + "@ohos/axios": "^2.1.1"
12 } 12 }
13 } 13 }
  1 +/node_modules
  2 +/oh_modules
  3 +/.preview
  4 +/build
  5 +/.cxx
  6 +/.test
  1 +export { WDRouterRule } from './src/main/ets/router/WDRouterRule'
  2 +
  3 +export { WDRouterPage } from './src/main/ets/router/WDRouterPage'
  4 +
  5 +export { registerRouter } from './src/main/ets/router/Action2Page'
  1 +{
  2 + "apiType": "stageMode",
  3 + "buildOption": {
  4 + "arkOptions": {
  5 + // "apPath": "./modules.ap" /* Profile used for profile-guided optimization (PGO), a compiler optimization technique to improve app runtime performance. */
  6 + }
  7 + },
  8 + "buildOptionSet": [
  9 + {
  10 + "name": "release",
  11 + "arkOptions": {
  12 + "obfuscation": {
  13 + "ruleOptions": {
  14 + "enable": true,
  15 + "files": [
  16 + "./obfuscation-rules.txt"
  17 + ]
  18 + }
  19 + }
  20 + }
  21 + },
  22 + ],
  23 + "targets": [
  24 + {
  25 + "name": "default"
  26 + }
  27 + ]
  28 +}
  1 +import { hspTasks } from '@ohos/hvigor-ohos-plugin';
  2 +
  3 +export default {
  4 + system: hspTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
  5 + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
  6 +}
  1 +# Define project specific obfuscation rules here.
  2 +# You can include the obfuscation configuration files in the current module's build-profile.json5.
  3 +#
  4 +# For more details, see
  5 +# https://gitee.com/openharmony/arkcompiler_ets_frontend/blob/master/arkguard/README.md
  6 +
  7 +# Obfuscation options:
  8 +# -disable-obfuscation: disable all obfuscations
  9 +# -enable-property-obfuscation: obfuscate the property names
  10 +# -enable-toplevel-obfuscation: obfuscate the names in the global scope
  11 +# -compact: remove unnecessary blank spaces and all line feeds
  12 +# -remove-log: remove all console.* statements
  13 +# -print-namecache: print the name cache that contains the mapping from the old names to new names
  14 +# -apply-namecache: reuse the given cache file
  15 +
  16 +# Keep options:
  17 +# -keep-property-name: specifies property names that you want to keep
  18 +# -keep-global-name: specifies names that you want to keep in the global scope
  1 +{
  2 + "license": "Apache-2.0",
  3 + "devDependencies": {},
  4 + "author": "",
  5 + "name": "wdrouter",
  6 + "description": "Please describe the basic information.",
  7 + "main": "Index.ets",
  8 + "version": "1.0.0",
  9 + "dependencies": {
  10 + "wdKit": "file:../wdKit",
  11 + "wdBean": "file:../wdBean"
  12 + }
  13 +}
  1 +import { WDRouterPage } from './WDRouterPage'
  2 +import { Action } from 'wdBean'
  3 +import ArrayList from '@ohos.util.ArrayList';
  4 +
  5 +interface HandleObject {
  6 + handle: (action: Action) => (WDRouterPage | undefined)
  7 + priority: number
  8 +}
  9 +
  10 +export class Action2Page {
  11 +
  12 + private static handles: Record<string, ArrayList<HandleObject>> = {};
  13 +
  14 + static register(actionType: string, handle: (action: Action) => (WDRouterPage | undefined), priority: number = 0) {
  15 + let handles = Action2Page.handles[actionType] ?? new ArrayList();
  16 + let obj: HandleObject = {
  17 + handle: handle,
  18 + priority: priority
  19 + };
  20 + handles.add(obj);
  21 + handles.sort((f, s) => {
  22 + return f.priority - s.priority;
  23 + })
  24 + Action2Page.handles[actionType] = handles;
  25 + }
  26 +
  27 + static get(action?: Action): WDRouterPage | undefined {
  28 + if (!action || !action.type) {
  29 + return undefined;
  30 + }
  31 + let handles = Action2Page.handles[action.type];
  32 + if (!handles) {
  33 + return undefined;
  34 + }
  35 + let page: WDRouterPage | undefined
  36 + for (let i = 0; i < handles.length; i++) {
  37 + let tmp = (handles[i] as HandleObject).handle(action);
  38 + if (tmp) {
  39 + page = tmp;
  40 + break
  41 + }
  42 + }
  43 + return page
  44 + }
  45 +}
  46 +
  47 +export function registerRouter() {
  48 + // Action2Page.register("USER_LOGIN", (action: Action) => {
  49 + // return WDRouterPage.webLoginPage
  50 + // })
  51 +
  52 + // Action2Page.register("JUMP_DETAIL_PAGE", (action) => {
  53 + // if (action.params?.pageID == "296ff8a4b07d457cb15b6f9e5f433cc0") {
  54 + // return WDRouterPage.tvLivePage
  55 + // }
  56 + // if (action.params?.detailPageType == 7 || action.params?.detailPageType == 8) {
  57 + // return WDRouterPage.shortVideoDetail
  58 + // }
  59 + // return WDRouterPage.playDetail
  60 + // })
  61 +
  62 + Action2Page.register("JUMP_H5_BY_WEB_VIEW", (action) => {
  63 + return WDRouterPage.defaultWebPage
  64 + })
  65 +
  66 + // Action2Page.register("JUMP_INNER_NEW_PAGE", (action) => {
  67 + // if (action.params?.pageID == "WORLDCUP_DETAIL") {
  68 + // return WDRouterPage.livependantpage
  69 + // }
  70 + // return undefined
  71 + // })
  72 +}
  1 +import bundleManager from '@ohos.bundle.bundleManager'
  2 +
  3 +export class WDRouterPage {
  4 + private moduleName: string
  5 + private pagePath: string
  6 +
  7 + constructor(moduleName: string, pagePath: string) {
  8 + this.moduleName = moduleName
  9 + this.pagePath = pagePath
  10 + }
  11 +
  12 + url() {
  13 + let bundleInfo = bundleManager.getBundleInfoForSelfSync(bundleManager.BundleFlag.GET_BUNDLE_INFO_DEFAULT)
  14 + return `@bundle:${bundleInfo.name}/${this.moduleName}/${this.pagePath}`
  15 + }
  16 +
  17 + // 主页
  18 + static index = new WDRouterPage("entry", "ets/pages/Index");
  19 + // 关于页面
  20 + // static aboutPage = new WDRouterPage("entry", "ets/pages/about/AboutPage");
  21 + // web默认页面
  22 + static defaultWebPage = new WDRouterPage("entry", "ets/pages/web/DefaultWebPage");
  23 +}
  1 +import router from '@ohos.router'
  2 +import { Action } from 'wdBean'
  3 +import { ToastUtils } from 'wdKit'
  4 +import { Action2Page } from './Action2Page'
  5 +import { WDRouterPage } from './WDRouterPage'
  6 +
  7 +export class WDRouterRule {
  8 + static jumpWithAction(action?: Action) {
  9 + if (!action || !action.type) {
  10 + ToastUtils.showToast("跳转参数异常", 1000);
  11 + return
  12 + }
  13 + let page = Action2Page.get(action);
  14 + WDRouterRule.jumpWithPage(page, action)
  15 + }
  16 +
  17 + private static jumpWithPage(page?: WDRouterPage, params?: object) {
  18 + if (page) {
  19 + if (params) {
  20 + // router.pushUrl({ url: 'pages/routerpage2', , params: params })
  21 + router.pushUrl({ url: page.url(), params: params })
  22 + } else {
  23 + router.pushUrl({ url: page.url() })
  24 + }
  25 + } else {
  26 + ToastUtils.showToast("功能开发中", 1000);
  27 + }
  28 + }
  29 +}
  1 +{
  2 + "module": {
  3 + "name": "wdRouter",
  4 + "type": "shared",
  5 + "description": "$string:shared_desc",
  6 + "deviceTypes": [
  7 + "phone",
  8 + "tablet",
  9 + "2in1"
  10 + ],
  11 + "deliveryWithInstall": true
  12 + }
  13 +}
  1 +{
  2 + "color": [
  3 + {
  4 + "name": "white",
  5 + "value": "#FFFFFF"
  6 + }
  7 + ]
  8 +}
  1 +{
  2 + "string": [
  3 + {
  4 + "name": "shared_desc",
  5 + "value": "description"
  6 + }
  7 + ]
  8 +}
  1 +import localUnitTest from './LocalUnit.test';
  2 +
  3 +export default function testsuite() {
  4 + localUnitTest();
  5 +}
  1 +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium';
  2 +
  3 +export default function localUnitTest() {
  4 + describe('localUnitTest',() => {
  5 + // Defines a test suite. Two parameters are supported: test suite name and test suite function.
  6 + beforeAll(() => {
  7 + // Presets an action, which is performed only once before all test cases of the test suite start.
  8 + // This API supports only one parameter: preset action function.
  9 + });
  10 + beforeEach(() => {
  11 + // Presets an action, which is performed before each unit test case starts.
  12 + // The number of execution times is the same as the number of test cases defined by **it**.
  13 + // This API supports only one parameter: preset action function.
  14 + });
  15 + afterEach(() => {
  16 + // Presets a clear action, which is performed after each unit test case ends.
  17 + // The number of execution times is the same as the number of test cases defined by **it**.
  18 + // This API supports only one parameter: clear action function.
  19 + });
  20 + afterAll(() => {
  21 + // Presets a clear action, which is performed after all test cases of the test suite end.
  22 + // This API supports only one parameter: clear action function.
  23 + });
  24 + it('assertContain', 0, () => {
  25 + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
  26 + let a = 'abc';
  27 + let b = 'b';
  28 + // Defines a variety of assertion methods, which are used to declare expected boolean conditions.
  29 + expect(a).assertContain(b);
  30 + expect(a).assertEqual(a);
  31 + });
  32 + });
  33 +}
  1 +/node_modules
  2 +/oh_modules
  3 +/.preview
  4 +/build
  5 +/.cxx
  6 +/.test
  1 +export { WdWebComponent } from './src/main/ets/pages/WdWebComponent'
  1 +{
  2 + "apiType": "stageMode",
  3 + "buildOption": {
  4 + "arkOptions": {
  5 + // "apPath": "./modules.ap" /* Profile used for profile-guided optimization (PGO), a compiler optimization technique to improve app runtime performance. */
  6 + }
  7 + },
  8 + "buildOptionSet": [
  9 + {
  10 + "name": "release",
  11 + "arkOptions": {
  12 + "obfuscation": {
  13 + "ruleOptions": {
  14 + "enable": true,
  15 + "files": [
  16 + "./obfuscation-rules.txt"
  17 + ]
  18 + }
  19 + }
  20 + }
  21 + },
  22 + ],
  23 + "targets": [
  24 + {
  25 + "name": "default"
  26 + }
  27 + ]
  28 +}
  1 +import { hspTasks } from '@ohos/hvigor-ohos-plugin';
  2 +
  3 +export default {
  4 + system: hspTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
  5 + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
  6 +}
  1 +# Define project specific obfuscation rules here.
  2 +# You can include the obfuscation configuration files in the current module's build-profile.json5.
  3 +#
  4 +# For more details, see
  5 +# https://gitee.com/openharmony/arkcompiler_ets_frontend/blob/master/arkguard/README.md
  6 +
  7 +# Obfuscation options:
  8 +# -disable-obfuscation: disable all obfuscations
  9 +# -enable-property-obfuscation: obfuscate the property names
  10 +# -enable-toplevel-obfuscation: obfuscate the names in the global scope
  11 +# -compact: remove unnecessary blank spaces and all line feeds
  12 +# -remove-log: remove all console.* statements
  13 +# -print-namecache: print the name cache that contains the mapping from the old names to new names
  14 +# -apply-namecache: reuse the given cache file
  15 +
  16 +# Keep options:
  17 +# -keep-property-name: specifies property names that you want to keep
  18 +# -keep-global-name: specifies names that you want to keep in the global scope
  1 +{
  2 + "license": "Apache-2.0",
  3 + "devDependencies": {},
  4 + "author": "",
  5 + "name": "wdwebcomponent",
  6 + "description": "Please describe the basic information.",
  7 + "main": "Index.ets",
  8 + "version": "1.0.0",
  9 + "dependencies": {
  10 + "wdConstant": "file:../wdConstant",
  11 + "wdKit": "file:../wdKit",
  12 + "wdJsBridge": "file:../wdJsBridge",
  13 + "wdBean": "file:../wdBean",
  14 + "wdRouter": "file:../wdRouter"
  15 + }
  16 +}
  1 +import { Action } from 'wdBean';
  2 +import { Callback } from 'wdJsBridge';
  3 +import { Logger, StringUtils, } from 'wdKit';
  4 +// import { AccountManagerUtils, ILoginService, Logger, ServiceManager, StringUtils, UserBean, UserInfo } from 'wdKit';
  5 +import { WDRouterPage, WDRouterRule } from 'wdRouter';
  6 +
  7 +// import { wdMenc } from 'wdMenc';
  8 +
  9 +/**
  10 + * h5调用native代码
  11 + * @param data
  12 + * @param call
  13 + */
  14 +export function performJSCallNative(data: Action, call: Callback) {
  15 +
  16 + // if (data.name == "GET_PROMOTION_SIGN") {
  17 + // wdMenc.getActivitySign(data.params?.intfId, (sign) => {
  18 + // if (sign) {
  19 + // call(JSON.stringify(sign));
  20 + // } else {
  21 + // call("")
  22 + // }
  23 + // })
  24 + // return
  25 + // }
  26 +
  27 + //TODO 数据校验
  28 + switch (data.type) {
  29 + //获取用户信息
  30 + case "GET_USER_INFO":
  31 + //测试环境
  32 + // call(JSON.stringify(getTestUserBean()))
  33 + // let isLogin = AccountManagerUtils.isLoginSync()
  34 + // Logger.info("WebComponent", `GET_USER_INFO#:::refresh==` + isLogin);
  35 + //
  36 + // if (isLogin) {
  37 + // const loginService = ServiceManager.getService(ILoginService.name) as ILoginService.Service
  38 + // let userBean: UserBean = loginService.getUserBean()
  39 + // // userBean.userInfo = JSON.stringify(loginService.getUserInfo())
  40 + // call(JSON.stringify(userBean))
  41 + // } else {
  42 + // call("fail")
  43 + // }
  44 +
  45 + break;
  46 + case "JUMP_DETAIL_PAGE":
  47 + WDRouterRule.jumpWithAction(data)
  48 + break;
  49 + case "JUMP_INNER_NEW_PAGE":
  50 + WDRouterRule.jumpWithAction(data)
  51 + break
  52 + case "GET_DEVICE_DATA":
  53 + break
  54 + //用户登陆
  55 + case "USER_LOGIN":
  56 + WDRouterRule.jumpWithAction(data)
  57 + //支付完成回调
  58 + case "REGISTER_H5_WEBVIEW_CREATE_ORDER_RESULT":
  59 + break
  60 + //打开H5页面
  61 + case "JUMP_H5_BY_WEB_VIEW":
  62 + WDRouterRule.jumpWithAction(data)
  63 + break
  64 + case "USER_LOGOUT":
  65 + // const loginService = ServiceManager.getService(ILoginService.name) as ILoginService.Service
  66 + // loginService.logout()
  67 + break
  68 + default:
  69 + call("this is def value")
  70 + }
  71 +
  72 +}
  73 +
  74 +// /**
  75 +// *
  76 +// * @returns 模拟测试环境的user信息
  77 +// */
  78 +// function getTestUserBean(): UserBean {
  79 +// const loginService = ServiceManager.getService(ILoginService.name) as ILoginService.Service
  80 +// //正是环境
  81 +// let userBean: UserBean = loginService.getUserBean()
  82 +// userBean.userId = "930855275"
  83 +// userBean.userToken = "nlps6FADECE38F5AAD2116F2"
  84 +// // userBean.clientId = "f1bf515c-4006-4606-a752-2b4cdd9343d0"
  85 +// // userBean.carrierCode = "CM"
  86 +// userBean.mobile = "NTTrcDO4ADN1cTM5MTM"
  87 +// userBean.uname = '139****0887'
  88 +// userBean.picture = "http://36.155.98.104:23380/publish/voms2/uic_service/picture/userImage/543/626/5181.jpg"
  89 +// // userBean.ssotoken = "STnid0000011700463753943SKPUlfNxEDJsrauGjCwUldiDfrd0mUuM"
  90 +// // userBean.clientProvinceCode = "210"
  91 +// // userBean.clientCityId = "0210"
  92 +// // userBean.sign = "617DAC548595B7C9EBB13043735F1BE0"
  93 +// // userBean.blurMobile = "177****9217"
  94 +// let userinfo: UserInfo = ({
  95 +// userId: "930855275",
  96 +// userNum: "NzDrsyN4gDM0UzNxkzMxYDO",
  97 +// mobile: "NTTrcDO4ADN1cTM5MTM",
  98 +// areaId: "210",
  99 +// cityId: "0210",
  100 +// carrierCode: "CM",
  101 +// passId: "602201990200225921",
  102 +// userToken: "nlps6FADECE38F5AAD2116F2",
  103 +// expiredOn: "1705647754000",
  104 +// blurMobile: "139****0887",
  105 +// encrypted: true
  106 +// })
  107 +// // userBean.userInfo = JSON.stringify(userinfo);
  108 +// return userBean
  109 +// }
  110 +//
  111 +// /**
  112 +// *
  113 +// * @returns 用户信息
  114 +// */
  115 +// function getUserBean(): UserBean {
  116 +// const loginService = ServiceManager.getService(ILoginService.name) as ILoginService.Service
  117 +// //正是环境
  118 +// let userBean: UserBean = loginService.getUserBean()
  119 +// userBean.userId = "1437725487"
  120 +// userBean.userToken = "nlps08468E117C554CA08A43"
  121 +// // userBean.clientId = "27fb3129-5a54-45bc-8af1-7dc8f1155501"
  122 +// // userBean.carrierCode = "CT"
  123 +// userBean.mobile = "OTTrcTMykTO4ATM3cTM"
  124 +// userBean.uname = '小可爱啊'
  125 +// userBean.picture = "http://img.cmvideo.cn:8080/publish/voms2/uic_service/picture/userImage/1437/725/487/20211224174128beax.png"
  126 +// // userBean.ssotoken = "STnid0000011700461738301N5rjsHdbvyzMpyzwvHrFRJsj7oNT1Juf"
  127 +// // userBean.clientProvinceCode = "100"
  128 +// // userBean.clientCityId = "0100"
  129 +// // userBean.sign = "4ABFB8442EE914B57CCD9F1DE587D96D"
  130 +// // userBean.blurMobile = "177****9217"
  131 +// let userinfo: UserInfo = ({
  132 +// userId: "1437725487",
  133 +// userNum: "MzDrsyNxITO5gDMxczNxYDO",
  134 +// mobile: "OTTrcTMykTO4ATM3cTM",
  135 +// areaId: "100",
  136 +// cityId: "0100",
  137 +// carrierCode: "CT",
  138 +// passId: "467464726359024540",
  139 +// userToken: "nlps08468E117C554CA08A43",
  140 +// expiredOn: "1705645738000",
  141 +// blurMobile: "177****9217",
  142 +// encrypted: true
  143 +// })
  144 +// // userBean.userInfo = JSON.stringify(userinfo);
  145 +// return userBean
  146 +// }
  147 +
  148 +
  1 +import router from '@ohos.router';
  2 +import { Action } from 'wdBean';
  3 +import { ConfigConstants } from 'wdConstant';
  4 +import { Logger } from 'wdKit';
  5 +import { BridgeHandler, BridgeUtil, BridgeWebViewControl, Callback } from 'wdJsBridge';
  6 +import { performJSCallNative } from './JsBridgeBiz';
  7 +import { setDefaultNativeWebSettings } from './WebComponentUtil';
  8 +
  9 +const TAG = 'WdWebComponent';
  10 +
  11 +@Component
  12 +export struct WdWebComponent {
  13 + private webviewControl: BridgeWebViewControl = new BridgeWebViewControl()
  14 + //TODO 默认网页
  15 + webUrl: string = ConfigConstants.DETAIL_URL
  16 + /**
  17 + * 对外暴露webview的回调,能力
  18 + */
  19 + onPageBegin: (url?: string) => void = () => {
  20 + }
  21 + onPageEnd: (url?: string) => void = () => {
  22 + }
  23 + onLoadIntercept: (url?: string) => boolean = () => {
  24 + return false
  25 + }
  26 + onHttpErrorReceive: (url?: string) => boolean = () => {
  27 + return false
  28 + }
  29 + @Prop @Watch('onReloadStateChanged') reload: number = 0
  30 + /**
  31 + * 默认【CallNative】逻辑处理
  32 + */
  33 + private defaultPerformJSCallNative: (data: Action, f: Callback) => void = (data: Action, f: Callback) => {
  34 + performJSCallNative(data, f)
  35 + }
  36 + /**
  37 + * jsBridge的处理
  38 + */
  39 + handleInfo: [string, BridgeHandler][] = []
  40 + backVisibility: boolean = false
  41 +
  42 + defaultRegisterHandler(): void {
  43 + this.webviewControl.registerHandler("CallNative", {
  44 + handle: (data: Action, f: Callback) => {
  45 + this.defaultPerformJSCallNative(data, f)
  46 + }
  47 + });
  48 +
  49 + }
  50 +
  51 + build() {
  52 + Column() {
  53 + Row() {
  54 + Image($r("app.media.ic_back"))
  55 + .width(44)
  56 + .padding(13)
  57 + .aspectRatio(1)
  58 + .onClick(() => {
  59 + router.back();
  60 + })
  61 + }.backgroundColor(Color.Black)
  62 + .width('100%')
  63 + .height(44)
  64 + .visibility(this.backVisibility ? Visibility.Visible : Visibility.None)
  65 +
  66 + Web({ src: this.webUrl, controller: this.webviewControl })
  67 + .domStorageAccess(true)
  68 + .databaseAccess(true)
  69 + .javaScriptAccess(true)
  70 + .onHttpErrorReceive((event) => {
  71 + //TODO 页面加载不成功的时候处理
  72 + Logger.info(TAG, 'onHttpErrorReceive event.request.getRequestUrl:' + event?.request.getRequestUrl());
  73 + Logger.info(TAG, 'onHttpErrorReceive event.response.getResponseCode:' + event?.response.getResponseCode());
  74 + })
  75 + .onPageEnd((event) => {
  76 + this.onPageEnd(event?.url)
  77 + })
  78 + .onPageBegin((event) => {
  79 + setDefaultNativeWebSettings(this.webviewControl, this.webUrl).then(()=>{
  80 + this.handleInfo && this.handleInfo.length > 1 ? this.handleInfo.forEach(value => {
  81 + this.webviewControl.registerHandler(value[0], value[1])
  82 + }) : this.defaultRegisterHandler()
  83 + setTimeout(()=>{
  84 + BridgeUtil.webViewLoadLocalJs(getContext(this), this.webviewControl)
  85 + },500)
  86 + })
  87 + this.onPageBegin(event?.url)
  88 + })
  89 + .onLoadIntercept((event) => {
  90 + let url: string = event.data.getRequestUrl().toString()
  91 + url = url.replace("%(?![0-9a-fA-F]{2})", "%25")
  92 + .replace("\\+", "%2B");
  93 + url = decodeURIComponent(url)
  94 + if (url.startsWith(BridgeUtil.YY_RETURN_DATA)) {
  95 + this.webviewControl.handlerReturnData(url)
  96 + return true
  97 + }
  98 + if (url.startsWith(BridgeUtil.YY_OVERRIDE_SCHEMA)) {
  99 + this.webviewControl.flushMessageQueue()
  100 + return true
  101 + }
  102 + return this.onLoadIntercept(event.data.getRequestUrl().toString())
  103 + })
  104 + }
  105 + }
  106 +
  107 + onReloadStateChanged() {
  108 + Logger.info(TAG, `onReloadStateChanged:::refresh, this.reload: ${this.reload}`);
  109 + if (this.reload > 0) {
  110 + this.webviewControl.refresh()
  111 + }
  112 + }
  113 +}
  114 +
  1 +import bundleManager from '@ohos.bundle.bundleManager';
  2 +import web_webview from '@ohos.web.webview';
  3 +import HashMap from '@ohos.util.HashMap';
  4 +import { StringUtils, AppUtils } from 'wdKit';
  5 +
  6 +/**
  7 + * 用于底层webview基础设置:ua,cookie等
  8 + */
  9 +export function setDefaultNativeWebSettings(control: WebviewController, url: string): Promise<void> {
  10 + //设置UA
  11 + let customUA = control.getCustomUserAgent();
  12 + return new Promise((resolve) => {
  13 + let versionName = AppUtils.getAppVersionName();
  14 + let versionCode = AppUtils.getAppVersionCode();
  15 + //TODO 设置cookie有问题
  16 + if(customUA.indexOf('miguvideo')===-1){
  17 + let temp = customUA + " Migu/miguvideo/" + versionName + "(" + versionCode + ")"
  18 + control.setCustomUserAgent(temp)
  19 + }else{
  20 + control.setCustomUserAgent(customUA)
  21 + }
  22 + //设置Cookie
  23 + try{
  24 + syncCookies(url, getBaseCookie())
  25 + web_webview.WebCookieManager.setCookie(url, "AppVersion=" + versionCode)
  26 + }catch(e){
  27 + }
  28 + resolve();
  29 + });
  30 +}
  31 +
  32 +function setCookie(url: string, value: string) {
  33 + if (StringUtils.isEmpty(value) || StringUtils.isEmpty(url) || !value.includes("=")) {
  34 + return
  35 + }
  36 + web_webview.WebCookieManager.setCookie(url, value)
  37 +}
  38 +
  39 +function getBaseCookie(): HashMap<string, string> {
  40 + let cookies: HashMap<string, string> = new HashMap<string, string>()
  41 + cookies.set("SupportAPI", "H5_CALL_NATIVE_HTTP_REQUEST")
  42 + cookies.set("PlatForm", "harmony")
  43 + return cookies
  44 +
  45 +}
  46 +
  47 +function syncCookies(url: string, map: HashMap<String, String>) {
  48 + if (map == undefined && StringUtils.isEmpty(url)) {
  49 + return
  50 + }
  51 + map.forEach((value, key) => {
  52 + setCookie(url, `${key}=${value}`)
  53 + })
  54 +}
  1 +{
  2 + "module": {
  3 + "name": "wdWebComponent",
  4 + "type": "shared",
  5 + "description": "$string:shared_desc",
  6 + "deviceTypes": [
  7 + "phone",
  8 + "tablet",
  9 + "2in1"
  10 + ],
  11 + "deliveryWithInstall": true
  12 + }
  13 +}
  1 +{
  2 + "color": [
  3 + {
  4 + "name": "white",
  5 + "value": "#FFFFFF"
  6 + }
  7 + ]
  8 +}
  1 +{
  2 + "string": [
  3 + {
  4 + "name": "shared_desc",
  5 + "value": "description"
  6 + }
  7 + ]
  8 +}
  1 +import localUnitTest from './LocalUnit.test';
  2 +
  3 +export default function testsuite() {
  4 + localUnitTest();
  5 +}
  1 +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium';
  2 +
  3 +export default function localUnitTest() {
  4 + describe('localUnitTest',() => {
  5 + // Defines a test suite. Two parameters are supported: test suite name and test suite function.
  6 + beforeAll(() => {
  7 + // Presets an action, which is performed only once before all test cases of the test suite start.
  8 + // This API supports only one parameter: preset action function.
  9 + });
  10 + beforeEach(() => {
  11 + // Presets an action, which is performed before each unit test case starts.
  12 + // The number of execution times is the same as the number of test cases defined by **it**.
  13 + // This API supports only one parameter: preset action function.
  14 + });
  15 + afterEach(() => {
  16 + // Presets a clear action, which is performed after each unit test case ends.
  17 + // The number of execution times is the same as the number of test cases defined by **it**.
  18 + // This API supports only one parameter: clear action function.
  19 + });
  20 + afterAll(() => {
  21 + // Presets a clear action, which is performed after all test cases of the test suite end.
  22 + // This API supports only one parameter: clear action function.
  23 + });
  24 + it('assertContain', 0, () => {
  25 + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
  26 + let a = 'abc';
  27 + let b = 'b';
  28 + // Defines a variety of assertion methods, which are used to declare expected boolean conditions.
  29 + expect(a).assertContain(b);
  30 + expect(a).assertEqual(a);
  31 + });
  32 + });
  33 +}