Showing
9 changed files
with
386 additions
and
168 deletions
| @@ -11,6 +11,8 @@ import { TrackConstants, TrackingButton } from 'wdTracking'; | @@ -11,6 +11,8 @@ import { TrackConstants, TrackingButton } from 'wdTracking'; | ||
| 11 | import { faceDetector } from '@kit.CoreVisionKit'; | 11 | import { faceDetector } from '@kit.CoreVisionKit'; |
| 12 | import mediaLibrary from '@ohos.multimedia.mediaLibrary'; | 12 | import mediaLibrary from '@ohos.multimedia.mediaLibrary'; |
| 13 | import fileIo from '@ohos.file.fs'; | 13 | import fileIo from '@ohos.file.fs'; |
| 14 | +import { httpRequest } from '../utils/httpRequest'; | ||
| 15 | +import { taskpool } from '@kit.ArkTS'; | ||
| 14 | 16 | ||
| 15 | const PERMISSIONS: Array<Permissions> = [ | 17 | const PERMISSIONS: Array<Permissions> = [ |
| 16 | 'ohos.permission.READ_IMAGEVIDEO', | 18 | 'ohos.permission.READ_IMAGEVIDEO', |
| @@ -21,6 +23,23 @@ const PERMISSIONS: Array<Permissions> = [ | @@ -21,6 +23,23 @@ const PERMISSIONS: Array<Permissions> = [ | ||
| 21 | * saveButton参考文档 | 23 | * saveButton参考文档 |
| 22 | * https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/savebutton-0000001820999677 | 24 | * https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/savebutton-0000001820999677 |
| 23 | * */ | 25 | * */ |
| 26 | +@Concurrent | ||
| 27 | +async function getPicture(imageUrl: string): Promise<ArrayBuffer> { | ||
| 28 | + let ret: ArrayBuffer = await new Promise((resolve, reject) => { | ||
| 29 | + httpRequest.httpRequestInStream(imageUrl, (res: ArrayBuffer) => { | ||
| 30 | + resolve(res); // 成功时解析Promise | ||
| 31 | + }, () => { | ||
| 32 | + // 下载失败时弹窗提示检查网络 | ||
| 33 | + promptAction.showToast({ | ||
| 34 | + message: $r('app.string.image_request_fail'), | ||
| 35 | + duration: 2000 | ||
| 36 | + }); | ||
| 37 | + reject(new Error('Image download failed')); // 失败时拒绝Promise | ||
| 38 | + }); | ||
| 39 | + }); | ||
| 40 | + return ret | ||
| 41 | +} | ||
| 42 | + | ||
| 24 | @Component | 43 | @Component |
| 25 | export struct ImageDownloadComponent { | 44 | export struct ImageDownloadComponent { |
| 26 | @State image: PixelMap | undefined = undefined; | 45 | @State image: PixelMap | undefined = undefined; |
| @@ -79,61 +98,12 @@ export struct ImageDownloadComponent { | @@ -79,61 +98,12 @@ export struct ImageDownloadComponent { | ||
| 79 | const context = getContext(this) as common.UIAbilityContext; | 98 | const context = getContext(this) as common.UIAbilityContext; |
| 80 | const atManager = abilityAccessCtrl.createAtManager(); | 99 | const atManager = abilityAccessCtrl.createAtManager(); |
| 81 | await atManager.requestPermissionsFromUser(context, PERMISSIONS); | 100 | await atManager.requestPermissionsFromUser(context, PERMISSIONS); |
| 82 | - this.getPicture(); | ||
| 83 | - } | ||
| 84 | - | ||
| 85 | - /** | ||
| 86 | - * 通过http的request方法从网络下载图片资源 | ||
| 87 | - */ | ||
| 88 | - async getPicture() { | ||
| 89 | - // 每一个httpRequest对应一个HTTP请求任务,不可复用 | ||
| 90 | - let httpRequest = http.createHttp(); | ||
| 91 | - // 用于订阅HTTP响应头事件 | ||
| 92 | - httpRequest.on('headersReceive', (header: Object) => { | ||
| 93 | - //console.info('header: ' + JSON.stringify(header)); | ||
| 94 | - }); | ||
| 95 | - // 用于订阅HTTP流式响应数据接收事件 | ||
| 96 | - let res = new ArrayBuffer(0); | ||
| 97 | - httpRequest.on('dataReceive', (data: ArrayBuffer) => { | ||
| 98 | - const newRes = new ArrayBuffer(res.byteLength + data.byteLength); | ||
| 99 | - const resView = new Uint8Array(newRes); | ||
| 100 | - resView.set(new Uint8Array(res)); | ||
| 101 | - resView.set(new Uint8Array(data), res.byteLength); | ||
| 102 | - res = newRes; | ||
| 103 | - // //console.info('dataReceive res length: ' + res.byteLength); | ||
| 104 | - }); | ||
| 105 | - // 用于订阅HTTP流式响应数据接收完毕事件 | ||
| 106 | - httpRequest.on('dataEnd', () => { | ||
| 107 | - this.transcodePixelMap(res); | ||
| 108 | - // 判断网络获取到的资源是否为ArrayBuffer类型 | ||
| 109 | - //console.info(`dataEnd getPicture ${res}`) | ||
| 110 | - if (res instanceof ArrayBuffer) { | ||
| 111 | - //console.info(`dataEnd getPicture`) | ||
| 112 | - this.imageBuffer = res as ArrayBuffer; | ||
| 113 | - } | ||
| 114 | - //console.info('No more data in response, data receive end'); | ||
| 115 | - }); | ||
| 116 | - httpRequest.requestInStream(this.url, | ||
| 117 | - (error: BusinessError, data: number) => { | ||
| 118 | - if (error) { | ||
| 119 | - // 下载失败时弹窗提示检查网络,不执行后续逻辑 | ||
| 120 | - promptAction.showToast({ | ||
| 121 | - message: $r('app.string.image_request_fail'), | ||
| 122 | - duration: 2000 | 101 | + // 通过任务池(taskpool)从网络下载图片资源 |
| 102 | + taskpool.execute(getPicture, this.url).then((res) => { | ||
| 103 | + const imgBuffer = res as ArrayBuffer | ||
| 104 | + this.imageBuffer = imgBuffer; | ||
| 105 | + this.transcodePixelMap(imgBuffer); | ||
| 123 | }) | 106 | }) |
| 124 | - //console.error(`http reqeust failed with. Code: ${error.code}, message: ${error.message}`); | ||
| 125 | - return; | ||
| 126 | - } | ||
| 127 | - // 取消订阅HTTP响应头事件 | ||
| 128 | - httpRequest.off('headersReceive'); | ||
| 129 | - // 取消订阅HTTP流式响应数据接收事件 | ||
| 130 | - httpRequest.off('dataReceive'); | ||
| 131 | - // 取消订阅HTTP流式响应数据接收完毕事件 | ||
| 132 | - httpRequest.off('dataEnd'); | ||
| 133 | - // 当该请求使用完毕时,调用destroy方法主动销毁 | ||
| 134 | - httpRequest.destroy(); | ||
| 135 | - } | ||
| 136 | - ) | ||
| 137 | } | 107 | } |
| 138 | 108 | ||
| 139 | /** | 109 | /** |
| @@ -6,11 +6,29 @@ import { OffsetModel } from '../model/OffsetModel'; | @@ -6,11 +6,29 @@ import { OffsetModel } from '../model/OffsetModel'; | ||
| 6 | import { WindowSizeManager } from '../utils/Managers'; | 6 | import { WindowSizeManager } from '../utils/Managers'; |
| 7 | import { runWithAnimation } from '../utils/FuncUtils'; | 7 | import { runWithAnimation } from '../utils/FuncUtils'; |
| 8 | import { PhotoListBean } from 'wdBean/Index'; | 8 | import { PhotoListBean } from 'wdBean/Index'; |
| 9 | -import { http } from '@kit.NetworkKit'; | ||
| 10 | import { router } from '@kit.ArkUI'; | 9 | import { router } from '@kit.ArkUI'; |
| 10 | +import { taskpool } from '@kit.ArkTS'; | ||
| 11 | +import { httpRequest } from '../utils/httpRequest'; | ||
| 11 | 12 | ||
| 12 | const TAG = 'MultiPictureDetailItemComponent'; | 13 | const TAG = 'MultiPictureDetailItemComponent'; |
| 13 | 14 | ||
| 15 | +@Concurrent | ||
| 16 | +async function getPicture(imageUrl: string): Promise<ArrayBuffer> { | ||
| 17 | + let ret: ArrayBuffer = await new Promise((resolve, reject) => { | ||
| 18 | + httpRequest.httpRequestInStream(imageUrl, (res: ArrayBuffer) => { | ||
| 19 | + resolve(res); // 成功时解析Promise | ||
| 20 | + }, () => { | ||
| 21 | + // 下载失败时弹窗提示检查网络 | ||
| 22 | + promptAction.showToast({ | ||
| 23 | + message: $r('app.string.image_request_fail'), | ||
| 24 | + duration: 2000 | ||
| 25 | + }); | ||
| 26 | + reject(new Error('Image download failed')); // 失败时拒绝Promise | ||
| 27 | + }); | ||
| 28 | + }); | ||
| 29 | + return ret | ||
| 30 | +} | ||
| 31 | + | ||
| 14 | @Reusable | 32 | @Reusable |
| 15 | @Component | 33 | @Component |
| 16 | export struct MultiPictureDetailItemComponent { | 34 | export struct MultiPictureDetailItemComponent { |
| @@ -34,65 +52,17 @@ export struct MultiPictureDetailItemComponent { | @@ -34,65 +52,17 @@ export struct MultiPictureDetailItemComponent { | ||
| 34 | windowSizeManager: WindowSizeManager = new WindowSizeManager(); | 52 | windowSizeManager: WindowSizeManager = new WindowSizeManager(); |
| 35 | 53 | ||
| 36 | 54 | ||
| 37 | - async aboutToAppear() { | 55 | + aboutToAppear() { |
| 38 | this.imageUri = this.MultiPictureDetailItem.picPath | 56 | this.imageUri = this.MultiPictureDetailItem.picPath |
| 39 | - this.getPicture() | ||
| 40 | - } | ||
| 41 | - | ||
| 42 | - /** | ||
| 43 | - * 通过http的request方法从网络下载图片资源 | ||
| 44 | - */ | ||
| 45 | - async getPicture() { | ||
| 46 | - // 每一个httpRequest对应一个HTTP请求任务,不可复用 | ||
| 47 | - let httpRequest = http.createHttp(); | ||
| 48 | - // 用于订阅HTTP响应头事件 | ||
| 49 | - httpRequest.on('headersReceive', (header: Object) => { | ||
| 50 | - console.info('header: ' + JSON.stringify(header)); | ||
| 51 | - }); | ||
| 52 | - // 用于订阅HTTP流式响应数据接收事件 | ||
| 53 | - let res = new ArrayBuffer(0); | ||
| 54 | - httpRequest.on('dataReceive', (data: ArrayBuffer) => { | ||
| 55 | - const newRes = new ArrayBuffer(res.byteLength + data.byteLength); | ||
| 56 | - const resView = new Uint8Array(newRes); | ||
| 57 | - resView.set(new Uint8Array(res)); | ||
| 58 | - resView.set(new Uint8Array(data), res.byteLength); | ||
| 59 | - res = newRes; | ||
| 60 | - // console.info('dataReceive res length: ' + res.byteLength); | ||
| 61 | - }); | ||
| 62 | - // 用于订阅HTTP流式响应数据接收完毕事件 | ||
| 63 | - httpRequest.on('dataEnd', () => { | ||
| 64 | - this.transcodePixelMap(res); | ||
| 65 | - // 判断网络获取到的资源是否为ArrayBuffer类型 | ||
| 66 | - console.info(`dataEnd getPicture ${res}`) | ||
| 67 | - if (res instanceof ArrayBuffer) { | ||
| 68 | - console.info(`dataEnd getPicture`) | ||
| 69 | - this.imageBuffer = res as ArrayBuffer; | ||
| 70 | - } | ||
| 71 | - console.info('No more data in response, data receive end'); | ||
| 72 | - }); | ||
| 73 | - httpRequest.requestInStream(this.imageUri, | ||
| 74 | - (error: BusinessError, data: number) => { | ||
| 75 | - if (error) { | ||
| 76 | - // 下载失败时弹窗提示检查网络,不执行后续逻辑 | ||
| 77 | - promptAction.showToast({ | ||
| 78 | - message: $r('app.string.image_request_fail'), | ||
| 79 | - duration: 2000 | 57 | + // 通过任务池(taskpool)从网络下载图片资源 |
| 58 | + taskpool.execute(getPicture, this.imageUri).then((res) => { | ||
| 59 | + const imgBuffer = res as ArrayBuffer | ||
| 60 | + this.imageBuffer = imgBuffer; | ||
| 61 | + this.transcodePixelMap(imgBuffer); | ||
| 80 | }) | 62 | }) |
| 81 | - console.error(`http reqeust failed with. Code: ${error.code}, message: ${error.message}`); | ||
| 82 | - return; | ||
| 83 | - } | ||
| 84 | - // 取消订阅HTTP响应头事件 | ||
| 85 | - httpRequest.off('headersReceive'); | ||
| 86 | - // 取消订阅HTTP流式响应数据接收事件 | ||
| 87 | - httpRequest.off('dataReceive'); | ||
| 88 | - // 取消订阅HTTP流式响应数据接收完毕事件 | ||
| 89 | - httpRequest.off('dataEnd'); | ||
| 90 | - // 当该请求使用完毕时,调用destroy方法主动销毁 | ||
| 91 | - httpRequest.destroy(); | ||
| 92 | - } | ||
| 93 | - ) | ||
| 94 | } | 63 | } |
| 95 | 64 | ||
| 65 | + | ||
| 96 | /** | 66 | /** |
| 97 | * 使用createPixelMap将ArrayBuffer类型的图片装换为PixelMap类型 | 67 | * 使用createPixelMap将ArrayBuffer类型的图片装换为PixelMap类型 |
| 98 | * @param data:网络获取到的资源 | 68 | * @param data:网络获取到的资源 |
| @@ -35,6 +35,8 @@ export class commentListModel extends PageModel { | @@ -35,6 +35,8 @@ export class commentListModel extends PageModel { | ||
| 35 | totalCommentNum: string = '0' | 35 | totalCommentNum: string = '0' |
| 36 | hasNext: number = 0 | 36 | hasNext: number = 0 |
| 37 | list: commentItemModel[] = [] | 37 | list: commentItemModel[] = [] |
| 38 | + hotList: commentItemModel[] = [] // 仅第一页存在 | ||
| 39 | + hotIds: string[] = [] // 仅第一页存在 | ||
| 38 | // constructor(pageNum:number, pageSize:number, totalCount: number, hasNext: number, list: commentItemModel[]) { | 40 | // constructor(pageNum:number, pageSize:number, totalCount: number, hasNext: number, list: commentItemModel[]) { |
| 39 | // super() | 41 | // super() |
| 40 | // this.pageNum = pageNum | 42 | // this.pageNum = pageNum |
| @@ -45,9 +47,16 @@ export class commentListModel extends PageModel { | @@ -45,9 +47,16 @@ export class commentListModel extends PageModel { | ||
| 45 | // } | 47 | // } |
| 46 | } | 48 | } |
| 47 | 49 | ||
| 50 | +export enum CommentItemCustomType { | ||
| 51 | + comment = 0, | ||
| 52 | + newTitle = 1, // 最新评论标题 | ||
| 53 | + hotTitle = 2, // 热门评论标题 | ||
| 54 | + hotComment = 3, | ||
| 55 | +} | ||
| 48 | 56 | ||
| 49 | @Observed | 57 | @Observed |
| 50 | export class commentItemModel { | 58 | export class commentItemModel { |
| 59 | + api_customType: CommentItemCustomType = CommentItemCustomType.comment | ||
| 51 | authorLike: string = '' | 60 | authorLike: string = '' |
| 52 | avatarFrame: string = '' | 61 | avatarFrame: string = '' |
| 53 | checkStatus: string = '' | 62 | checkStatus: string = '' |
| 1 | import { DateTimeUtils, EmitterEventId, EmitterUtils, LazyDataSource, | 1 | import { DateTimeUtils, EmitterEventId, EmitterUtils, LazyDataSource, |
| 2 | PublicDialogManager, | 2 | PublicDialogManager, |
| 3 | StringUtils } from 'wdKit/Index'; | 3 | StringUtils } from 'wdKit/Index'; |
| 4 | -import { commentItemModel, WDPublicUserType } from '../model/CommentModel'; | 4 | +import { CommentItemCustomType, commentItemModel, WDPublicUserType } from '../model/CommentModel'; |
| 5 | import commentViewModel from '../viewmodel/CommentViewModel'; | 5 | import commentViewModel from '../viewmodel/CommentViewModel'; |
| 6 | import { CommentText } from './CommentText'; | 6 | import { CommentText } from './CommentText'; |
| 7 | import { CommentCustomDialog } from './CommentCustomDialog'; | 7 | import { CommentCustomDialog } from './CommentCustomDialog'; |
| @@ -37,6 +37,7 @@ export struct CommentComponent { | @@ -37,6 +37,7 @@ export struct CommentComponent { | ||
| 37 | listScroller: ListScroller = new ListScroller(); // scroller控制器 | 37 | listScroller: ListScroller = new ListScroller(); // scroller控制器 |
| 38 | historyOffset: number = 0; // 上次浏览到列表距离顶端的偏移量offset | 38 | historyOffset: number = 0; // 上次浏览到列表距离顶端的偏移量offset |
| 39 | @State allDatas: LazyDataSource<commentItemModel> = new LazyDataSource(); | 39 | @State allDatas: LazyDataSource<commentItemModel> = new LazyDataSource(); |
| 40 | + firstPageHotIds: string = '' | ||
| 40 | @State dialogController: CustomDialogController | null = null; | 41 | @State dialogController: CustomDialogController | null = null; |
| 41 | // @State private browSingModel: commentListModel = new commentListModel() | 42 | // @State private browSingModel: commentListModel = new commentListModel() |
| 42 | 43 | ||
| @@ -49,6 +50,7 @@ export struct CommentComponent { | @@ -49,6 +50,7 @@ export struct CommentComponent { | ||
| 49 | // 是否在弹框中 | 50 | // 是否在弹框中 |
| 50 | @Provide inDialog: boolean = false | 51 | @Provide inDialog: boolean = false |
| 51 | private dialogBeforeJumpOtherPageAction: () => void = () => {} | 52 | private dialogBeforeJumpOtherPageAction: () => void = () => {} |
| 53 | + private dialogUpdateTitle: (title: string) => void = () => {} | ||
| 52 | 54 | ||
| 53 | // 在自定义组件即将析构销毁时将dialogControlle置空 | 55 | // 在自定义组件即将析构销毁时将dialogControlle置空 |
| 54 | aboutToDisappear() { | 56 | aboutToDisappear() { |
| @@ -99,7 +101,16 @@ export struct CommentComponent { | @@ -99,7 +101,16 @@ export struct CommentComponent { | ||
| 99 | /*一级评论*/ | 101 | /*一级评论*/ |
| 100 | // if (this.publishCommentModel.lastCommentModel) | 102 | // if (this.publishCommentModel.lastCommentModel) |
| 101 | if (this.publishCommentModel.lastCommentModel.parentId == '-1') { | 103 | if (this.publishCommentModel.lastCommentModel.parentId == '-1') { |
| 102 | - this.allDatas.addFirstItem(model) | 104 | + |
| 105 | + let newCommentHeaderIndex = this.indexOfNewCommentHeaderTitle() | ||
| 106 | + if (newCommentHeaderIndex === -1) { | ||
| 107 | + let newCommentTitle = new commentItemModel() | ||
| 108 | + newCommentTitle.api_customType = CommentItemCustomType.newTitle | ||
| 109 | + this.allDatas.addItems([newCommentTitle, model]) | ||
| 110 | + } else { | ||
| 111 | + this.allDatas.addItem(model, newCommentHeaderIndex + 1) | ||
| 112 | + } | ||
| 113 | + | ||
| 103 | } else { | 114 | } else { |
| 104 | //二级评论 | 115 | //二级评论 |
| 105 | this.allDatas.getDataArray().forEach(element => { | 116 | this.allDatas.getDataArray().forEach(element => { |
| @@ -116,14 +127,19 @@ export struct CommentComponent { | @@ -116,14 +127,19 @@ export struct CommentComponent { | ||
| 116 | 127 | ||
| 117 | /*标题:全部评论*/ | 128 | /*标题:全部评论*/ |
| 118 | @Builder | 129 | @Builder |
| 119 | - titleHeader() { | 130 | + titleHeader(title: string = "最新评论", showGapLine: boolean = false) { |
| 131 | + | ||
| 132 | + Column() { | ||
| 133 | + if (showGapLine) { | ||
| 134 | + Divider().strokeWidth(6).color('#f5f5f5') | ||
| 135 | + } | ||
| 120 | 136 | ||
| 121 | Row() { | 137 | Row() { |
| 122 | Row() { | 138 | Row() { |
| 123 | Image($r('app.media.redLine')) | 139 | Image($r('app.media.redLine')) |
| 124 | .height(16) | 140 | .height(16) |
| 125 | .width(3) | 141 | .width(3) |
| 126 | - Text('全部评论') | 142 | + Text(title) |
| 127 | .fontSize(16)// .fontColor('#222222') | 143 | .fontSize(16)// .fontColor('#222222') |
| 128 | .fontColor($r('app.color.color_222222')) | 144 | .fontColor($r('app.color.color_222222')) |
| 129 | .fontWeight(FontWeight.Medium) | 145 | .fontWeight(FontWeight.Medium) |
| @@ -145,12 +161,7 @@ export struct CommentComponent { | @@ -145,12 +161,7 @@ export struct CommentComponent { | ||
| 145 | .height(44) | 161 | .height(44) |
| 146 | .width('100%') | 162 | .width('100%') |
| 147 | .justifyContent(FlexAlign.SpaceBetween) | 163 | .justifyContent(FlexAlign.SpaceBetween) |
| 148 | - .onClick(() => { | ||
| 149 | - // this.allDatas.push(new commentItemModel()) | ||
| 150 | - // this.allDatas.addFirstItem(new commentItemModel()) | ||
| 151 | - // this.allDatas.reloadData(); | ||
| 152 | - }) | ||
| 153 | - | 164 | + } |
| 154 | } | 165 | } |
| 155 | 166 | ||
| 156 | /*1级评论作为titleHeader*/ | 167 | /*1级评论作为titleHeader*/ |
| @@ -177,16 +188,29 @@ export struct CommentComponent { | @@ -177,16 +188,29 @@ export struct CommentComponent { | ||
| 177 | build() { | 188 | build() { |
| 178 | Column() { | 189 | Column() { |
| 179 | List({ scroller: this.listScroller }) { | 190 | List({ scroller: this.listScroller }) { |
| 191 | + if (!this.isComments) { | ||
| 180 | if (this.showTitleComponent) { | 192 | if (this.showTitleComponent) { |
| 181 | ListItemGroup({ header: this.titleHeader() }) | 193 | ListItemGroup({ header: this.titleHeader() }) |
| 182 | } | 194 | } |
| 183 | - | ||
| 184 | - if (!this.isComments) { | ||
| 185 | EmptyComponent({ emptyType: 17 }) | 195 | EmptyComponent({ emptyType: 17 }) |
| 186 | .height(300) | 196 | .height(300) |
| 187 | } else { | 197 | } else { |
| 188 | LazyForEach(this.allDatas, (item: commentItemModel, index: number) => { | 198 | LazyForEach(this.allDatas, (item: commentItemModel, index: number) => { |
| 189 | - if (item.hasMore) { | 199 | + if (item.api_customType === CommentItemCustomType.newTitle) { |
| 200 | + if (this.inDialog && index === 0) { | ||
| 201 | + ListItemGroup() | ||
| 202 | + } else { | ||
| 203 | + ListItemGroup({ header: this.titleHeader("最新评论", index !== 0) }) | ||
| 204 | + } | ||
| 205 | + } | ||
| 206 | + else if (item.api_customType === CommentItemCustomType.hotTitle) { | ||
| 207 | + if (this.inDialog && index === 0) { | ||
| 208 | + ListItemGroup() | ||
| 209 | + } else { | ||
| 210 | + ListItemGroup({ header: this.titleHeader("热门评论") }) | ||
| 211 | + } | ||
| 212 | + } | ||
| 213 | + else if (item.hasMore) { | ||
| 190 | ListItemGroup({ | 214 | ListItemGroup({ |
| 191 | header: this.CommentHeaderItem(item, index), | 215 | header: this.CommentHeaderItem(item, index), |
| 192 | footer: this.GroupFooterView(item, index) | 216 | footer: this.GroupFooterView(item, index) |
| @@ -234,6 +258,9 @@ export struct CommentComponent { | @@ -234,6 +258,9 @@ export struct CommentComponent { | ||
| 234 | } | 258 | } |
| 235 | .scrollBar(BarState.Off) | 259 | .scrollBar(BarState.Off) |
| 236 | .margin({ bottom: 10 }) | 260 | .margin({ bottom: 10 }) |
| 261 | + .onScrollIndex((start) => { | ||
| 262 | + this.updateDialogTitleWithStartIndex(start) | ||
| 263 | + }) | ||
| 237 | .onReachEnd(() => { | 264 | .onReachEnd(() => { |
| 238 | if (!this.fixedHeightMode) { | 265 | if (!this.fixedHeightMode) { |
| 239 | return | 266 | return |
| @@ -252,6 +279,30 @@ export struct CommentComponent { | @@ -252,6 +279,30 @@ export struct CommentComponent { | ||
| 252 | 279 | ||
| 253 | } | 280 | } |
| 254 | 281 | ||
| 282 | + updateDialogTitleWithStartIndex(start: number) { | ||
| 283 | + if (!this.inDialog) { | ||
| 284 | + return | ||
| 285 | + } | ||
| 286 | + if (this.allDatas.size() === 0) { | ||
| 287 | + this.dialogUpdateTitle("评论") | ||
| 288 | + return | ||
| 289 | + } | ||
| 290 | + if (this.allDatas.getFirst().api_customType !== CommentItemCustomType.hotTitle) { | ||
| 291 | + this.dialogUpdateTitle("最新评论") | ||
| 292 | + return | ||
| 293 | + } | ||
| 294 | + let newCommentHeaderIndex = this.indexOfNewCommentHeaderTitle() | ||
| 295 | + if (newCommentHeaderIndex == -1) { | ||
| 296 | + this.dialogUpdateTitle("热门评论") | ||
| 297 | + return | ||
| 298 | + } | ||
| 299 | + if (start < newCommentHeaderIndex + 1) { | ||
| 300 | + this.dialogUpdateTitle("热门评论") | ||
| 301 | + } else { | ||
| 302 | + this.dialogUpdateTitle("最新评论") | ||
| 303 | + } | ||
| 304 | + } | ||
| 305 | + | ||
| 255 | parentOnReachEnd() { | 306 | parentOnReachEnd() { |
| 256 | if (this.fixedHeightMode) { | 307 | if (this.fixedHeightMode) { |
| 257 | return | 308 | return |
| @@ -268,11 +319,41 @@ export struct CommentComponent { | @@ -268,11 +319,41 @@ export struct CommentComponent { | ||
| 268 | //获取数据 | 319 | //获取数据 |
| 269 | async getData() { | 320 | async getData() { |
| 270 | let pageIndex = this.currentPage | 321 | let pageIndex = this.currentPage |
| 271 | - commentViewModel.fetchContentCommentList(pageIndex + '', this.publishCommentModel.targetId, | ||
| 272 | - this.publishCommentModel.targetType) | 322 | + commentViewModel.fetchContentCommentList(pageIndex + '' |
| 323 | + ,this.publishCommentModel.targetId | ||
| 324 | + ,this.publishCommentModel.targetType | ||
| 325 | + ,this.firstPageHotIds) | ||
| 273 | .then(commentListModel => { | 326 | .then(commentListModel => { |
| 274 | console.log('评论:', JSON.stringify(commentListModel.list)) | 327 | console.log('评论:', JSON.stringify(commentListModel.list)) |
| 275 | 328 | ||
| 329 | + if (pageIndex == 1) { | ||
| 330 | + // 保存第一页热门评论ids | ||
| 331 | + if (commentListModel.hotIds.length > 0) { | ||
| 332 | + this.firstPageHotIds = commentListModel.hotIds.join(",") | ||
| 333 | + } | ||
| 334 | + if (commentListModel.list.length > 0) { // 热门评论增加头部 | ||
| 335 | + let newCommentTitle = new commentItemModel() | ||
| 336 | + newCommentTitle.api_customType = CommentItemCustomType.newTitle | ||
| 337 | + let newArray = [newCommentTitle] | ||
| 338 | + commentListModel.list = newArray.concat(commentListModel.list) | ||
| 339 | + } | ||
| 340 | + if (commentListModel.hotList.length > 0) { // 最新评论增加头部 | ||
| 341 | + let hotCommentTitle = new commentItemModel() | ||
| 342 | + hotCommentTitle.api_customType = CommentItemCustomType.hotTitle | ||
| 343 | + let newArray = [hotCommentTitle] | ||
| 344 | + commentListModel.hotList = newArray.concat(commentListModel.hotList) | ||
| 345 | + | ||
| 346 | + commentListModel.list = commentListModel.hotList.concat(commentListModel.list) | ||
| 347 | + } | ||
| 348 | + } else { // 非首页数据 | ||
| 349 | + if (commentListModel.list.length > 0 && !this.hasNewCommentHeaderTitle()) { // 如果之前仅存在热门评论,这里需要补下数据 | ||
| 350 | + let newCommentTitle = new commentItemModel() | ||
| 351 | + newCommentTitle.api_customType = CommentItemCustomType.newTitle | ||
| 352 | + let newArray = [newCommentTitle] | ||
| 353 | + commentListModel.list = newArray.concat(commentListModel.list) | ||
| 354 | + } | ||
| 355 | + } | ||
| 356 | + | ||
| 276 | // 这里需要先赋值,否则下次UI刷新可能重复进入第1页两次 | 357 | // 这里需要先赋值,否则下次UI刷新可能重复进入第1页两次 |
| 277 | this.currentPage = pageIndex + 1 | 358 | this.currentPage = pageIndex + 1 |
| 278 | 359 | ||
| @@ -313,6 +394,29 @@ export struct CommentComponent { | @@ -313,6 +394,29 @@ export struct CommentComponent { | ||
| 313 | } | 394 | } |
| 314 | }) | 395 | }) |
| 315 | } | 396 | } |
| 397 | + | ||
| 398 | + hasNewCommentHeaderTitle() { | ||
| 399 | + let hasNewCommentHeader = false | ||
| 400 | + this.allDatas.getDataArray().forEach((comment) => { | ||
| 401 | + if (comment.api_customType === CommentItemCustomType.newTitle) { | ||
| 402 | + hasNewCommentHeader = true | ||
| 403 | + } | ||
| 404 | + }) | ||
| 405 | + return hasNewCommentHeader | ||
| 406 | + } | ||
| 407 | + | ||
| 408 | + indexOfNewCommentHeaderTitle() { | ||
| 409 | + let resultIndex = -1; | ||
| 410 | + const array = this.allDatas.getDataArray() | ||
| 411 | + for (let index = 0; index < array.length; index++) { | ||
| 412 | + if (array[index].api_customType === CommentItemCustomType.newTitle) { | ||
| 413 | + resultIndex = index; | ||
| 414 | + break | ||
| 415 | + } | ||
| 416 | + } | ||
| 417 | + return resultIndex | ||
| 418 | + } | ||
| 419 | + | ||
| 316 | } | 420 | } |
| 317 | 421 | ||
| 318 | 422 |
| @@ -74,6 +74,7 @@ struct CommentListDialog { | @@ -74,6 +74,7 @@ struct CommentListDialog { | ||
| 74 | /// 内部使用 | 74 | /// 内部使用 |
| 75 | @Link publishCommentModel: publishCommentModel | 75 | @Link publishCommentModel: publishCommentModel |
| 76 | @State private operationButtonList: string[] = [] | 76 | @State private operationButtonList: string[] = [] |
| 77 | + @State title: string = "评论" | ||
| 77 | 78 | ||
| 78 | /// 外部初始化 | 79 | /// 外部初始化 |
| 79 | @Link contentDetailData: ContentDetailDTO // 详情页传 | 80 | @Link contentDetailData: ContentDetailDTO // 详情页传 |
| @@ -122,6 +123,9 @@ struct CommentListDialog { | @@ -122,6 +123,9 @@ struct CommentListDialog { | ||
| 122 | if (this.onClose) { | 123 | if (this.onClose) { |
| 123 | this.onClose() | 124 | this.onClose() |
| 124 | } | 125 | } |
| 126 | + }, | ||
| 127 | + dialogUpdateTitle: (title) => { | ||
| 128 | + this.title = title | ||
| 125 | } | 129 | } |
| 126 | }).layoutWeight(1) | 130 | }).layoutWeight(1) |
| 127 | 131 | ||
| @@ -153,7 +157,7 @@ struct CommentListDialog { | @@ -153,7 +157,7 @@ struct CommentListDialog { | ||
| 153 | Image($r('app.media.redLine')) | 157 | Image($r('app.media.redLine')) |
| 154 | .height(16) | 158 | .height(16) |
| 155 | .width(3) | 159 | .width(3) |
| 156 | - Text('全部评论') | 160 | + Text(this.title) |
| 157 | .fontSize(16)// .fontColor('#222222') | 161 | .fontSize(16)// .fontColor('#222222') |
| 158 | .fontColor($r('app.color.color_222222')) | 162 | .fontColor($r('app.color.color_222222')) |
| 159 | .fontWeight(FontWeight.Medium) | 163 | .fontWeight(FontWeight.Medium) |
| @@ -8,6 +8,7 @@ import { HttpRequest } from 'wdNetwork/src/main/ets/http/HttpRequest'; | @@ -8,6 +8,7 @@ import { HttpRequest } from 'wdNetwork/src/main/ets/http/HttpRequest'; | ||
| 8 | import { ProcessUtils, WDRouterPage, WDRouterRule } from 'wdRouter/Index'; | 8 | import { ProcessUtils, WDRouterPage, WDRouterRule } from 'wdRouter/Index'; |
| 9 | import { TrackConstants, TrackingContent } from 'wdTracking/Index'; | 9 | import { TrackConstants, TrackingContent } from 'wdTracking/Index'; |
| 10 | import { | 10 | import { |
| 11 | + CommentItemCustomType, | ||
| 11 | commentItemModel, | 12 | commentItemModel, |
| 12 | commentListModel, | 13 | commentListModel, |
| 13 | commentStatusListModel, | 14 | commentStatusListModel, |
| @@ -33,9 +34,13 @@ class CommentViewModel { | @@ -33,9 +34,13 @@ class CommentViewModel { | ||
| 33 | } | 34 | } |
| 34 | 35 | ||
| 35 | /*获取所有评论*/ | 36 | /*获取所有评论*/ |
| 36 | - fetchContentCommentList(pageNum: string, contentId: string, contentType: string): Promise<commentListModel> { | 37 | + fetchContentCommentList(pageNum: string, contentId: string, contentType: string, firstPageHotIds: string = ''): Promise<commentListModel> { |
| 37 | 38 | ||
| 38 | let url = HttpUrlUtils.getContentCommentListDataUrl() + `?&pageSize=${10}&pageNum=${pageNum}&contentId=${contentId}&contentType=${contentType}&deviceId=${HttpUtils.getDeviceId()}&userId=${HttpUtils.getUserId()}&userType=${HttpUtils.getUserType()}&time=${DateTimeUtils.getCurTime(DateTimeUtils.PATTERN_DATE_TIME_HYPHEN)}` | 39 | let url = HttpUrlUtils.getContentCommentListDataUrl() + `?&pageSize=${10}&pageNum=${pageNum}&contentId=${contentId}&contentType=${contentType}&deviceId=${HttpUtils.getDeviceId()}&userId=${HttpUtils.getUserId()}&userType=${HttpUtils.getUserType()}&time=${DateTimeUtils.getCurTime(DateTimeUtils.PATTERN_DATE_TIME_HYPHEN)}` |
| 40 | + url = url + "&hotComment=1" | ||
| 41 | + if (pageNum !== "1" && firstPageHotIds.length > 0) { | ||
| 42 | + url = url + `&hotIds=` + firstPageHotIds | ||
| 43 | + } | ||
| 39 | url = url.replace(' ', '%20') | 44 | url = url.replace(' ', '%20') |
| 40 | 45 | ||
| 41 | return new Promise<commentListModel>((success, fail) => { | 46 | return new Promise<commentListModel>((success, fail) => { |
| @@ -49,10 +54,24 @@ class CommentViewModel { | @@ -49,10 +54,24 @@ class CommentViewModel { | ||
| 49 | return | 54 | return |
| 50 | } | 55 | } |
| 51 | let listData = data.data as commentListModel | 56 | let listData = data.data as commentListModel |
| 52 | - this.fetchCommentStatusAndConfigAuthIcon(listData).then((commentListModel) => { | 57 | + this.fetchCommentStatusAndConfigAuthIcon(listData, false).then((commentListModel) => { |
| 53 | console.log(TAG, 'fetchCommentStatusAndConfigAuthIcon完成') | 58 | console.log(TAG, 'fetchCommentStatusAndConfigAuthIcon完成') |
| 59 | + | ||
| 60 | + if (pageNum !== "1") { | ||
| 61 | + success(commentListModel) | ||
| 62 | + return | ||
| 63 | + } | ||
| 64 | + | ||
| 65 | + // 热门评论批查 | ||
| 66 | + this.fetchCommentStatusAndConfigAuthIcon(listData, true).then((commentListModel) => { | ||
| 67 | + console.log(TAG, 'hot comment fetchCommentStatusAndConfigAuthIcon完成') | ||
| 68 | + | ||
| 69 | + listData.hotList.forEach((item) => { | ||
| 70 | + item.api_customType = CommentItemCustomType.hotComment | ||
| 71 | + }) | ||
| 54 | success(commentListModel) | 72 | success(commentListModel) |
| 55 | }) | 73 | }) |
| 74 | + }) | ||
| 56 | 75 | ||
| 57 | }, (error: Error) => { | 76 | }, (error: Error) => { |
| 58 | fail(error.message) | 77 | fail(error.message) |
| @@ -213,7 +232,7 @@ class CommentViewModel { | @@ -213,7 +232,7 @@ class CommentViewModel { | ||
| 213 | } | 232 | } |
| 214 | 233 | ||
| 215 | /*多接口批查*/ | 234 | /*多接口批查*/ |
| 216 | - fetchCommentStatusAndConfigAuthIcon(model: commentListModel): Promise<commentListModel> { | 235 | + fetchCommentStatusAndConfigAuthIcon(model: commentListModel, hot: boolean = false): Promise<commentListModel> { |
| 217 | 236 | ||
| 218 | let commentIDs: string[] = []; | 237 | let commentIDs: string[] = []; |
| 219 | 238 | ||
| @@ -222,7 +241,7 @@ class CommentViewModel { | @@ -222,7 +241,7 @@ class CommentViewModel { | ||
| 222 | let creatorIDs: string[] = []; | 241 | let creatorIDs: string[] = []; |
| 223 | 242 | ||
| 224 | //主评论 | 243 | //主评论 |
| 225 | - for (const element of model.list) { | 244 | + for (const element of (hot ? model.hotList : model.list)) { |
| 226 | if ((element.id + '').length > 0) { | 245 | if ((element.id + '').length > 0) { |
| 227 | commentIDs.push(element.id + '') | 246 | commentIDs.push(element.id + '') |
| 228 | } | 247 | } |
| @@ -277,7 +296,7 @@ class CommentViewModel { | @@ -277,7 +296,7 @@ class CommentViewModel { | ||
| 277 | let listData = data.data as commentStatusModel[] | 296 | let listData = data.data as commentStatusModel[] |
| 278 | //点赞 | 297 | //点赞 |
| 279 | for (const element of listData) { | 298 | for (const element of listData) { |
| 280 | - for (const commentModel of model.list) { | 299 | + for (const commentModel of (hot ? model.hotList : model.list)) { |
| 281 | if (element.commentId == commentModel.id) { | 300 | if (element.commentId == commentModel.id) { |
| 282 | commentModel.api_status = element.status | 301 | commentModel.api_status = element.status |
| 283 | } | 302 | } |
| @@ -319,7 +338,7 @@ class CommentViewModel { | @@ -319,7 +338,7 @@ class CommentViewModel { | ||
| 319 | let listData = data.data as commentStatusModel[] | 338 | let listData = data.data as commentStatusModel[] |
| 320 | 339 | ||
| 321 | for (const element of listData) { | 340 | for (const element of listData) { |
| 322 | - for (const commentModel of model.list) { | 341 | + for (const commentModel of (hot ? model.hotList : model.list)) { |
| 323 | if (element.userId == commentModel.fromUserId) { | 342 | if (element.userId == commentModel.fromUserId) { |
| 324 | commentModel.api_levelHead = element.levelHead | 343 | commentModel.api_levelHead = element.levelHead |
| 325 | } | 344 | } |
| @@ -364,7 +383,7 @@ class CommentViewModel { | @@ -364,7 +383,7 @@ class CommentViewModel { | ||
| 364 | let listData = data.data as commentStatusModel[] | 383 | let listData = data.data as commentStatusModel[] |
| 365 | 384 | ||
| 366 | for (const element of listData) { | 385 | for (const element of listData) { |
| 367 | - for (const commentModel of model.list) { | 386 | + for (const commentModel of (hot ? model.hotList : model.list)) { |
| 368 | if (element.creatorId == commentModel.fromCreatorId) { | 387 | if (element.creatorId == commentModel.fromCreatorId) { |
| 369 | commentModel.api_authIcon = element.authIcon | 388 | commentModel.api_authIcon = element.authIcon |
| 370 | } | 389 | } |
| @@ -400,6 +419,7 @@ class CommentViewModel { | @@ -400,6 +419,7 @@ class CommentViewModel { | ||
| 400 | deepCopyCommentItemModel(model: commentItemModel) { | 419 | deepCopyCommentItemModel(model: commentItemModel) { |
| 401 | let newModel = new commentItemModel() | 420 | let newModel = new commentItemModel() |
| 402 | 421 | ||
| 422 | + newModel.api_customType = model.api_customType | ||
| 403 | newModel.authorLike = model.authorLike | 423 | newModel.authorLike = model.authorLike |
| 404 | newModel.avatarFrame = model.avatarFrame | 424 | newModel.avatarFrame = model.avatarFrame |
| 405 | newModel.checkStatus = model.checkStatus | 425 | newModel.checkStatus = model.checkStatus |
| 1 | +import { http } from '@kit.NetworkKit'; | ||
| 2 | + | ||
| 3 | +const TAG = 'httpRequestInStream' | ||
| 4 | +export class httpRequest { | ||
| 5 | + // 大于5M的下载请求,使用流下载 | ||
| 6 | + /** | ||
| 7 | + * 发起HTTP请求以下载图片资源 | ||
| 8 | + * @param {string} imageUrl 图片的URL | ||
| 9 | + * @param {Function} onSuccess 成功回调函数 | ||
| 10 | + * @param {Function} onError 失败回调函数 | ||
| 11 | + */ | ||
| 12 | + public static httpRequestInStream(imageUrl:string, onSuccess:Function, onError:Function) { | ||
| 13 | + // 每一个httpRequest对应一个HTTP请求任务,不可复用 | ||
| 14 | + const httpRequest = http.createHttp(); | ||
| 15 | + | ||
| 16 | + // 订阅HTTP响应头事件 | ||
| 17 | + httpRequest.on('headersReceive', (header) => { | ||
| 18 | + // console.info('header: ' + JSON.stringify(header)); | ||
| 19 | + }); | ||
| 20 | + | ||
| 21 | + // 用于订阅HTTP流式响应数据接收事件 | ||
| 22 | + let res = new ArrayBuffer(0); | ||
| 23 | + | ||
| 24 | + httpRequest.on('dataReceive', (data) => { | ||
| 25 | + const newRes = new ArrayBuffer(res.byteLength + data.byteLength); | ||
| 26 | + const resView = new Uint8Array(newRes); | ||
| 27 | + resView.set(new Uint8Array(res)); | ||
| 28 | + resView.set(new Uint8Array(data), res.byteLength); | ||
| 29 | + res = newRes; | ||
| 30 | + // console.info(TAG, 'dataReceive res length: ' + res.byteLength); | ||
| 31 | + }); | ||
| 32 | + | ||
| 33 | + // 用于订阅HTTP流式响应数据接收完毕事件 | ||
| 34 | + httpRequest.on('dataEnd', () => { | ||
| 35 | + if (res instanceof ArrayBuffer) { | ||
| 36 | + // 如果成功,调用onSuccess回调 | ||
| 37 | + // console.info(TAG, 'Success in response, data receive end'); | ||
| 38 | + onSuccess(res); | ||
| 39 | + } else { | ||
| 40 | + // 如果数据不是ArrayBuffer类型,可以在这里处理异常 | ||
| 41 | + // console.error(TAG, 'Unexpected data type:', res); | ||
| 42 | + onError(new Error('Data is not an ArrayBuffer')); | ||
| 43 | + } | ||
| 44 | + // console.info(TAG, 'No more data in response, data receive end'); | ||
| 45 | + }); | ||
| 46 | + | ||
| 47 | + httpRequest.requestInStream(imageUrl, (error, data) => { | ||
| 48 | + if (error) { | ||
| 49 | + // 如果发生错误,取消订阅事件并销毁请求对象 | ||
| 50 | + httpRequest.off('headersReceive'); | ||
| 51 | + httpRequest.off('dataReceive'); | ||
| 52 | + httpRequest.off('dataEnd'); | ||
| 53 | + httpRequest.destroy(); | ||
| 54 | + // console.error(`http request failed with. Code: ${error.code}, message: ${error.message}`); | ||
| 55 | + // 调用onError回调 | ||
| 56 | + onError(error); | ||
| 57 | + return; | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | + // 取消订阅事件 | ||
| 61 | + httpRequest.off('headersReceive'); | ||
| 62 | + httpRequest.off('dataReceive'); | ||
| 63 | + httpRequest.off('dataEnd'); | ||
| 64 | + | ||
| 65 | + // 销毁请求对象 | ||
| 66 | + httpRequest.destroy(); | ||
| 67 | + }); | ||
| 68 | + } | ||
| 69 | +} |
| @@ -94,7 +94,8 @@ export struct PlayerTitleView { | @@ -94,7 +94,8 @@ export struct PlayerTitleView { | ||
| 94 | } | 94 | } |
| 95 | clipStr += strArr[i] | 95 | clipStr += strArr[i] |
| 96 | } | 96 | } |
| 97 | - console.log(TAG, 'clipStr:', clipStr) | 97 | + clipStr += this.isOverLines ? '...' : ''; |
| 98 | + console.log(TAG, 'clipStr2:', clipStr) | ||
| 98 | return clipStr | 99 | return clipStr |
| 99 | } | 100 | } |
| 100 | 101 | ||
| @@ -130,7 +131,8 @@ export struct PlayerTitleView { | @@ -130,7 +131,8 @@ export struct PlayerTitleView { | ||
| 130 | } | 131 | } |
| 131 | clipStr += strArr[i] | 132 | clipStr += strArr[i] |
| 132 | } | 133 | } |
| 133 | - console.log(TAG, 'clipTitleText clipStr:', clipStr) | 134 | + console.log(TAG, 'clipTitleText clipStr1:', clipStr) |
| 135 | + clipStr += this.isTitleOverLines ? '...' : ''; | ||
| 134 | return clipStr | 136 | return clipStr |
| 135 | } | 137 | } |
| 136 | 138 | ||
| @@ -217,7 +219,54 @@ export struct PlayerTitleView { | @@ -217,7 +219,54 @@ export struct PlayerTitleView { | ||
| 217 | // }) | 219 | // }) |
| 218 | // } | 220 | // } |
| 219 | // } else { | 221 | // } else { |
| 222 | + this.detailDesc() | ||
| 223 | + // } | ||
| 224 | + Text(DateTimeUtils.formatDate(new Date(this.contentDetailData?.publishTime).getTime(), | ||
| 225 | + DateTimeUtils.PATTERN_DATE_TIME_HYPHEN_MM)) | ||
| 226 | + .fontSize(12) | ||
| 227 | + .fontColor(Color.White) | ||
| 228 | + .opacity(0.7) | ||
| 229 | + .lineHeight(16) | ||
| 230 | + .fontWeight(400) | ||
| 231 | + .fontFamily('PingFang SC-Regular') | ||
| 232 | + .margin({ top: 8, bottom: 8 }) | ||
| 233 | + | ||
| 234 | + } | ||
| 235 | + .width(this.windowWidth - 150 + 'px') | ||
| 236 | + .padding({ left: 16, right: 22 }) | ||
| 237 | + .alignItems(HorizontalAlign.Start) | ||
| 238 | + .visibility(this.isOpenDetail || this.isDragging ? Visibility.None : Visibility.Visible) | ||
| 239 | + } | ||
| 240 | + | ||
| 241 | + @Builder | ||
| 242 | + detailDesc() { | ||
| 243 | + /** | ||
| 244 | + * 标题大于三行或存在简介显示查看详情按钮 | ||
| 245 | + */ | ||
| 246 | + // if (this.rmhPlatform == 1) { | ||
| 247 | + // if (this.titleHeight > 200 || this.summary) { | ||
| 248 | + // Text('查看详情 > ') | ||
| 249 | + // .padding({ | ||
| 250 | + // left: 6, | ||
| 251 | + // right: 6, | ||
| 252 | + // top: 4, | ||
| 253 | + // bottom: 4 | ||
| 254 | + // }) | ||
| 255 | + // .borderRadius(2) | ||
| 256 | + // .backgroundColor('#99636363') | ||
| 257 | + // .fontFamily('PingFang SC-Regular') | ||
| 258 | + // .fontColor(Color.White) | ||
| 259 | + // .fontSize(12) | ||
| 260 | + // .lineHeight(14) | ||
| 261 | + // .fontWeight(400) | ||
| 262 | + // .onClick(() => { | ||
| 263 | + // this.isOpenDetail = true | ||
| 264 | + // this.dialogController?.open() | ||
| 265 | + // }) | ||
| 266 | + // } | ||
| 267 | + // } else { | ||
| 220 | if (this.summary && this.titleLines < 4) { | 268 | if (this.summary && this.titleLines < 4) { |
| 269 | + Stack({ alignContent: Alignment.TopStart }) { | ||
| 221 | Text() { | 270 | Text() { |
| 222 | Span(this.clipText(this.summary, 14, this.summaryLines, this.windowWidth - 150 - vp2px(50))) | 271 | Span(this.clipText(this.summary, 14, this.summaryLines, this.windowWidth - 150 - vp2px(50))) |
| 223 | .fontSize(14) | 272 | .fontSize(14) |
| @@ -229,9 +278,18 @@ export struct PlayerTitleView { | @@ -229,9 +278,18 @@ export struct PlayerTitleView { | ||
| 229 | this.isOpenDetail = true | 278 | this.isOpenDetail = true |
| 230 | this.dialogController?.open() | 279 | this.dialogController?.open() |
| 231 | }) | 280 | }) |
| 281 | + } | ||
| 282 | + // .position({ x: 0, y: 0 }) | ||
| 283 | + .padding({ | ||
| 284 | + left: 0, | ||
| 285 | + right: 6, | ||
| 286 | + top: 0, | ||
| 287 | + bottom: 8 | ||
| 288 | + }) | ||
| 232 | if (this.isOverLines) { | 289 | if (this.isOverLines) { |
| 233 | - Span('... 全文') | ||
| 234 | - .fontColor('#888888') | 290 | + Text() { |
| 291 | + Span('全文') | ||
| 292 | + .fontColor('#99FFFFFF') | ||
| 235 | .fontWeight(400) | 293 | .fontWeight(400) |
| 236 | .fontFamily('PingFang SC-Regular') | 294 | .fontFamily('PingFang SC-Regular') |
| 237 | .fontSize(12) | 295 | .fontSize(12) |
| @@ -251,37 +309,31 @@ export struct PlayerTitleView { | @@ -251,37 +309,31 @@ export struct PlayerTitleView { | ||
| 251 | this.isOpenDetail = true | 309 | this.isOpenDetail = true |
| 252 | this.dialogController?.open() | 310 | this.dialogController?.open() |
| 253 | }) | 311 | }) |
| 254 | - | ||
| 255 | - } | ||
| 256 | } | 312 | } |
| 313 | + .textAlign(TextAlign.Center) | ||
| 314 | + // .width('100%') | ||
| 315 | + .position({ x: '100%', y: this.summaryLines*23 }) //行高+margin | ||
| 316 | + .translate({ x: '-100%', y: '-100%' }) | ||
| 317 | + // .markAnchor({ x: '100%', y: '100%' }) | ||
| 257 | .padding({ | 318 | .padding({ |
| 258 | - left: 0, //6 | 319 | + left: 0, |
| 259 | right: 6, | 320 | right: 6, |
| 260 | - top: 0, //4 | ||
| 261 | - bottom: 8 | 321 | + top: 0, |
| 322 | + bottom: 6 | ||
| 262 | }) | 323 | }) |
| 263 | - | ||
| 264 | } | 324 | } |
| 265 | - // } | ||
| 266 | - Text(DateTimeUtils.formatDate(new Date(this.contentDetailData?.publishTime).getTime(), | ||
| 267 | - DateTimeUtils.PATTERN_DATE_TIME_HYPHEN_MM)) | ||
| 268 | - .fontSize(12) | ||
| 269 | - .fontColor(Color.White) | ||
| 270 | - .opacity(0.7) | ||
| 271 | - .lineHeight(16) | ||
| 272 | - .fontWeight(400) | ||
| 273 | - .fontFamily('PingFang SC-Regular') | ||
| 274 | - .margin({ top: 8, bottom: 8 }) | ||
| 275 | - | ||
| 276 | } | 325 | } |
| 277 | - .width(this.windowWidth - 150 + 'px') | ||
| 278 | - .padding({ left: 16, right: 22 }) | ||
| 279 | - .alignItems(HorizontalAlign.Start) | ||
| 280 | - .visibility(this.isOpenDetail || this.isDragging ? Visibility.None : Visibility.Visible) | 326 | + .width('100%') |
| 327 | + } | ||
| 281 | } | 328 | } |
| 282 | 329 | ||
| 330 | + /** | ||
| 331 | + * 标题 | ||
| 332 | + * */ | ||
| 283 | @Builder | 333 | @Builder |
| 284 | titleBuilder() { | 334 | titleBuilder() { |
| 335 | + // Stack({ alignContent: this.isTitleOverLines ? Alignment.BottomEnd : Alignment.Start }) { | ||
| 336 | + Stack({ alignContent: Alignment.TopStart }) { | ||
| 285 | Text() { | 337 | Text() { |
| 286 | Span(this.clipTitleText(this.getTitle(), 16, 4, this.windowWidth - 234 - vp2px(50))) | 338 | Span(this.clipTitleText(this.getTitle(), 16, 4, this.windowWidth - 234 - vp2px(50))) |
| 287 | .fontSize(16) | 339 | .fontSize(16) |
| @@ -289,9 +341,28 @@ export struct PlayerTitleView { | @@ -289,9 +341,28 @@ export struct PlayerTitleView { | ||
| 289 | .lineHeight(22) | 341 | .lineHeight(22) |
| 290 | .fontWeight(600) | 342 | .fontWeight(600) |
| 291 | .fontFamily('PingFang SC-Regular') | 343 | .fontFamily('PingFang SC-Regular') |
| 344 | + | ||
| 345 | + } | ||
| 346 | + // .position({ x: 0, y: 0 }) | ||
| 347 | + .onAreaChange((oldArea: Area, newArea: Area) => { | ||
| 348 | + //console.info(`cj2024 titleLines = ${newArea.height as number} line = ${(newArea.height as number) / 20}`) | ||
| 349 | + this.titleLines = Math.floor((newArea.height as number) / 22) // 22是行高 | ||
| 350 | + //console.info(`cj2024 titleLines = ${this.titleLines}`) | ||
| 351 | + this.updateSummaryLines() | ||
| 352 | + }) | ||
| 353 | + .maxLines(4) | ||
| 354 | + .textOverflow({ overflow: TextOverflow.Ellipsis }) | ||
| 355 | + .padding({ | ||
| 356 | + left: 0, //6 | ||
| 357 | + right: 6, | ||
| 358 | + top: 0, //4 | ||
| 359 | + bottom: 8 | ||
| 360 | + }) | ||
| 361 | + | ||
| 362 | + Text() { | ||
| 292 | if (this.isTitleOverLines) { | 363 | if (this.isTitleOverLines) { |
| 293 | - Span('... 全文') | ||
| 294 | - .fontColor(Color.White) | 364 | + Span('全文') |
| 365 | + .fontColor('#99FFFFFF') | ||
| 295 | .fontWeight(600) | 366 | .fontWeight(600) |
| 296 | .fontFamily('PingFang SC-Regular') | 367 | .fontFamily('PingFang SC-Regular') |
| 297 | .fontSize(12) | 368 | .fontSize(12) |
| @@ -311,15 +382,14 @@ export struct PlayerTitleView { | @@ -311,15 +382,14 @@ export struct PlayerTitleView { | ||
| 311 | this.isOpenDetail = true | 382 | this.isOpenDetail = true |
| 312 | this.dialogController?.open() | 383 | this.dialogController?.open() |
| 313 | }) | 384 | }) |
| 314 | - | ||
| 315 | } | 385 | } |
| 316 | } | 386 | } |
| 317 | - .onAreaChange((oldArea: Area, newArea: Area) => { | ||
| 318 | - //console.info(`cj2024 titleLines = ${newArea.height as number} line = ${(newArea.height as number) / 20}`) | ||
| 319 | - this.titleLines = Math.floor((newArea.height as number) / 22) // 22是行高 | ||
| 320 | - //console.info(`cj2024 titleLines = ${this.titleLines}`) | ||
| 321 | - this.updateSummaryLines() | ||
| 322 | - }) | 387 | + .textAlign(TextAlign.Center) |
| 388 | + // .width('100%') | ||
| 389 | + .position({ x: '100%', y: this.titleLines*23 }) //行高+margin | ||
| 390 | + .translate({ x: '-100%', y: '-100%' }) | ||
| 391 | + // .position({ x: '100%', y: '100%' }) | ||
| 392 | + // .markAnchor({ x: '100%', y: '100%' }) | ||
| 323 | .padding({ | 393 | .padding({ |
| 324 | left: 0, //6 | 394 | left: 0, //6 |
| 325 | right: 6, | 395 | right: 6, |
| @@ -327,4 +397,6 @@ export struct PlayerTitleView { | @@ -327,4 +397,6 @@ export struct PlayerTitleView { | ||
| 327 | bottom: 8 | 397 | bottom: 8 |
| 328 | }) | 398 | }) |
| 329 | } | 399 | } |
| 400 | + .width('100%') | ||
| 401 | + } | ||
| 330 | } | 402 | } |
| 1 | -<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="16" height="16" viewBox="0 0 16 16"><g transform="matrix(0,-1,1,0,-16,16)"><g><path d="M10.303455641479491,17.960819560243227L4.363755241479492,23.900515460243227Q4.324434578479492,23.939835460243224,4.324704443879492,23.995445460243225Q4.324434578479492,24.051055460243226,4.363755241479492,24.090375460243223L10.303455641479491,30.030075460243225Q10.342505641479491,30.069075460243226,10.397735641479493,30.069075460243226Q10.452965641479492,30.069075460243226,10.492015641479492,30.030075460243225L11.387685641479493,29.134375460243227Q11.406435641479492,29.115675460243224,11.416585641479493,29.091175460243225Q11.426735641479493,29.066675460243225,11.426735641479493,29.040075460243223Q11.426735641479493,29.013575460243224,11.416585641479493,28.989075460243225Q11.406435641479492,28.964575460243225,11.387685641479493,28.945875460243226L6.437285641479493,23.995445460243225L11.387685641479493,19.045045460243227Q11.406435641479492,19.026295460243226,11.416585641479493,19.001795460243226Q11.426735641479493,18.977295460243226,11.426735641479493,18.950765460243225Q11.426735641479493,18.924245460243224,11.416585641479493,18.899744460243227Q11.406435641479492,18.875241460243224,11.387685641479493,18.856488460243224L10.492015641479492,17.960819560243227Q10.452965641479492,17.921767119783226,10.397735641479493,17.921767119783226Q10.342505641479491,17.921767119783226,10.303455641479491,17.960819560243227Z" fill-rule="evenodd" fill="#888888" fill-opacity="1"/></g></g></svg> | ||
| 1 | +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="16" height="16" viewBox="0 0 16 16"><g transform="matrix(0,-1,1,0,-16,16)"><g><path d="M10.303455641479491,17.960819560243227L4.363755241479492,23.900515460243227Q4.324434578479492,23.939835460243224,4.324704443879492,23.995445460243225Q4.324434578479492,24.051055460243226,4.363755241479492,24.090375460243223L10.303455641479491,30.030075460243225Q10.342505641479491,30.069075460243226,10.397735641479493,30.069075460243226Q10.452965641479492,30.069075460243226,10.492015641479492,30.030075460243225L11.387685641479493,29.134375460243227Q11.406435641479492,29.115675460243224,11.416585641479493,29.091175460243225Q11.426735641479493,29.066675460243225,11.426735641479493,29.040075460243223Q11.426735641479493,29.013575460243224,11.416585641479493,28.989075460243225Q11.406435641479492,28.964575460243225,11.387685641479493,28.945875460243226L6.437285641479493,23.995445460243225L11.387685641479493,19.045045460243227Q11.406435641479492,19.026295460243226,11.416585641479493,19.001795460243226Q11.426735641479493,18.977295460243226,11.426735641479493,18.950765460243225Q11.426735641479493,18.924245460243224,11.416585641479493,18.899744460243227Q11.406435641479492,18.875241460243224,11.387685641479493,18.856488460243224L10.492015641479492,17.960819560243227Q10.452965641479492,17.921767119783226,10.397735641479493,17.921767119783226Q10.342505641479491,17.921767119783226,10.303455641479491,17.960819560243227Z" fill-rule="evenodd" fill="#FFFFFF" fill-opacity="0.6"/></g></g></svg> |
-
Please register or login to post a comment