ref |> 必修--文章详情页H5外链鸿蒙版跳转页面后展示效果与安卓/IOS不一致
http://192.168.1.3:8080/zentao/bug-view-19286.html
Showing
8 changed files
with
210 additions
and
8 deletions
| @@ -66,4 +66,10 @@ export class SpConstants{ | @@ -66,4 +66,10 @@ export class SpConstants{ | ||
| 66 | static GETUI_PUSH_DEVICE_TOKEN = "deviceToken" | 66 | static GETUI_PUSH_DEVICE_TOKEN = "deviceToken" |
| 67 | //link | 67 | //link |
| 68 | static HAS_LINK="has_link" | 68 | static HAS_LINK="has_link" |
| 69 | + | ||
| 70 | + // 是否开启H5白名单 | ||
| 71 | + static H5_WHITE_LIST_ENABLE ="h5_whilte_list_enable" | ||
| 72 | + static H5_WHITE_LIST_LAST_DATA_MD5 ="h5_whilte_list_last_data_md5" | ||
| 73 | + | ||
| 74 | + | ||
| 69 | } | 75 | } |
| 1 | 1 | ||
| 2 | import fs from '@ohos.file.fs'; | 2 | import fs from '@ohos.file.fs'; |
| 3 | import { BusinessError } from '@kit.BasicServicesKit'; | 3 | import { BusinessError } from '@kit.BasicServicesKit'; |
| 4 | +import { util } from '@kit.ArkTS'; | ||
| 4 | 5 | ||
| 5 | export class FileUtils { | 6 | export class FileUtils { |
| 6 | 7 | ||
| @@ -31,4 +32,26 @@ export class FileUtils { | @@ -31,4 +32,26 @@ export class FileUtils { | ||
| 31 | }) | 32 | }) |
| 32 | }) | 33 | }) |
| 33 | } | 34 | } |
| 35 | + | ||
| 36 | + static readFile(path: string): ArrayBuffer { | ||
| 37 | + try { | ||
| 38 | + let stat = fs.statSync(path) | ||
| 39 | + let fd = fs.openSync(path, fs.OpenMode.READ_ONLY).fd; | ||
| 40 | + let length = stat.size | ||
| 41 | + let buf = new ArrayBuffer(length); | ||
| 42 | + fs.readSync(fd, buf) | ||
| 43 | + fs.closeSync(fd) | ||
| 44 | + return buf | ||
| 45 | + } catch (e) { | ||
| 46 | + console.log("FileUtils - readFilePicSync " + e) | ||
| 47 | + return new ArrayBuffer(0) | ||
| 48 | + } | ||
| 49 | + } | ||
| 50 | + | ||
| 51 | + static readFileAsString(path: string): string { | ||
| 52 | + const data = FileUtils.readFile(path) | ||
| 53 | + let decoder = util.TextDecoder.create('utf-8'); | ||
| 54 | + let str = decoder.decodeToString(new Uint8Array(data)); | ||
| 55 | + return str | ||
| 56 | + } | ||
| 34 | } | 57 | } |
| 1 | import { SpConstants } from 'wdConstant/Index'; | 1 | import { SpConstants } from 'wdConstant/Index'; |
| 2 | -import { DeviceUtil, SPHelper, StringUtils } from 'wdKit/Index'; | 2 | +import { DeviceUtil, Logger, SPHelper, StringUtils } from 'wdKit/Index'; |
| 3 | import { HttpRequest } from '../http/HttpRequest'; | 3 | import { HttpRequest } from '../http/HttpRequest'; |
| 4 | +import { http } from '@kit.NetworkKit'; | ||
| 5 | +import fs from '@ohos.file.fs'; | ||
| 6 | +import { BusinessError } from '@kit.BasicServicesKit'; | ||
| 7 | +import { JSON } from '@kit.ArkTS'; | ||
| 4 | 8 | ||
| 5 | const TAG: string = '[HttpUtils]' | 9 | const TAG: string = '[HttpUtils]' |
| 6 | 10 | ||
| @@ -81,4 +85,37 @@ export class HttpUtils { | @@ -81,4 +85,37 @@ export class HttpUtils { | ||
| 81 | } | 85 | } |
| 82 | return true | 86 | return true |
| 83 | } | 87 | } |
| 88 | + | ||
| 89 | + static downloadUrlToPathWithout(url: string, toFilePath: string): Promise<boolean> { | ||
| 90 | + Logger.debug(TAG, "will donwload url:" + url + " ======> " + toFilePath); | ||
| 91 | + | ||
| 92 | + return new Promise((reslove, fail) => { | ||
| 93 | + | ||
| 94 | + let httpRequest = http.createHttp() | ||
| 95 | + httpRequest.request(url, (err, data) => { | ||
| 96 | + | ||
| 97 | + if (!err && data.responseCode == http.ResponseCode.OK) { | ||
| 98 | + let imgFile = fs.openSync(toFilePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); | ||
| 99 | + let wroteLength = 0 | ||
| 100 | + fs.write(imgFile.fd, data.result as ArrayBuffer).then((writeLen: number) => { | ||
| 101 | + Logger.debug(TAG, "write data to file succeed and size is:" + writeLen); | ||
| 102 | + wroteLength = writeLen | ||
| 103 | + }).catch((err: BusinessError) => { | ||
| 104 | + Logger.error(TAG, "write data to file failed with error message: " + err.message + ", error code: " + err.code); | ||
| 105 | + }).finally(() => { | ||
| 106 | + fs.closeSync(imgFile); | ||
| 107 | + httpRequest.destroy() | ||
| 108 | + | ||
| 109 | + reslove(wroteLength > 0) | ||
| 110 | + }); | ||
| 111 | + return | ||
| 112 | + } | ||
| 113 | + | ||
| 114 | + Logger.error(TAG, "download failed " + JSON.stringify(err)); | ||
| 115 | + httpRequest.destroy() | ||
| 116 | + fail("failed") | ||
| 117 | + }); | ||
| 118 | + | ||
| 119 | + }) | ||
| 120 | + } | ||
| 84 | } | 121 | } |
| @@ -114,6 +114,9 @@ struct LaunchPage { | @@ -114,6 +114,9 @@ struct LaunchPage { | ||
| 114 | if (!dataModelStr) { | 114 | if (!dataModelStr) { |
| 115 | //直接跳转首页 | 115 | //直接跳转首页 |
| 116 | WDRouterRule.jumpWithReplacePage(WDRouterPage.mainPage) | 116 | WDRouterRule.jumpWithReplacePage(WDRouterPage.mainPage) |
| 117 | + | ||
| 118 | + //同意隐私协议后每次启动app请求启动页相关数据,并更新数据 | ||
| 119 | + this.requestLaunchPageData(); | ||
| 117 | return | 120 | return |
| 118 | } | 121 | } |
| 119 | 122 |
| @@ -2,22 +2,26 @@ | @@ -2,22 +2,26 @@ | ||
| 2 | import LaunchDataModel from '../viewModel/LaunchDataModel' | 2 | import LaunchDataModel from '../viewModel/LaunchDataModel' |
| 3 | 3 | ||
| 4 | import { HttpRequest } from 'wdNetwork/src/main/ets/http/HttpRequest'; | 4 | import { HttpRequest } from 'wdNetwork/src/main/ets/http/HttpRequest'; |
| 5 | -import { HttpUrlUtils, ResponseDTO } from 'wdNetwork/Index'; | ||
| 6 | -import { DisplayUtils, Logger, SPHelper } from 'wdKit/Index'; | 5 | +import { HttpUrlUtils, HttpUtils, ResponseDTO } from 'wdNetwork/Index'; |
| 6 | +import { AppUtils, DisplayUtils, Logger, SPHelper } from 'wdKit/Index'; | ||
| 7 | import { SpConstants } from 'wdConstant/Index'; | 7 | import { SpConstants } from 'wdConstant/Index'; |
| 8 | +import { FileUtils } from '@ohos/imageknife'; | ||
| 8 | 9 | ||
| 9 | 10 | ||
| 10 | export class LaunchPageModel { | 11 | export class LaunchPageModel { |
| 11 | 12 | ||
| 12 | getLaunchPageData(): Promise<LaunchDataModel> { | 13 | getLaunchPageData(): Promise<LaunchDataModel> { |
| 13 | return new Promise<LaunchDataModel>((success, fail) => { | 14 | return new Promise<LaunchDataModel>((success, fail) => { |
| 14 | - HttpRequest.get<ResponseDTO<LaunchDataModel>>(HttpUrlUtils.getLaunchPageDataUrl()+ `?height=${DisplayUtils.getDeviceHeight()}&width=${DisplayUtils.getDeviceWidth()}`).then((data: ResponseDTO<LaunchDataModel>) => { | 15 | + HttpRequest.get<ResponseDTO<LaunchDataModel>>(HttpUrlUtils.getLaunchPageDataUrl()+ `?height=${DisplayUtils.getDeviceHeight()}&width=${DisplayUtils.getDeviceWidth()}`) |
| 16 | + .then(async (data: ResponseDTO<LaunchDataModel>) => { | ||
| 15 | if (!data || !data.data) { | 17 | if (!data || !data.data) { |
| 16 | fail("数据为空") | 18 | fail("数据为空") |
| 19 | + LaunchPageModel.dealWithLaunchDataModel() | ||
| 17 | return | 20 | return |
| 18 | } | 21 | } |
| 19 | if (data.code != 0) { | 22 | if (data.code != 0) { |
| 20 | fail(data.message) | 23 | fail(data.message) |
| 24 | + LaunchPageModel.dealWithLaunchDataModel() | ||
| 21 | return | 25 | return |
| 22 | } | 26 | } |
| 23 | // Logger.debug("LaunchPageModel获取启动相关数据获取成功:success ", JSON.stringify(data)) | 27 | // Logger.debug("LaunchPageModel获取启动相关数据获取成功:success ", JSON.stringify(data)) |
| @@ -27,6 +31,8 @@ export class LaunchPageModel { | @@ -27,6 +31,8 @@ export class LaunchPageModel { | ||
| 27 | // console.log(obj) | 31 | // console.log(obj) |
| 28 | SPHelper.default.saveSync(SpConstants.APP_LAUNCH_PAGE_DATA_MODEL,obj) | 32 | SPHelper.default.saveSync(SpConstants.APP_LAUNCH_PAGE_DATA_MODEL,obj) |
| 29 | 33 | ||
| 34 | + LaunchPageModel.dealWithLaunchDataModel(data.data) | ||
| 35 | + | ||
| 30 | }, (error: Error) => { | 36 | }, (error: Error) => { |
| 31 | // Logger.debug("LaunchPageModel获取启动相关数据获取失败:error ", error.toString()) | 37 | // Logger.debug("LaunchPageModel获取启动相关数据获取失败:error ", error.toString()) |
| 32 | fail(error.message) | 38 | fail(error.message) |
| @@ -34,6 +40,47 @@ export class LaunchPageModel { | @@ -34,6 +40,47 @@ export class LaunchPageModel { | ||
| 34 | }) | 40 | }) |
| 35 | } | 41 | } |
| 36 | 42 | ||
| 43 | + static async dealWithLaunchDataModel(model?: LaunchDataModel) { | ||
| 44 | + if (!model) { | ||
| 45 | + let dataModelStr = SPHelper.default.getSync(SpConstants.APP_LAUNCH_PAGE_DATA_MODEL, '') as string | ||
| 46 | + model = JSON.parse(dataModelStr ?? "") | ||
| 47 | + if (!model) { return } | ||
| 48 | + } | ||
| 49 | + | ||
| 50 | + LaunchPageModel.dealWithWhiteListWith(model) | ||
| 51 | + | ||
| 52 | + // TODO: others | ||
| 53 | + | ||
| 54 | + | ||
| 55 | + | ||
| 56 | + | ||
| 57 | + | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | + static async dealWithWhiteListWith(model: LaunchDataModel) { | ||
| 61 | + SPHelper.default.saveSync(SpConstants.H5_WHITE_LIST_ENABLE, model.operationUrl.enabled) | ||
| 62 | + | ||
| 63 | + const lastMD5 = SPHelper.default.getSync(SpConstants.H5_WHITE_LIST_LAST_DATA_MD5, "") as string | ||
| 64 | + if (lastMD5 && lastMD5 == model.operationUrl.md5) { | ||
| 65 | + // MD5未变更,保持已下载的白名单 | ||
| 66 | + if (AppUtils.gotApplicationContextFunc) { | ||
| 67 | + let filePath = AppUtils.gotApplicationContextFunc().getApplicationContext().filesDir + "/h5_whitelist.txt" | ||
| 68 | + if (FileUtils.getInstance().exist(filePath)) { | ||
| 69 | + return | ||
| 70 | + } | ||
| 71 | + } | ||
| 72 | + } | ||
| 73 | + | ||
| 74 | + if (!AppUtils.gotApplicationContextFunc) { | ||
| 75 | + return | ||
| 76 | + } | ||
| 77 | + let filePath = AppUtils.gotApplicationContextFunc().getApplicationContext().filesDir + "/h5_whitelist.txt" | ||
| 78 | + const result = await HttpUtils.downloadUrlToPathWithout(model.operationUrl.linkUrl, filePath) | ||
| 79 | + if (result) { | ||
| 80 | + SPHelper.default.saveSync(SpConstants.H5_WHITE_LIST_LAST_DATA_MD5, model.operationUrl.md5 ?? "") | ||
| 81 | + } | ||
| 82 | + } | ||
| 83 | + | ||
| 37 | getMournsInfoData(): Promise<LaunchDataModel> { | 84 | getMournsInfoData(): Promise<LaunchDataModel> { |
| 38 | return new Promise<LaunchDataModel>((success, fail) => { | 85 | return new Promise<LaunchDataModel>((success, fail) => { |
| 39 | HttpRequest.get<ResponseDTO<LaunchDataModel>>(HttpUrlUtils.getLaunchPageDataUrl()).then((data: ResponseDTO<LaunchDataModel>) => { | 86 | HttpRequest.get<ResponseDTO<LaunchDataModel>>(HttpUrlUtils.getLaunchPageDataUrl()).then((data: ResponseDTO<LaunchDataModel>) => { |
| @@ -62,10 +62,8 @@ struct H5TipsPage { | @@ -62,10 +62,8 @@ struct H5TipsPage { | ||
| 62 | 62 | ||
| 63 | // 获取系统剪贴板对象 | 63 | // 获取系统剪贴板对象 |
| 64 | let systemPasteboard = pasteboard.getSystemPasteboard(); | 64 | let systemPasteboard = pasteboard.getSystemPasteboard(); |
| 65 | - // 创建一条纯文本类型的剪贴板内容对象createPlainTextData | ||
| 66 | - let pasteData = pasteboard.createPlainTextData(this.webUrl); | ||
| 67 | - pasteData.addTextRecord(this.webUrl); | ||
| 68 | - // 将数据写入系统剪贴板 | 65 | + let pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_PLAIN, this.webUrl) |
| 66 | + // // 将数据写入系统剪贴板 | ||
| 69 | systemPasteboard.setData(pasteData).then(()=>{ | 67 | systemPasteboard.setData(pasteData).then(()=>{ |
| 70 | // 存入成功,处理正常场景 | 68 | // 存入成功,处理正常场景 |
| 71 | ToastUtils.shortToast('复制成功') | 69 | ToastUtils.shortToast('复制成功') |
| 1 | +import { FileUtils as imageFileUtils } from '@ohos/imageknife' | ||
| 2 | +import { Action } from 'wdBean' | ||
| 3 | +import { AppUtils, FileUtils, SPHelper } from 'wdKit' | ||
| 4 | +import { JumpInterceptorAction, RouterJumpInterceptor, WDRouterPage } from 'wdRouter' | ||
| 5 | +import { JSON, uri } from '@kit.ArkTS' | ||
| 6 | +import { SpConstants } from 'wdConstant' | ||
| 7 | +import { router } from '@kit.ArkUI' | ||
| 8 | + | ||
| 9 | +interface WhiteListModel { | ||
| 10 | + whiteurls: string[] | ||
| 11 | +} | ||
| 12 | + | ||
| 13 | +class DefaultWebJumpHandler implements JumpInterceptorAction { | ||
| 14 | + | ||
| 15 | + /// 说明是调用了跳转 WDRouterPage.loginPage 页面的行为 | ||
| 16 | + on(params?: object | undefined, singleMode?: boolean | undefined): boolean { | ||
| 17 | + let action = params as Action | ||
| 18 | + | ||
| 19 | + if (action.params?.url) { | ||
| 20 | + | ||
| 21 | + const whiteListEnable = SPHelper.default.getSync(SpConstants.H5_WHITE_LIST_ENABLE, false) as boolean | ||
| 22 | + if (!whiteListEnable) { | ||
| 23 | + return false | ||
| 24 | + } | ||
| 25 | + | ||
| 26 | + const jumpHost = new uri.URI(action.params?.url).host | ||
| 27 | + const list = this.configWhiteLists() | ||
| 28 | + list.push(...this.localWhiteLists()) | ||
| 29 | + | ||
| 30 | + const inWhilteList = list.filter((host) => { | ||
| 31 | + return host == jumpHost | ||
| 32 | + }).length > 0 | ||
| 33 | + | ||
| 34 | + if (false == inWhilteList) { | ||
| 35 | + router.pushUrl({url: WDRouterPage.h5TipsPage.url(), params: action.params}) | ||
| 36 | + return true | ||
| 37 | + } | ||
| 38 | + } | ||
| 39 | + return false | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + configWhiteLists() : string[] { | ||
| 43 | + let list : string[] = [] | ||
| 44 | + | ||
| 45 | + if (!AppUtils.gotApplicationContextFunc) { | ||
| 46 | + return list | ||
| 47 | + } | ||
| 48 | + let filePath = AppUtils.gotApplicationContextFunc().getApplicationContext().filesDir + "/h5_whitelist.txt" | ||
| 49 | + const jsonStr = FileUtils.readFileAsString(filePath) | ||
| 50 | + const listObj = JSON.parse(jsonStr) as WhiteListModel | ||
| 51 | + if (listObj && listObj.whiteurls && listObj.whiteurls.length) { | ||
| 52 | + | ||
| 53 | + const urls = listObj.whiteurls.map((obj) => { | ||
| 54 | + if (obj.startsWith("http")) { | ||
| 55 | + return new uri.URI(obj).host | ||
| 56 | + } | ||
| 57 | + return new uri.URI("https://" + obj).host | ||
| 58 | + }) | ||
| 59 | + | ||
| 60 | + list.push(...urls) | ||
| 61 | + } | ||
| 62 | + return list | ||
| 63 | + } | ||
| 64 | + | ||
| 65 | + localWhiteLists() : string[] { | ||
| 66 | + const list = [ | ||
| 67 | + "https://cdnpeoplefrontdev.aikan.pdnews.cn", | ||
| 68 | + "https://cdnpeoplefrontsit.aikan.pdnews.cn", | ||
| 69 | + "https://cdnpeoplefrontuat.aikan.pdnews.cn", | ||
| 70 | + "https://cdnpeoplefront.aikan.pdnews.cn", | ||
| 71 | + "https://pd-people-uat.pdnews.cn", | ||
| 72 | + "https://pd-people-sit.pdnews.cn", | ||
| 73 | + "https://pd-people-dev.pdnews.cn", | ||
| 74 | + "https://www.peopleapp.com", | ||
| 75 | + "https://h5.peopleapp.com" | ||
| 76 | + ] | ||
| 77 | + return list.map((url) => { | ||
| 78 | + return new uri.URI(url).host | ||
| 79 | + }) | ||
| 80 | + } | ||
| 81 | +} | ||
| 82 | + | ||
| 83 | +export function registerDefaultWebJumpInterceptor() { | ||
| 84 | + RouterJumpInterceptor.register(WDRouterPage.defaultWebPage, new DefaultWebJumpHandler()) | ||
| 85 | + RouterJumpInterceptor.register(WDRouterPage.h5NewsWebPage, new DefaultWebJumpHandler()) | ||
| 86 | +} |
| @@ -27,6 +27,7 @@ import { initGlobalPlayerSettings } from 'wdPlayer/src/main/ets/utils/GlobalSett | @@ -27,6 +27,7 @@ import { initGlobalPlayerSettings } from 'wdPlayer/src/main/ets/utils/GlobalSett | ||
| 27 | import { BackgroundAudioController } from 'wdPlayer/Index' | 27 | import { BackgroundAudioController } from 'wdPlayer/Index' |
| 28 | import { SpConstants } from 'wdConstant' | 28 | import { SpConstants } from 'wdConstant' |
| 29 | import { WDShareBase } from 'wdShareBase/Index'; | 29 | import { WDShareBase } from 'wdShareBase/Index'; |
| 30 | +import { registerDefaultWebJumpInterceptor } from '../pages/web/WebPageJumpInterceptor' | ||
| 30 | 31 | ||
| 31 | const TAG = "[StartupManager]" | 32 | const TAG = "[StartupManager]" |
| 32 | 33 | ||
| @@ -59,6 +60,7 @@ export class StartupManager { | @@ -59,6 +60,7 @@ export class StartupManager { | ||
| 59 | KVStoreHelper.init(context) | 60 | KVStoreHelper.init(context) |
| 60 | // 路由注册 | 61 | // 路由注册 |
| 61 | registerRouter(); | 62 | registerRouter(); |
| 63 | + registerDefaultWebJumpInterceptor() | ||
| 62 | 64 | ||
| 63 | // 设置全局context | 65 | // 设置全局context |
| 64 | AppUtils.gotApplicationContextFunc = () => { | 66 | AppUtils.gotApplicationContextFunc = () => { |
-
Please register or login to post a comment