xugenyuan

ref |> 处理直播上墙、回复消息、封禁、解封、预显控制、弹幕开关、结束直播、显示垫片控制

... ... @@ -46,6 +46,14 @@ export interface LiveRoomItemBean {
senderUserId?: string
// 未登录的设备id
deviceId?: string
// data字段,评论预显开关
data?: string
// receiver
receiverText?: string
receiverTime?: string
receiverUserId?: string
receiverUserName?: string
receiverAvatarUrl?: string
// 自定义字段
customFormIM?: boolean // 默认来自网络接口
... ...
... ... @@ -73,7 +73,7 @@ export struct LiveOperRowListView {
private isLlive = false
/// comment
@State showCommentInput: boolean = false
private banComment: boolean = true // 是否已禁言
@Consume banComment: boolean // 上层可以直播IM控制
private commentInputDialogController?: CustomDialogController
@State publishCommentModel: publishCommentModel = new publishCommentModel()
... ...
... ... @@ -13,6 +13,7 @@ import { TrackConstants, TrackingContent, TrackParamConvert } from 'wdTracking/I
import { onlyWifiLoadVideo } from 'wdComponent/src/main/ets/utils/lazyloadImg';
import { LiveDetailChatRoomController } from '../im/LiveDetailChatRoomController';
import { LiveMessageOptType, LiveMessageRoomType } from 'wdBean/src/main/ets/bean/live/LiveRoomBean';
import { LiveDetailPageLogic } from '../viewModel/LiveDetailPageLogic';
let TAG: string = 'DetailPlayLivePage';
... ... @@ -41,9 +42,13 @@ export struct DetailPlayLivePage {
// 尽量不要动属性。用来作为输入了评论之后,值传递
@State lastInputedLiveComment: LiveRoomItemBean = {} as LiveRoomItemBean // 上次输入的直播间消息
@State lastInputedChatComment: LiveRoomItemBean = {} as LiveRoomItemBean // 上次输入的大家聊消息
@State lastLiveControl: LiveRoomItemBean = {} as LiveRoomItemBean // IM 控制消息
// 顶部状态栏高度
@Consume topSafeHeight: number
chatRoomController: LiveDetailChatRoomController = new LiveDetailChatRoomController()
@Provide banComment: boolean = true
@State isEnd: boolean = false
@Consume liveDetailPageLogic: LiveDetailPageLogic
@State toastText: ResourceStr = "这是一个非Wi-Fi环境。请注意流量消耗"
dialogToast: CustomDialogController = new CustomDialogController({
... ... @@ -106,8 +111,49 @@ export struct DetailPlayLivePage {
}
}
this.chatRoomController.onLiveMessage = (liveRoomItemBean: LiveRoomItemBean) => {
if (liveRoomItemBean.optionType == LiveMessageOptType.ZH_ROOM_NUMBER_MSG) {
switch (liveRoomItemBean.optionType) {
case LiveMessageOptType.ZH_ROOM_NUMBER_MSG: {
this.liveRoomDataBean.pv = Number(liveRoomItemBean.pv)
} break
case LiveMessageOptType.ZH_BARRAGE_SWITCH_MSG: {
const openComment = liveRoomItemBean.data == "1"
this.contentDetailData.liveInfo.openComment = openComment ? 1 : 0
} break
case LiveMessageOptType.ZH_PRE_DISPLAY_CHANGE: {
const preCommentFlag = liveRoomItemBean.data == "1"
this.contentDetailData.liveInfo.preCommentFlag = preCommentFlag ? 1 : 0
} break
case LiveMessageOptType.ZH_BARRAGE_BAN_MESSAGE:
case LiveMessageOptType.ZH_BARRAGE_UNBAN_MESSAGE: {
const banComment = liveRoomItemBean.data == "1"
this.banComment = banComment
} break
case LiveMessageOptType.ZH_STOP_LIVE:
case LiveMessageOptType.ZH_START_LIVE:
case LiveMessageOptType.ZH_CHANGE_PAD: { // 直播垫片控制
this.lastLiveControl = liveRoomItemBean
} break
case LiveMessageOptType.ZH_REPLY_MSG: {
this.lastInputedChatComment = liveRoomItemBean
} break
case LiveMessageOptType.ZH_UPDATE_MSG: {
this.lastInputedLiveComment = liveRoomItemBean
} break
case LiveMessageOptType.ZH_DELETE_MSG: {
this.lastInputedLiveComment = liveRoomItemBean
} break
case LiveMessageOptType.ZH_TOP_MSG: {
this.lastInputedLiveComment = liveRoomItemBean
} break
case LiveMessageOptType.ZH_UN_TOP_MSG: {
this.lastInputedLiveComment = liveRoomItemBean
} break
case LiveMessageOptType.ZH_WALL_MSG: {
this.lastInputedLiveComment = liveRoomItemBean
} break
default: {
Logger.warn(TAG, "暂未处理类型:" + liveRoomItemBean.optionType)
} break
}
}
this.chatRoomController.configDetail(this.contentDetailData)
... ... @@ -115,7 +161,7 @@ export struct DetailPlayLivePage {
build() {
Column() {
TopPlayComponent({ playerController: this.playerController })
TopPlayComponent({ playerController: this.playerController, isEnd: this.isEnd, lastLiveControl: this.lastLiveControl })
.height(this.displayDirection == DisplayDirection.VERTICAL ? 211 : '100%')
.margin({
top: this.displayDirection == DisplayDirection.VERTICAL ? px2vp(this.topSafeHeight) : 0
... ...
import { ContentDetailDTO, LiveRoomDataBean, LiveRoomItemBean } from 'wdBean/Index';
import { LiveViewModel } from '../viewModel/LiveViewModel';
import { CustomToast, WindowModel } from 'wdKit/Index';
import { CustomToast, Logger, WindowModel } from 'wdKit/Index';
import { PlayerComponent } from '../widgets/vertical/PlayerComponent';
import { PlayerInfoComponent } from '../widgets/vertical/PlayerInfoComponent';
import { WDAliPlayerController } from 'wdPlayer/Index';
... ... @@ -13,6 +13,7 @@ import { onlyWifiLoadVideo } from 'wdComponent/src/main/ets/utils/lazyloadImg';
import { StringUtils } from 'wdKit';
import { LiveDetailChatRoomController } from '../im/LiveDetailChatRoomController';
import { LiveMessageOptType } from 'wdBean/src/main/ets/bean/live/LiveRoomBean';
import { JSON } from '@kit.ArkTS';
const storage = LocalStorage.getShared();
const TAG = 'DetailPlayVLivePage'
... ... @@ -47,6 +48,7 @@ export struct DetailPlayVLivePage {
@State isCanplay: boolean = false
@State toastText: ResourceStr = "这是一个非Wi-Fi环境。请注意流量消耗"
chatRoomController: LiveDetailChatRoomController = new LiveDetailChatRoomController()
@Provide banComment: boolean = true
dialogToast: CustomDialogController = new CustomDialogController({
builder: CustomToast({
... ... @@ -103,8 +105,35 @@ export struct DetailPlayVLivePage {
this.lastInputedComment = liveRoomItemBean
}
this.chatRoomController.onLiveMessage = (liveRoomItemBean: LiveRoomItemBean) => {
if (liveRoomItemBean.optionType == LiveMessageOptType.ZH_ROOM_NUMBER_MSG) {
switch (liveRoomItemBean.optionType) {
case LiveMessageOptType.ZH_ROOM_NUMBER_MSG: {
this.liveRoomDataBean.pv = Number(liveRoomItemBean.pv)
} break
case LiveMessageOptType.ZH_BARRAGE_SWITCH_MSG: {
const openComment = liveRoomItemBean.data == "1"
this.contentDetailData.liveInfo.openComment = openComment ? 1 : 0
} break
case LiveMessageOptType.ZH_PRE_DISPLAY_CHANGE: {
const preCommentFlag = liveRoomItemBean.data == "1"
this.contentDetailData.liveInfo.preCommentFlag = preCommentFlag ? 1 : 0
} break
case LiveMessageOptType.ZH_BARRAGE_BAN_MESSAGE:
case LiveMessageOptType.ZH_BARRAGE_UNBAN_MESSAGE: {
const banComment = liveRoomItemBean.data == "1"
this.banComment = banComment
} break
case LiveMessageOptType.ZH_STOP_LIVE: {
this.liveState = "end"
this.contentDetailData.liveInfo.liveState = "end"
} break
case LiveMessageOptType.ZH_CHANGE_PAD: {
const padObj = JSON.parse(liveRoomItemBean.data ?? "") as Record<string, string | number | boolean>
const showPad = padObj["showPad"] == "1"
this.liveDetailPageLogic.showPad = showPad
} break
default: {
Logger.warn(TAG, "暂未处理类型:" + liveRoomItemBean.optionType)
} break
}
}
this.chatRoomController.configDetail(this.contentDetailData)
... ... @@ -135,7 +164,7 @@ export struct DetailPlayVLivePage {
// 有垫片
if (this.liveDetailPageLogic.padImageUri.length > 0) {
// 配置了垫片资源
Image(this.liveDetailPageLogic.padImageUri).objectFit(ImageFit.Fill).width('100%').height('100%')
Image(this.liveDetailPageLogic.padImageUri).objectFit(ImageFit.Contain).width('100%').height('100%')
} else {
// 没有配置垫片资源
... ...
... ... @@ -220,4 +220,15 @@ export class LiveViewModel {
return false
}
isMySelfComment(comment: LiveRoomItemBean) {
let mySelf = false
const userId = HttpUtils.getUserId()
const deviceId = HttpUtils.getDeviceId()
if (comment.senderUserId && comment.senderUserId == userId) {
mySelf = true
} else if (comment.deviceId && comment.deviceId == deviceId) {
mySelf = true
}
return mySelf
}
}
... ...
... ... @@ -3,7 +3,7 @@ import { Logger, StringUtils } from 'wdKit/Index'
// import { Action, LiveRoomItemBean, Params, PhotoListBean } from 'wdBean/Index'
import { WDRouterRule } from 'wdRouter'
import { ExtraDTO } from 'wdBean/src/main/ets/bean/component/extra/ExtraDTO'
import { LiveMessageOptType } from 'wdBean/src/main/ets/bean/live/LiveRoomBean'
import { LiveMessageOptType, LiveMessageRole } from 'wdBean/src/main/ets/bean/live/LiveRoomBean'
const TAG = "TabChatItemComponent"
... ... @@ -23,20 +23,7 @@ export struct TabChatItemComponent {
.width(24)
.height(24)
Column() {
Row() {
Text() {
Span((this.item.senderUserName ?? "游客") + ': ')
.fontColor('#666666')
Span(this.item.text)
.fontColor('#222222')
}
.margin({ left: 8 })
.lineHeight(20)
.layoutWeight(1)
.fontSize('14fp')
.fontWeight(400)
}
.alignItems(VerticalAlign.Top)
this.messageContentText()
if (this.item.pictureUrls && this.item.pictureUrls.length > 0) {
Image(this.item.pictureUrls[0])
... ... @@ -68,6 +55,47 @@ export struct TabChatItemComponent {
}
@Builder messageContentText() {
Row() {
Text() {
if (this.item.receiverUserName && this.item.receiverUserName.length > 0) {
/// 回复的消息处理
Span((this.item.senderUserName ?? "游客") + " ").fontColor('#2696FF')
if (this.item.role == LiveMessageRole.host) {
Span(' 主持人 ')
.fontSize(11)
.lineHeight(20)
.textBackgroundStyle({ color: "#70FFC63F", radius: 2 })
Span(' ')
}
if (this.item.role == LiveMessageRole.guest) {
Span(' 嘉宾 ')
.fontSize(11)
.lineHeight(20)
.textBackgroundStyle({ color: "#70FFC63F", radius: 2 })
Span(' ')
}
Span("回复了 ").fontColor('#222222')
Span((this.item.receiverUserName ?? "游客") + ': ').fontColor('#666666')
Span(this.item.text).fontColor('#222222')
} else {
// 普通消息
Span((this.item.senderUserName ?? "游客") + ': ').fontColor('#666666')
Span(this.item.text).fontColor('#222222')
}
}
.margin({ left: 8 })
.lineHeight(20)
.layoutWeight(1)
.fontSize('14fp')
.fontWeight(400)
}
.alignItems(VerticalAlign.Top)
}
/**
* 大图列表页
* @param content
... ...
... ... @@ -35,6 +35,24 @@ export struct TabLiveComponent {
lastInputedCommentChanged(info: string) {
Logger.debug(TAG, "1显示评论》》》: " + JSON.stringify(this.lastInputedComment))
switch (this.lastInputedComment.optionType) {
case LiveMessageOptType.ZH_UPDATE_MSG: {
} break
case LiveMessageOptType.ZH_DELETE_MSG: {
} break
case LiveMessageOptType.ZH_TOP_MSG: {
} break
case LiveMessageOptType.ZH_UN_TOP_MSG: {
} break
case LiveMessageOptType.ZH_WALL_MSG: {
} break
}
if (this.liveList.totalCount() === 0) {
this.liveList.push(this.liveViewModel.deepCopyLiveRoomItem(this.lastInputedComment))
} else {
... ...
import { Action, LiveRoomItemBean, Params, PhotoListBean } from 'wdBean/Index'
import { ExtraDTO } from 'wdBean/src/main/ets/bean/component/extra/ExtraDTO'
import { LiveMessageOptType } from 'wdBean/src/main/ets/bean/live/LiveRoomBean'
import { LiveMessageOptType, LiveMessageRole } from 'wdBean/src/main/ets/bean/live/LiveRoomBean'
import { AudioRowComponent } from 'wdComponent/Index'
import { DateTimeUtils, StringUtils } from 'wdKit/Index'
import { WDRouterRule } from 'wdRouter/Index'
... ... @@ -155,6 +155,11 @@ export struct TabLiveItemComponent {
this.gotoVideoPlayPage()
})
}
// 上墙或回复消息
else if (this.item.receiverUserName && this.item.receiverUserName.length > 0) {
this.wallOrReplySubMessage()
}
}
.margin({
left: 8,
... ... @@ -234,4 +239,64 @@ export struct TabLiveItemComponent {
}
return 1
}
// 上墙子消息
@Builder wallOrReplySubMessage() {
Row() {
Image(StringUtils.isEmpty(this.item.receiverAvatarUrl) ? $r('app.media.default_head') : this.item.receiverAvatarUrl)
.borderRadius(90)
.width(24)
.height(24)
Column() {
Row() {
Text() {
Span((this.item.receiverUserName ?? "游客") + ': ').fontColor('#666666')
}.lineHeight(20).fontSize('14fp').fontWeight(400)
if (this.item.isWall == 1) {
Blank().layoutWeight(1)
Text() {
Span(' 上墙 ')
.foregroundColor("#CB0000")
.fontSize(11)
.lineHeight(20)
.textBackgroundStyle({ color: "#70FFC63F", radius: 2 })
}.lineHeight(20).fontSize('14fp').fontWeight(400)
}
}
.alignItems(VerticalAlign.Top)
Text() {
Span(this.item.receiverText ?? "").fontColor('#222222')
}
.margin({top: 8})
.lineHeight(20)
.fontSize('14fp')
.fontWeight(400)
if (this.item.pictureUrls && this.item.pictureUrls.length > 0) {
Image(this.item.pictureUrls[0])
.width(this.item.customizeExpression === 1 ? 72 : `100%`)
.objectFit(ImageFit.Contain)
.borderRadius(4)
.margin({
top: 10, bottom: 4
})
.onClick(() => {
this.gotoMultipleListImagePage(0)
})
}
}
.margin({
left: 8,
right: 8
})
.layoutWeight(1)
.alignItems(HorizontalAlign.Start)
}
.alignItems(VerticalAlign.Top)
.padding({ top: 15 })
}
}
\ No newline at end of file
... ...
import { ContentDetailDTO } from 'wdBean/Index';
import { ContentDetailDTO, LiveRoomItemBean } from 'wdBean/Index';
import { Logger, StringUtils } from 'wdKit/Index';
import { PlayerConstants, WDAliPlayerController, WDPlayerRenderLiveView } from 'wdPlayer/Index';
import { PlayUIComponent } from './PlayUIComponent';
... ... @@ -6,6 +6,7 @@ import { PictureLoading } from '../../vertical/PictureLoading';
import { TrackConstants } from 'wdTracking/Index';
import { LiveDetailPageLogic } from '../../../viewModel/LiveDetailPageLogic';
import { LiveEmptyComponent, WDLiveViewDefaultType } from 'wdComponent/Index';
import { LiveMessageOptType } from 'wdBean/src/main/ets/bean/live/LiveRoomBean';
const TAG: string = 'TopPlayComponent'
... ... @@ -23,7 +24,7 @@ export struct TopPlayComponent {
//未开始
@State isWait: boolean = false
//已结束直播
@State isEnd: boolean = false
@Link isEnd: boolean
//播放错误
@State isPlayerError: boolean = false
// loading 控制字段
... ... @@ -38,6 +39,7 @@ export struct TopPlayComponent {
@Consume @Watch('pageShowChange') pageShow: number
@Consume @Watch('pageHideChange') pageHide: number
init: boolean = false
@Prop @Watch("liveIMControlMessageChange") lastLiveControl: LiveRoomItemBean = {} as LiveRoomItemBean // IM 控制消息
pageShowChange() {
this.playerController?.play()
... ... @@ -166,6 +168,27 @@ export struct TopPlayComponent {
// `---0------>` + this.isWait + ' ->' + this.isHideLoading + ' ->' + this.isEnd + ' -->' + this.isVideoSource)
}
liveIMControlMessageChange() {
switch (this.lastLiveControl.optionType) {
case LiveMessageOptType.ZH_STOP_LIVE: {
this.liveDetailPageLogic.showPad = false
this.contentDetailData.liveInfo.liveState = "end"
this.isEnd = true
}
break
case LiveMessageOptType.ZH_START_LIVE: {
// TODO:
}
break
case LiveMessageOptType.ZH_CHANGE_PAD: { // 直播垫片控制
const padObj = JSON.parse(this.lastLiveControl.data ?? "") as Record<string, string | number | boolean>
const showPad = padObj["showPad"] == "1"
this.liveDetailPageLogic.showPad = showPad
}
break
}
}
tryToPlay() {
if (!this.xComponentIsLoaded) {
... ...