wangyujian_wd

feat:1)直播详情信息简介页和预约倒计时接口调试

... ... @@ -466,6 +466,20 @@ export class DateTimeUtils {
static getLunar(_date?: string) {
return getLunar(_date)
}
/**
* 获取指定日期的时间戳
* @returns
*/
static getDateTimestamp(date: string): number {
if (StringUtils.isEmpty(date))
return 0
try {
return new Date(date).getTime()
} catch (e) {
return 0
}
}
}
// const dateTimeUtils = new DateTimeUtils()
\ No newline at end of file
... ...
... ... @@ -186,6 +186,11 @@ export class HttpUrlUtils {
*/
static readonly RELATED_SEARCH_CONTENT_DATA_PATH: string = "/api/rmrb-search-api/zh/c/suggestions/";
/**
* 直播详情
*/
static readonly LIVE_DETAILS_PATH: string = "/api/rmrb-bff-display-zh/content/zh/c/content/detail";
/**
* 早晚报列表
* 根据页面id获取页面楼层列表
* https://pdapis.pdnews.cn/api/rmrb-bff-display-zh/display/zh/c/pageInfo?pageId=28927
... ... @@ -555,6 +560,10 @@ export class HttpUrlUtils {
return url
}
static getLiveDetailsUrl() {
let url = HttpUrlUtils._hostUrl + HttpUrlUtils.LIVE_DETAILS_PATH
return url
}
// static getYcgCommonHeaders(): HashMap<string, string> {
// let headers: HashMap<string, string> = new HashMap<string, string>()
... ...
... ... @@ -105,4 +105,6 @@ export { OperDataList } from './src/main/ets/bean/morningevening/OperDataList';
export { ShareInfo } from './src/main/ets/bean/morningevening/ShareInfo';
export { slideShows } from './src/main/ets/bean/morningevening/slideShows';
\ No newline at end of file
export { slideShows } from './src/main/ets/bean/morningevening/slideShows';
export { LiveDetailsBean } from './src/main/ets/bean/live/LiveDetailsBean';
\ No newline at end of file
... ...
export interface LiveDetailsBean {
/**
* {
"code": "0",
"data": [
{
"activityInfos": [],
"appstyle": 2,
"audioList": [],
"authorList": [
{
"authorName": "雷崔捷"
}
],
"bestNoticer": null,
"commentDisplay": 0,
"editorName": "",
"firstFrameImageUri": "",
"fullColumnImgUrls": [
{
"format": null,
"height": null,
"landscape": null,
"size": null,
"url": "https://rmrbcmsonline.peopleapp.com/upload/image/202404/rmrb_71671711971849.png",
"weight": null
}
],
"hasPopUp": null,
"isNewspaper": false,
"itemId": "",
"itemTypeCode": "",
"keyArticle": 0,
"likesStyle": null,
"liveInfo": {
"background": {
"imageUrl": "",
"name": ""
},
"backgroundStyle": null,
"cornerFlag": 0,
"cornerImgUrl": "",
"cornerLinkUrl": "",
"createUserId": "",
"createUserName": "",
"endTime": "2024-04-03 11:08:00",
"handAngleImageUri": "",
"handAngleLink": "",
"handAngleSwitch": false,
"likeEnable": 1,
"likesStyle": "thumb",
"liveExperience": 1,
"liveExperienceTime": 3,
"liveLandScape": "news",
"liveState": "end",
"liveStyle": 0,
"liveWay": 0,
"mlive": {
"barrageShowEnable": false,
"giftEnable": false,
"mliveId": 20000016257,
"roomId": "5381b934-cea8-4338-bd12-5bf70af43e0c"
},
"notice": "",
"openComment": 1,
"padImageUri": "",
"planStartTime": "2024-04-03 05:00:00",
"playbackSwitch": true,
"preCommentFlag": 1,
"previewType": 1,
"previewUrl": "",
"shareSwitch": "",
"startTime": "2024-04-03 05:03:23",
"tplId": 5,
"vlive": [
{
"coverImageUrl": "",
"definition": [],
"liveStreamManagerId": null,
"liveStreamType": 1,
"liveUrl": "https://plwbthird.live.weibo.com/alicdn/5018938748437049.m3u8",
"name": "线路1",
"replayUri": "http://mlive3.video.weibocdn.com/record/alicdn/5018726527666338/index.m3u8",
"serialNum": null,
"shiftEnable": false,
"showPad": false,
"type": "play",
"vliveId": 186728
}
],
"vrType": 0
},
"menuShow": 1,
"newIntroduction": "眼前有山河,心中有家国!每年清明节前夕,宁夏固原市第二中学和固原市弘文中学会组织入学新生,一天之内徒步54公里从学校往返任山河烈士陵园,用这种方式缅怀烈士们,这份坚定与执着已经延续了29年。",
"newLinkObject": null,
"newsBodyTitle": "",
"newsContent": "",
"newsContentBak": "",
"newsDownTitle": "",
"newsId": 20000016229,
"newsLinkUrl": "",
"newsShortTitle": "",
"newsSource": "41",
"newsSourceName": "",
"newsSummary": "",
"newsTags": "",
"newsTitle": "徒步54公里的思政课,坚守29年的薪火传承",
"newsType": 2,
"oldNewsId": "7218507",
"openAudio": 0,
"openComment": null,
"openLikes": null,
"photoList": [],
"popUps": [],
"preCommentFlag": null,
"publishTime": "2024-04-01 19:44:00",
"reLInfo": {
"channelId": 2061,
"relId": "500005272745",
"relObjectId": 2061,
"relType": "1"
},
"readFlag": 0,
"recommendShow": null,
"rmhInfo": null,
"rmhPlatform": 0,
"sceneId": "",
"serials": null,
"shareInfo": {
"shareCoverUrl": "https://rmrbcmsonline.peopleapp.com/upload/image/202404/202404011944259539.png?x-oss-process=image/resize,w_400",
"shareOpen": 1,
"sharePosterCoverUrl": "https://rmrbcmsonline.peopleapp.com/upload/image/202404/rmrb_71671711971849.png?x-oss-process=image/resize,m_fill,h_450,w_800,limit_0/quality,q_90",
"sharePosterOpen": 1,
"shareSummary": "人民日报,有品质的新闻",
"shareTitle": "徒步54公里的思政课,坚守29年的薪火传承",
"shareUrl": "https://people.pdnews.cn/column/20000016229-500005272745"
},
"specialColumnId": null,
"specialColumnName": "",
"subSceneId": "",
"timeline": null,
"topicInfo": null,
"traceId": "",
"traceInfo": "",
"userInfo": null,
"videoInfo": [],
"viewCount": 0,
"visitorComment": 1,
"voteInfo": null
}
],
"message": "Success",
"meta": null,
"requestId": "",
"success": true,
"timestamp": 1712807514322
}
*/
liveInfo: LiveInfo
fullColumnImgUrls: Array<FullColumnImgUrls>
vlive: Array<Vlive>
newsTitle: string
newIntroduction: string
}
export interface LiveInfo {
//直播新闻-直播状态 wait待开播running直播中end已结束cancel已取消paused暂停
liveState: string
//2024-04-12 15:00:00 直播开始时间
planStartTime: string
}
export interface FullColumnImgUrls {
url: string
}
export interface Vlive {
//拉流直播 url
liveUrl: string
//直播回看地址,多路直播录制文件URL
replayUri: string
}
\ No newline at end of file
... ...
... ... @@ -7,6 +7,10 @@
"main": "Index.ets",
"version": "1.0.0",
"dependencies": {
"wdComponent": "file:../../features/wdComponent"
"wdComponent": "file:../../features/wdComponent",
"wdPlayer": "file:../../features/wdPlayer",
"wdNetwork": "file:../../commons/wdNetwork",
"wdKit": "file:../../commons/wdKit",
"wdBean": "file:../../features/wdBean"
}
}
... ...
import { LiveDetailsBean } from 'wdBean/Index';
import { LiveViewModel } from '../viewModel/LiveViewModel';
import { BottomComponent } from '../widgets/details/BottomComponent';
import { TabComponent } from '../widgets/details/TabComponent';
import { TopPlayComponent } from '../widgets/details/video/TopPlayComponet';
@Entry
@Component
export struct DetailPlayLivePage {
TAG: string = 'DetailPlayLivePage';
@State playUrl:string=''
aboutToAppear(): void {
liveViewModel: LiveViewModel = new LiveViewModel()
@Provide liveDetailsBean: LiveDetailsBean = {} as LiveDetailsBean
aboutToAppear(): void {
this.getLiveDetails()
}
build() {
Column() {
TopPlayComponent({playUrl:this.playUrl})
// TopPlayComponent({playUrl:this.playUrl})
TabComponent()
BottomComponent()
}
... ... @@ -22,7 +25,21 @@ export struct DetailPlayLivePage {
}
onPageShow(): void {
this.playUrl='https://rmrbcmsonline.peopleapp.com/upload/rmh/video/mp4/202404/1712667051b573b0f3a7a22375.mp4'
}
getLiveDetails() {
this.liveViewModel.getLiveDetails('20000016333', '500005300349', '1')//2024-04-12 15:00:00
// this.liveViewModel.getLiveDetails('20000016229', '500005272745', '1')//2024-04-03 05:00:00
.then(
(data) => {
if (data.length > 0) {
this.liveDetailsBean = data[0]
}
},
() => {
})
}
aboutToDisappear(): void {
... ...
import HashMap from '@ohos.util.HashMap';
import { HttpUrlUtils, ResponseDTO } from 'wdNetwork';
import { HttpRequest } from 'wdNetwork/src/main/ets/http/HttpRequest';
import { Logger } from 'wdKit';
import { LiveDetailsBean } from 'wdBean/Index';
const TAG = 'LiveModel'
export class LiveModel {
/**
* 直播内容详情
* @param contentId
* @param relId 关系id
* @param relType 关系类型;1.频道关系;2.专题关系;
* @returns
*/
getLiveDetails(contentId: string, relId: string, relType: string) {
let headers: HashMap<string, string> = HttpUrlUtils.getCommonHeaders();
return new Promise<Array<LiveDetailsBean>>((success, fail) => {
HttpRequest.get<ResponseDTO<Array<LiveDetailsBean>>>(
HttpUrlUtils.getLiveDetailsUrl() + `?relId=${relId}&relType=${relType}&contentId=${contentId}`,
headers).then((data: ResponseDTO<Array<LiveDetailsBean>>) => {
if (!data || !data.data) {
fail("数据为空")
return
}
if (data.code != 0) {
fail(data.message)
return
}
success(data.data)
}, (error: Error) => {
fail(error.message)
Logger.debug(TAG + ":error ", error.toString())
})
})
}
}
... ...
import { LiveDetailsBean } from 'wdBean/Index'
import { LiveModel } from './LiveModel'
const TAG = "LiveViewModel"
export class LiveViewModel {
liveModel: LiveModel
constructor() {
this.liveModel = new LiveModel()
}
//直播详情
getLiveDetails(contentId: string, relId: string, relType: string) {
return new Promise<Array<LiveDetailsBean>>((success, fail) => {
this.liveModel.getLiveDetails(contentId, relId, relType).then((data) => {
success(data)
}).catch((message: string) => {
fail(message)
})
})
}
}
\ No newline at end of file
... ...
import font from '@ohos.font'
import { LiveDetailsBean } from 'wdBean/Index'
import { DateTimeUtils, StringUtils } from 'wdKit/Index'
@Component
export struct LiveCountdownComponent {
@Consume @Watch('calculateDataStatus') liveDetailsBean: LiveDetailsBean
textTimerController: TextTimerController = new TextTimerController()
@State format: string = 'HH:mm:ss'
@State month: string = ''
@State day: string = ''
@State hour: string = ''
@State minute: string = ''
@State differenceTimeStamp: number = 0
@State isCountDownStart: boolean = false
aboutToAppear(): void {
//注册字体
... ... @@ -38,7 +47,7 @@ export struct LiveCountdownComponent {
@Builder
showTitle() {
Text('距离直播开始还有')
Text(this.isCountDownStart ? '距离直播开始还有' : '直播开始时间')
.maxLines(2)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.fontSize('14fp')
... ... @@ -49,18 +58,30 @@ export struct LiveCountdownComponent {
@Builder
showCountDown() {
Row() {
this.showTimeStyle('10', true, 0)
this.showTimeStyle('月', false, 3)
this.showTimeStyle('8', true, 3)
this.showTimeStyle('日', false, 3)
this.showTimeStyle('16', true, 10)
this.showTimeStyle(':', true, 0)
this.showTimeStyle('05', true, 0)
Text(this.month)
.showTimeStyleBold()
Text('月')
.showTimeStyleNormal()
.margin({ left: 3 })
Text(this.day)
.showTimeStyleBold()
.margin({ left: 3 })
Text('日')
.showTimeStyleNormal()
.margin({ left: 3 })
Text(this.hour)
.showTimeStyleBold()
.margin({ left: 10 })
Text(':')
.showTimeStyleBold()
Text(this.minute)
.showTimeStyleBold()
}
.margin({ top: 10 })
.visibility(Visibility.None)
.visibility(this.isCountDownStart ? Visibility.None : Visibility.Visible
)
TextTimer({ isCountDown: true, count: 24 * 60 * 60 * 1000 - 1000, controller: this.textTimerController })
TextTimer({ isCountDown: true, count: this.differenceTimeStamp, controller: this.textTimerController })
.format(this.format)
.fontSize('40fp')
.fontWeight(FontWeight.Bold)
... ... @@ -70,6 +91,7 @@ export struct LiveCountdownComponent {
console.info('textTimer notCountDown utc is:' + utc + ', elapsedTime: ' + elapsedTime)
})
.margin({ top: 10 })
.visibility(this.isCountDownStart ? Visibility.Visible : Visibility.None)
}
@Builder
... ... @@ -89,13 +111,37 @@ export struct LiveCountdownComponent {
// .backgroundColor('#CCCCCC')
}
@Builder
showTimeStyle(value: string, isBold: boolean, left: number) {
Text(value)
.fontSize(isBold ? '40fp' : '16fp')
.fontFamily(isBold ? 'BebasNeue_Regular' : '')
.fontWeight(isBold ? FontWeight.Bold : 500)
.fontColor('#222222')
.margin({ left: left })
calculateDataStatus() {
let startTimeStamp: number = DateTimeUtils.getDateTimestamp(this.liveDetailsBean.liveInfo.planStartTime)
let currentTimeStamp: number = DateTimeUtils.getTimeStamp()
let _differenceTimeStampTmp = startTimeStamp - currentTimeStamp
this.isCountDownStart = _differenceTimeStampTmp <= 4 * 60 * 60 * 1000
if (this.isCountDownStart) {
this.differenceTimeStamp = _differenceTimeStampTmp
return
}
//2024-04-01 19:44:00-trim->2024-04-0119:44:00
if (StringUtils.isNotEmpty(this.liveDetailsBean.liveInfo.planStartTime)) {
let playStartTimeTmp = this.liveDetailsBean.liveInfo.planStartTime.trim()
this.month = playStartTimeTmp.substring(5, 7)
this.day = playStartTimeTmp.substring(8, 10)
this.hour = playStartTimeTmp.substring(11, 13)
this.minute = playStartTimeTmp.substring(14, 16)
}
}
}
@Extend(Text)
function showTimeStyleNormal() {
.fontSize('16fp')
.fontWeight(500)
.fontColor('#222222')
}
@Extend(Text)
function showTimeStyleBold() {
.fontSize('40fp')
.fontFamily('BebasNeue_Regular')
.fontWeight(FontWeight.Bold)
.fontColor('#222222')
}
\ No newline at end of file
... ...
import { LiveDetailsBean } from 'wdBean/Index'
import { TabChatComponent } from './TabChatComponent'
import { TabInfoComponent } from './TabInfoComponent'
import { TabLiveComponent } from './TabLiveComponent'
... ...
import { LiveDetailsBean } from 'wdBean/Index'
import { LiveCountdownComponent } from './LiveCountdownComponent'
@Component
export struct TabInfoComponent {
@Consume liveDetailsBean: LiveDetailsBean
aboutToAppear(): void {
}
... ... @@ -23,7 +26,7 @@ export struct TabInfoComponent {
@Builder
showLiveTitle() {
Text('国新办发布会丨介绍防汛抗旱工国新办发布会丨介绍防汛抗旱工作情况国新办发布会丨介绍防汛抗旱工作情况作情况国新办发布会丨介绍防汛抗旱工作情况')
Text(this.liveDetailsBean.newsTitle)
.maxLines(2)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.fontSize('18fp')
... ... @@ -33,7 +36,7 @@ export struct TabInfoComponent {
@Builder
showLiveDetails() {
Text('国务院新闻办公室将于7月25日上午10时举行国务院政策例行吹风会,请应急管理部副部长、水利部副部长王道席和自然资源部、水利部、应急管理部、中国气象局、国家消防救援局有关负责人介绍防汛抗旱工作情况,并答记者问。')
Text(this.liveDetailsBean.newIntroduction)
.maxLines(5)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.fontSize('14fp')
... ...