zhenghy

直播结束页面

@@ -172,9 +172,10 @@ export interface LiveDetailsBean { @@ -172,9 +172,10 @@ export interface LiveDetailsBean {
172 export interface LiveInfo { 172 export interface LiveInfo {
173 //直播新闻-直播状态 wait 待开播 running 直播中 end 已结束cancel已取消paused暂停 173 //直播新闻-直播状态 wait 待开播 running 直播中 end 已结束cancel已取消paused暂停
174 liveState: string 174 liveState: string
175 -  
176 //2024-04-12 15:00:00 直播开始时间 175 //2024-04-12 15:00:00 直播开始时间
177 planStartTime: string 176 planStartTime: string
  177 + startTime: string
  178 + endTime: string
178 //直播样式 0-正常模式 , 1-隐藏直播间,2-隐藏大家聊 【人民号发布是竖屏的,为空】 179 //直播样式 0-正常模式 , 1-隐藏直播间,2-隐藏大家聊 【人民号发布是竖屏的,为空】
179 liveStyle: number; 180 liveStyle: number;
180 vlive: Array<Vlive> 181 vlive: Array<Vlive>
@@ -7,5 +7,7 @@ export { PlayError } from './src/main/ets/view/PlayError' @@ -7,5 +7,7 @@ export { PlayError } from './src/main/ets/view/PlayError'
7 7
8 export { devicePLSensorManager } from './src/main/ets/utils/devicePortLandSensor' 8 export { devicePLSensorManager } from './src/main/ets/utils/devicePortLandSensor'
9 9
  10 +export { postInteractAccentionOperateParams } from './src/main/ets/request/ContentDetailRequest'
  11 +
10 12
11 13
@@ -7,6 +7,7 @@ import { PlayerInfoComponent } from '../widgets/vertical/PlayerInfoComponent'; @@ -7,6 +7,7 @@ import { PlayerInfoComponent } from '../widgets/vertical/PlayerInfoComponent';
7 import { WDPlayerController } from 'wdPlayer/Index'; 7 import { WDPlayerController } from 'wdPlayer/Index';
8 import { DisplayDirection } from 'wdConstant/Index'; 8 import { DisplayDirection } from 'wdConstant/Index';
9 import { LiveEmptyComponent, WDLiveViewDefaultType } from 'wdComponent/Index'; 9 import { LiveEmptyComponent, WDLiveViewDefaultType } from 'wdComponent/Index';
  10 +import { PlayerEndView } from '../widgets/vertical/PlayerEndView';
10 11
11 const storage = LocalStorage.getShared(); 12 const storage = LocalStorage.getShared();
12 const TAG = 'DetailPlayVLivePage' 13 const TAG = 'DetailPlayVLivePage'
@@ -29,6 +30,7 @@ export struct DetailPlayVLivePage { @@ -29,6 +30,7 @@ export struct DetailPlayVLivePage {
29 @State contentId: string = '' 30 @State contentId: string = ''
30 @State relType: string = '' 31 @State relType: string = ''
31 @State swiperIndex: number = 1 32 @State swiperIndex: number = 1
  33 + @State imgUrl: string = ''
32 34
33 aboutToAppear(): void { 35 aboutToAppear(): void {
34 console.log(TAG, 'aboutToAppear') 36 console.log(TAG, 'aboutToAppear')
@@ -51,50 +53,52 @@ export struct DetailPlayVLivePage { @@ -51,50 +53,52 @@ export struct DetailPlayVLivePage {
51 } 53 }
52 54
53 build() { 55 build() {
54 - Column() { 56 +
  57 + Stack() {
  58 + Image(this.imgUrl)
  59 + .height('100%')
  60 + .width('100%')
  61 + .blur(100)
  62 + .renderFit(RenderFit.RESIZE_COVER)
55 // 直播结束且无回看 63 // 直播结束且无回看
56 if (this.liveState === 'end' && !this.playUrl) { 64 if (this.liveState === 'end' && !this.playUrl) {
57 - LiveEmptyComponent({  
58 - emptyType: WDLiveViewDefaultType.WDViewDefaultType_NoLiveEnd  
59 - }) 65 + PlayerEndView()
60 } else { 66 } else {
61 - Stack() {  
62 - // 直播暂停,仍然可以评论  
63 - if (this.liveState === 'pause') {  
64 - LiveEmptyComponent({  
65 - emptyType: WDLiveViewDefaultType.WDViewDefaultType_NoLiveSuspend  
66 - })  
67 - } else {  
68 - PlayerComponent({  
69 - playerController: this.playerController  
70 - })  
71 - }  
72 -  
73 - PlayerInfoComponent({  
74 - playerController: this.playerController,  
75 - swiperController: this.swiperController,  
76 - swiperIndex: $swiperIndex 67 + // 直播暂停,仍然可以评论
  68 + if (this.liveState === 'pause') {
  69 + LiveEmptyComponent({
  70 + emptyType: WDLiveViewDefaultType.WDViewDefaultType_NoLiveSuspend
  71 + })
  72 + .height('60%')
  73 + } else {
  74 + PlayerComponent({
  75 + playerController: this.playerController
77 }) 76 })
78 -  
79 - Image($r('app.media.icon_live_more'))  
80 - .width(40)  
81 - .aspectRatio(1)  
82 - .visibility(this.swiperIndex === 0 ? Visibility.Visible : Visibility.Hidden)  
83 - .animation({ duration: 500 })  
84 - .position({ x: '100%', y: '100%' })  
85 - .markAnchor({ x: 56, y: 56 })  
86 - .onClick(() => {  
87 - this.swiperController.showNext()  
88 - })  
89 } 77 }
90 - .height('100%')  
91 - .width('100%') 78 +
  79 + PlayerInfoComponent({
  80 + playerController: this.playerController,
  81 + swiperController: this.swiperController,
  82 + swiperIndex: $swiperIndex
  83 + })
  84 +
  85 + Image($r('app.media.icon_live_more'))
  86 + .width(40)
  87 + .aspectRatio(1)
  88 + .visibility(this.swiperIndex === 0 ? Visibility.Visible : Visibility.Hidden)
  89 + .animation({ duration: 500 })
  90 + .position({ x: '100%', y: '100%' })
  91 + .markAnchor({ x: 56, y: 56 })
  92 + .onClick(() => {
  93 + this.swiperController.showNext()
  94 + })
92 } 95 }
93 96
94 97
95 } 98 }
96 .height('100%') 99 .height('100%')
97 .width('100%') 100 .width('100%')
  101 + .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])
98 } 102 }
99 103
100 getLiveDetails() { 104 getLiveDetails() {
@@ -103,7 +107,11 @@ export struct DetailPlayVLivePage { @@ -103,7 +107,11 @@ export struct DetailPlayVLivePage {
103 (data) => { 107 (data) => {
104 if (data.length > 0) { 108 if (data.length > 0) {
105 this.liveDetailsBean = data[0] 109 this.liveDetailsBean = data[0]
106 - this.liveState = this.liveDetailsBean.liveInfo?.liveState //直播新闻-直播状态 wait待开播running直播中end已结束cancel已取消paused暂停 110 + this.liveState = 'end' // this.liveDetailsBean.liveInfo?.liveState //直播新闻-直播状态 wait待开播running直播中end已结束cancel已取消paused暂停
  111 + if (this.liveDetailsBean.fullColumnImgUrls && this.liveDetailsBean.fullColumnImgUrls.length > 0) {
  112 + this.imgUrl = this.liveDetailsBean.fullColumnImgUrls[0].url
  113 + }
  114 +
107 if (this.liveDetailsBean.liveInfo.liveState == 'end') { 115 if (this.liveDetailsBean.liveInfo.liveState == 'end') {
108 this.playUrl = this.liveDetailsBean.liveInfo.vlive[0].replayUri 116 this.playUrl = this.liveDetailsBean.liveInfo.vlive[0].replayUri
109 } 117 }
@@ -66,12 +66,7 @@ export struct PlayerComponent { @@ -66,12 +66,7 @@ export struct PlayerComponent {
66 build() { 66 build() {
67 Column() { 67 Column() {
68 Stack() { 68 Stack() {
69 - Image(this.imgUrl)  
70 - .height('100%')  
71 - .width('100%')  
72 - .blur(100)  
73 - .renderFit(RenderFit.RESIZE_COVER)  
74 - 69 +
75 // TODO:判断横竖屏,liveStreamType=1竖屏铺满屏幕,裁剪不拉伸,liveStreamType=0横屏正常展示 70 // TODO:判断横竖屏,liveStreamType=1竖屏铺满屏幕,裁剪不拉伸,liveStreamType=0横屏正常展示
76 if (this.liveStreamType == null) { 71 if (this.liveStreamType == null) {
77 WDPlayerRenderVLiveView({ 72 WDPlayerRenderVLiveView({
  1 +import { LiveDetailsBean, LiveRoomDataBean, postBatchAttentionStatusParams, } from 'wdBean/Index'
  2 +import { MultiPictureDetailViewModel } from 'wdComponent/src/main/ets/viewmodel/MultiPictureDetailViewModel'
  3 +import { SpConstants } from 'wdConstant/Index'
  4 +import { ContentDetailRequest, postInteractAccentionOperateParams } from 'wdDetailPlayApi/Index'
  5 +import { NumberFormatterUtils, DateTimeUtils, SPHelper } from 'wdKit/Index'
  6 +import { WDRouterPage, WDRouterRule } from 'wdRouter/Index'
  7 +
  8 +const TAG = 'PlayerEndView'
  9 +
  10 +@Preview
  11 +@Component
  12 +export struct PlayerEndView {
  13 + @Consume liveDetailsBean: LiveDetailsBean
  14 + @Consume liveRoomDataBean: LiveRoomDataBean
  15 + @State duration: string = ''
  16 + @State followStatus: String = '0';
  17 +
  18 + aboutToAppear(): void {
  19 + const sn = DateTimeUtils.parseDate(this.liveDetailsBean.liveInfo.startTime, DateTimeUtils.PATTERN_DATE_TIME_HYPHEN)
  20 + const en = DateTimeUtils.parseDate(this.liveDetailsBean.liveInfo.endTime, DateTimeUtils.PATTERN_DATE_TIME_HYPHEN)
  21 + const sd = DateTimeUtils.getDuration(sn, en)
  22 + this.duration = DateTimeUtils.secondToTime(sd / 1000)
  23 + this.getBatchAttentionStatus()
  24 + }
  25 +
  26 + /**
  27 + * 查询当前登录用户是否关注作品号主
  28 + * */
  29 + async getBatchAttentionStatus() {
  30 + try {
  31 + const params: postBatchAttentionStatusParams = {
  32 + creatorIds: [{ creatorId: this.liveDetailsBean?.rmhInfo?.rmhId ?? '' }]
  33 + }
  34 + let data = await MultiPictureDetailViewModel.getBatchAttentionStatus(params)
  35 + this.followStatus = data[0]?.status;
  36 + console.log(TAG, `followStatus:${JSON.stringify(this.followStatus)}`)
  37 + } catch (exception) {
  38 +
  39 + }
  40 + }
  41 +
  42 + /**
  43 + * 关注号主
  44 + */
  45 + async handleAccention() {
  46 + // 未登录,跳转登录
  47 + const user_id = await SPHelper.default.get(SpConstants.USER_ID, '')
  48 + if (!user_id) {
  49 + WDRouterRule.jumpWithPage(WDRouterPage.loginPage)
  50 + return
  51 + }
  52 + // TODO:直播间没有携带人民号信息
  53 + const params2: postInteractAccentionOperateParams = {
  54 + attentionUserType: this.liveDetailsBean?.rmhInfo?.userType || '', //被关注用户类型(1 普通用户 2 视频号 3 矩阵号)
  55 + attentionUserId: this.liveDetailsBean?.rmhInfo?.userId || '', // 被关注用户号主id
  56 + attentionCreatorId: this.liveDetailsBean?.rmhInfo?.rmhId || '', // 被关注用户号主id
  57 + status: this.followStatus == '0' ? 1 : 0,
  58 + }
  59 +
  60 +
  61 + ContentDetailRequest.postInteractAccentionOperate(params2).then(res => {
  62 + console.log('关注号主==', JSON.stringify(res.data))
  63 + if (this.followStatus == '1') {
  64 + this.followStatus = '0'
  65 + } else {
  66 + this.followStatus = '1'
  67 + }
  68 + }).catch(() => {
  69 + AlertDialog.show({ message: '关注失败' })
  70 + })
  71 + }
  72 +
  73 + build() {
  74 + Column() {
  75 + Text('直播已结束').fontWeight(500)
  76 + .fontSize(20)
  77 + .fontColor(Color.White)
  78 + .padding({ bottom: 40, top: 120 })
  79 +
  80 + Stack() {
  81 + Column() {
  82 + Text(this.liveDetailsBean?.rmhInfo?.rmhName)
  83 + .fontWeight(400)
  84 + .fontSize(18)
  85 + .fontColor(Color.White)
  86 + .padding({ top: 52 })
  87 + Text(this.liveDetailsBean?.rmhInfo?.rmhDesc || '')
  88 + .fontWeight(400)
  89 + .fontSize(13)
  90 + .fontColor('#B2FFFFFF')
  91 + .padding({ top: 8 })
  92 +
  93 + Row() {
  94 + Column() {
  95 + Text(this.duration).fontWeight(600).fontSize(24).fontColor(Color.White)
  96 + Text('时长').fontWeight(400).fontSize(13).fontColor(Color.White)
  97 + }
  98 +
  99 + Text('').width(1).height(32).margin({ left: 36, right: 36 }).backgroundColor('#33FFFFFF')
  100 + Column() {
  101 + Text(NumberFormatterUtils.formatNumberWithWan(this.liveRoomDataBean?.pv || ''))
  102 + .fontWeight(600)
  103 + .fontSize(24)
  104 + .fontColor(Color.White)
  105 + Text('观看人数').fontWeight(400).fontSize(13).fontColor(Color.White)
  106 + }
  107 + }
  108 + .padding({ top: 16 })
  109 +
  110 + Row() {
  111 + Text(this.followStatus == '0' ? '关注' : '已关注')
  112 + .fontWeight(400)
  113 + .fontSize(16)
  114 + .fontColor(Color.White)
  115 + .padding({ top: 8, bottom: 8, left: 122, right: 122 })
  116 + .backgroundColor(this.followStatus == '0' ? '#FFED2800' : Color.Grey)
  117 + .borderRadius(4)
  118 + .onClick(() => {
  119 + this.handleAccention()
  120 + })
  121 + }
  122 + .padding({ top: 24 })
  123 +
  124 + }
  125 + .width(307)
  126 + .height(254)
  127 + .backgroundColor('#999999')
  128 + .borderRadius(4)
  129 +
  130 + Image(this.liveDetailsBean?.fullColumnImgUrls[0]?.url)
  131 + .width(80)
  132 + .height(80)
  133 + .borderRadius(40)
  134 + .borderWidth(1)
  135 + .borderColor(Color.White)
  136 + .borderStyle(BorderStyle.Solid)
  137 + .position({ x: '50%', y: 0 })
  138 + .markAnchor({ x: '50%', y: '50%' })
  139 + }
  140 + .width(307)
  141 + .padding({ top: 40 })
  142 + }
  143 + .height('100%')
  144 +
  145 + }
  146 +}
@@ -44,29 +44,30 @@ export struct PlayerTitleComponent { @@ -44,29 +44,30 @@ export struct PlayerTitleComponent {
44 44
45 } 45 }
46 46
  47 + if (this.liveRoomDataBean.liveId) {
  48 + Row() {
  49 + if (this.liveState == 'running') {
  50 + Image($r('app.media.icon_live_status_running'))
  51 + .width(22)
  52 + .height(18)
  53 + .margin({ right: 1 })
  54 + }
47 55
48 - Row() {  
49 - if (this.liveState == 'running') {  
50 - Image($r('app.media.icon_live_status_running'))  
51 - .width(22)  
52 - .height(18)  
53 - .margin({ right: 1 }) 56 + Text(this.liveState == 'running' ? '直播中' : '回看')
  57 + .fontSize(11)
  58 + .fontWeight(400)
  59 + .fontColor(Color.White)
  60 + Image($r('app.media.icon_live_player_status_end'))
  61 + .width(12)
  62 + .height(12)
  63 + Text(`${NumberFormatterUtils.formatNumberWithWan(this.liveRoomDataBean.pv)}人参与`)
  64 + .fontSize('11fp')
  65 + .fontWeight(400)
  66 + .fontColor(Color.White)
54 } 67 }
55 -  
56 - Text(this.liveState == 'running' ? '直播中' : '回看')  
57 - .fontSize(11)  
58 - .fontWeight(400)  
59 - .fontColor(Color.White)  
60 - Image($r('app.media.icon_live_player_status_end'))  
61 - .width(12)  
62 - .height(12)  
63 - Text(`${NumberFormatterUtils.formatNumberWithWan(this.liveRoomDataBean.pv)}人参与`)  
64 - .fontSize('11fp')  
65 - .fontWeight(400)  
66 - .fontColor(Color.White) 68 + .backgroundColor('#4D000000')
  69 + .borderRadius(2)
  70 + .padding(this.liveState == 'running' ? { left: 0, right: 4, top: 0, bottom: 0 } : 4)
67 } 71 }
68 - .backgroundColor('#4D000000')  
69 - .borderRadius(2)  
70 - .padding(this.liveState == 'running' ? { left: 0, right: 4, top: 0, bottom: 0 } : 4)  
71 } 72 }
72 } 73 }