diff --git a/chatkit_ui/src/main/ets/model/ChatInfo.ets b/chatkit_ui/src/main/ets/model/ChatInfo.ets index 22ffcc2..c099ea4 100644 --- a/chatkit_ui/src/main/ets/model/ChatInfo.ets +++ b/chatkit_ui/src/main/ets/model/ChatInfo.ets @@ -5,6 +5,7 @@ * */ +import { authStore, BasicConstant, patientDbManager } from '@itcast/basic'; import { ChatKitClient } from '@nimkit/chatkit'; import { V2NIMMessagePin } from '@nimsdk/base'; import { V2NIMMessage, V2NIMMessageSendingState } from '@nimsdk/base/src/main/ets/nim/sdk/V2NIMMessageService'; @@ -67,7 +68,12 @@ export class ChatInfo { }; getCurrentUserAvatarUrl(message?: V2NIMMessage): string { - return ''; + + + return BasicConstant.urlHtml+authStore.getUser().photo; + + + }; getCurrentUserAvatarName(): string { diff --git a/chatkit_ui/src/main/ets/pages/ChatP2PPage.ets b/chatkit_ui/src/main/ets/pages/ChatP2PPage.ets index eed5d4a..39c2e24 100644 --- a/chatkit_ui/src/main/ets/pages/ChatP2PPage.ets +++ b/chatkit_ui/src/main/ets/pages/ChatP2PPage.ets @@ -23,6 +23,7 @@ import { NECommonUtils, NetworkBrokenBuilder, PermissionsUtils, + UserUtils, VideoViewerDialog } from '@nimkit/common'; import { NECameraSelectView } from '../view/NECameraSelectView'; @@ -179,6 +180,7 @@ export struct ChatP2PPage { cornerRadius: 4, width: '70%', }) + @Local showName:string=String(this.chatUserInfo.conversationName) waDialog: CustomDialogController = new CustomDialogController({ builder: NewWaDialog({ firstCallBack:()=>{ @@ -401,7 +403,7 @@ export struct ChatP2PPage { }) } - patientDetail() + patientDetail() { this.sessionId = ChatKitClient.nim.conversationIdUtil.parseConversationTargetId(this.conversationId) this.patientUuid=this.sessionId @@ -411,14 +413,13 @@ export struct ChatP2PPage { let json = JSON.parse(res+'') as Record; let datas=json.data as Record; this.patientUuid=datas.uuid + this.showName=await UserUtils.getAvatarName(this.patientUuid,String(this.chatUserInfo.conversationName)) }).catch((err: BusinessError) => { }) } - - aboutToAppear(): void { - + aboutToAppear() { NEEmojiManager.instance.setup(); DeviceUtils.rootDirPath = getContext(this).filesDir this.operationMoreDataList = setupMoreOperationData() @@ -455,7 +456,7 @@ export struct ChatP2PPage { }) this.initDialog() this. getOutList() - this.patientDetail() + } computeScrollHeight() { @@ -522,6 +523,7 @@ export struct ChatP2PPage { this.chatUserInfo.setConversationId(this.conversationId) this.chatViewModel.init(this.conversationId, this.chatUserInfo); this.chatViewModel.loadData(); + this.patientDetail() } async showImageDetail(msg?: NIMMessageInfo, onlyMsg?: boolean) { @@ -571,7 +573,7 @@ export struct ChatP2PPage { build() { NavDestination() { NavigationBackBuilder({ - title: this.chatUserInfo.conversationName, + title:this.showName , rightButtonIcon: this.showMultiSelect ? undefined : $r('app.media.ic_public_more_dot'), rightButtonTitle: this.showMultiSelect ? $r('app.string.chat_msg_dialog_cancel') : undefined, top:this.statusBarHeight, diff --git a/chatkit_ui/src/main/ets/view/MessageComponent.ets b/chatkit_ui/src/main/ets/view/MessageComponent.ets index d3c9bf7..792fc81 100644 --- a/chatkit_ui/src/main/ets/view/MessageComponent.ets +++ b/chatkit_ui/src/main/ets/view/MessageComponent.ets @@ -13,6 +13,7 @@ import { AvatarColorUntil, AvatarItem, CommonAvatar } from '@nimkit/common'; import { messageContent } from './MessageComponentBuilder'; import { MessageItemClick } from './MessageItemClick'; import { ChatKitConfig } from '../ChatKitConfig'; +import { authStore, BasicConstant } from '@itcast/basic'; /** * 消息组件按照UI样式,划分为发送消息组件、接收消息组件、通知消息组件和提示消息组件 @@ -243,7 +244,7 @@ export struct SenderMessageComponent { CommonAvatar({ item: new AvatarItem(this.chatUserInfo != null ? - this.chatUserInfo?.getCurrentUserAvatarUrl() : '', + this.chatUserInfo?.getCurrentUserAvatarUrl() : BasicConstant.urlHtml+authStore.getUser().photo, this.chatUserInfo?.getCurrentUserAvatarName() ?? '', AvatarColorUntil.getBackgroundColorById(this.message.message.senderId), ), diff --git a/chatkit_ui/src/main/ets/viewmodel/ChatBaseViewModel.ets b/chatkit_ui/src/main/ets/viewmodel/ChatBaseViewModel.ets index f207e90..0c5b19e 100644 --- a/chatkit_ui/src/main/ets/viewmodel/ChatBaseViewModel.ets +++ b/chatkit_ui/src/main/ets/viewmodel/ChatBaseViewModel.ets @@ -60,6 +60,7 @@ import { instanceToPlain } from 'class-transformer'; import { NECommonUtils } from '@nimkit/common'; import { HashMap, JSON } from '@kit.ArkTS'; import { assign } from '@nimsdk/vendor'; +import { BasicConstant, ChatExtModel } from '@itcast/basic'; @ObservedV2 export class ChatBaseViewModel { @@ -681,13 +682,20 @@ export class ChatBaseViewModel { async sendTextMessage(text: string, replyMsg?: NIMMessageInfo, aitModel?: AitModel, pushList?: string[]) { const message = ChatRepo.createTextMessage(text) //设置Ait - if (aitModel && aitModel.aitBlocks.size > 0) { - let extensionMap: YxAitMsg = { - yxAitMsg: aitModel.aitBlocks - } - let extension = JSON.stringify(instanceToPlain(extensionMap)) - message.serverExtension = extension + // if (aitModel && aitModel.aitBlocks.size > 0) { + // let extensionMap: YxAitMsg = { + // yxAitMsg: aitModel.aitBlocks + // } + // let extension = JSON.stringify(instanceToPlain(extensionMap)) + // message.serverExtension = extension + // } + let extension:ChatExtModel= { + gdxz_sessionType: '', + gdxz_consult_uuid: '', + gdxz_nickName: '' } + message.serverExtension =JSON.stringify(extension) + //设置推送 let params: V2NIMSendMessageParams | undefined = undefined @@ -742,6 +750,7 @@ export class ChatBaseViewModel { } params.aiConfig = aiParams } + this.sendMessage(message, params) } diff --git a/common/Index.ets b/common/Index.ets index aef2068..3bf1ab6 100644 --- a/common/Index.ets +++ b/common/Index.ets @@ -75,4 +75,6 @@ export { MatchSearchText } from './src/main/ets/view/MatchSearchText' export {CommonLongLoadingProgress } from './src/main/ets/builder/CommonLongLoadingProgress' -export { BreakpointConstants} from './src/main/ets/constants/BreakpointConstants' \ No newline at end of file +export { BreakpointConstants} from './src/main/ets/constants/BreakpointConstants' + +export { UserUtils } from './src/main/ets/utils/UserUtils'; \ No newline at end of file diff --git a/common/oh-package.json5 b/common/oh-package.json5 index 63459bc..447761c 100644 --- a/common/oh-package.json5 +++ b/common/oh-package.json5 @@ -6,6 +6,7 @@ "author": "", "license": "Apache-2.0", "dependencies": { - "@ohos/pinyin4js": "^2.0.0" + "@ohos/pinyin4js": "^2.0.0", + "@itcast/basic":"file:../commons/basic" } } \ No newline at end of file diff --git a/common/src/main/ets/utils/UserUtils.ets b/common/src/main/ets/utils/UserUtils.ets new file mode 100644 index 0000000..037eef5 --- /dev/null +++ b/common/src/main/ets/utils/UserUtils.ets @@ -0,0 +1,22 @@ +import { patientDbManager } from "@itcast/basic" + +export class UserUtils { + static async getAvatarName(account: string,names:string){ + let patient =await patientDbManager.getPatientByUuid(account) + if(patient!=null) + { + if(patient.nickname!=null&&patient.nickname!='') + { + return patient.nickname + } + if(patient.realName!=null&&patient.realName!='') + { + return patient.realName + } + } + + + return String(names) + + } +} \ No newline at end of file diff --git a/common/src/main/ets/view/CommonAvatar.ets b/common/src/main/ets/view/CommonAvatar.ets index d20be7a..a5d7309 100644 --- a/common/src/main/ets/view/CommonAvatar.ets +++ b/common/src/main/ets/view/CommonAvatar.ets @@ -4,7 +4,7 @@ * found in the LICENSE file. * */ - +import { authStore, BasicConstant, patientDbManager } from '@itcast/basic'; @ComponentV2 export struct CommonAvatar { /** @@ -29,24 +29,48 @@ export struct CommonAvatar { if (this.item != null) { if (this.item.avatarUrl == null || this.item.avatarUrl.toString().length <= 0) { - Stack() { - Column() { - }.width('100%').height('100%').backgroundColor(this.item.color) - .borderRadius(this.roundRadius) + Image(BasicConstant.urlHtml+authStore.getUser().photo) + .onError(() => { + if(this.item!=null) + { + this.item.avatarUrl = $r('app.media.icon_touxiang_persion_new'); + } + + }) + .syncLoad(true) + .borderRadius(this.roundRadius) + .onGestureJudgeBegin(() => { + return GestureJudgeResult.CONTINUE; + }).parallelGesture(LongPressGesture().onAction(event => { + this.longPressGesture?.(event) + } + )) + // Stack() { + // Column() { + // }.width('100%').height('100%').backgroundColor(this.item.color) + // .borderRadius(this.roundRadius) + // + // Text(this.item.name) + // .fontSize(this.textSize) + // .fontColor(this.textColor) + // .ellipsisMode(EllipsisMode.END) + // .textAlign(TextAlign.Center) + // .margin({ + // left: 6, right: 6 + // }) + // .width('100%') + // .maxLines(1) + // }.gesture(LongPressGesture().onAction(this.longPressGesture)) - Text(this.item.name) - .fontSize(this.textSize) - .fontColor(this.textColor) - .ellipsisMode(EllipsisMode.END) - .textAlign(TextAlign.Center) - .margin({ - left: 6, right: 6 - }) - .width('100%') - .maxLines(1) - }.gesture(LongPressGesture().onAction(this.longPressGesture)) } else { Image(this.item.avatarUrl) + .onError(() => { + if(this.item!=null) + { + this.item.avatarUrl = $r('app.media.icon_touxiang_persion_new'); + } + + }) .syncLoad(true) .borderRadius(this.roundRadius) .onGestureJudgeBegin(() => { diff --git a/common/src/main/resources/base/media/icon_touxiang_persion_new.png b/common/src/main/resources/base/media/icon_touxiang_persion_new.png new file mode 100644 index 0000000..9a9955f Binary files /dev/null and b/common/src/main/resources/base/media/icon_touxiang_persion_new.png differ diff --git a/commons/basic/Index.ets b/commons/basic/Index.ets index b1b63bf..92808e7 100644 --- a/commons/basic/Index.ets +++ b/commons/basic/Index.ets @@ -85,4 +85,6 @@ export { ViewImageInfo } from './src/main/ets/models/ViewImageInfo' export { ChangePhotoGrids } from './src/main/ets/components/ChangePhotoGrids' -export { InputPopWindow } from './src/main/ets/Views/InputPopWindow' \ No newline at end of file +export { InputPopWindow } from './src/main/ets/Views/InputPopWindow' + +export { ChatExtModel } from './src/main/ets/models/ChatExtModel' \ No newline at end of file diff --git a/commons/basic/src/main/ets/Views/PerfactInputSheet.ets b/commons/basic/src/main/ets/Views/PerfactInputSheet.ets index c119075..78a5c02 100644 --- a/commons/basic/src/main/ets/Views/PerfactInputSheet.ets +++ b/commons/basic/src/main/ets/Views/PerfactInputSheet.ets @@ -14,7 +14,7 @@ export struct PerfactInputSheet { @State okText:ResourceStr='确定' @State cancelText:ResourceStr='取消' private inputCallBack: (input: string,title:string) => void = () => {}; - + @State needcancelCallBack:boolean=false // 修改构造函数 constructor(controller: CustomDialogController, inputCallBack: (input: string,title:string) => void) { super(); @@ -115,6 +115,8 @@ export struct PerfactInputSheet { .textAlign(TextAlign.Center) .width('45%').height(30) .onClick(() => { + + this.controller.close() }) Text('').height(30).width(1) @@ -171,6 +173,10 @@ export struct PerfactInputSheet { .width('45%').height(30) .onClick(() => { + if(this.needcancelCallBack) + { + this.inputCallBack(this.inputText, 'needcancelCallBack'); + } this.controller.close() }) Text('').height(30).width(1) diff --git a/commons/basic/src/main/ets/constants/BasicConstant.ets b/commons/basic/src/main/ets/constants/BasicConstant.ets index ebaac48..c0b8bc1 100644 --- a/commons/basic/src/main/ets/constants/BasicConstant.ets +++ b/commons/basic/src/main/ets/constants/BasicConstant.ets @@ -79,6 +79,7 @@ export class BasicConstant { static readonly listMyAnsweredInterrogation = BasicConstant.urlExpertAPI +"listMyAnsweredInterrogation";// 一问多答 我回答的一问多答列表 static readonly getInterrogation = BasicConstant.urlExpertAPI +"getInterrogation";// 一问多答 详情页 static readonly InterrogationPatientInfo = BasicConstant.urlExpertAPI +"InterrogationPatientInfo";// 一问多答 患者详情页 + static readonly updateInterrogationAnswer = BasicConstant.urlExpertAPI+"updateInterrogationAnswer";// 一问多答 编辑回答 static readonly province=['全国','北京市','天津市','河北省','山西省' ,'内蒙古自治区','辽宁省','吉林省','黑龙江省','上海市','江苏省','浙江省' ,'安徽省','福建省','江西省','山东省','河南省','湖北省','湖南省','广东省', diff --git a/commons/basic/src/main/ets/models/ChatExtModel.ets b/commons/basic/src/main/ets/models/ChatExtModel.ets new file mode 100644 index 0000000..ce5342a --- /dev/null +++ b/commons/basic/src/main/ets/models/ChatExtModel.ets @@ -0,0 +1,8 @@ + + +export interface ChatExtModel{ + gdxz_sessionType:string,//是否为公益咨询 + gdxz_consult_uuid:string,//公益咨询uuid + gdxz_nickName:string//患者备注姓名 + +} \ No newline at end of file diff --git a/commons/basic/src/main/ets/utils/ChangeUtil.ets b/commons/basic/src/main/ets/utils/ChangeUtil.ets index 0781c04..119324d 100644 --- a/commons/basic/src/main/ets/utils/ChangeUtil.ets +++ b/commons/basic/src/main/ets/utils/ChangeUtil.ets @@ -8,6 +8,7 @@ import { fileIo } from '@kit.CoreFileKit'; import util from '@ohos.util'; import { i18n } from '@kit.LocalizationKit'; import { connection } from '@kit.NetworkKit'; +import http from '@ohos.net.http' export class ChangeUtil { /** * 将HashMap转成JsonString @@ -191,10 +192,46 @@ export class ChangeUtil { } static stringIsUndefinedAndNull (string:string | undefined):boolean { - if (string == undefined || string == "null" || string == "" || string == "(null)" || string == 'undefined' || string.length <= 0) { + if (string == null||string == undefined || string == "null" || string == "" || string == "(null)" || string == 'undefined' || string.length <= 0) { return true } else { return false } + } + + static map2JsonO(map:HashMap) { + let jsonObject: Record = {}; + map.forEach((value, key) => { + if(key != undefined && value != undefined){ + jsonObject[key] = value; + } + }) + return jsonObject; + } + + static async getImageBase64(url: string): Promise { + // 创建 http 实例 + let httpRequest = http.createHttp(); + // 发起 GET 请求 + let response = await httpRequest.request(url, { + method: http.RequestMethod.GET, + // 重要:设置 responseType 为 arraybuffer,获取二进制数据 + expectDataType: http.HttpDataType.ARRAY_BUFFER + }); + // 检查响应 + if (response.responseCode === 200 && response.result) { + // 1. 转成 Uint8Array + const buffernew=await ChangeUtil.compression(response.result as ArrayBuffer,"image/jpeg",0.5) + // let uint8Arr = new Uint8Array(response.result as ArrayBuffer) + const base64Helper = new util.Base64Helper(); + return base64Helper.encodeToStringSync(new Uint8Array(buffernew)); + // response.result 是 ArrayBuffer + // let base64Str = base64.encode(response.result as ArrayBuffer); + // // 可选:拼接 data url 前缀 + // return "data:image/png;base64," + base64Str; + } + return ""; + } + } \ No newline at end of file diff --git a/commons/basic/src/main/ets/utils/PatientsEntity.ets b/commons/basic/src/main/ets/utils/PatientsEntity.ets index 655516d..5513c84 100644 --- a/commons/basic/src/main/ets/utils/PatientsEntity.ets +++ b/commons/basic/src/main/ets/utils/PatientsEntity.ets @@ -249,8 +249,7 @@ export class PatientDao { if (!this.rdbStore) { throw new Error('数据库连接为空'); } - - const sql = 'SELECT * FROM patients WHERE uuid = ?'; + const sql = 'SELECT * FROM patients WHERE LOWER(uuid) = LOWER(?)'; const resultSet = await this.rdbStore.querySql(sql, [uuid]); if (resultSet.rowCount > 0) { diff --git a/commons/basic/src/main/ets/utils/request.ets b/commons/basic/src/main/ets/utils/request.ets index 3bb151f..946248a 100644 --- a/commons/basic/src/main/ets/utils/request.ets +++ b/commons/basic/src/main/ets/utils/request.ets @@ -67,7 +67,40 @@ class HdHttp { httpInstance.destroy() }) } + private requestObject(path: string, method: http.RequestMethod = http.RequestMethod.POST, extraDatas :HashMap) { + const httpInstance = http.createHttp() + const options: http.HttpRequestOptions = { + method: http.RequestMethod.POST, + // 可选,默认为60s + connectTimeout: 60000, + // 可选,默认为60s + readTimeout: 60000, + // 开发者根据自身业务需要添加header字段 + header: { + 'Content-Type': 'application/json', + 'sign':this.getSignO(extraDatas), + 'User-Agent':this.osFullName + }, + extraData:ChangeUtil.map2JsonO(extraDatas) + } + + let fullUrl = this.baseURL + path + + + return httpInstance.request(fullUrl, options).then((res) => { + logger.info('Response param'+JSON.stringify(extraDatas)) + logger.info('Response fullUrl:' +fullUrl+ res.result); + const result = res.result as HdResponse + return result + }).catch((err: BusinessError) => { + logger.info(fullUrl+`Response succeeded: ${err}`); + promptAction.showToast({ message: err.message || '网络错误' }) + return Promise.reject(err) + }).finally(() => { + httpInstance.destroy() + }) + } private requestafter(path: string, method: http.RequestMethod = http.RequestMethod.GET, extraData?: Object) { const httpInstance = http.createHttp() @@ -129,6 +162,9 @@ class HdHttp { posts(url: string, data: HashMap): Promise> { return this.request(url, http.RequestMethod.POST, data) } + postO(url: string, data: HashMap): Promise> { + return this.requestObject(url, http.RequestMethod.POST, data) + } httpReq(url: string, datas: HashMap): Promise> { // 创建httpRequest对象。 let httpRequest = http.createHttp(); @@ -171,6 +207,47 @@ class HdHttp { }) } + httpReqObject(url: string, datas: HashMap): Promise> { + // 创建httpRequest对象。 + let httpRequest = http.createHttp(); + let url1 = "https://dev-app.igandan.com/app/manager/getSystemTimeStamp"; + let promise = httpRequest.request( + // 请求url地址 + url1, + { + // 请求方式 + method: http.RequestMethod.GET, + // 可选,默认为60s + connectTimeout: 60000, + // 可选,默认为60s + readTimeout: 60000, + // 开发者根据自身业务需要添加header字段 + header: { + 'Content-Type': 'application/json' + } + }); + // 处理响应结果。 + return promise.then(async (data) => { + if (data.responseCode === http.ResponseCode.OK) { + logger.info('Response httpReq:' + data.result); + let json:TimestampBean = JSON.parse(data.result.toString()) as TimestampBean; + let tp = json.timestamp; + datas.set("user_uuid", authStore.getUser().uuid?authStore.getUser().uuid:''); + datas.set("client_type", 'H'); + datas.set("version", await this.getVersion() ); + datas.set('timestamp',tp+''); + return this.postO(url, datas); + } else { + return this.postO(url, datas); + } + } + ).catch((err:BusinessError) => { + logger.info('Response httpReq error:' + JSON.stringify(err)); + return Promise.reject(err); + }).finally(() => { + httpRequest.destroy() + }) + } httpReqSimply(url: string) { // 创建httpRequest对象。 let httpRequest = http.createHttp(); @@ -203,6 +280,29 @@ class HdHttp { }) } + getSignO(extraDatas1:HashMap): string { + let secret= extraDatas1.get("timestamp")+'' + if(secret!=null) { + let keyValueStr: string = ""; + let entriesArray: Array = Array.from(extraDatas1.keys()); + entriesArray.sort(); + + let sortedMap:HashMap = new HashMap(); + entriesArray.forEach((value: string, index: number) => { + sortedMap.set(value,extraDatas1.get(value)); + // keyValueStr +=value+extraDatas1.get(value) + keyValueStr +=value+JSON.stringify(extraDatas1.get(value)) + }); + keyValueStr = keyValueStr + CryptoJS.MD5(secret).toString(); + keyValueStr = keyValueStr.replaceAll(" ", "").replaceAll("\"", "").replaceAll(":","="); + let Md5keyValueStr: string = CryptoJS.MD5(keyValueStr).toString(); + let base64Str:string=Base64Util.encodeToStrSync(Md5keyValueStr); + return base64Str; + } else { + return ''; + } + } + getSign(extraDatas1:HashMap): string { let secret= extraDatas1.get("timestamp") if(secret!=null) { diff --git a/features/Home/src/main/ets/components/HomeIconComp.ets b/features/Home/src/main/ets/components/HomeIconComp.ets index b66b616..b0251da 100644 --- a/features/Home/src/main/ets/components/HomeIconComp.ets +++ b/features/Home/src/main/ets/components/HomeIconComp.ets @@ -1,6 +1,6 @@ import { iconsModel } from '../model/HomeModel' import { patientDbManager, PatientEntity } from '@itcast/basic'; -import { promptAction } from '@kit.ArkUI'; +import { promptAction, router } from '@kit.ArkUI'; // interface iconsModel { // img:string; @@ -57,6 +57,13 @@ export struct HomeIconComp { const patients = await patientDbManager.getAllPatients(); console.info(`添加了 ${patients.length} 个患者`); promptAction.showToast({message:`添加了 ${patients.length} 个患者`}) + if(item.name=='公益咨询') { + router.pushUrl({ url: 'pages/Netease/PublicConsultationPage' }) + } + else if(item.name=='我的患者') { + router.pushUrl({url:'pages/Netease/imTabPage'}) + } + }) }) }.width('100%').backgroundColor(Color.White) diff --git a/features/Home/src/main/ets/pages/VideoPage.ets b/features/Home/src/main/ets/pages/VideoPage.ets index 6be6af7..4e8d206 100644 --- a/features/Home/src/main/ets/pages/VideoPage.ets +++ b/features/Home/src/main/ets/pages/VideoPage.ets @@ -198,9 +198,9 @@ export struct VideoPage { }) .margin({bottom:60}) .onClick(() => { - // router.pushUrl({url:'pages/VideoPage/PastVideoPage'}) + router.pushUrl({url:'pages/VideoPage/PastVideoPage'}) // router.pushUrl({url:'pages/Netease/imTabPage'}) - router.pushUrl({url:'pages/Netease/PublicConsultationPage'}) + // router.pushUrl({url:'pages/Netease/PublicConsultationPage'}) }) } diff --git a/features/netease/src/main/ets/view/ConsultationDetailComp.ets b/features/netease/src/main/ets/view/ConsultationDetailComp.ets index 2258bbe..bed936f 100644 --- a/features/netease/src/main/ets/view/ConsultationDetailComp.ets +++ b/features/netease/src/main/ets/view/ConsultationDetailComp.ets @@ -32,6 +32,8 @@ export struct ConsultationDetailComp { builder:PerfactInputSheet({ controller:this.custom, inputTitle:'', + okText:'是', + cancelText:'否', inputPlaceholder:this.inputPlaceholder, style:'2', okColor:$r('app.color.top_title'), diff --git a/features/netease/src/main/ets/view/InterrogationDetailComp.ets b/features/netease/src/main/ets/view/InterrogationDetailComp.ets index 95e230a..5dd09ea 100644 --- a/features/netease/src/main/ets/view/InterrogationDetailComp.ets +++ b/features/netease/src/main/ets/view/InterrogationDetailComp.ets @@ -263,11 +263,21 @@ export struct InterrogationDetailComp { .backgroundColor($r('app.color.patient_theme')) .fontColor(Color.White) .onClick(() => { + if(this.params.isHistory =='false') + { + router.pushUrl({ + url: 'pages/Netease/MyOpinionPage', + params: { uuid:this.params.uuid,isHistory:this.params.isHistory} + }); + } + else + { + router.pushUrl({ + url: 'pages/Netease/MyOpinionPage', + params: { uuid:this.params.uuid,isHistory:this.params.isHistory,myAnswer:this.getMyanswer(this.AnswerList)} + }); + } - router.pushUrl({ - url: 'pages/Netease/MyOpinionPage', - // params: { uuid: this.item.uuid} - }); }) } @@ -307,5 +317,11 @@ export struct InterrogationDetailComp { } + getMyanswer(AnswerList:AnswerListBean[]) + { + let targetItem = AnswerList.find(item => authStore.getUser().uuid ==item.expert_uuid ); + return targetItem + + } } diff --git a/features/netease/src/main/ets/view/MyOpinionComp.ets b/features/netease/src/main/ets/view/MyOpinionComp.ets index 87ed401..5f9affe 100644 --- a/features/netease/src/main/ets/view/MyOpinionComp.ets +++ b/features/netease/src/main/ets/view/MyOpinionComp.ets @@ -1,6 +1,16 @@ -import { ChangePhotoGrids, HdNav, ViewImageInfo } from "@itcast/basic" +import { BasicConstant, ChangePhotoGrids, + ChangeUtil, + hdHttp, + HdLoadingDialog, HdNav, + HdResponse, + preferenceStore, ViewImageInfo } from "@itcast/basic" import { PhotoActionSheet } from '@itcast/basic' - +import { AnswerListBean } from "../model/ConsulModel" +import { router } from "@kit.ArkUI" +import { PerfactInputSheet } from "@itcast/basic/src/main/ets/Views/PerfactInputSheet" +import { BusinessError } from "@kit.BasicServicesKit" +import { HashMap } from "@kit.ArkTS" +import { rcp } from '@kit.RemoteCommunicationKit'; @Component export struct MyOpinionComp { @State photos: string[] = [] @@ -10,12 +20,15 @@ export struct MyOpinionComp { @State @Watch('onRemoveImg') removeImg: boolean=false - + @State text: string = '' @State @Watch('onAddImg') addImg: boolean=false - + @State params:param = router.getParams() as param; @State removeIndex: number=0 + hashMap: HashMap = new HashMap(); + hashMapImg: HashMap = new HashMap(); + onAddImg() { this.photoSheetDialog.open() @@ -25,6 +38,42 @@ export struct MyOpinionComp { this.photos.splice(this.removeIndex, 1) this.maxSelectNumber = this.maxSelectNumber - this.photos.length; } + private custom!:CustomDialogController; + dialog: CustomDialogController = new CustomDialogController({ + builder: HdLoadingDialog({ message: '加载中...' }), + customStyle: true, + alignment: DialogAlignment.Center + }) + initDialog() { + this.custom = new CustomDialogController({ + builder:PerfactInputSheet({ + controller:this.custom, + inputTitle:'提示', + okText:'保存', + needcancelCallBack:true, + okColor:$r('app.color.top_title'), + inputPlaceholder:'您有未发布的内容,是否保存?', + style:'2', + inputCallBack:(input: string,title:string)=>{ + if(title=='needcancelCallBack') + { + preferenceStore.setItemString('MyOpinionComp'+this.params.uuid,'') + } + else + { + preferenceStore.setItemString('MyOpinionComp'+this.params.uuid,this.text) + } + router.back() + + } + }), + alignment: DialogAlignment.Center, + customStyle: true, + autoCancel: false, + backgroundColor: ('rgba(0,0,0,0.5)'), + height: '100%' + }) + } private initPhotoDialog() { this.photoSheetDialog = new CustomDialogController({ builder: PhotoActionSheet({ @@ -44,13 +93,7 @@ export struct MyOpinionComp { } - // onPhotoSelected: async (uri: string) => { - // if (uri && this.photos.length < 9) { - // this.photos.push(uri) - // } - // // this.photoPath = uri; - // // this.base64Stringphoto = await ChangeUtil.convertUriToBase64(uri); - // } + }), alignment: DialogAlignment.Bottom, customStyle: true, @@ -60,17 +103,90 @@ export struct MyOpinionComp { }); } aboutToAppear(): void { + console.log('Response aboutToAppear') this.initPhotoDialog() + this.initDialog() + if(this.params.isHistory =='true') + { + this.text=this.params.myAnswer.note + if(this.params.myAnswer.imgs!=null) + { + this.photos.push(...this.changeToImgs(this.params.myAnswer.imgs.split(","))) + this.maxSelectNumber = this.maxSelectNumber - this.photos.length; + } + + } + else + { + this.text=preferenceStore.getItemString('MyOpinionComp'+this.params.uuid) + + } } build() { Column() { - HdNav({ title: '我的意见', showRightIcon: false, showLeftIcon: true }) + HdNav({ title: '我的意见', showRightIcon: false, showLeftIcon: true ,isLeftAction:true,leftItemAction:()=>{ + if(this.params.isHistory =='false') + { + if(this.text.length>0) + { + this.custom.open() + } + else + { + router.back() + } + } + else + { + router.back() + } + }}) + Text('我的意见 *').fontSize(17).fontColor($r('app.color.top_title')).padding(10).width('100%').textAlign(TextAlign.Start) + TextArea({ placeholder: '请依据患者的个人信息、疾病资料及患者所咨询的问题详细解答患者的问题(信息仅提问患者及医生可见、最多输入300个字)', text: $$this.text }) + .fontColor($r('app.color.common_gray_03')) + .height(100) + .textAlign(TextAlign.Start) + .fontSize(14).padding(9).margin({left:10,right:10,bottom:10}) + .backgroundColor($r('app.color.f6f6f6')).borderRadius(8) + Text('相关图片').fontSize(17).fontColor($r('app.color.top_title')).padding({left:10,right:10,bottom:10}).width('100%').textAlign(TextAlign.Start) + Text('可以用部分科普或文献来协助问答问题,最多6张').fontSize(14).fontColor($r('app.color.999999')).padding({left:10,right:10,bottom:10}).width('100%').textAlign(TextAlign.Start) ChangePhotoGrids({imgList:this.changeToImg(this.photos),maxSelectNumber:6 - ,addImg:this.addImg,removeImg:this.removeImg,removeIndex:this.removeIndex}) - .backgroundColor(Color.Red) + ,addImg:this.addImg,removeImg:this.removeImg,removeIndex:this.removeIndex}).layoutWeight(1) + Column() + { + Button({ type: ButtonType.Normal }){ + Text('提交') + } + .width('100%') + .height(53) + .backgroundColor($r('app.color.patient_theme')) + .fontColor(Color.White) + .onClick(() => { + if(this.params.isHistory =='false') + { + // router.pushUrl({ + // url: 'pages/Netease/MyOpinionPage', + // params: { uuid:this.params.uuid,isHistory:this.params.isHistory} + // }); + } + else + { + this.updateInterrogationAnswer() + // router.pushUrl({ + // url: 'pages/Netease/MyOpinionPage', + // params: { uuid:this.params.uuid,isHistory:this.params.isHistory,myAnswer:this.getMyanswer(this.AnswerList)} + // }); + } + + + }) + } + .backgroundColor(Color.White) + .width('100%') + } @@ -78,6 +194,48 @@ export struct MyOpinionComp { .width('100%') } + async getUploadImg() + { + this.hashMapImg.clear(); + + if(this.photos.length>0) + { + for (let index = 0; index < this.photos.length; index++) { + if(this.photos[index].includes('http')) + { + this.hashMapImg.set('img'+index+1,await ChangeUtil.getImageBase64(this.photos[index])) + } + else + { + this.hashMapImg.set('img'+index+1, await ChangeUtil.convertUriToBase64(this.photos[index])) + + } + + } + } + return this.hashMapImg + } + + async updateInterrogationAnswer() + { + this.dialog.open() + this.hashMap.clear(); + this.hashMap.set("note",this.text); + this.hashMap.set('uuid', this.params.uuid) + this.hashMap.set('imgsBean',await this.getUploadImg()) + hdHttp.httpReqObject(BasicConstant.updateInterrogationAnswer,this.hashMap).then(async (res: HdResponse) => { + this.dialog.close() + + + + }).catch((err: BusinessError) => { + this.dialog.close() + + }) + + // let req = new rcp.Request("http://example.com", "POST", headers, simpleForm, cookies, transferRange, configuration); + } + changeToImg( imgListurl:string[]) { let imgListtmps:ViewImageInfo[]=[] @@ -88,4 +246,21 @@ export struct MyOpinionComp { return imgListtmps } -} \ No newline at end of file + changeToImgs( imgListurl:string[]) + { + let imgListtmps:string[]=[] + imgListurl.forEach((url: string) => { + let item = BasicConstant.urlHtml + url + imgListtmps.push(item) + }) + return imgListtmps + + } +} +interface param{ + uuid:string, + isHistory:string, + myAnswer:AnswerListBean +} + + diff --git a/localconversationkit_ui/src/main/ets/view/ConversationViewItem.ets b/localconversationkit_ui/src/main/ets/view/ConversationViewItem.ets index 856b2e4..09252a0 100644 --- a/localconversationkit_ui/src/main/ets/view/ConversationViewItem.ets +++ b/localconversationkit_ui/src/main/ets/view/ConversationViewItem.ets @@ -5,8 +5,9 @@ * */ +import { patientDbManager, PatientEntity } from '@itcast/basic'; import { ChatKitClient } from '@nimkit/chatkit'; -import { AvatarColorUntil, AvatarItem, CommonAvatar } from '@nimkit/common'; +import { AvatarColorUntil, AvatarItem, CommonAvatar, UserUtils } from '@nimkit/common'; import { DateUtil } from '@nimkit/common/src/main/ets/utils/DateUtil'; import { V2NIMLocalConversation, V2NIMMessageCallAttachment, V2NIMMessageType } from '@nimsdk/base'; import { LocalConversationOperationDialog } from './LocalConversationOperationDialog'; @@ -25,6 +26,12 @@ export struct ConversationViewItem { width: '60%', borderColor: '#ffDCDFE5' }) + @Local showName:string=String(this.conversationInfo?.name) + + async aboutToAppear(): Promise { + let account = ChatKitClient.nim.conversationIdUtil.parseConversationTargetId(this.conversationInfo?.conversationId) + this.showName=await UserUtils.getAvatarName(account,String(this.conversationInfo?.name)) + } build() { if (this.conversationInfo !== null) { @@ -59,7 +66,7 @@ export struct ConversationViewItem { Column() { //item 显示名称 - Text(this.conversationInfo.name) + Text(this.showName) .fontSize(16) .fontColor("#ff333333") .textOverflow({ overflow: TextOverflow.Ellipsis }) @@ -160,6 +167,25 @@ export struct ConversationViewItem { } } + // async getAvatarName(sourceName: string){ + // let account = ChatKitClient.nim.conversationIdUtil.parseConversationTargetId(this.conversationInfo?.conversationId) + // let patient =await patientDbManager.getPatientByUuid(account) + // if(patient!=null) + // { + // if(patient.nickname!=null&&patient.nickname!='') + // { + // return patient.nickname + // } + // if(patient.realName!=null&&patient.realName!='') + // { + // return patient.realName + // } + // } + // + // + // return String(this.conversationInfo?.name) + // + // } /** * 头像只显示后两位 * @param sourceName diff --git a/products/expert/oh-package.json5 b/products/expert/oh-package.json5 index 83e968c..c3f651e 100644 --- a/products/expert/oh-package.json5 +++ b/products/expert/oh-package.json5 @@ -7,10 +7,10 @@ "license": "", "dependencies": { "@itcast/basic": "file:../../commons/basic", - "mypage":"file:../../features/mypage", - "home": 'file:../../features/Home', - "register": 'file:../../features/register', - "patient": 'file:../../features/patient', + "mypage": "file:../../features/mypage", + "home": "file:../../features/Home", + "register": "file:../../features/register", + "patient": "file:../../features/patient", "scene_single_video": "file:../../scene_single_video", "media-player-common": "file:../../polyv", "@polyvharmony/media-player-sdk": "2.5.0", @@ -28,7 +28,8 @@ "@nimsdk/nim": "10.9.10", "@nimsdk/base": "10.9.10", "@nimkit/corekit": "file:../../corekit", - '@nimkit/chatkit': "file:../../chatkit", - 'netease': "file:../../features/netease" + "@nimkit/chatkit": "file:../../chatkit", + "netease": "file:../../features/netease", + } } \ No newline at end of file diff --git a/products/expert/src/main/ets/entryability/NimRepository.ets b/products/expert/src/main/ets/entryability/NimRepository.ets index 637bdc8..555db6e 100644 --- a/products/expert/src/main/ets/entryability/NimRepository.ets +++ b/products/expert/src/main/ets/entryability/NimRepository.ets @@ -52,9 +52,9 @@ export class NimRepository { console.debug(`Performance Test im start loginSuccess`) await this.nim.loginService.login(accountId, token); console.error('----------- 登录成功 -----------') - router.pushUrl({ - url: 'pages/Netease/imTabPage' - }); + // router.pushUrl({ + // url: 'pages/Netease/imTabPage' + // }); console.debug(`Performance Test im loginSuccess`) ChatKitClient.init(this.nim, appKey) @@ -62,6 +62,7 @@ export class NimRepository { } catch (error) { console.error('----------- 登录失败 -----------', error) + ChatKitClient.init(this.nim, appKey) throw error as Error } } diff --git a/products/expert/src/main/ets/pages/WebView/WebPageSnapshot.ets b/products/expert/src/main/ets/pages/WebView/WebPageSnapshot.ets new file mode 100644 index 0000000..d214208 --- /dev/null +++ b/products/expert/src/main/ets/pages/WebView/WebPageSnapshot.ets @@ -0,0 +1,344 @@ +import webview from '@ohos.web.webview'; +import { HdNav } from '@itcast/basic'; +import router from '@ohos.router'; +import { image } from '@kit.ImageKit'; +import { photoAccessHelper } from '@kit.MediaLibraryKit'; +import { promptAction } from '@kit.ArkUI'; +import { componentSnapshot } from '@kit.ArkUI'; +import { fileIo, fileUri } from '@kit.CoreFileKit'; +import { display} from '@kit.ArkUI'; + + +const TAG = 'WebViewSaveImage'; + +@Entry +@Component +struct WebPageSnapshot { + private controller: webview.WebviewController = new webview.WebviewController(); + @State params:RouteParams = router.getParams() as RouteParams; + + @State contentWidth: number = 0; + @State contentHeight: number = 0; + @State url: string = this.params.url; + @State title: string = this.params.title; + customUserAgent: string = 'gdxz-expert'; + // 网页尺寸 + @State h5Width: number = 0; + @State h5Height: number = 0; + // Web组件尺寸 + private webWidth: number = 0; + private webHeight: number = 0; + // 当前网页位置 + private curXOffset: number = 0; + private curYOffset: number = 0; + // 备份当前网页位置 + private xOffsetBefore: number = 0; + private yOffsetBefore: number = 0; + // 截图过程的Web组件覆盖 + @State webMaskImage: PixelMap | undefined = undefined; + private webMaskImageZIndex: number = -1; + // 合并后的图片 + @State mergedImage: PixelMap | undefined = undefined; + + @State snapPopupPosition: Position = { x: 0, y: 0 }; + //Web是否已经滚动到底部 + @State WebTouchBottom: boolean = false; + // 屏幕尺寸 + private displayWidth: number = 0; + private displayHeight: number = 0; + onBackPress(): boolean | void { + if (this.controller.accessStep(-1)) { + this.controller.backward(); + return true; + } + return false; + } + + build() { + Column() { + HdNav({ title: this.title, showRightIcon: false, hasBorder: true ,isLeftAction:true,leftItemAction:()=>{ + if (this.controller.accessBackward()) { + this.controller.backward(); + } else { + router.back(); + } + }}) + + Web({ + src: this.url, + controller: this.controller + }) + .id('webViewShot') + .mixedMode(MixedMode.All) + .overScrollMode(OverScrollMode.ALWAYS) + .domStorageAccess(true) + .onAreaChange((oldValue, newValue) => { + // TODO: 高性能知识点: onAreaChange为高频回调,组件变动时每帧都会调用,避免冗余和耗时操作。 + this.webWidth = newValue.width as number; + this.webHeight = newValue.height as number; + + }) + .onControllerAttached(() => { + let userAgent = this.controller.getUserAgent() + this.customUserAgent; + this.controller.setCustomUserAgent(userAgent); + }) + .onOverScroll((event) => { + if (event?.yOffset > 0) { + this.WebTouchBottom = true + } else if (event?.yOffset === 0 && this.WebTouchBottom) { + this.WebTouchBottom = false + } + }) + .onScroll((event) => { + this.curXOffset = event.xOffset; + this.curYOffset = event.yOffset; + + }) + .width('100%') + .layoutWeight(1)// 占据剩余空间 + .height('100%') + + if (this.title == '随访二维码') { + Row(){ + SaveButton({text:SaveDescription.SAVE_IMAGE,buttonType:ButtonType.Normal}) + .fontSize(16) + .fontColor(Color.White) + .backgroundColor('rgb(63,199,193)') + .width('100%').height(50) + .onClick( () => { + + this.snapShot(); + + }) + }.width('100%').height(56).backgroundColor(Color.White).alignItems(VerticalAlign.Top) + } + } + .height('100%')// 关键:约束父容器高度 + } + aboutToAppear(): void { + let a=this.url + // 获取屏幕尺寸 + const displayData = display.getDefaultDisplaySync(); + this.displayWidth = px2vp(displayData.width); + this.displayHeight = px2vp(displayData.height); + + } + async saveWebViewImage() { + try { + // 1. 获取整个网页的长截图 + this.controller.webPageSnapshot({ + id: "webView", + size: { width: this.contentWidth, height:this.contentHeight } // 确保捕获全尺寸 + }, async (error, result) => { + if (error) { + promptAction.showToast({ message: `截图失败: ${error.message}` }); + console.error('webPageSnapshot error:', error); + return; + } + + if (!result?.imagePixelMap) { + promptAction.showToast({ message: '获取截图数据失败' }); + return; + } + + // 2. 转为JPEG并写入沙箱 + const ctx = getContext(this); + const imagePacker = image.createImagePacker(); + const arrayBuffer = await imagePacker.packToData( + result.imagePixelMap, + { format: 'image/jpeg', quality: 100 } // 平衡质量与大小 + ); + + const sandboxPath = ctx.cacheDir + `/web_fullpage_${Date.now()}.jpg`; + const file = fileIo.openSync(sandboxPath, fileIo.OpenMode.CREATE | fileIo.OpenMode.READ_WRITE); + fileIo.writeSync(file.fd, arrayBuffer); + fileIo.closeSync(file.fd); + + // 3. 保存到相册 + const helper = photoAccessHelper.getPhotoAccessHelper(ctx); + const sandboxUri = fileUri.getUriFromPath(sandboxPath); + const request = photoAccessHelper.MediaAssetChangeRequest.createImageAssetRequest(ctx, sandboxUri); + await helper.applyChanges(request); + + promptAction.showToast({ message: '网页已保存至相册' }); + }); + } catch (e) { + promptAction.showToast({ message: '保存失败: ' + e.message }); + console.error('saveWebViewImage error:', e); + } + } + /** + * 截图函数。 + */ + async snapShot() { + // 获取Web页面尺寸 + this.getWebSize(); + // 截图前的状态初始化 + await this.beforeSnapshot(); + // TODO: 性能知识点: 使用Canvas离屏绘制在缓冲区拼接截图 + const canvasSetting: RenderingContextSettings = new RenderingContextSettings(true); + const offCanvasCtx: OffscreenCanvasRenderingContext2D = + new OffscreenCanvasRenderingContext2D(this.h5Width, this.h5Height, canvasSetting); + // 前置常量 + const snipTimes = Math.ceil(this.h5Height / this.webHeight); + + const lastTime = snipTimes - 1; + const leftoverHeight = this.h5Height % this.webHeight; + let cropLeftover: image.Region = { x: 0, y: 0, size: { height: 0, width: 0 } } + if (this.WebTouchBottom) { + // 这里要分两种情况,1.滚动到底部时,裁剪应该取最后一张除去重复部分以外的底部 + cropLeftover = { + x: 0, + y: vp2px(this.webHeight - leftoverHeight), + size: { + height: vp2px(leftoverHeight), + width: vp2px(this.webWidth) + } + }; + } else { + // 2.未滚动到底部时,裁剪应该取最后一张leftoverHeight的上部分 + cropLeftover = { + x: 0, + y: 0, + size: { + height: vp2px(leftoverHeight), + width: vp2px(this.webWidth) + } + }; + } + + // 开始截图 + for (let i = 0; i < snipTimes; i++) { + const curSnip = await componentSnapshot.get('webViewShot'); + // 最后一次截图需要特殊处理,去除重复部分 + if (i === lastTime) { + + await curSnip.crop(cropLeftover); + offCanvasCtx.drawImage(curSnip, 0, this.webHeight * i, this.webWidth, leftoverHeight); + } else { + offCanvasCtx.drawImage(curSnip, 0, this.webHeight * i, this.webWidth, this.webHeight); + } + + // 继续滚动 + this.controller.scrollBy(0, this.webHeight); + // 延时保证滚动完成 + await sleep(200); + } + // 截图后的操作 + await this.afterSnapshot(); + // 获取pixelMap + this.mergedImage = offCanvasCtx.getPixelMap(0, 0, this.h5Width, this.h5Height); + try { + // 2. 转为JPEG并写入沙箱 + const ctx = getContext(this); + const imagePacker = image.createImagePacker(); + const arrayBuffer = await imagePacker.packToData( + this.mergedImage, + { format: 'image/jpeg', quality: 100 } // 平衡质量与大小 + ); + + const sandboxPath = ctx.cacheDir + `/web_fullpage_${Date.now()}.jpg`; + const file = fileIo.openSync(sandboxPath, fileIo.OpenMode.CREATE | fileIo.OpenMode.READ_WRITE); + fileIo.writeSync(file.fd, arrayBuffer); + fileIo.closeSync(file.fd); + + // 3. 保存到相册 + const helper = photoAccessHelper.getPhotoAccessHelper(ctx); + const sandboxUri = fileUri.getUriFromPath(sandboxPath); + const request = photoAccessHelper.MediaAssetChangeRequest.createImageAssetRequest(ctx, sandboxUri); + await helper.applyChanges(request); + + promptAction.showToast({ message: '网页已保存至相册' }); + // 拼接之后修改可动画变量 + // this.afterGeneratorImage(); + } catch (e) { + promptAction.showToast({ message: '保存失败: ' + e.message }); + console.error('saveWebViewImage error:', e); + } + } + + /** + * 截图前获取尺寸 + */ + getWebSize() { + const SCRIPT = '[document.documentElement.scrollWidth, document.documentElement.scrollHeight]'; + this.controller.runJavaScriptExt(SCRIPT).then((result) => { + try { + switch (result.getType()) { + case webview.JsMessageType.ARRAY: + this.h5Width = (result.getArray() as number[])[0]; // 单位是vp + this.h5Height = (result.getArray() as number[])[1]; + + break; + default: + + break; + } + } catch (e) { + + } + }); + } + + /** + * 截图开始前的操作。 + * - 保存网页当前位置,用于恢复状态 + * - 截图当前页面作为遮罩层,避免用户察觉组件的滚动,提高用户体验 + * - Web页面滚动到顶部,准备开始截图 + * - 设置截图后小弹窗的位置,提示用户暂时不要操作,等待截图 + * - 开启提示小弹窗 + */ + async beforeSnapshot() { + // 保存网页当前位置,用于恢复 + this.xOffsetBefore = this.curXOffset; + this.yOffsetBefore = this.curYOffset; + this.h5Height = this.curYOffset + Math.ceil(this.webHeight); + // TODO: 知识点: 使用componentSnapshot.get接口直接获取组件的渲染结果,而不需要将屏幕截图 + this.webMaskImage = await componentSnapshot.get('webViewShot'); + this.webMaskImageZIndex =2; + this.controller.scrollTo(0, 0); + promptAction.showToast({ + message: '正在截图,请勿操作...', + duration: 2000 + }); + + // 延时确保已经滚动到了顶部 + await sleep(200); + } + + /** + * 截图之后的操作。 + * - 恢复web页面到截图之前的位置 + * - 取消遮罩层 + */ + async afterSnapshot() { + this.controller.scrollTo(this.xOffsetBefore, this.yOffsetBefore); + await sleep(200); + this.webMaskImageZIndex = -1; + this.webMaskImage = undefined; + } + + /** + * 生成拼接后图片的操作。用于窗口形成移动的动画。 + */ + async afterGeneratorImage() { + // 小窗在屏幕中间短暂停留,避免位置突变,无法形成动画 + await sleep(200); + // 修改弹窗位置,形成移动动画 + + } +} + +interface RouteParams { + url:string; + title:string; +} + +/** + * 异步延时函数。 + * @param ms 延时时长,单位 ms。 + * @returns Promise 对象,执行回调。 + */ +export function sleep(ms: number): Promise { + return new Promise(resolve => setTimeout(resolve, ms)); +} \ No newline at end of file diff --git a/products/expert/src/main/resources/base/profile/main_pages.json b/products/expert/src/main/resources/base/profile/main_pages.json index 3cec50e..0d69699 100644 --- a/products/expert/src/main/resources/base/profile/main_pages.json +++ b/products/expert/src/main/resources/base/profile/main_pages.json @@ -41,6 +41,7 @@ "pages/Netease/InterrogationDetailCompPage", "pages/Netease/PatientSimplyPage", "pages/Netease/MyOpinionPage", - "pages/PatientsPage/GroupManagementPage" + "pages/PatientsPage/GroupManagementPage", + "pages/WebView/WebPageSnapshot" ] } \ No newline at end of file