import web_webview from '@ohos.web.webview'; import webview from '@ohos.web.webview'; import { router } from '@kit.ArkUI'; import { XDialogController } from '../dialog/XDialogController'; import { XDialogList } from '../dialog/XDialogList'; import { picker } from '@kit.CoreFileKit'; import { BusinessError } from '@kit.BasicServicesKit'; import { ToolsHelper } from '../utils/ToolsHelper'; import { XWebController, XWebParams } from '../utils/XWebHelper'; import { WindowHelper } from '../utils/WindowHelper'; import { SZYXLocalStorageHelper } from '../utils/SZYXLocalStorageHelper'; import { SZYXLocalStorageKeys } from '../utils/SZYXLocalStorageKeys'; import { XWebManager } from '../utils/XWebManager'; @Entry({ routeName: 'XWebview' }) @Component export struct XWebview { // 手机号 @State url?: string = (router.getParams() as XWebParams).url @State zoomAccess?: boolean = (router.getParams() as XWebParams).zoomAccess @State content?: string = (router.getParams() as XWebParams).content @State title?: string = (router.getParams() as XWebParams).title @State xController?: XWebController = (router.getParams() as XWebParams).controller @State closeTag?: string = (router.getParams() as XWebParams).closeTag @State showMenu: boolean = (router.getParams() as XWebParams).showMenu ?? false @State errorInfo: string | null = null @State progress: number = 0 @State _uuid?: string = (router.getParams() as XWebParams)._uuid @State _uuidToHtml?: string = (router.getParams() as XWebParams)._uuidToHtml controller: web_webview.WebviewController = new web_webview.WebviewController(); dialogController: XDialogController = {} as XDialogController ports: webview.WebMessagePort[] = []; aboutToAppear(): void { SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.XWebViewCLose, undefined) webview.WebviewController.setWebDebuggingAccess(true); if (this.content) { try { this.controller.loadData(this.content, "text/html", "UTF-8", '', '') } catch (e) { ToolsHelper.showAlertDialog({ title: '警告', msg: e.message ?? '加载内容失败', action: { onClick: () => { router.back() } } }) } } if (this._uuidToHtml) { XWebManager.addOnMessageToHtml(this._uuidToHtml, (msg) => { if (this.ports && this.ports[1]) { this.ports[1].postMessageEvent(msg); } }) } } aboutToDisappear(): void { if (this.closeTag !== undefined) { SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.XWebViewCLose, this.closeTag) } XWebManager.removeOnMessage(this._uuid) XWebManager.removeOnMessageToHtml(this._uuidToHtml) } onBackPress(): boolean | void { if (this.controller.accessBackward()) { this.controller.backward() } else { ToolsHelper.doubleAndExit(() => { router.back() }) } return true } build() { Column() { Row() { Row() { Button({ buttonStyle: ButtonStyleMode.TEXTUAL }) { Image($r('sys.media.ohos_ic_back')) .width(26).height(26) }.onClick(() => { this.onBackPress() }) Button({ buttonStyle: ButtonStyleMode.TEXTUAL }) { Image($r('sys.media.ohos_ic_public_close')) .width(26).height(26) }.margin({ left: 12 }) .onClick(() => { router.back() }) }.width(65) Text(this.title) .maxLines(1) .fontColor('#222222') .fontSize(18) .textAlign(TextAlign.Center) .width('50%') .ellipsisMode(EllipsisMode.END) .textOverflow({ overflow: TextOverflow.Ellipsis }) Button({ buttonStyle: ButtonStyleMode.TEXTUAL }) { Image($r('sys.media.ohos_ic_public_more')) .width(26).height(26) }.width(65) .onClick(() => { if (this.dialogController != null) { this.dialogController.open() } }).visibility(this.showMenu ? Visibility.Visible : Visibility.Hidden) } .width('100%') .height(45) .justifyContent(FlexAlign.SpaceBetween) .padding({ left: 15, right: 15 }) Row().backgroundColor('#CCCCCC').height(2).width('100%') Progress({ value: this.progress, type: ProgressType.Linear }) .visibility(this.progress > 95 || this.progress == 0 ? Visibility.None : Visibility.Visible) .width('100%') Web({ src: this.url ?? 'www.example.com', controller: this.controller }) .javaScriptAccess(true) .domStorageAccess(true) .geolocationAccess(true) .width('100%') .height('100%') .visibility(this.errorInfo == null ? Visibility.Visible : Visibility.None) .mixedMode(MixedMode.All)//允许加载HTTP和HTTPS混合内容 .zoomAccess(this.zoomAccess ?? false)//不支持手势进行缩放 .mediaPlayGestureAccess(false)//有声视频播放不需要用户手动点击 .cacheMode(CacheMode.None)//设置缓存模式 .onConfirm((event) => { // 自定义Confirm弹窗 if (event) { console.log("event.url:" + event.url) console.log("event.message:" + event.message) AlertDialog.show({ title: '提示', message: event.message, primaryButton: { value: '取消', action: () => { event.result.handleCancel() } }, secondaryButton: { value: '确定', action: () => { event.result.handleConfirm() } }, cancel: () => { event.result.handleCancel() } }) } return true }) .onAlert((event) => { // 自定义Alert弹窗 if (event) { console.log("event.url:" + event.url) console.log("event.message:" + event.message) AlertDialog.show({ title: '提示', message: event.message, secondaryButton: { value: '确定', action: () => { event.result.handleConfirm() } } }) } return true }) .onDownloadStart((event) => { // 下载文件 if (event) { console.log('url:' + event.url) console.log('userAgent:' + event.userAgent) console.log('contentDisposition:' + event.contentDisposition) console.log('contentLength:' + event.contentLength) console.log('mimetype:' + event.mimetype) } }) .onPageEnd((url) => { ToolsHelper.log(url.url) // 1、创建两个消息端口。 this.ports = this.controller.createWebMessagePorts(); this.ports[1].onMessageEvent((result: webview.WebMessage) => { if (typeof (result) === 'string') { ToolsHelper.log(result, typeof (result)) XWebManager.sendMessage(result) } }) this.controller.postMessage('__init_port__', [this.ports[0]], '*'); }) .onControllerAttached(() => { try { let userAgent = this.controller.getUserAgent() + '/szyx_sdk'; this.controller.setCustomUserAgent(userAgent); // this.controller.runJavaScript('window.SZYX_YWX_WebViewBridge.onIsYwxApp()'); } catch (error) { console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`); } }) .onErrorReceive((event) => { // 加载失败 if (this.progress > 65) { return } if (event) { this.errorInfo = `错误码:${event.error.getErrorCode()}\n${event.error.getErrorInfo()}` } else { this.errorInfo = '错误码:-1\n未知错误' } ToolsHelper.log(JSON.stringify(event), this.url) }) .onHttpErrorReceive((event) => { // 加载失败 if (this.progress > 65) { return } if (event) { this.errorInfo = `错误码:${event.response.getResponseCode()}\n${event.response.getReasonMessage()}` } else { this.errorInfo = '错误码:-1\n未知错误' } ToolsHelper.log(this.errorInfo, this.url) }) .onProgressChange((event) => { // 加载进度 if (event) { console.log('newProgress:' + event.newProgress) this.progress = event.newProgress } }) .onTitleReceive((event) => { // 如果没有传输title,则从H5获取title赋值 if (event && !this.title) { this.title = event.title } }) .onShowFileSelector((event) => { // 选择文件 console.log('MyFileUploader onShowFileSelector invoked') const documentSelectOptions = new picker.DocumentSelectOptions() let uri: string | null = null; const documentViewPicker = new picker.DocumentViewPicker(); documentViewPicker.select(documentSelectOptions).then((documentSelectResult) => { uri = documentSelectResult[0]; console.info('documentViewPicker.select to file succeed and uri is:' + uri); if (event) { event.result.handleFileList([uri]); } }).catch((err: BusinessError) => { if (event) { event.result.handleFileList([]) } ToolsHelper.showMessage(`Invoke documentViewPicker.select failed, code is ${err.code}, message is ${err.message}`) console.error(`Invoke documentViewPicker.select failed, code is ${err.code}, message is ${err.message}`); }) return true }) Column() { Text(this.errorInfo) Button('点击重试') .onClick(() => { this.controller.refresh() this.errorInfo = null this.progress = 0 }) .margin({ top: 30 }) } .visibility(this.errorInfo == null ? Visibility.None : Visibility.Visible) .width('100%') .height('100%') .justifyContent(FlexAlign.Center) .padding({ bottom: 80 }) XDialogList({ // 控制器 controller: this.dialogController, // 标题(可选) title: '选择您的操作', // 选择内容列表 values: ['刷新', '浏览器打开', '分享', '复制地址'], // 用户选择事件 onSelected: (index: number, value: string) => { ToolsHelper.showMessage(`用户选择了第${index}个,内容为:${value}`) }, // 用户取消事件 onCancel: () => { ToolsHelper.showMessage('用户取消操作') }, // 是否可取消(点击空白处,或者物理返回键) autoCancel: true }) }.width('100%').height('100%') .padding({ top: WindowHelper.topRectHeight, bottom: WindowHelper.bottomRectHeight }) } }