陈剑华

Merge remote-tracking branch 'origin/main'

Showing 32 changed files with 1383 additions and 153 deletions
@@ -96,10 +96,10 @@ export struct RmhTitle { @@ -96,10 +96,10 @@ export struct RmhTitle {
96 build() { 96 build() {
97 Flex() { 97 Flex() {
98 Stack() { 98 Stack() {
99 - Image(this.rmhInfo.rmhHeadUrl) 99 + Image(this.rmhInfo?.rmhHeadUrl)
100 .width(36) 100 .width(36)
101 .height(36).borderRadius(50) 101 .height(36).borderRadius(50)
102 - Image(this.rmhInfo.authIcon) 102 + Image(this.rmhInfo?.authIcon)
103 .width(14) 103 .width(14)
104 .height(14) 104 .height(14)
105 .borderRadius(50) 105 .borderRadius(50)
@@ -109,7 +109,7 @@ export struct RmhTitle { @@ -109,7 +109,7 @@ export struct RmhTitle {
109 .flexShrink(0) 109 .flexShrink(0)
110 110
111 Column() { 111 Column() {
112 - Text(this.rmhInfo.rmhName) 112 + Text(this.rmhInfo?.rmhName)
113 .fontSize($r('app.float.font_size_13')) 113 .fontSize($r('app.float.font_size_13'))
114 .fontColor($r('app.color.color_222222')) 114 .fontColor($r('app.color.color_222222'))
115 .fontWeight(600) 115 .fontWeight(600)
@@ -122,13 +122,13 @@ export struct RmhTitle { @@ -122,13 +122,13 @@ export struct RmhTitle {
122 .fontSize($r("app.float.font_size_12")) 122 .fontSize($r("app.float.font_size_12"))
123 .fontColor($r("app.color.color_B0B0B0")) 123 .fontColor($r("app.color.color_B0B0B0"))
124 } 124 }
125 - if (this.publishTime && this.rmhInfo.rmhDesc) { 125 + if (this.publishTime && this.rmhInfo?.rmhDesc) {
126 Image($r('app.media.point')) 126 Image($r('app.media.point'))
127 .width(16) 127 .width(16)
128 .height(16) 128 .height(16)
129 } 129 }
130 } 130 }
131 - Text(this.rmhInfo.rmhDesc) 131 + Text(this.rmhInfo?.rmhDesc)
132 .fontSize($r("app.float.font_size_12")) 132 .fontSize($r("app.float.font_size_12"))
133 .fontColor($r("app.color.color_B0B0B0")) 133 .fontColor($r("app.color.color_B0B0B0"))
134 .maxLines(1) 134 .maxLines(1)
@@ -141,7 +141,7 @@ export struct RmhTitle { @@ -141,7 +141,7 @@ export struct RmhTitle {
141 } 141 }
142 142
143 Blank() 143 Blank()
144 - if (this.rmhInfo.cnIsAttention) { 144 + if (this.rmhInfo?.cnIsAttention) {
145 Row() { 145 Row() {
146 if (Number(this.followStatus) === 0) { 146 if (Number(this.followStatus) === 0) {
147 Image($r('app.media.rmh_follow')) 147 Image($r('app.media.rmh_follow'))
@@ -40,7 +40,7 @@ export struct Card17Component { @@ -40,7 +40,7 @@ export struct Card17Component {
40 this.contentDTO.fullColumnImgUrls.length > 0 ? this.contentDTO.fullColumnImgUrls[0].url : '' : '') 40 this.contentDTO.fullColumnImgUrls.length > 0 ? this.contentDTO.fullColumnImgUrls[0].url : '' : '')
41 .backgroundColor(this.loadImg ? '#f5f5f5' : 0xf5f5f5) 41 .backgroundColor(this.loadImg ? '#f5f5f5' : 0xf5f5f5)
42 .width(CommonConstants.FULL_WIDTH) 42 .width(CommonConstants.FULL_WIDTH)
43 - .aspectRatio(16 / 9) 43 + .height(160)// .aspectRatio(CompUtils.ASPECT_RATIO_16_9)
44 .borderRadius({ 44 .borderRadius({
45 topLeft: $r('app.float.image_border_radius'), 45 topLeft: $r('app.float.image_border_radius'),
46 bottomLeft: $r('app.float.image_border_radius'), 46 bottomLeft: $r('app.float.image_border_radius'),
@@ -52,7 +52,7 @@ export struct Card17Component { @@ -52,7 +52,7 @@ export struct Card17Component {
52 this.contentDTO.fullColumnImgUrls.length > 1 ? this.contentDTO.fullColumnImgUrls[1].url : '' : '') 52 this.contentDTO.fullColumnImgUrls.length > 1 ? this.contentDTO.fullColumnImgUrls[1].url : '' : '')
53 .backgroundColor(this.loadImg ? '#f5f5f5' : 0xf5f5f5) 53 .backgroundColor(this.loadImg ? '#f5f5f5' : 0xf5f5f5)
54 .width(CommonConstants.FULL_WIDTH) 54 .width(CommonConstants.FULL_WIDTH)
55 - .aspectRatio(16 / 9) 55 + .height(79)// .aspectRatio(CompUtils.ASPECT_RATIO_16_9)
56 .margin({ bottom: 1 }) 56 .margin({ bottom: 1 })
57 .borderRadius({ 57 .borderRadius({
58 topRight: $r('app.float.image_border_radius'), 58 topRight: $r('app.float.image_border_radius'),
@@ -69,7 +69,7 @@ export struct Card17Component { @@ -69,7 +69,7 @@ export struct Card17Component {
69 this.contentDTO.fullColumnImgUrls.length > 2 ? this.contentDTO.fullColumnImgUrls[2].url : '' : '') 69 this.contentDTO.fullColumnImgUrls.length > 2 ? this.contentDTO.fullColumnImgUrls[2].url : '' : '')
70 .backgroundColor(this.loadImg ? '#f5f5f5' : 0xf5f5f5) 70 .backgroundColor(this.loadImg ? '#f5f5f5' : 0xf5f5f5)
71 .width(CommonConstants.FULL_WIDTH) 71 .width(CommonConstants.FULL_WIDTH)
72 - .aspectRatio(16 / 9) 72 + .height(79)// .aspectRatio(CompUtils.ASPECT_RATIO_16_9)
73 .margin({ top: 1 }) 73 .margin({ top: 1 })
74 .borderRadius({ 74 .borderRadius({
75 bottomRight: $r('app.float.image_border_radius'), 75 bottomRight: $r('app.float.image_border_radius'),
@@ -107,4 +107,12 @@ export struct Card17Component { @@ -107,4 +107,12 @@ export struct Card17Component {
107 bottom: $r('app.float.card_comp_pagePadding_tb') 107 bottom: $r('app.float.card_comp_pagePadding_tb')
108 }) 108 })
109 } 109 }
  110 +}
  111 +
  112 +// 全局公共样式
  113 +@Styles
  114 +function ImageSize() {
  115 + .padding({ right: 18, left: 18 })
  116 + .width('100%')
  117 + .margin({ top: 10 })
110 } 118 }
@@ -68,7 +68,7 @@ export class commentItemModel { @@ -68,7 +68,7 @@ export class commentItemModel {
68 fromUserHeader: string = '' 68 fromUserHeader: string = ''
69 fromUserId: string = '' 69 fromUserId: string = ''
70 fromUserName: string = '' 70 fromUserName: string = ''
71 - fromUserType: WDPublicUserType = 0 71 + fromUserType: WDPublicUserType = 1
72 id: string = '' 72 id: string = ''
73 likeNum: string = '0' 73 likeNum: string = '0'
74 mySelf: string = '' 74 mySelf: string = ''
@@ -3,8 +3,8 @@ import curves from '@ohos.curves'; @@ -3,8 +3,8 @@ import curves from '@ohos.curves';
3 import { BusinessError } from '@ohos.base'; 3 import { BusinessError } from '@ohos.base';
4 import display from '@ohos.display'; 4 import display from '@ohos.display';
5 5
6 -const collapseString = '...展开全文'  
7 -const uncollapseString = '...收起' 6 +const collapseString = '...展开'
  7 +const uncollapseString = ' 收起'
8 8
9 const TestLongText = "超过三行超\n过三行超过\n三行超超过三行\n超过三行超过三行超过三\n行超过" 9 const TestLongText = "超过三行超\n过三行超过\n三行超超过三行\n超过三行超过三行超过三\n行超过"
10 10
@@ -129,7 +129,9 @@ export struct CommentText { @@ -129,7 +129,9 @@ export struct CommentText {
129 // Stack({ alignContent: Alignment.BottomEnd }) { 129 // Stack({ alignContent: Alignment.BottomEnd }) {
130 Text(this.longMessage) { 130 Text(this.longMessage) {
131 Span(this.expandedStates ? this.longMessage : this.maxLineMesssage) 131 Span(this.expandedStates ? this.longMessage : this.maxLineMesssage)
132 - Span(this.collapseText).onClick(() => { 132 + Span(this.collapseText)
  133 + .fontColor("#999999")
  134 + .onClick(() => {
133 if (this.collapseText == collapseString) { 135 if (this.collapseText == collapseString) {
134 this.collapseText = uncollapseString; 136 this.collapseText = uncollapseString;
135 this.expandedStates = true; 137 this.expandedStates = true;
@@ -26,7 +26,7 @@ export struct QualityCommentsComponent { @@ -26,7 +26,7 @@ export struct QualityCommentsComponent {
26 private scroller: Scroller = new Scroller(); 26 private scroller: Scroller = new Scroller();
27 @State tileOpacity: number = 0; 27 @State tileOpacity: number = 0;
28 firstPositionY: number = 0; 28 firstPositionY: number = 0;
29 - bottomSafeHeight: string = AppStorage.get<number>('bottomSafeHeight') + 'px'; 29 + bottomSafeHeight: number = AppStorage.get<number>('bottomSafeHeight') || 0;
30 topSafeHeight: number = AppStorage.get<number>('topSafeHeight') as number; 30 topSafeHeight: number = AppStorage.get<number>('topSafeHeight') as number;
31 lastWindowColor: string = '#ffffff' 31 lastWindowColor: string = '#ffffff'
32 currentWindowColor: string = '#FF4202' 32 currentWindowColor: string = '#FF4202'
@@ -247,9 +247,9 @@ export struct QualityCommentsComponent { @@ -247,9 +247,9 @@ export struct QualityCommentsComponent {
247 ListItem() { 247 ListItem() {
248 if (this.hasMore === false) NoMoreLayout() 248 if (this.hasMore === false) NoMoreLayout()
249 } 249 }
250 - ListItem() {  
251 -  
252 - }.height(this.bottomSafeHeight) 250 + // ListItem() {
  251 + //
  252 + // }.height(this.bottomSafeHeight)
253 }.onReachEnd(()=>{ 253 }.onReachEnd(()=>{
254 this.currentPage++ 254 this.currentPage++
255 this.getData() 255 this.getData()
@@ -257,8 +257,7 @@ export struct QualityCommentsComponent { @@ -257,8 +257,7 @@ export struct QualityCommentsComponent {
257 .margin({ top: 196 }) 257 .margin({ top: 196 })
258 .height("100%") 258 .height("100%")
259 .width("100%") 259 .width("100%")
260 - // .edgeEffect(EdgeEffect.None) // 必须设置列表为滑动到边缘无效果  
261 - .edgeEffect(EdgeEffect.Spring) 260 + .edgeEffect(EdgeEffect.None) // 必须设置列表为滑动到边缘无效果
262 .nestedScroll({ 261 .nestedScroll({
263 scrollForward: NestedScrollMode.PARENT_FIRST, 262 scrollForward: NestedScrollMode.PARENT_FIRST,
264 scrollBackward: NestedScrollMode.SELF_FIRST 263 scrollBackward: NestedScrollMode.SELF_FIRST
@@ -352,7 +351,7 @@ struct QualityCommentItem { @@ -352,7 +351,7 @@ struct QualityCommentItem {
352 Row() { 351 Row() {
353 Row() { 352 Row() {
354 Image($r('app.media.comment_img_link')).width(16).height(16) 353 Image($r('app.media.comment_img_link')).width(16).height(16)
355 - Text(this.item.shareInfo.shareTitle) 354 + Text(this.item.targetTitle)
356 .fontSize(14) 355 .fontSize(14)
357 .fontColor('#666666') 356 .fontColor('#666666')
358 .margin({ left: 6, right: 12 }) 357 .margin({ left: 6, right: 12 })
@@ -485,10 +485,13 @@ class CommentViewModel { @@ -485,10 +485,13 @@ class CommentViewModel {
485 485
486 jumpToAccountPage(commentItem: commentItemModel) { 486 jumpToAccountPage(commentItem: commentItemModel) {
487 let url = HttpUrlUtils.getOtherUserDetailDataUrl() 487 let url = HttpUrlUtils.getOtherUserDetailDataUrl()
488 - let item : Record<string, string >= {  
489 - "creatorId": commentItem.fromCreatorId || "",  
490 - "userType": `${commentItem.fromUserType}`,  
491 - "userId": commentItem.fromUserId || "-1", 488 + let item : Record<string, string >= {}
  489 +
  490 + if (commentItem.fromCreatorId) {
  491 + item["creatorId"] = commentItem.fromCreatorId
  492 + } else {
  493 + item["userType"] = `${commentItem.fromUserType}`
  494 + item["userId"] = commentItem.fromUserId
492 } 495 }
493 HttpBizUtil.post<ResponseDTO<MasterDetailRes>>(url, item).then((result) => { 496 HttpBizUtil.post<ResponseDTO<MasterDetailRes>>(url, item).then((result) => {
494 if (!result.data || result.data.mainControl != 1) { 497 if (!result.data || result.data.mainControl != 1) {
1 -import { CompDTO, ContentDTO } from 'wdBean'; 1 +import { CompDTO, ContentDTO, LiveRoomDataBean } from 'wdBean';
2 import { CommonConstants } from 'wdConstant/Index'; 2 import { CommonConstants } from 'wdConstant/Index';
3 import { Logger } from 'wdKit/Index'; 3 import { Logger } from 'wdKit/Index';
4 import { ProcessUtils } from 'wdRouter'; 4 import { ProcessUtils } from 'wdRouter';
@@ -20,6 +20,9 @@ export struct ZhGridLayout02 { @@ -20,6 +20,9 @@ export struct ZhGridLayout02 {
20 @State compDTO: CompDTO = {} as CompDTO 20 @State compDTO: CompDTO = {} as CompDTO
21 @State operDataList: ContentDTO[] = [] 21 @State operDataList: ContentDTO[] = []
22 @State loadImg: boolean = false; 22 @State loadImg: boolean = false;
  23 + @State liveRoomList: LiveRoomDataBean[] = []
  24 + currentPage = 1
  25 + pageSize = 12
23 26
24 async aboutToAppear(): Promise<void> { 27 async aboutToAppear(): Promise<void> {
25 Logger.debug(TAG, 'aboutToAppear ' + this.compDTO.objectTitle) 28 Logger.debug(TAG, 'aboutToAppear ' + this.compDTO.objectTitle)
@@ -27,14 +30,12 @@ export struct ZhGridLayout02 { @@ -27,14 +30,12 @@ export struct ZhGridLayout02 {
27 PageViewModel.getLiveReviewUrl(this.currentPage, this.pageSize).then((liveReviewDTO) => { 30 PageViewModel.getLiveReviewUrl(this.currentPage, this.pageSize).then((liveReviewDTO) => {
28 this.operDataList = [] 31 this.operDataList = []
29 this.operDataList.push(...liveReviewDTO.list) 32 this.operDataList.push(...liveReviewDTO.list)
  33 + this.getLiveRoomDataInfo(this.operDataList)
30 }) 34 })
31 35
32 this.loadImg = await onlyWifiLoadImg(); 36 this.loadImg = await onlyWifiLoadImg();
33 } 37 }
34 38
35 - currentPage = 1  
36 - pageSize = 12  
37 -  
38 build() { 39 build() {
39 Column() { 40 Column() {
40 Scroll() { 41 Scroll() {
@@ -50,7 +51,7 @@ export struct ZhGridLayout02 { @@ -50,7 +51,7 @@ export struct ZhGridLayout02 {
50 .fontWeight(600) 51 .fontWeight(600)
51 } 52 }
52 .justifyContent(FlexAlign.Start) 53 .justifyContent(FlexAlign.Start)
53 - .margin({ top: 8, bottom: 8 }) 54 + .margin({ top: 16, bottom: 8 })
54 .width(CommonConstants.FULL_WIDTH) 55 .width(CommonConstants.FULL_WIDTH)
55 56
56 GridRow({ 57 GridRow({
@@ -100,13 +101,26 @@ export struct ZhGridLayout02 { @@ -100,13 +101,26 @@ export struct ZhGridLayout02 {
100 @Builder 101 @Builder
101 buildItemCard(item: ContentDTO) { 102 buildItemCard(item: ContentDTO) {
102 Column() { 103 Column() {
103 - Image(this.loadImg ? item.fullColumnImgUrls[0].url : '')  
104 - .backgroundColor(0xf5f5f5)  
105 - .width('100%')  
106 - .height(95)  
107 - .borderRadius(4) 104 + Stack({ alignContent: Alignment.BottomEnd }) {
  105 + Image(this.loadImg ? item.fullColumnImgUrls[0].url : '')
  106 + .backgroundColor(0xf5f5f5)
  107 + .width('100%')
  108 + .height(95)
  109 + .borderRadius(4)
  110 + if (this.getLiveRoomNumber(item).length > 0) {
  111 + Text(this.getLiveRoomNumber(item))
  112 + .fontSize('11vp')
  113 + .fontWeight(400)
  114 + .fontColor(Color.White)
  115 + .margin({
  116 + right: '5vp',
  117 + bottom: '5vp'
  118 + })
  119 + }
  120 + }
  121 +
108 Text(item.newsTitle) 122 Text(item.newsTitle)
109 - .margin({top:'5'}) 123 + .margin({ top: '5' })
110 .fontSize(13) 124 .fontSize(13)
111 .maxLines(2) 125 .maxLines(2)
112 .textOverflow({ overflow: TextOverflow.Ellipsis }) 126 .textOverflow({ overflow: TextOverflow.Ellipsis })
@@ -117,14 +131,56 @@ export struct ZhGridLayout02 { @@ -117,14 +131,56 @@ export struct ZhGridLayout02 {
117 }) 131 })
118 } 132 }
119 133
  134 + // 获取评论数
  135 + async getLiveRoomDataInfo(list: ContentDTO[]) {
  136 + const reserveIds = this.getLiveDetailIds(list)
  137 + PageViewModel.getLiveRoomBatchInfo(reserveIds).then((result) => {
  138 + if (result && result.length > 0) {
  139 + this.liveRoomList.push(...result)
  140 + }
  141 + }).catch(() => {
  142 + })
  143 + }
  144 +
  145 + // 判断是否预约
  146 + getLiveRoomNumber(item: ContentDTO): string {
  147 + const objc = this.liveRoomList.find((element: LiveRoomDataBean) => {
  148 + return element.liveId.toString() == item.objectId
  149 + })
  150 + if (objc && objc.pv && objc.pv > 0) {
  151 + return this.computeShowNum(objc.pv)
  152 + }
  153 + return ''
  154 + }
  155 +
120 addItems() { 156 addItems() {
121 Logger.debug(TAG, 'addItems') 157 Logger.debug(TAG, 'addItems')
122 this.currentPage++ 158 this.currentPage++
123 PageViewModel.getLiveReviewUrl(this.currentPage, this.pageSize).then((liveReviewDTO) => { 159 PageViewModel.getLiveReviewUrl(this.currentPage, this.pageSize).then((liveReviewDTO) => {
124 this.operDataList.push(...liveReviewDTO.list) 160 this.operDataList.push(...liveReviewDTO.list)
  161 + this.getLiveRoomDataInfo(this.operDataList)
125 Logger.debug(TAG, 'addItems after: ' + this.operDataList.length) 162 Logger.debug(TAG, 'addItems after: ' + this.operDataList.length)
126 }) 163 })
127 } 164 }
  165 +
  166 + private getLiveDetailIds(list: ContentDTO[]): string {
  167 + let idList: string[] = []
  168 + list.forEach(item => {
  169 + idList.push(item.objectId)
  170 + });
  171 + return idList.join(',')
  172 + }
  173 +
  174 + private computeShowNum(count: number): string {
  175 + if (count >= 10000) {
  176 + let num = (count / 10000).toFixed(1)
  177 + if (Number(num.substring(num.length - 1)) == 0) {
  178 + num = num.substring(0, num.length - 2)
  179 + }
  180 + return num + '万人参加'
  181 + }
  182 + return `${count}人参加`
  183 + }
128 } 184 }
129 185
130 186
@@ -3,6 +3,7 @@ import { WDRouterPage, WDRouterRule } from 'wdRouter/Index' @@ -3,6 +3,7 @@ import { WDRouterPage, WDRouterRule } from 'wdRouter/Index'
3 import { WDMessageCenterMessageType } from '../../../model/InteractMessageModel' 3 import { WDMessageCenterMessageType } from '../../../model/InteractMessageModel'
4 import MinePageDatasModel from '../../../model/MinePageDatasModel' 4 import MinePageDatasModel from '../../../model/MinePageDatasModel'
5 import { MessageItem } from '../../../viewmodel/MessageItem' 5 import { MessageItem } from '../../../viewmodel/MessageItem'
  6 +import { CustomPullToRefresh } from '../../reusable/CustomPullToRefresh'
6 import { CustomTitleUI } from '../../reusable/CustomTitleUI' 7 import { CustomTitleUI } from '../../reusable/CustomTitleUI'
7 import { MessageListItemUI } from './MessageListItemUI' 8 import { MessageListItemUI } from './MessageListItemUI'
8 9
@@ -11,6 +12,7 @@ const TAG = "MessageListUI" @@ -11,6 +12,7 @@ const TAG = "MessageListUI"
11 @Component 12 @Component
12 export struct MessageListUI { 13 export struct MessageListUI {
13 @State msgData: MessageItem[] = [] 14 @State msgData: MessageItem[] = []
  15 + private scroller: Scroller = new Scroller();
14 16
15 aboutToAppear() { 17 aboutToAppear() {
16 this.msgData = MinePageDatasModel.getMessageData() 18 this.msgData = MinePageDatasModel.getMessageData()
@@ -138,45 +140,72 @@ export struct MessageListUI { @@ -138,45 +140,72 @@ export struct MessageListUI {
138 //标题栏目 140 //标题栏目
139 CustomTitleUI({ titleName: "消息" }) 141 CustomTitleUI({ titleName: "消息" })
140 142
141 - List() {  
142 - ForEach(this.msgData, (item: MessageItem, index: number) => {  
143 - ListItem() {  
144 - MessageListItemUI({ item: item, index: index })  
145 - }  
146 - .padding({ left: "31lpx", right: "31lpx" })  
147 - .onClick(() => {  
148 - switch (index) {  
149 - case 0: //互动消息  
150 - if(item.unReadCount > 0){  
151 - this.sendEnterEvent(WDMessageCenterMessageType.WDMessageCenterMessageType_Interact)  
152 - }  
153 - WDRouterRule.jumpWithPage(WDRouterPage.interactMessagePage)  
154 - break;  
155 - case 1: //预约消息  
156 - if(item.unReadCount > 0){  
157 - this.sendEnterEvent(WDMessageCenterMessageType.WDMessageCenterMessageType_Subscribe)  
158 - }  
159 - WDRouterRule.jumpWithPage(WDRouterPage.subscribeMessagePage)  
160 - break;  
161 - case 2: //历史推送  
162 - break;  
163 - case 3: //系统消息  
164 - break;  
165 - }  
166 - })  
167 - .height('154lpx')  
168 - .width("100%")  
169 - })  
170 - } 143 + CustomPullToRefresh({
  144 + alldata:this.msgData,
  145 + scroller:this.scroller,
  146 + customList:()=>{
  147 + this.ListLayout()
  148 + },
  149 + onRefresh:(resolve)=>{
  150 +
  151 + if(resolve) resolve('刷新成功')
  152 + },
  153 + onLoadMore:(resolve)=> {
  154 + }
  155 + })
171 } 156 }
172 .backgroundColor($r('app.color.white')) 157 .backgroundColor($r('app.color.white'))
173 .height('100%') 158 .height('100%')
174 .width('100%') 159 .width('100%')
175 } 160 }
176 161
  162 + @Builder ListLayout(){
  163 + List({scroller: this.scroller}) {
  164 + ForEach(this.msgData, (item: MessageItem, index: number) => {
  165 + ListItem() {
  166 + MessageListItemUI({ item: item, index: index })
  167 + }
  168 + .padding({ left: "31lpx", right: "31lpx" })
  169 + .onClick(() => {
  170 + switch (index) {
  171 + case 0: //互动消息
  172 + if(item.unReadCount > 0){
  173 + this.sendEnterEvent(WDMessageCenterMessageType.WDMessageCenterMessageType_Interact)
  174 + }
  175 + WDRouterRule.jumpWithPage(WDRouterPage.interactMessagePage)
  176 + break;
  177 + case 1: //预约消息
  178 + if(item.unReadCount > 0){
  179 + this.sendEnterEvent(WDMessageCenterMessageType.WDMessageCenterMessageType_Subscribe)
  180 + }
  181 + WDRouterRule.jumpWithPage(WDRouterPage.subscribeMessagePage)
  182 + break;
  183 + case 2: //历史推送
  184 + break;
  185 + case 3: //系统消息
  186 + break;
  187 + }
  188 + })
  189 + .height('154lpx')
  190 + .width("100%")
  191 + })
  192 + }
  193 + }
  194 +
  195 +
177 sendEnterEvent(type:number){ 196 sendEnterEvent(type:number){
178 MinePageDatasModel.sendEnterMessageData(type).then((value) => { 197 MinePageDatasModel.sendEnterMessageData(type).then((value) => {
179 - console.log(TAG, "消息已读") 198 + this.msgData.forEach((item) => {
  199 + if (item.title == "预约消息" && type === 2) {
  200 + if(item.unReadCount > 0){
  201 + item.unReadCount = 0
  202 + }
  203 + }else if(item.title == "互动消息" && type === 1){
  204 + if(item.unReadCount > 0){
  205 + item.unReadCount = 0
  206 + }
  207 + }
  208 + })
180 }).catch((err: Error) => { 209 }).catch((err: Error) => {
181 console.log(TAG, JSON.stringify(err)) 210 console.log(TAG, JSON.stringify(err))
182 }) 211 })
@@ -2,6 +2,7 @@ import { LazyDataSource, StringUtils } from 'wdKit/Index'; @@ -2,6 +2,7 @@ import { LazyDataSource, StringUtils } from 'wdKit/Index';
2 import { Remark, SubscribeMessageModel, 2 import { Remark, SubscribeMessageModel,
3 WDMessageCenterMessageType } from '../../../../model/InteractMessageModel'; 3 WDMessageCenterMessageType } from '../../../../model/InteractMessageModel';
4 import MinePageDatasModel from '../../../../model/MinePageDatasModel'; 4 import MinePageDatasModel from '../../../../model/MinePageDatasModel';
  5 +import { CustomPullToRefresh } from '../../../reusable/CustomPullToRefresh';
5 import { CustomTitleUI } from '../../../reusable/CustomTitleUI'; 6 import { CustomTitleUI } from '../../../reusable/CustomTitleUI';
6 import { ListHasNoMoreDataUI } from '../../../reusable/ListHasNoMoreDataUI'; 7 import { ListHasNoMoreDataUI } from '../../../reusable/ListHasNoMoreDataUI';
7 import { EmptyComponent } from '../../../view/EmptyComponent'; 8 import { EmptyComponent } from '../../../view/EmptyComponent';
@@ -17,6 +18,7 @@ export struct SubscribeMessageComponent{ @@ -17,6 +18,7 @@ export struct SubscribeMessageComponent{
17 @State hasMore: boolean = true 18 @State hasMore: boolean = true
18 curPageNum: number = 1; 19 curPageNum: number = 1;
19 @State isGetRequest: boolean = false 20 @State isGetRequest: boolean = false
  21 + private scroller: Scroller = new Scroller();
20 22
21 aboutToAppear() { 23 aboutToAppear() {
22 this.getNewPageData() 24 this.getNewPageData()
@@ -32,33 +34,28 @@ export struct SubscribeMessageComponent{ @@ -32,33 +34,28 @@ export struct SubscribeMessageComponent{
32 .height('100%') 34 .height('100%')
33 .width('100%') 35 .width('100%')
34 } 36 }
35 -  
36 } else { 37 } else {
37 - //刷新控件 TODO  
38 - //List  
39 - List() {  
40 - LazyForEach(this.data, (item: SubscribeMessageModel, index: number) => {  
41 - ListItem() {  
42 - SubscribeListChildComponent({ item: item })  
43 - }.width('100%')  
44 - .onClick(() => {  
45 - })  
46 - })  
47 -  
48 - //没有更多数据 显示提示  
49 - if (!this.hasMore) {  
50 - ListItem() {  
51 - ListHasNoMoreDataUI() 38 + CustomPullToRefresh({
  39 + alldata:this.data,
  40 + scroller:this.scroller,
  41 + customList:()=>{
  42 + this.ListLayout()
  43 + },
  44 + onRefresh:(resolve)=>{
  45 + this.curPageNum = 1;
  46 + this.hasMore = true
  47 + this.isGetRequest = false
  48 + this.data.clear()
  49 + if (!this.isLoading) {
  50 + this.getNewPageData()
  51 + }
  52 + if(resolve) resolve('刷新成功')
  53 + },
  54 + onLoadMore:(resolve)=> {
  55 + if (!this.isLoading) {
  56 + //加载分页数据
  57 + this.getNewPageData()
52 } 58 }
53 - }  
54 - }.width('100%')  
55 - .cachedCount(4)  
56 - .scrollBar(BarState.Off)  
57 - .layoutWeight(1)  
58 - .onReachEnd(() => {  
59 - if (!this.isLoading) {  
60 - //加载分页数据  
61 - this.getNewPageData()  
62 } 59 }
63 }) 60 })
64 } 61 }
@@ -68,6 +65,25 @@ export struct SubscribeMessageComponent{ @@ -68,6 +65,25 @@ export struct SubscribeMessageComponent{
68 .width('100%') 65 .width('100%')
69 } 66 }
70 67
  68 + @Builder ListLayout(){
  69 + List({scroller: this.scroller}) {
  70 + LazyForEach(this.data, (item: SubscribeMessageModel, index: number) => {
  71 + ListItem() {
  72 + SubscribeListChildComponent({ item: item })
  73 + }.width('100%')
  74 + })
  75 + //没有更多数据 显示提示
  76 + if (!this.hasMore) {
  77 + ListItem() {
  78 + ListHasNoMoreDataUI()
  79 + }
  80 + }
  81 + }.width('100%')
  82 + .cachedCount(4)
  83 + .scrollBar(BarState.Off)
  84 + .layoutWeight(1)
  85 + }
  86 +
71 getNewPageData() { 87 getNewPageData() {
72 this.isLoading = true 88 this.isLoading = true
73 if (this.hasMore) { 89 if (this.hasMore) {
@@ -67,16 +67,17 @@ export struct PrivacySettingPage { @@ -67,16 +67,17 @@ export struct PrivacySettingPage {
67 getArrowCell({ item:item, index:index }); 67 getArrowCell({ item:item, index:index });
68 } 68 }
69 }.onClick(() => { 69 }.onClick(() => {
70 - if (index != 0) {  
71 - if (!item.permission) {  
72 - //跳转权限设置  
73 - const permissionUtil = new PermissionUtil();  
74 - PermissionUtil.reqPermissionsFromUser([item.permissionKey], this).then((res)=>{  
75 - item.permission = res;  
76 - });  
77 - }else{  
78 - PermissionUtil.openPermissionsInSystemSettings(this);  
79 - } 70 + if (item.privacyName == DiyString) {
  71 + return
  72 + }
  73 + if (!item.permission) {
  74 + //跳转权限设置
  75 + const permissionUtil = new PermissionUtil();
  76 + PermissionUtil.reqPermissionsFromUser([item.permissionKey], this).then((res)=>{
  77 + item.permission = res;
  78 + });
  79 + }else{
  80 + PermissionUtil.openPermissionsInSystemSettings(this);
80 } 81 }
81 }) 82 })
82 }) 83 })
@@ -49,7 +49,7 @@ export class LiveModel { @@ -49,7 +49,7 @@ export class LiveModel {
49 success(data.data) 49 success(data.data)
50 }, (error: Error) => { 50 }, (error: Error) => {
51 fail(error.message) 51 fail(error.message)
52 - Logger.debug(TAG + ":error ", error.toString()) 52 + Logger.debug(TAG + ":error ", error.message)
53 }) 53 })
54 }) 54 })
55 } 55 }
@@ -64,11 +64,11 @@ export struct TabChatComponent { @@ -64,11 +64,11 @@ export struct TabChatComponent {
64 ListLayout() { 64 ListLayout() {
65 List() { 65 List() {
66 ListItem() { 66 ListItem() {
67 - // 下拉刷新  
68 - RefreshLayout({  
69 - refreshBean: new RefreshLayoutBean(this.pageModel.isVisiblePullDown, this.pageModel.pullDownRefreshImage,  
70 - this.pageModel.pullDownRefreshText, this.pageModel.pullDownRefreshHeight)  
71 - }) 67 + // 下拉刷新 TODO 待对接新的下拉刷新组件
  68 + // RefreshLayout({
  69 + // refreshBean: new RefreshLayoutBean(this.pageModel.isVisiblePullDown, this.pageModel.pullDownRefreshImage,
  70 + // this.pageModel.pullDownRefreshText, this.pageModel.pullDownRefreshHeight)
  71 + // })
72 } 72 }
73 73
74 ForEach(this.liveChatList, (item: LiveRoomItemBean) => { 74 ForEach(this.liveChatList, (item: LiveRoomItemBean) => {
@@ -26,32 +26,57 @@ export struct TabComponent { @@ -26,32 +26,57 @@ export struct TabComponent {
26 } 26 }
27 27
28 build() { 28 build() {
29 - Tabs({ barPosition: BarPosition.Start, index: this.currentIndex, controller: this.controller }) {  
30 - ForEach(this.tabs, (item: string, index: number) => {  
31 - TabContent() {  
32 - if ('简介' === item) {  
33 - TabInfoComponent()  
34 - } else if ('直播间' === item) {  
35 - TabLiveComponent()  
36 - } else if ('大家聊' === item) {  
37 - TabChatComponent() 29 + Stack({alignContent: Alignment.TopStart}) {
  30 + Tabs({ barPosition: BarPosition.Start, index: this.currentIndex, controller: this.controller }) {
  31 + ForEach(this.tabs, (item: string, index: number) => {
  32 + TabContent() {
  33 + if ('简介' === item) {
  34 + TabInfoComponent()
  35 + } else if ('直播间' === item) {
  36 + TabLiveComponent()
  37 + } else if ('大家聊' === item) {
  38 + TabChatComponent()
  39 + }
38 } 40 }
39 - }.tabBar(this.tabBuilder(index, item))  
40 - .backgroundColor('#F5F5F5')  
41 - }, (item: string, index: number) => {  
42 - return item + index 41 + .backgroundColor('#F5F5F5')
  42 + }, (item: string, index: number) => {
  43 + return item + index
  44 + })
  45 + }
  46 + .layoutWeight(1)
  47 + .vertical(false)
  48 + .barMode(BarMode.Fixed)
  49 + .barHeight(48)
  50 + .animationDuration(100)
  51 + .onChange((index: number) => {
  52 + this.currentIndex = index
43 }) 53 })
44 - }  
45 - .layoutWeight(1)  
46 - .vertical(false)  
47 - .barMode(BarMode.Fixed)  
48 - .barWidth(70 * this.tabs.length)  
49 - .barHeight(48)  
50 - .animationDuration(100)  
51 - .onChange((index: number) => {  
52 - this.currentIndex = index  
53 - })  
54 - .backgroundColor(Color.White) 54 + .backgroundColor(Color.White)
  55 +
  56 + // 页签
  57 + Row() {
  58 + Scroll() {
  59 + Row({space: '24vp'}) {
  60 + ForEach(this.tabs, (item: string, index: number) => {
  61 + this.tabBuilder(index, item)
  62 + })
  63 + }
  64 + .width('100%')
  65 + .justifyContent(FlexAlign.Center)
  66 + }
  67 + .backgroundColor(Color.White)
  68 + .align(Alignment.Start)
  69 + .scrollable(ScrollDirection.Horizontal)
  70 + .scrollBar(BarState.Off)
  71 + .width('100%')
  72 + }
  73 + .backgroundColor(Color.White)
  74 + .height('48vp')
  75 + .alignItems(VerticalAlign.Bottom)
  76 + .width('100%')
  77 + }.layoutWeight(1)
  78 +
  79 +
55 } 80 }
56 81
57 @Builder 82 @Builder
@@ -60,7 +85,7 @@ export struct TabComponent { @@ -60,7 +85,7 @@ export struct TabComponent {
60 Text(name) 85 Text(name)
61 .margin({ top: 6 }) 86 .margin({ top: 6 })
62 .fontColor(this.currentIndex === index ? this.selectedFontColor : this.fontColor) 87 .fontColor(this.currentIndex === index ? this.selectedFontColor : this.fontColor)
63 - .fontSize('18fp') 88 + .fontSize('18vp')
64 .fontWeight(this.currentIndex === index ? 600 : 400) 89 .fontWeight(this.currentIndex === index ? 600 : 400)
65 Divider() 90 Divider()
66 .strokeWidth(2) 91 .strokeWidth(2)
@@ -68,7 +93,13 @@ export struct TabComponent { @@ -68,7 +93,13 @@ export struct TabComponent {
68 .width(15) 93 .width(15)
69 .color('#CB0000') 94 .color('#CB0000')
70 .visibility(this.currentIndex === index ? Visibility.Visible : Visibility.Hidden) 95 .visibility(this.currentIndex === index ? Visibility.Visible : Visibility.Hidden)
71 - }.width('100%') 96 + }.justifyContent(FlexAlign.Center)
  97 + .constraintSize({ minWidth: 35 })
  98 + .height('48vp')
  99 + .onClick(() => {
  100 + this.controller.changeIndex(index)
  101 + this.currentIndex = index
  102 + })
72 } 103 }
73 104
74 aboutToDisappear(): void { 105 aboutToDisappear(): void {
@@ -46,11 +46,11 @@ export struct TabLiveComponent { @@ -46,11 +46,11 @@ export struct TabLiveComponent {
46 ListLayout() { 46 ListLayout() {
47 List() { 47 List() {
48 ListItem() { 48 ListItem() {
49 - // 下拉刷新  
50 - RefreshLayout({  
51 - refreshBean: new RefreshLayoutBean(this.pageModel.isVisiblePullDown, this.pageModel.pullDownRefreshImage,  
52 - this.pageModel.pullDownRefreshText, this.pageModel.pullDownRefreshHeight)  
53 - }) 49 + // 下拉刷新 TODO 待对接新的下拉刷新组件
  50 + // RefreshLayout({
  51 + // refreshBean: new RefreshLayoutBean(this.pageModel.isVisiblePullDown, this.pageModel.pullDownRefreshImage,
  52 + // this.pageModel.pullDownRefreshText, this.pageModel.pullDownRefreshHeight)
  53 + // })
54 } 54 }
55 55
56 ForEach(this.liveList, (item: LiveRoomItemBean) => { 56 ForEach(this.liveList, (item: LiveRoomItemBean) => {
@@ -11,3 +11,7 @@ export { PlayerConstants } from "./src/main/ets/constants/PlayerConstants" @@ -11,3 +11,7 @@ export { PlayerConstants } from "./src/main/ets/constants/PlayerConstants"
11 export { SpeedBean } from "./src/main/ets/bean/SpeedBean" 11 export { SpeedBean } from "./src/main/ets/bean/SpeedBean"
12 12
13 export { DateFormatUtil } from "./src/main/ets/utils/DateFormatUtil" 13 export { DateFormatUtil } from "./src/main/ets/utils/DateFormatUtil"
  14 +
  15 +export { WDAliPlayerController } from "./src/main/ets/controller/WDAliPlayerController"
  16 +
  17 +export { WDListPlayerData, WDAliListPlayerController } from "./src/main/ets/controller/WDAliListPlayerController"
@@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
7 "main": "Index.ets", 7 "main": "Index.ets",
8 "version": "1.0.0", 8 "version": "1.0.0",
9 "dependencies": { 9 "dependencies": {
10 - "wdKit": "file:../../commons/wdKit" 10 + "wdKit": "file:../../commons/wdKit",
  11 + "premierlibrary": "file:./libs/premierlibrary.har"
11 } 12 }
12 } 13 }
@@ -5,6 +5,8 @@ export class PlayerConstants { @@ -5,6 +5,8 @@ export class PlayerConstants {
5 static readonly STATUS_START: number = 1; 5 static readonly STATUS_START: number = 1;
6 static readonly STATUS_PAUSE: number = 2; 6 static readonly STATUS_PAUSE: number = 2;
7 static readonly STATUS_STOP: number = 3; 7 static readonly STATUS_STOP: number = 3;
  8 + static readonly STATUS_ERROR: number = 4;
  9 + static readonly STATUS_COMPLETION: number = 5;
8 10
9 static readonly OPERATE_STATE: Array<string> = ['prepared','playing', 'paused', 'completed']; 11 static readonly OPERATE_STATE: Array<string> = ['prepared','playing', 'paused', 'completed'];
10 12
  1 +import { AliPlayerFactory, AliPlayer, InfoBean, UrlSource, ErrorInfo, InfoCode } from 'premierlibrary';
  2 +import {
  3 + idle,
  4 + initalized,
  5 + prepared,
  6 + started,
  7 + paused,
  8 + stopped,
  9 + completion,
  10 + error} from 'premierlibrary/src/main/ets/com/aliyun/player/IPlayer';
  11 +import { AliListPlayer } from 'premierlibrary/src/main/ets/com/aliyun/player/AliListPlayer'
  12 +
  13 +import { initGlobalPlayerSettings, setupPlayerConfig } from '../utils/GlobalSetting';
  14 +import prompt from '@ohos.promptAction';
  15 +import { Logger } from '../utils/Logger';
  16 +import { PlayerConstants, AVPlayerStatus, Events } from '../constants/PlayerConstants';
  17 +
  18 +export interface WDListPlayerData {
  19 + uid: string
  20 + url: string
  21 + surfaceId?: string
  22 +}
  23 +
  24 +/*
  25 +
  26 + * 此播放器为阿里播放器鸿蒙版本封装,可播放单个视频、列表多个视频
  27 + * 列表上下滑场景用:WDAliListPlayerController
  28 + *
  29 + * 阿里文档链接:https://help.aliyun.com/zh/apsara-video-sdk/developer-reference/integrated-hongmeng-harmonyos-next-framework-player-sdk
  30 + */
  31 +@Observed
  32 +export class WDAliListPlayerController {
  33 + private initPromise: Promise<void>;
  34 + private avPlayer?: AliListPlayer;
  35 +
  36 + // 内部播放器状态
  37 + private avPlayerStatus: number = idle
  38 + private duration: number = 0;
  39 + private status: number = PlayerConstants.STATUS_IDLE;
  40 + private loop: boolean = false;
  41 + private url: string = '';
  42 + private surfaceId: string = '';
  43 + private playSpeed: number = 1;
  44 + private seekTime: number = 0;
  45 + private positionY: number = 0;
  46 + private startTime: number = 0
  47 +
  48 + public errorCode?: number
  49 + public errorMesage?: string
  50 +
  51 + public onVideoSizeChange?: (width: number, height: number) => void;
  52 + public onBufferUpdate?: (buffered: number, duration: number) => void;
  53 + public onTimeUpdate?: (position: number, duration: number) => void;
  54 + public onVolumeUpdate?: (volume: number) => void;
  55 +
  56 + // 播放完成,决定是否继续播放回调
  57 + public continue?: () => void;
  58 +
  59 + // 准备完成,决定是否播放回调。如果不实现,则自动播放
  60 + public onCanplay?: () => void;
  61 + public onStatusChange?: (status: number) => void;
  62 + public onFirstFrameDisplay?: () => void
  63 +
  64 + //// ------------ 以下为列表播放器属性
  65 + private playSources: WDListPlayerData[] = []
  66 + private currentPlayRecord?: WDListPlayerData
  67 +
  68 + constructor() {
  69 + Logger.info("初始化")
  70 + initGlobalPlayerSettings()
  71 + this.initPromise = this.createAVPlayer();
  72 + }
  73 +
  74 + /**
  75 + * 创建 videoPlayer对象
  76 + */
  77 + private createAVPlayer(): Promise<void> {
  78 + return new Promise((resolve, reject) => {
  79 + Logger.debug("开始创建")
  80 + let traceId = ''
  81 + this.avPlayer = AliPlayerFactory.createAliListPlayer(getContext(), traceId)
  82 + if (this.avPlayer) {
  83 + Logger.debug("创建完成1")
  84 + setupPlayerConfig(this.avPlayer!)
  85 + this.bindState();
  86 + resolve();
  87 + } else {
  88 + Logger.error("创建完成0")
  89 + Logger.error('[WDPlayerController] createAvPlayer fail!');
  90 + reject();
  91 + }
  92 + });
  93 + }
  94 +
  95 + public destory() {
  96 + Logger.debug("播放器销毁")
  97 + this.avPlayer?.stop()
  98 + this.avPlayer?.release()
  99 + this.playSources = []
  100 + this.currentPlayRecord = undefined
  101 + }
  102 +
  103 + /**
  104 + * AliPlayer 绑定事件.
  105 + */
  106 + private bindState() {
  107 + this.avPlayer?.setOnPreparedListener({
  108 + // 当调用play()方法后,会调用
  109 + onPrepared: () => {
  110 + this.duration = this.avPlayer?.getDuration();
  111 + Logger.debug("已准备好", `${this.duration}`)
  112 + }
  113 + }
  114 + );
  115 + this.avPlayer?.setOnRenderingStartListener({
  116 + onRenderingStart: () => {
  117 + Logger.debug("首帧开始显示")
  118 + if (this.onFirstFrameDisplay) {
  119 + this.onFirstFrameDisplay()
  120 + }
  121 + }
  122 + });
  123 + this.avPlayer?.setOnCompletionListener({
  124 + onCompletion: () => {
  125 + Logger.debug("播放完成")
  126 + }
  127 + });
  128 + this.avPlayer?.setOnInfoListener({
  129 + onInfo: (bean: InfoBean) => {
  130 +
  131 + if (bean.getCode() === InfoCode.CurrentPosition) {
  132 + let position : number = bean.getExtraValue()
  133 + Logger.debug(`播放进度条:${position}/ ${this.duration}`)
  134 + this.initProgress(position);
  135 +
  136 + } else if (bean.getCode() === InfoCode.BufferedPosition) {
  137 + let buffer : number = bean.getExtraValue()
  138 + if (this.onBufferUpdate) {
  139 + this.onBufferUpdate(buffer, this.duration)
  140 + }
  141 +
  142 + } else if (bean.getCode() === InfoCode.SwitchToSoftwareVideoDecoder) {
  143 + Logger.debug(`DOWNGRADE TO SOFTWARE DECODE`)
  144 + // this.mSwitchedToSoftListener?.onSwitched();
  145 + }
  146 + }
  147 + });
  148 + this.avPlayer?.setOnStateChangedListener({
  149 + onStateChanged: (status: number) => {
  150 + this.avPlayerStatus = status
  151 + Logger.debug("status update:" + `${this.getStatusStringWith(status)}`)
  152 +
  153 + switch (status) {
  154 + case initalized: {
  155 + //this.avPlayer?.prepare();
  156 + } break
  157 + case prepared: {
  158 + if (this.startTime) {
  159 + this.setSeekTime(this.startTime, SliderChangeMode.Begin);
  160 + }
  161 + this.duration = this.avPlayer?.getDuration();
  162 + if (this.onVideoSizeChange) {
  163 + this.onVideoSizeChange(this.avPlayer?.getVideoWidth(), this.avPlayer?.getVideoHeight());
  164 + }
  165 + if (this.onCanplay) {
  166 + this.onCanplay()
  167 + } else {
  168 + this.play()
  169 + }
  170 + } break
  171 + case started: {
  172 + this.setBright();
  173 + this.status = PlayerConstants.STATUS_START;
  174 + this.watchStatus();
  175 + } break
  176 + case paused: {
  177 + this.status = PlayerConstants.STATUS_PAUSE;
  178 + this.watchStatus();
  179 + } break
  180 + case stopped: {
  181 + this.status = PlayerConstants.STATUS_STOP;
  182 + this.watchStatus();
  183 + } break
  184 + case completion: {
  185 + this.status = PlayerConstants.STATUS_COMPLETION;
  186 + this.watchStatus();
  187 + if (this.continue) {
  188 + this.continue();
  189 + } else {
  190 + //TODO:
  191 + //this.duration = 0;
  192 + //this.url = this.avPlayer.url || '';
  193 + //this.avPlayer.reset();
  194 + }
  195 + } break
  196 + case error: {
  197 + // 这里拿不到错误信息
  198 + // this.status = PlayerConstants.STATUS_ERROR;
  199 + // this.watchStatus();
  200 + }
  201 + }
  202 + }
  203 + });
  204 + this.avPlayer?.setOnErrorListener({
  205 + onError:(errorInfo) => {
  206 + Logger.error("播放错误", JSON.stringify(errorInfo))
  207 + this.errorCode = errorInfo.getCode()
  208 + this.errorMesage = errorInfo.getMsg()
  209 + this.status = PlayerConstants.STATUS_ERROR;
  210 + this.watchStatus();
  211 + }
  212 + });
  213 + this.avPlayer?.setOnLoadingStatusListener({
  214 + onLoadingBegin: () => {
  215 + // Logger.error("开始加载。。。")
  216 + },
  217 + onLoadingProgress: (percent: number, netSpeed: number) => {
  218 + // this.loadingProgress = percent;
  219 + // this.loadingSpeed = netSpeed;
  220 + },
  221 + onLoadingEnd: () => {
  222 + // Logger.error("结束加载")
  223 + // this.showLoadingScene = false;
  224 + // this.loadingProgress = 0;
  225 + // this.loadingSpeed = 0;
  226 + }
  227 + });
  228 + this.avPlayer?.setOnSeekCompleteListener({
  229 + onSeekComplete: () => {
  230 + this.initProgress(this.avPlayer?.getCurrentPosition());
  231 + }
  232 + })
  233 + }
  234 +
  235 + private getStatusStringWith(status: number) : string {
  236 + switch (status) {
  237 + case idle: return 'idle'
  238 + case initalized: return 'initalized'
  239 + case prepared: return 'prepared'
  240 + case started: return 'started'
  241 + case paused: return 'paused'
  242 + case stopped: return 'stopped'
  243 + case completion: return 'completion'
  244 + case error: return 'error'
  245 + }
  246 + return 'unknow'
  247 + }
  248 +
  249 + public setXComponentController(controller: XComponentController) {
  250 + this.setSurfaceId(controller.getXComponentSurfaceId())
  251 + }
  252 +
  253 + public setSurfaceId(surfaceId: string) {
  254 + this.surfaceId = surfaceId
  255 + }
  256 +
  257 + public async addSources(sources: WDListPlayerData[]) {
  258 + if (this.avPlayer == null) {
  259 + Logger.info("等待播放器初始化")
  260 + await this.initPromise;
  261 + }
  262 + if (this.avPlayer == null) {
  263 + return
  264 + }
  265 +
  266 + /// 追加数据源
  267 + this.playSources.splice(this.playSources.length, 0, ...sources)
  268 + sources.map(data => {
  269 + this.avPlayer?.addUrl(data.url, data.uid)
  270 + })
  271 + }
  272 +
  273 + public moveTo(uid: string, surfaceId: string) {
  274 + let uidDatas = this.playSources.filter(data => data.uid === uid)
  275 + if (uidDatas.length == 0) {
  276 + Logger.info("请先addSources()添加数据源url" + uid)
  277 + return
  278 + }
  279 + this.currentPlayRecord = uidDatas[0]
  280 + this.avPlayer?.setSurfaceId(surfaceId)
  281 +
  282 + // this.setAliPlayerURL(this.currentPlayRecord.url)
  283 +
  284 + let result = this.avPlayer?.moveTo(uid)
  285 + Logger.info("moveTo" + uid + ` result:${result}`)
  286 + this.avPlayer?.prepare()
  287 + }
  288 +
  289 + private setAliPlayerURL(url: string) {
  290 + let urlSource : UrlSource = new UrlSource()
  291 + urlSource.setUri(url)
  292 + this.avPlayer?.setUrlDataSource(urlSource)
  293 + }
  294 +
  295 + private release() {
  296 + if (this.avPlayer == null) {
  297 + return
  298 + }
  299 + this.avPlayer.release()
  300 + this.avPlayer = undefined
  301 + }
  302 +
  303 + public pause() {
  304 + Logger.debug("暂停", this.url)
  305 + this.avPlayer?.pause();
  306 + }
  307 +
  308 + public play() {
  309 + Logger.debug("播放", this.url)
  310 + this.avPlayer?.start();
  311 + }
  312 +
  313 + public stop() {
  314 + Logger.debug("停止", this.url)
  315 + this.avPlayer?.stop();
  316 + }
  317 +
  318 + public setLoop(loop: boolean) {
  319 + this.loop = loop;
  320 + this.avPlayer?.setLoop(loop);
  321 + }
  322 +
  323 + public setMute(mute: boolean) {
  324 + this.avPlayer?.setMute(mute)
  325 + }
  326 +
  327 + public setSpeed(playSpeed: number) {
  328 + this.playSpeed = playSpeed;
  329 + this.avPlayer?.setSpeed(this.playSpeed);
  330 + }
  331 +
  332 + public switchPlayOrPause() {
  333 + if (this.avPlayerStatus == started) {
  334 + this.avPlayer?.pause();
  335 + } else if (this.avPlayerStatus == completion) {
  336 + this.avPlayer?.seekTo(0, 0)
  337 + this.avPlayer?.start()
  338 + } else {
  339 + this.avPlayer?.start();
  340 + }
  341 + }
  342 +
  343 + public setSeekTime(value: number, mode: SliderChangeMode) {
  344 + // if (this.avPlayer == null) {
  345 + // await this.initPromise;
  346 + // }
  347 + // if (this.avPlayer == null) {
  348 + // return
  349 + // }
  350 + // if (mode == SliderChangeMode.Begin) {
  351 + // this.seekTime = value * 1000;
  352 + // this.avPlayer?.seek(this.seekTime, media.SeekMode.SEEK_PREV_SYNC);
  353 + // }
  354 + if (mode === SliderChangeMode.Moving) {
  355 + // this.progressThis.progressVal = value;
  356 + // this.progressThis.currentTime = DateFormatUtil.secondToTime(Math.floor(value * this.duration /
  357 + // 100 / 1000));
  358 + }
  359 + if (mode === SliderChangeMode.End) {
  360 + this.seekTime = Math.floor(value * this.duration / 100);
  361 + this.avPlayer?.seekTo(this.seekTime, 0);
  362 + }
  363 + }
  364 +
  365 + public setBright() {
  366 + // globalThis.windowClass.setWindowBrightness(this.playerThis.bright)
  367 + }
  368 +
  369 + public getStatus() {
  370 + return this.status;
  371 + }
  372 +
  373 + public getPlayer() {
  374 + return this.avPlayer != undefined
  375 + }
  376 +
  377 + initProgress(time: number) {
  378 + if (this.onTimeUpdate) {
  379 + this.onTimeUpdate(time, this.duration);
  380 + }
  381 + }
  382 +
  383 + resetProgress() {
  384 + this.seekTime = 0;
  385 + this.duration = 0;
  386 + }
  387 +
  388 + onVolumeActionStart(event: GestureEvent) {
  389 + this.positionY = event.offsetY;
  390 + }
  391 +
  392 + onBrightActionStart(event: GestureEvent) {
  393 + this.positionY = event.offsetY;
  394 + }
  395 +
  396 + volume: number = 1
  397 +
  398 + onVolumeActionUpdate(event: GestureEvent) {
  399 + if (!this.avPlayer) {
  400 + return
  401 + }
  402 + if (this.avPlayerStatus != prepared &&
  403 + this.avPlayerStatus != started &&
  404 + this.avPlayerStatus != paused &&
  405 + this.avPlayerStatus != completion) {
  406 + return;
  407 + }
  408 + let changeVolume = (event.offsetY - this.positionY) / 300;
  409 + let currentVolume = this.volume - changeVolume;
  410 + if (currentVolume > 1) {
  411 + currentVolume = 1;
  412 + }
  413 + if (currentVolume <= 0) {
  414 + currentVolume = 0;
  415 + }
  416 + this.volume = currentVolume;
  417 + this.avPlayer?.setVolume(this.volume);
  418 + this.positionY = event.offsetY;
  419 + if (this.onVolumeUpdate) {
  420 + this.onVolumeUpdate(this.volume);
  421 + }
  422 + console.log("volume : " + this.volume)
  423 + }
  424 +
  425 + onBrightActionUpdate(event: GestureEvent) {
  426 + // if (!this.playerThis.volumeShow) {
  427 + // this.playerThis.brightShow = true;
  428 + // let changeBright = (this.positionY - event.offsetY) / globalThis.screenHeight;
  429 + // let currentBright = this.playerThis.bright + changeBright;
  430 + // let brightMinFlag = currentBright <= 0;
  431 + // let brightMaxFlag = currentBright > 1;
  432 + // this.playerThis.bright = brightMinFlag ? 0 :
  433 + // (brightMaxFlag ? 1 : currentBright);
  434 + // this.setBright();
  435 + // this.positionY = event.offsetY;
  436 + // }
  437 + }
  438 +
  439 + onActionEnd() {
  440 + setTimeout(() => {
  441 + this.positionY = 0;
  442 + }, 200);
  443 + }
  444 +
  445 + watchStatus() {
  446 + console.log('watchStatus', this.status)
  447 + if (this.onStatusChange) {
  448 + this.onStatusChange(this.status)
  449 + }
  450 + // if (this.status === PlayConstants.STATUS_START) {
  451 + // globalThis.windowClass.setWindowKeepScreenOn(true);
  452 + // } else {
  453 + // globalThis.windowClass.setWindowKeepScreenOn(false);
  454 + // }
  455 + }
  456 +
  457 + playError(msg?: string) {
  458 + prompt.showToast({
  459 + duration: 3000,
  460 + message: msg ? msg : "请检查地址输入正确且网络正常"
  461 + });
  462 + }
  463 +
  464 + setStartTime(time?: number) {
  465 + this.startTime = time ?? 0;
  466 + }
  467 +}
  1 +import { AliPlayerFactory, AliPlayer, InfoBean, UrlSource, ErrorInfo, InfoCode } from 'premierlibrary';
  2 +import {
  3 + idle,
  4 + initalized,
  5 + prepared,
  6 + started,
  7 + paused,
  8 + stopped,
  9 + completion,
  10 + error} from 'premierlibrary/src/main/ets/com/aliyun/player/IPlayer';
  11 +
  12 +import { initGlobalPlayerSettings, setupPlayerConfig } from '../utils/GlobalSetting';
  13 +import prompt from '@ohos.promptAction';
  14 +import { Logger } from '../utils/Logger';
  15 +import { PlayerConstants, AVPlayerStatus, Events } from '../constants/PlayerConstants';
  16 +
  17 +/*
  18 + * 此播放器为阿里播放器鸿蒙版本封装,可播放单个视频、或直播
  19 + * 列表上下滑场景用:WDListPlayerController
  20 + *
  21 + * 阿里文档链接:https://help.aliyun.com/zh/apsara-video-sdk/developer-reference/integrated-hongmeng-harmonyos-next-framework-player-sdk
  22 + */
  23 +@Observed
  24 +export class WDAliPlayerController {
  25 + private initPromise: Promise<void>;
  26 + private avPlayer?: AliPlayer;
  27 +
  28 + // 内部播放器状态
  29 + private avPlayerStatus: number = idle
  30 + private duration: number = 0;
  31 + private status: number = PlayerConstants.STATUS_IDLE;
  32 + private loop: boolean = false;
  33 + private url: string = '';
  34 + private surfaceId: string = '';
  35 + private playSpeed: number = 1;
  36 + private seekTime: number = 0;
  37 + private positionY: number = 0;
  38 + private startTime: number = 0
  39 +
  40 + public errorCode?: number
  41 + public errorMesage?: string
  42 +
  43 + public onVideoSizeChange?: (width: number, height: number) => void;
  44 + public onBufferUpdate?: (buffered: number, duration: number) => void;
  45 + public onTimeUpdate?: (position: number, duration: number) => void;
  46 + public onVolumeUpdate?: (volume: number) => void;
  47 +
  48 + // 播放完成,决定是否继续播放回调
  49 + public continue?: () => void;
  50 +
  51 + // 准备完成,决定是否播放回调。如果不实现,则自动播放
  52 + public onCanplay?: () => void;
  53 + public onStatusChange?: (status: number) => void;
  54 + public onFirstFrameDisplay?: () => void
  55 +
  56 + constructor() {
  57 + Logger.info("初始化")
  58 + initGlobalPlayerSettings()
  59 + this.initPromise = this.createAVPlayer();
  60 + }
  61 +
  62 + /**
  63 + * 创建 videoPlayer对象
  64 + */
  65 + private createAVPlayer(): Promise<void> {
  66 + return new Promise((resolve, reject) => {
  67 + Logger.debug("开始创建")
  68 + let traceId = ''
  69 + this.avPlayer = AliPlayerFactory.createAliPlayer(getContext(), traceId)
  70 + if (this.avPlayer) {
  71 + Logger.debug("创建完成1")
  72 + setupPlayerConfig(this.avPlayer!)
  73 + this.bindState();
  74 + resolve();
  75 + } else {
  76 + Logger.error("创建完成0")
  77 + Logger.error('[WDPlayerController] createAvPlayer fail!');
  78 + reject();
  79 + }
  80 + });
  81 + }
  82 +
  83 + public destory() {
  84 + Logger.debug("播放器销毁")
  85 + this.avPlayer?.stop()
  86 + this.avPlayer?.release()
  87 + }
  88 +
  89 + /**
  90 + * AliPlayer 绑定事件.
  91 + */
  92 + private bindState() {
  93 + this.avPlayer?.setOnPreparedListener({
  94 + // 当调用play()方法后,会调用
  95 + onPrepared: () => {
  96 + this.duration = this.avPlayer?.getDuration();
  97 + Logger.debug("已准备好", `${this.duration}`)
  98 + }
  99 + }
  100 + );
  101 + this.avPlayer?.setOnRenderingStartListener({
  102 + onRenderingStart: () => {
  103 + Logger.debug("首帧开始显示")
  104 + if (this.onFirstFrameDisplay) {
  105 + this.onFirstFrameDisplay()
  106 + }
  107 + }
  108 + });
  109 + this.avPlayer?.setOnCompletionListener({
  110 + onCompletion: () => {
  111 + Logger.debug("播放完成")
  112 + }
  113 + });
  114 + this.avPlayer?.setOnInfoListener({
  115 + onInfo: (bean: InfoBean) => {
  116 +
  117 + if (bean.getCode() === InfoCode.CurrentPosition) {
  118 + let position : number = bean.getExtraValue()
  119 + Logger.debug(`播放进度条:${position}/ ${this.duration}`)
  120 + this.initProgress(position);
  121 +
  122 + } else if (bean.getCode() === InfoCode.BufferedPosition) {
  123 + let buffer : number = bean.getExtraValue()
  124 + if (this.onBufferUpdate) {
  125 + this.onBufferUpdate(buffer, this.duration)
  126 + }
  127 +
  128 + } else if (bean.getCode() === InfoCode.SwitchToSoftwareVideoDecoder) {
  129 + Logger.debug(`DOWNGRADE TO SOFTWARE DECODE`)
  130 + // this.mSwitchedToSoftListener?.onSwitched();
  131 + }
  132 + }
  133 + });
  134 + this.avPlayer?.setOnStateChangedListener({
  135 + onStateChanged: (status: number) => {
  136 + this.avPlayerStatus = status
  137 + Logger.debug("status update:" + `${this.getStatusStringWith(status)}`)
  138 +
  139 + switch (status) {
  140 + case initalized: {
  141 + //this.avPlayer?.prepare();
  142 + } break
  143 + case prepared: {
  144 + if (this.startTime) {
  145 + this.setSeekTime(this.startTime, SliderChangeMode.Begin);
  146 + }
  147 + this.duration = this.avPlayer?.getDuration();
  148 + if (this.onVideoSizeChange) {
  149 + this.onVideoSizeChange(this.avPlayer?.getVideoWidth(), this.avPlayer?.getVideoHeight());
  150 + }
  151 + if (this.onCanplay) {
  152 + this.onCanplay()
  153 + } else {
  154 + this.play()
  155 + }
  156 + } break
  157 + case started: {
  158 + this.setBright();
  159 + this.status = PlayerConstants.STATUS_START;
  160 + this.watchStatus();
  161 + } break
  162 + case paused: {
  163 + this.status = PlayerConstants.STATUS_PAUSE;
  164 + this.watchStatus();
  165 + } break
  166 + case stopped: {
  167 + this.status = PlayerConstants.STATUS_STOP;
  168 + this.watchStatus();
  169 + } break
  170 + case completion: {
  171 + this.status = PlayerConstants.STATUS_COMPLETION;
  172 + this.watchStatus();
  173 + if (this.continue) {
  174 + this.continue();
  175 + } else {
  176 + //TODO:
  177 + //this.duration = 0;
  178 + //this.url = this.avPlayer.url || '';
  179 + //this.avPlayer.reset();
  180 + }
  181 + } break
  182 + case error: {
  183 + // 这里拿不到错误信息
  184 + // this.status = PlayerConstants.STATUS_ERROR;
  185 + // this.watchStatus();
  186 + }
  187 + }
  188 + }
  189 + });
  190 + this.avPlayer?.setOnErrorListener({
  191 + onError:(errorInfo) => {
  192 + Logger.error("播放错误", JSON.stringify(errorInfo))
  193 + this.errorCode = errorInfo.getCode()
  194 + this.errorMesage = errorInfo.getMsg()
  195 + this.status = PlayerConstants.STATUS_ERROR;
  196 + this.watchStatus();
  197 + }
  198 + });
  199 + this.avPlayer?.setOnLoadingStatusListener({
  200 + onLoadingBegin: () => {
  201 + // Logger.error("开始加载。。。")
  202 + },
  203 + onLoadingProgress: (percent: number, netSpeed: number) => {
  204 + // this.loadingProgress = percent;
  205 + // this.loadingSpeed = netSpeed;
  206 + },
  207 + onLoadingEnd: () => {
  208 + // Logger.error("结束加载")
  209 + // this.showLoadingScene = false;
  210 + // this.loadingProgress = 0;
  211 + // this.loadingSpeed = 0;
  212 + }
  213 + });
  214 + this.avPlayer?.setOnSeekCompleteListener({
  215 + onSeekComplete: () => {
  216 + this.initProgress(this.avPlayer?.getCurrentPosition());
  217 + }
  218 + })
  219 + }
  220 +
  221 + private setAliPlayerURL(url: string) {
  222 + let urlSource : UrlSource = new UrlSource()
  223 + urlSource.setUri(url)
  224 + this.avPlayer?.setUrlDataSource(urlSource)
  225 + }
  226 +
  227 + private getStatusStringWith(status: number) : string {
  228 + switch (status) {
  229 + case idle: return 'idle'
  230 + case initalized: return 'initalized'
  231 + case prepared: return 'prepared'
  232 + case started: return 'started'
  233 + case paused: return 'paused'
  234 + case stopped: return 'stopped'
  235 + case completion: return 'completion'
  236 + case error: return 'error'
  237 + }
  238 + return 'unknow'
  239 + }
  240 +
  241 + setXComponentController(controller: XComponentController) {
  242 + this.setSurfaceId(controller.getXComponentSurfaceId())
  243 + }
  244 +
  245 + setSurfaceId(surfaceId: string) {
  246 + this.surfaceId = surfaceId
  247 + }
  248 +
  249 + async firstPlay(url: string) {
  250 + this.url = url;
  251 + if (this.avPlayer == null) {
  252 + Logger.info("等待播放器初始化")
  253 + await this.initPromise;
  254 + } else {
  255 + if (this.avPlayerStatus != idle) {
  256 + this.destory()
  257 + this.initPromise = this.createAVPlayer();
  258 + await this.initPromise;
  259 + }
  260 + }
  261 + if (this.avPlayer == null) {
  262 + return
  263 + }
  264 + this.duration = 0
  265 + this.errorCode = undefined
  266 + this.errorMesage = undefined
  267 + this.avPlayerStatus = idle
  268 + this.status = PlayerConstants.STATUS_IDLE
  269 +
  270 + this.avPlayer?.setAutoPlay(false)
  271 +
  272 + Logger.debug("开始播放", this.url)
  273 + this.setAliPlayerURL(this.url);
  274 +
  275 + Logger.info("设置SurfaceId" + this.surfaceId)
  276 + this.avPlayer?.setSurfaceId(this.surfaceId)
  277 +
  278 + this.avPlayer?.prepare()
  279 + }
  280 +
  281 + release() {
  282 + if (this.avPlayer == null) {
  283 + return
  284 + }
  285 + this.avPlayer.release()
  286 + this.avPlayer = undefined
  287 + }
  288 +
  289 + pause() {
  290 + Logger.debug("暂停", this.url)
  291 + this.avPlayer?.pause();
  292 + }
  293 +
  294 + play() {
  295 + Logger.debug("播放", this.url)
  296 + this.avPlayer?.start();
  297 + }
  298 +
  299 + stop() {
  300 + Logger.debug("停止", this.url)
  301 + this.avPlayer?.stop();
  302 + }
  303 +
  304 + setLoop(loop: boolean) {
  305 + this.loop = loop;
  306 + this.avPlayer?.setLoop(loop);
  307 + }
  308 +
  309 + setMute(mute: boolean) {
  310 + this.avPlayer?.setMute(mute)
  311 + }
  312 +
  313 + setSpeed(playSpeed: number) {
  314 + this.playSpeed = playSpeed;
  315 + this.avPlayer?.setSpeed(this.playSpeed);
  316 + }
  317 +
  318 + switchPlayOrPause() {
  319 + if (this.avPlayerStatus == started) {
  320 + this.avPlayer?.pause();
  321 + } else if (this.avPlayerStatus == completion) {
  322 + this.avPlayer?.seekTo(0, 0)
  323 + this.avPlayer?.start()
  324 + } else {
  325 + this.avPlayer?.start();
  326 + }
  327 + }
  328 +
  329 + setSeekTime(value: number, mode: SliderChangeMode) {
  330 + // if (this.avPlayer == null) {
  331 + // await this.initPromise;
  332 + // }
  333 + // if (this.avPlayer == null) {
  334 + // return
  335 + // }
  336 + // if (mode == SliderChangeMode.Begin) {
  337 + // this.seekTime = value * 1000;
  338 + // this.avPlayer?.seek(this.seekTime, media.SeekMode.SEEK_PREV_SYNC);
  339 + // }
  340 + if (mode === SliderChangeMode.Moving) {
  341 + // this.progressThis.progressVal = value;
  342 + // this.progressThis.currentTime = DateFormatUtil.secondToTime(Math.floor(value * this.duration /
  343 + // 100 / 1000));
  344 + }
  345 + if (mode === SliderChangeMode.End) {
  346 + this.seekTime = Math.floor(value * this.duration / 100);
  347 + this.avPlayer?.seekTo(this.seekTime, 0);
  348 + }
  349 + }
  350 +
  351 + setBright() {
  352 + // globalThis.windowClass.setWindowBrightness(this.playerThis.bright)
  353 + }
  354 +
  355 + getStatus() {
  356 + return this.status;
  357 + }
  358 +
  359 + getPlayer() {
  360 + return this.avPlayer != undefined
  361 + }
  362 +
  363 + initProgress(time: number) {
  364 + if (this.onTimeUpdate) {
  365 + this.onTimeUpdate(time, this.duration);
  366 + }
  367 + }
  368 +
  369 + resetProgress() {
  370 + this.seekTime = 0;
  371 + this.duration = 0;
  372 + }
  373 +
  374 + onVolumeActionStart(event: GestureEvent) {
  375 + this.positionY = event.offsetY;
  376 + }
  377 +
  378 + onBrightActionStart(event: GestureEvent) {
  379 + this.positionY = event.offsetY;
  380 + }
  381 +
  382 + volume: number = 1
  383 +
  384 + onVolumeActionUpdate(event: GestureEvent) {
  385 + if (!this.avPlayer) {
  386 + return
  387 + }
  388 + if (this.avPlayerStatus != prepared &&
  389 + this.avPlayerStatus != started &&
  390 + this.avPlayerStatus != paused &&
  391 + this.avPlayerStatus != completion) {
  392 + return;
  393 + }
  394 + let changeVolume = (event.offsetY - this.positionY) / 300;
  395 + let currentVolume = this.volume - changeVolume;
  396 + if (currentVolume > 1) {
  397 + currentVolume = 1;
  398 + }
  399 + if (currentVolume <= 0) {
  400 + currentVolume = 0;
  401 + }
  402 + this.volume = currentVolume;
  403 + this.avPlayer?.setVolume(this.volume);
  404 + this.positionY = event.offsetY;
  405 + if (this.onVolumeUpdate) {
  406 + this.onVolumeUpdate(this.volume);
  407 + }
  408 + console.log("volume : " + this.volume)
  409 + }
  410 +
  411 + onBrightActionUpdate(event: GestureEvent) {
  412 + // if (!this.playerThis.volumeShow) {
  413 + // this.playerThis.brightShow = true;
  414 + // let changeBright = (this.positionY - event.offsetY) / globalThis.screenHeight;
  415 + // let currentBright = this.playerThis.bright + changeBright;
  416 + // let brightMinFlag = currentBright <= 0;
  417 + // let brightMaxFlag = currentBright > 1;
  418 + // this.playerThis.bright = brightMinFlag ? 0 :
  419 + // (brightMaxFlag ? 1 : currentBright);
  420 + // this.setBright();
  421 + // this.positionY = event.offsetY;
  422 + // }
  423 + }
  424 +
  425 + onActionEnd() {
  426 + setTimeout(() => {
  427 + this.positionY = 0;
  428 + }, 200);
  429 + }
  430 +
  431 + watchStatus() {
  432 + console.log('watchStatus', this.status)
  433 + if (this.onStatusChange) {
  434 + this.onStatusChange(this.status)
  435 + }
  436 + // if (this.status === PlayConstants.STATUS_START) {
  437 + // globalThis.windowClass.setWindowKeepScreenOn(true);
  438 + // } else {
  439 + // globalThis.windowClass.setWindowKeepScreenOn(false);
  440 + // }
  441 + }
  442 +
  443 + playError(msg?: string) {
  444 + prompt.showToast({
  445 + duration: 3000,
  446 + message: msg ? msg : "请检查地址输入正确且网络正常"
  447 + });
  448 + }
  449 +
  450 + setStartTime(time?: number) {
  451 + this.startTime = time ?? 0;
  452 + }
  453 +}
@@ -144,6 +144,10 @@ export class WDPlayerController { @@ -144,6 +144,10 @@ export class WDPlayerController {
144 this.xComponentController = controller 144 this.xComponentController = controller
145 } 145 }
146 146
  147 + setSurfaceId(surfaceId: string) {
  148 + this.surfaceId = surfaceId
  149 + }
  150 +
147 async firstPlay(url: string) { 151 async firstPlay(url: string) {
148 this.url = url; 152 this.url = url;
149 if (this.avPlayer == null) { 153 if (this.avPlayer == null) {
@@ -2,6 +2,7 @@ import componentUtils from '@ohos.arkui.componentUtils'; @@ -2,6 +2,7 @@ import componentUtils from '@ohos.arkui.componentUtils';
2 import { WDPlayerController } from '../controller/WDPlayerController' 2 import { WDPlayerController } from '../controller/WDPlayerController'
3 import { WindowModel } from 'wdKit'; 3 import { WindowModel } from 'wdKit';
4 import { Logger } from '../utils/Logger'; 4 import { Logger } from '../utils/Logger';
  5 +import { enableAliPlayer } from '../utils/GlobalSetting';
5 6
6 class Size { 7 class Size {
7 width: Length = "100%"; 8 width: Length = "100%";
@@ -74,8 +75,9 @@ export struct WDPlayerRenderLiveView { @@ -74,8 +75,9 @@ export struct WDPlayerRenderLiveView {
74 Row() { 75 Row() {
75 // 设置为“surface“类型时XComponent组件可以和其他组件一起进行布局和渲染。 76 // 设置为“surface“类型时XComponent组件可以和其他组件一起进行布局和渲染。
76 XComponent({ 77 XComponent({
77 - id: 'xComponentId',  
78 - type: 'surface', 78 + id: enableAliPlayer ? this.insId : 'xComponentId',
  79 + type: XComponentType.SURFACE,
  80 + libraryname: enableAliPlayer ? "premierlibrary" : undefined,
79 controller: this.xComponentController 81 controller: this.xComponentController
80 }) 82 })
81 .onLoad(async (event) => { 83 .onLoad(async (event) => {
@@ -87,7 +89,11 @@ export struct WDPlayerRenderLiveView { @@ -87,7 +89,11 @@ export struct WDPlayerRenderLiveView {
87 surfaceWidth: 1920, 89 surfaceWidth: 1920,
88 surfaceHeight: 720 90 surfaceHeight: 720
89 }); 91 });
90 - this.playerController?.setXComponentController(this.xComponentController) 92 + if (enableAliPlayer) {
  93 + this.playerController?.setSurfaceId(this.insId)
  94 + } else {
  95 + this.playerController?.setXComponentController(this.xComponentController)
  96 + }
91 if (this.onLoad) { 97 if (this.onLoad) {
92 this.onLoad(event) 98 this.onLoad(event)
93 } 99 }
@@ -2,6 +2,7 @@ import componentUtils from '@ohos.arkui.componentUtils'; @@ -2,6 +2,7 @@ import componentUtils from '@ohos.arkui.componentUtils';
2 import { WDPlayerController } from '../controller/WDPlayerController' 2 import { WDPlayerController } from '../controller/WDPlayerController'
3 import { WindowModel } from 'wdKit'; 3 import { WindowModel } from 'wdKit';
4 import { Logger } from '../utils/Logger'; 4 import { Logger } from '../utils/Logger';
  5 +import { enableAliPlayer } from '../utils/GlobalSetting';
5 6
6 class Size { 7 class Size {
7 width: Length = "100%"; 8 width: Length = "100%";
@@ -73,8 +74,9 @@ export struct WDPlayerRenderVLiveView { @@ -73,8 +74,9 @@ export struct WDPlayerRenderVLiveView {
73 Row() { 74 Row() {
74 // 设置为“surface“类型时XComponent组件可以和其他组件一起进行布局和渲染。 75 // 设置为“surface“类型时XComponent组件可以和其他组件一起进行布局和渲染。
75 XComponent({ 76 XComponent({
76 - id: 'xComponentId',  
77 - type: 'surface', 77 + id: enableAliPlayer ? this.insId : 'xComponentId',
  78 + type: XComponentType.SURFACE,
  79 + libraryname: enableAliPlayer ? "premierlibrary" : undefined,
78 controller: this.xComponentController 80 controller: this.xComponentController
79 }) 81 })
80 .onLoad(async (event) => { 82 .onLoad(async (event) => {
@@ -84,7 +86,11 @@ export struct WDPlayerRenderVLiveView { @@ -84,7 +86,11 @@ export struct WDPlayerRenderVLiveView {
84 surfaceWidth: 1920, 86 surfaceWidth: 1920,
85 surfaceHeight: 1080 87 surfaceHeight: 1080
86 }); 88 });
87 - this.playerController?.setXComponentController(this.xComponentController) 89 + if (enableAliPlayer) {
  90 + this.playerController?.setSurfaceId(this.insId)
  91 + } else {
  92 + this.playerController?.setXComponentController(this.xComponentController)
  93 + }
88 if (this.onLoad) { 94 if (this.onLoad) {
89 this.onLoad(event) 95 this.onLoad(event)
90 } 96 }
@@ -2,6 +2,7 @@ import componentUtils from '@ohos.arkui.componentUtils'; @@ -2,6 +2,7 @@ import componentUtils from '@ohos.arkui.componentUtils';
2 import { WDPlayerController } from '../controller/WDPlayerController' 2 import { WDPlayerController } from '../controller/WDPlayerController'
3 import { WindowModel } from 'wdKit'; 3 import { WindowModel } from 'wdKit';
4 import { Logger } from '../utils/Logger'; 4 import { Logger } from '../utils/Logger';
  5 +import { enableAliPlayer } from '../utils/GlobalSetting';
5 6
6 class Size { 7 class Size {
7 width: Length = "100%"; 8 width: Length = "100%";
@@ -77,6 +78,7 @@ export struct WDPlayerRenderView { @@ -77,6 +78,7 @@ export struct WDPlayerRenderView {
77 XComponent({ 78 XComponent({
78 id: this.insId, 79 id: this.insId,
79 type: XComponentType.SURFACE, 80 type: XComponentType.SURFACE,
  81 + libraryname: enableAliPlayer ? "premierlibrary" : undefined,
80 controller: this.xComponentController 82 controller: this.xComponentController
81 }) 83 })
82 .onLoad(async (event) => { 84 .onLoad(async (event) => {
@@ -85,7 +87,11 @@ export struct WDPlayerRenderView { @@ -85,7 +87,11 @@ export struct WDPlayerRenderView {
85 surfaceWidth: 1920, 87 surfaceWidth: 1920,
86 surfaceHeight: 1080 88 surfaceHeight: 1080
87 }); 89 });
88 - this.playerController?.setXComponentController(this.xComponentController) 90 + if (enableAliPlayer) {
  91 + this.playerController?.setSurfaceId(this.insId)
  92 + } else {
  93 + this.playerController?.setXComponentController(this.xComponentController)
  94 + }
89 if (this.onLoad) { 95 if (this.onLoad) {
90 this.onLoad(event) 96 this.onLoad(event)
91 } 97 }
  1 +import { AliPlayerGlobalSettings, AliPlayer } from 'premierlibrary';
  2 +
  3 +import fs from '@ohos.file.fs';
  4 +import common from '@ohos.app.ability.common';
  5 +import { error } from 'premierlibrary/src/main/ets/com/aliyun/player/IPlayer';
  6 +import { BusinessError } from '@kit.BasicServicesKit';
  7 +
  8 +let currentContext = getContext() as common.UIAbilityContext
  9 +
  10 +export function initGlobalPlayerSettings(context?: common.UIAbilityContext) {
  11 +
  12 + AliPlayerGlobalSettings.setUseHttp2(true);
  13 +
  14 + let filesDir = (context != undefined ? context : currentContext).filesDir;
  15 + let cachePath = filesDir + "/player-cache"
  16 +
  17 + fs.stat(cachePath).catch((error: BusinessError) => {
  18 + if (error.code = 13900002) {
  19 + fs.mkdirSync(cachePath)
  20 + }
  21 + })
  22 +
  23 + AliPlayerGlobalSettings.enableLocalCache(true,1 * 1024, cachePath)
  24 +
  25 + AliPlayerGlobalSettings.setCacheFileClearConfig(3 * 24 * 6, 1024, 300)
  26 +}
  27 +
  28 +export function setupPlayerConfig(player: AliPlayer) {
  29 + let config = player.getConfig()
  30 + if (config) {
  31 + config.mMaxDelayTime = 500
  32 + config.mMaxBufferDuration = 50000
  33 + config.mHighBufferDuration = 3000
  34 + config.mStartBufferDuration = 50
  35 + player.setConfig(config)
  36 + }
  37 +}
  38 +
  39 +/*
  40 + * 开启前注意:
  41 + * 1、配置好包名对应的license文件
  42 + * 2、页面组件播放器控制器使用WDAliPlayerController
  43 + * 3、WDAliListPlayerController 暂时由于SDK问题,不能使用
  44 + * 4、
  45 + * */
  46 +export const enableAliPlayer = false
@@ -9,6 +9,22 @@ @@ -9,6 +9,22 @@
9 "2in1" 9 "2in1"
10 ], 10 ],
11 "deliveryWithInstall": true, 11 "deliveryWithInstall": true,
12 - "pages": "$profile:main_pages" 12 + "pages": "$profile:main_pages",
  13 +
  14 + "metadata": [
  15 + {
  16 + "name": "com.aliyun.alivc_license.licensekey",
  17 + "value": "IoKwpV6clXePXoR4rf67e402d71b34952ac19b24d13ecf8c5"
  18 + },
  19 + {
  20 + "name": "com.aliyun.alivc_license.licensefile",
  21 + "value": "AliVideoCert-com_peopledailychina_hosactivity-20240514172039.crt"
  22 + },
  23 + {
  24 + "name": "com.aliyun.alivc_license.service_env",
  25 +// "value": "PreRelease"
  26 + "value": "Release"
  27 + }
  28 + ]
13 } 29 }
14 } 30 }
@@ -75,7 +75,7 @@ export struct UpgradeTipDialog { @@ -75,7 +75,7 @@ export struct UpgradeTipDialog {
75 Row().width("100%").height(1).backgroundColor("#50E6E6E6") 75 Row().width("100%").height(1).backgroundColor("#50E6E6E6")
76 76
77 Button() { 77 Button() {
78 - Text("立即升级").fontColor(Color.White) 78 + Text("立即更新").fontColor(Color.White)
79 79
80 }.borderRadius(4) 80 }.borderRadius(4)
81 .buttonStyle(ButtonStyleMode.NORMAL) 81 .buttonStyle(ButtonStyleMode.NORMAL)
@@ -41,7 +41,7 @@ @@ -41,7 +41,7 @@
41 "requestPermissions": [ 41 "requestPermissions": [
42 { 42 {
43 "name": "ohos.permission.CAMERA", 43 "name": "ohos.permission.CAMERA",
44 - "reason": "$string:EntryAbility_desc", 44 + "reason": "$string:permission_camera_tip",
45 "usedScene": { 45 "usedScene": {
46 "abilities": [ 46 "abilities": [
47 "FormAbility" 47 "FormAbility"
@@ -51,7 +51,7 @@ @@ -51,7 +51,7 @@
51 }, 51 },
52 { 52 {
53 "name": "ohos.permission.READ_MEDIA", 53 "name": "ohos.permission.READ_MEDIA",
54 - "reason": "$string:EntryAbility_desc", 54 + "reason": "$string:permission_photo_tip",
55 "usedScene": { 55 "usedScene": {
56 "abilities": [ 56 "abilities": [
57 "FormAbility" 57 "FormAbility"
@@ -61,7 +61,7 @@ @@ -61,7 +61,7 @@
61 }, 61 },
62 { 62 {
63 "name": "ohos.permission.WRITE_MEDIA", 63 "name": "ohos.permission.WRITE_MEDIA",
64 - "reason": "$string:EntryAbility_desc", 64 + "reason": "$string:permission_photo_tip",
65 "usedScene": { 65 "usedScene": {
66 "abilities": [ 66 "abilities": [
67 "FormAbility" 67 "FormAbility"
@@ -71,7 +71,7 @@ @@ -71,7 +71,7 @@
71 }, 71 },
72 { 72 {
73 "name": "ohos.permission.APPROXIMATELY_LOCATION", 73 "name": "ohos.permission.APPROXIMATELY_LOCATION",
74 - "reason": "$string:EntryAbility_desc", 74 + "reason": "$string:permission_location_tip",
75 "usedScene": { 75 "usedScene": {
76 "abilities": [ 76 "abilities": [
77 "FormAbility" 77 "FormAbility"
@@ -81,7 +81,7 @@ @@ -81,7 +81,7 @@
81 }, 81 },
82 { 82 {
83 "name": "ohos.permission.MICROPHONE", 83 "name": "ohos.permission.MICROPHONE",
84 - "reason": "$string:EntryAbility_desc", 84 + "reason": "$string:permission_microphone_tip",
85 "usedScene": { 85 "usedScene": {
86 "abilities": [ 86 "abilities": [
87 "FormAbility" 87 "FormAbility"
@@ -13,6 +13,22 @@ @@ -13,6 +13,22 @@
13 "value": "$string:app_name" 13 "value": "$string:app_name"
14 }, 14 },
15 { 15 {
  16 + "name": "permission_photo_tip",
  17 + "value": "开启之后即可用于保存新闻图片到相册、发视频、设置封面、设置头像、缓存图片和视频来展示内容等功能"
  18 + },
  19 + {
  20 + "name": "permission_camera_tip",
  21 + "value": "开启之后即可用于拍摄视频、拍摄头像、扫一扫功能"
  22 + },
  23 + {
  24 + "name": "permission_location_tip",
  25 + "value": "开启之后可为你推荐你可能感兴趣的内容及附近的相关信息,以提升浏览体验。不授权该权限不影响APP正常使用。"
  26 + },
  27 + {
  28 + "name": "permission_microphone_tip",
  29 + "value": "开启之后即可用于收录声音进行拍摄视频、语音搜索、语音评论功能,"
  30 + },
  31 + {
16 "name": "dialog_text_title", 32 "name": "dialog_text_title",
17 "value": "个人隐私保护指引" 33 "value": "个人隐私保护指引"
18 }, 34 },
  1 +-----BEGIN ALI VIDEO CERT-----
  2 +LmlsQS5jaUwAAWRjY2FhYTU1OTAxNzE0NDg2OWJlOGJkNzczZTc5ZjAzM2YwMDhiO
  3 +WY5ODUwNTc5MGY4NDEyOTRiMzNjMmZiYjg1NGUxZThlNjAwNzRmNTgxZTU0MDY2Mj
  4 +RiMGFiM2JkNWVmOTE3ZDE0MDJlNDQ0ZDUwNmExMTc5ZjFlYjYyODQ2MDRiYzdiYjA
  5 +zOTI2ZjYyOTE1OWVjYjY0ZDk1ZDhhN2Q5ZWZlOTRjOTdkMTA0Yzc1MWU5OGEwNGY3
  6 +OTdkOTdiYTAzMWEyMDFlMzc2Mjg0NGI1MTEyYWRkZDQzNTgyZDA2NTJkYTk0MDk1Y
  7 +TIxYjY2NWJmYjY0ZTkwMWQyZGNjNmVjMjY1ODFkYmJjZjBhY2ZmZjFhNDU3NTJjND
  8 +QwNTMzZmJlZDk3YTIzMmMyOWQ4YWVkZDY0YmZhZDc2ZDY1MTRiZGU5MmM3YTdjMGZ
  9 +iYjI3OTNhNjZiMDEzMjBkODgxYzBhMjA1YTExN2Q1YmU3ZTgyMzYyYzI5MDJhZDNk
  10 +MmFiZTcxNTQ5NzI2YzI4NTVjOTc5MWVmZDVjMGU4NDZmMDZlZDhlYTY1MjgzYWUzM
  11 +2JkOTYzOWJiZTkwOGU4ZTBmY2QwNDc1OWQ5N2U3OTk1NDNhMzdkNDQ2YzZlMDJhMj
  12 +BkODI2YTUzZGIzNTNjNWU3MDVjYmJmYzg5ODVjYjRkMWIxAAAB2PGgogBWDSMl+Ev
  13 +CnkTbpe7pVHhLurU6CoTQGJh5nrXIbv7GBXTy0w+1cUK4Eki34SCrotEebFvKf2uV
  14 +47Xun8dLUXn5ysvM5njas1xGSon/NqMvQdXn9JM+JHjkhn9Z/miRkWAIqZwI+3GpY
  15 +8a5rjsI4/NHlgKfdm49NW6q03c8qWO7wnCmeiOZ+llN9tc5yGy65WcUK7L7VNEKNS
  16 +W7UCV95Y2gv6LHW8FVY4q7Dlbwb7neo2NhyGGHn5OiNVv3WWvGSiHIdCCIToDL6jr
  17 +w3c/DcBG03fXwEwKHuGOG5n+HB2IMc7zCZwTv/Z1Zxc8cdvdKxeDCyAFMY7Krz3bw
  18 +bJV90qRaAAAAiQDvtWvOOZ0ln0STiitxvsI9N0c/bfJ7AeLNTHUTzFJxHgUOZrLMh
  19 +gWg3wumH+XUdVsn2EAHBq4HwMn3eNJHGSQ7eRNu3mtfbdZfIbWg/902QPGiVLAfip
  20 +xtjtqg/FVayMq3D5oD141qonHybKWb9PaDsngGV3em/42Dy/bI0hPvOajd5jZRBI+
  21 +8SyLTg+S9P8hBtY/jlrFjp2j1DSigfuIbuXf+cZdGI/OrMQkhij05Dt9gBr9I4w3T
  22 +IuwLRK9M2G7qSOkp4sEHze/TXFvflSsOw19D8xJkK6jr3Q4hSTOHc6yb2r5+aLzFM
  23 +FapnFDSOViWKDrEUebz1AbUESC+oXIAAAGPdmdmhgAAAFgAAAAgZzg1NTBlMTRlOD
  24 +RmNDQ3ZDljZDhiZWUxMmVlNzRhM2EAAAABAAAALAAAAAAAAABAAAAAIGNvbS5wZW9
  25 +wbGVkYWlseWNoaW5hLmhvc2FjdGl2aXR5AAAAAQAAACUAAAACAAAAAAAAAEAAACPx
  26 +AAAB2OnnGAAAAAAACAAAAAEAAAAA
  27 +-----END ALI VIDEO CERT-----
  1 +-----BEGIN ALI VIDEO CERT-----
  2 +LmlsQS5jaUwAAWU1MGY1NWU1Y2U1MzIxMDc5MjQ4ZjUzNGQ2ZjVmZmQ2ZmY1MTFmM
  3 +WMzZTlmZDU4NjUxNmU4YmI0NmMxNzM0MTU1OTBjYzQyY2Y4NGY4Y2U2MGZmYjMzMG
  4 +Q5NTQ1NjFmMGMxNzBjMmUyZGQ5MjYwNjY2YjVlN2Y2YTlhMjZhMzc0YjNhNjExN2N
  5 +lYzRlNGYzMGIxODViMmRlOTVhNzU1Nzg2YzY4MzhkYTY1YWI5NTUzMjQyNjRkN2Q0
  6 +OGE0OTExZjFkYzM5MzllZGQ2YjE2OThkNjJjMGI3ZmUwNDRkOGMwYTI0ZTgzZTRiM
  7 +jUwMTk2MDgwNWFkYzBmMGMwNDU3MDE5ZGI0NDNjYzRiNjc3MjRhMTg5YjAyYmU1YT
  8 +E4NDg1ZWQ4NWRmZDQxYzVkZTUzOTUyNmZiOWNiODNjNTE5MWZhMWE4N2E3YjE3M2I
  9 +xY2I4NzI2YTFiZDFjZjBkZTNlNzM2ZmU3NmFmMjQyOWRlY2FjNTUzYjdhZmFjNDM1
  10 +NTRhNDYwY2RkNWE2NGFmZDg5N2ZmYmVjMWQ3NTc0MDdlOGM2ODBkYzMyYjM1YzU0Z
  11 +Dk1N2MyMTk2YjlmYzEwNjA0YTVmZGQ1Yzg0OTE1N2VkZDNiYjk4OTc4YjZjMGY1OD
  12 +Q4MDY5MjQzMTQzZmMyZDA1ZGJiNTJjMjVhZjMwMWFjYTNkAAAB1u6ksgCgo8C07iY
  13 +q52y6BA6nGYLr+YxZCDTYa0zPm21WZhNlUYE8xR1KKPxoOfhgADCG7FubFonJ5pyD
  14 +2+O7g21xWr3CbYQ1S1D/qWE9pYtIoIUl3USIr8pfRQz2/Lk4TUPO/VzgAWeQrbclC
  15 +wgz50pvVzVAwGjBQfofHlCMO6iIbgSazoopOZSeDfOULs7dPkIOfjeSm1ZMCpytgh
  16 +SKCsd0GwaV+yWn+Uk2DOLafFk2logpRGmQzxcZ/K+vJuedUPHzMSRV8VfXc86wix9
  17 +Tx1sokTb9Xt3wqYgbO/5jn2RhOdBYruFUOrFt3LIp1rKj8XngtwI7Cjr7oBAlEXMf
  18 +Uk2A1s/+AAABZB0FG6sG6bbq5JZuwpbmlC7QuD/rUW5iJavqQwZbylmgDuHTZKe22
  19 +mpbwLrw+3w0j9WAsytGn1C07nnmdjzJGe7oujnqOEgUSId9kkBN898rVMjfMy0ckt
  20 +QgBLtxy6nHvgXLbxUzG4rXHccWAwyTGnEfwNl3FRSuB8jGPewQvrV/HyRKMY7MASv
  21 +EA2uo6NGxLfkz+YrqKjFywqsBmTACkE7kJzL2MoNJ6hfJkKl92Z1+HvpwJEV7EdwN
  22 +Qd7MoB+Jd2gF9YLbnk0h+h+d+aI9tIoM8CksdkHsCLLAONvi7LwwN/RcoytfKts8i
  23 +YQ+b5do3+z/ybD/XZVSPswWmuW1BqEAAAGNchb17gAAAFMAAAAgZ2E3ODYwZGNhMT
  24 +g1NDQ0MTlhNTMzNzBhYTQ4ZGIzZDEAAAABAAAAJwAAAAAAAABAAAAAG2NvbS5hbGl
  25 +5dW4ucGxheWVyLm9ob3NfZGVtbwAAAAEAAAEFAAAAAgAAAAAAAABAAAAj8QAAAZiU
  26 +tdAAAQAAAOgAAAABAAAACAAAABgAAE4hAAABjXIW8ngAAAGYlLXQAAAAAAAAAAAYA
  27 +ABOIgAAAY1yFvJ4AAABmJS10AAAAAAAAAAAGAAATiMAAAGNchbyeAAAAZiUtdAAAA
  28 +AAAAAAABgAAE4kAAABjXIW8ngAAAGYlLXQAAAAAAAAAAAYAABOJQAAAY1yFvJ4AAA
  29 +BmJS10AAAAAAAAAAAGAAATiYAAAGNchbyeAAAAZiUtdAAAAAAAAAAABgAAE4nAAAB
  30 +jXIW8ngAAAGYlLXQAAAAAAAAAAAYAABOhQAAAY1yFvJ4AAABmJS10AAAAAAA
  31 +-----END ALI VIDEO CERT-----