668 lines
22 KiB
Vue
668 lines
22 KiB
Vue
<template>
|
|
<div ref="videoRoom" class="room-content border-radius-8" v-vdrag :class="zoomActive ? `room-content-big` : 'room-content-small'">
|
|
<div class="room-top flex-row justify-content-between align-items-center">
|
|
<div class="f16 f-weight600 flex-row">
|
|
<div class="mr-8">调解视频画面</div>
|
|
<div class="color-F53F3F" v-if="videoRecordingSts">{{ formattedTime }}</div>
|
|
</div>
|
|
<div class="flex-row">
|
|
<div v-if="remoteUsersViews.length == 1" class="room-top-btn background-color-fff flex-row align-items-center border-radius-4 cursor-pointer mr-8"
|
|
@click="handleClose">
|
|
<span class="mr-4">退出房间</span>
|
|
</div>
|
|
<div class="room-top-btn background-color-fff flex-row align-items-center border-radius-4 cursor-pointer"
|
|
@click="toggleZoom">
|
|
<span class="mr-4">{{ zoomActive ? '缩小' : '放大' }}</span>
|
|
<svg-icon :icon-class="zoomActive ? `zoom-1` : 'zoom-2'" className="tabs-svg" />
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
<div class="room-middle">
|
|
<!-- 本地 -->
|
|
<div class="video-col position-r" :class="personnelNumber <= 4 ? 'w-50' : 'w-33'" v-show="camStatus">
|
|
<div class="video-col-Graphics border-radius-4" id="realTimeVideo0"></div>
|
|
<div class="video-col-name text-center color-fff f12">调解人</div>
|
|
</div>
|
|
<!-- 远端 -->
|
|
<div class="video-col position-r" :class="personnelNumber <= 4 ? 'w-50' : 'w-33'"
|
|
v-for="(item, index) in remoteUsersViews" :key="index">
|
|
<div class="video-col-Graphics border-radius-4" :id="item.id"></div>
|
|
<div class="video-col-btn" v-if="zoomActive">
|
|
<div class="cursor-pointer" v-if="item.microphone" @click="handleOffRemoteAudio(item.userId)">
|
|
<svg-icon class="mb-8" icon-class="sound-off" className="tabs-svg" />
|
|
</div>
|
|
<div class="cursor-pointer" v-if="!item.microphone" @click="handleOnRemoteAudio(item.userId)">
|
|
<svg-icon class="mb-8" icon-class="sound-on" className="tabs-svg" />
|
|
</div>
|
|
<div class="cursor-pointer" @click="handleKickOut(item.userId)"><svg-icon icon-class="remove-room" className="tabs-svg" /></div>
|
|
</div>
|
|
<div class="video-col-name text-center color-fff f12">{{item.name}}</div>
|
|
</div>
|
|
</div>
|
|
<div v-if="zoomActive" class="room-bottom border-radius-8 background-color-fff flex-row justify-content-between align-items-center">
|
|
<div class="flex-row align-items-center cursor-pointer" @click="handleVideoRecording">
|
|
<svg-icon :icon-class="videoRecordingSts ? 'video-recording-2' : 'video-recording-1'" className="tabs-svg" />
|
|
<div class="pl-4 f14" :class="videoRecordingSts ? 'color-F53F3F' : ''">{{ videoRecordingSts ? '结束': '录制' }}</div>
|
|
</div>
|
|
<div class="flex-row align-items-center cursor-pointer" @click="InviteDialog={caseId:caseId,id:eventDialog.id}">
|
|
<svg-icon icon-class="Invite-room" className="tabs-svg" />
|
|
<div class="pl-4 f14">邀请</div>
|
|
</div>
|
|
<div class="flex-row align-items-center cursor-pointer" v-if="micStatus" @click="handleStopLocalAudio">
|
|
<i class="f24 el-icon-microphone color-4E5969"></i>
|
|
<div class="pl-4 f14">关闭语音</div>
|
|
</div>
|
|
<div class="flex-row align-items-center cursor-pointer" v-if="!micStatus" @click="handleStartLocalAudio">
|
|
<i class="f24 el-icon-turn-off-microphone color-4E5969"></i>
|
|
<div class="pl-4 f14">开启语音</div>
|
|
</div>
|
|
<div class="flex-row align-items-center cursor-pointer"
|
|
@click="audioRecordingSts ? handleOffRemoteAudio('') : handleOnRemoteAudio('')">
|
|
<svg-icon icon-class="mute-all" className="tabs-svg" />
|
|
<div class="pl-4 f14">{{audioRecordingSts ? '全部静音' : '全部开启'}}</div>
|
|
</div>
|
|
<div class="room-bottom-btn-finish cursor-pointer border-radius-4 f14 color-fff" @click="handleStopMediate">
|
|
结束调解
|
|
</div>
|
|
</div>
|
|
|
|
<VideoInvitation v-if="InviteDialog" :eventDialog.sync="InviteDialog" />
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import TRTC from 'trtc-sdk-v5';
|
|
import videoTelephone from "@/services/videoTelephone";
|
|
export default {
|
|
components: {
|
|
VideoInvitation: () => import('./VideoInvitation'),//邀请视频
|
|
},
|
|
props: {
|
|
eventDialog: {
|
|
type: Object,
|
|
default: () => {
|
|
return {}
|
|
},
|
|
},
|
|
},
|
|
data() {
|
|
return {
|
|
zoomActive: true,// 布局状态
|
|
|
|
caseId: '',
|
|
arrPersonnel: [],
|
|
roomId: 0,
|
|
sdkAppId: 0,
|
|
userId: '',
|
|
userSig: '',
|
|
cameraId: '',// 本地视频通道
|
|
microphoneId: '',// 本地音频通道
|
|
camStatus: false,// 本地流
|
|
vidStatus: false,// 本地视频状态
|
|
micStatus: false,// 本地音频状态
|
|
|
|
trtc: null,
|
|
personnelNumber: 1,
|
|
remoteUsersViews: [],
|
|
|
|
audioRecordingSts: true, // 全部音频状态
|
|
videoRecordingSts: false, // 录制状态
|
|
startTime: null,
|
|
timerId: null,
|
|
duration: 0, // 记录录制时间(秒)
|
|
|
|
InviteDialog: null, // 邀请
|
|
};
|
|
},
|
|
computed: {
|
|
zoomedStyles() {
|
|
return {
|
|
left: '269px',
|
|
top: '330px'
|
|
};
|
|
},
|
|
defaultTop() {
|
|
const itemsPerRow = 4;
|
|
const rowHeight = 35.5;
|
|
const numberOfRows = Math.ceil(this.personnelNumber / itemsPerRow);
|
|
return `${numberOfRows * rowHeight + 37.5}px`;
|
|
},
|
|
formattedTime() {
|
|
const hours = Math.floor(this.duration / 3600);
|
|
const minutes = Math.floor((this.duration % 3600) / 60);
|
|
const seconds = this.duration % 60;
|
|
return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:${String(Math.floor(seconds)).padStart(2, '0')}`;
|
|
}
|
|
},
|
|
mounted() {
|
|
this.initMedia();
|
|
this.getVideoDetail();
|
|
this.getRoomArgument();
|
|
},
|
|
methods: {
|
|
handleClose() {
|
|
this.handleKickedOut()
|
|
this.$emit('update:eventDialog', null)
|
|
},
|
|
toggleZoom() {
|
|
this.zoomActive = !this.zoomActive;
|
|
|
|
this.$nextTick(() => {
|
|
if (this.$refs.videoRoom) {
|
|
console.log(this.defaultTop, this.personnelNumber, '---this.defaultTop')
|
|
this.$refs.videoRoom.style.left = this.zoomActive ? this.zoomedStyles.left : '157px';
|
|
this.$refs.videoRoom.style.top = this.zoomActive ? this.zoomedStyles.top : this.defaultTop;
|
|
}
|
|
});
|
|
},
|
|
|
|
// 获取详情
|
|
getVideoDetail() {
|
|
videoTelephone.videoDetail({id: this.eventDialog.id}).then((res) => {
|
|
// console.log(res, '---videoDetail')
|
|
this.caseId = res.caseId;
|
|
this.arrPersonnel = [...res.litigants, ...res.members];
|
|
});
|
|
},
|
|
// 获取房间参数
|
|
getRoomArgument() {
|
|
let {roomId, sdkAppId, userId, userSig} = this.eventDialog;
|
|
console.log(roomId, sdkAppId, userId, userSig, '---roomId, sdkAppId, userId, userSig')
|
|
this.roomId = parseInt(roomId, 10);
|
|
this.sdkAppId = parseInt(sdkAppId, 10);
|
|
this.userId = userId;
|
|
this.userSig = userSig;
|
|
console.log(this.roomId, this.sdkAppId, this.userId, this.userSig, '---this.roomId, sdkAppId, userId, userSig')
|
|
this.handleEnterRoom();
|
|
// videoTelephone.getEnterById({id: this.eventDialog.id}).then((res) => {
|
|
// let {roomId, sdkAppId, userId, userSig} = res;
|
|
// this.roomId = roomId;
|
|
// this.sdkAppId = sdkAppId;
|
|
// this.userId = userId;
|
|
// this.userSig = userSig;
|
|
// console.log(res, '---房间参数')
|
|
// this.handleEnterRoom();
|
|
// });
|
|
},
|
|
|
|
// 获取视频、音频权限
|
|
async getDeviceList() {
|
|
let camera = await TRTC.getCameraList();
|
|
let microphone = await TRTC.getMicrophoneList();
|
|
console.log(camera, '---camera')
|
|
console.log(microphone, '---microphone')
|
|
this.cameraId = camera[0].deviceId;
|
|
this.microphoneId = microphone[0].deviceId;
|
|
},
|
|
async initMedia() {
|
|
if (navigator.mediaDevices.getUserMedia) {
|
|
navigator.mediaDevices.getUserMedia({ audio: true, video: true }).then((stream) => {
|
|
console.log('音视频初始化完毕:', stream)
|
|
// stream.getTracks().forEach(track => track.stop());
|
|
this.getDeviceList();
|
|
}).catch(err =>{
|
|
this.$message.error("访问用户媒体设备失败,请重新打开视频通话!");
|
|
console.log('访问用户媒体设备失败:' , err)
|
|
});
|
|
} else {
|
|
this.$message.error("你的浏览器不支持访问用户媒体设备!");
|
|
console.log('你的浏览器不支持访问用户媒体设备')
|
|
}
|
|
},
|
|
// 获取进入房间的参数
|
|
handleEnterRoom() {
|
|
this.enterRoom();
|
|
this.handleStartLocalAudio();
|
|
this.handleStartLocalVideo();
|
|
},
|
|
async enterRoom() {
|
|
this.trtc = TRTC.create();
|
|
try {
|
|
await this.trtc.enterRoom({
|
|
strRoomId: this.roomId.toString(),
|
|
// sdkAppId: parseInt(this.sdkAppId, 10),
|
|
sdkAppId: this.sdkAppId,
|
|
userId: this.userId,
|
|
userSig: this.userSig,
|
|
});
|
|
this.installEventHandlers();
|
|
this.startGetAudioLevel();
|
|
}catch (e) {
|
|
console.log('视频云初始化报错!', e)
|
|
throw e;
|
|
}
|
|
|
|
},
|
|
|
|
// 本地音频
|
|
async handleStartLocalAudio() {
|
|
if (this.micStatus) {
|
|
return;
|
|
}
|
|
try {
|
|
await this.trtc.startLocalAudio({
|
|
option: {
|
|
microphoneId: this.microphoneId,
|
|
},
|
|
});
|
|
this.micStatus = true;
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
},
|
|
async handleStopLocalAudio() {
|
|
if (!this.micStatus) {
|
|
return;
|
|
}
|
|
try {
|
|
await this.trtc.stopLocalAudio();
|
|
this.micStatus = false;
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
},
|
|
// 本地视频
|
|
async handleStartLocalVideo() {
|
|
if (this.vidStatus) {
|
|
return;
|
|
}
|
|
try {
|
|
await this.trtc.startLocalVideo({
|
|
view: 'realTimeVideo0',
|
|
option: {
|
|
cameraId: this.cameraId,
|
|
profile: '1080p',
|
|
},
|
|
});
|
|
this.camStatus = true;
|
|
this.vidStatus = true;
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
},
|
|
async handleStopLocalVideo() {
|
|
if (!this.vidStatus) {
|
|
return;
|
|
}
|
|
try {
|
|
await this.trtc.stopLocalVideo();
|
|
this.vidStatus = false;
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
},
|
|
// 退出房间-结束调解
|
|
async exitRoom() {
|
|
this.stopGetAudioLevel();
|
|
try {
|
|
await this.trtc.exitRoom();
|
|
this.micStatus = false;
|
|
this.personnelNumber = 1;
|
|
this.remoteUsersViews = [];
|
|
this.uninstallEventHandlers();
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
await this.trtc.stopLocalAudio();// 停止本地麦克风的采集及发布
|
|
await this.trtc.stopLocalVideo();// 停止本地摄像头的采集、预览及发布
|
|
this.trtc = null;
|
|
// await this.trtc.stopScreenShare();// 停止屏幕分享
|
|
},
|
|
|
|
// 音量
|
|
startGetAudioLevel() {
|
|
this.trtc.on(TRTC.EVENT.AUDIO_VOLUME, (event) => {
|
|
event.result.forEach(({ userId, volume }) => {
|
|
const isMe = userId === '';
|
|
if (isMe) {
|
|
console.log(`my volume: ${volume}`);
|
|
} else {
|
|
console.log(`user: ${userId} volume: ${volume}`);
|
|
}
|
|
});
|
|
});
|
|
this.trtc.enableAudioVolumeEvaluation(2000);
|
|
},
|
|
stopGetAudioLevel() {
|
|
this.trtc && this.trtc.enableAudioVolumeEvaluation(-1); // 开启或关闭音量大小回调
|
|
},
|
|
|
|
installEventHandlers() {
|
|
this.trtc.on(TRTC.EVENT.KICKED_OUT, this.handleKickedOut);
|
|
this.trtc.on(TRTC.EVENT.REMOTE_VIDEO_AVAILABLE, this.handleRemoteVideoAvailable);
|
|
this.trtc.on(TRTC.EVENT.REMOTE_VIDEO_UNAVAILABLE, this.handleRemoteVideoUnavailable);
|
|
this.trtc.on(TRTC.EVENT.CUSTOM_MESSAGE, this.handleCustomMessage);
|
|
},
|
|
uninstallEventHandlers() {
|
|
this.trtc.off(TRTC.EVENT.KICKED_OUT, this.handleKickedOut);
|
|
this.trtc.off(TRTC.EVENT.REMOTE_VIDEO_AVAILABLE, this.handleRemoteVideoAvailable);
|
|
this.trtc.off(TRTC.EVENT.REMOTE_VIDEO_UNAVAILABLE, this.handleRemoteVideoUnavailable);
|
|
this.trtc.off(TRTC.EVENT.CUSTOM_MESSAGE, this.handleCustomMessage);
|
|
},
|
|
|
|
// 退出房间
|
|
async handleKickedOut(event) {
|
|
// this.trtc = null;
|
|
await this.exitRoom();
|
|
},
|
|
// 远端进入房间
|
|
handleRemoteVideoAvailable(event) {
|
|
console.log(event, '---event远端进入房间')
|
|
const { userId, streamType } = event;
|
|
try {
|
|
let obj = this.arrPersonnel.find(item => item.phone === userId)
|
|
let data = {
|
|
id: `${userId}_main`,
|
|
name: obj.name,
|
|
userId: userId,
|
|
microphone: true
|
|
}
|
|
|
|
this.personnelNumber++;
|
|
this.remoteUsersViews.push(data);
|
|
this.$nextTick(async () => {
|
|
await this.trtc.startRemoteVideo({ userId, streamType, view: `${userId}_main` });
|
|
});
|
|
} catch (error) {
|
|
console.log(error)
|
|
}
|
|
},
|
|
// 远端退出房间
|
|
handleRemoteVideoUnavailable(event) {
|
|
console.log(event, '---event远端退出房间')
|
|
const { streamType } = event;
|
|
this.trtc.stopRemoteVideo({ userId: event.userId, streamType });
|
|
if (this.personnelNumber>1){this.personnelNumber--;}
|
|
this.remoteUsersViews = this.remoteUsersViews.filter(item => item.userId !== event.userId);
|
|
},
|
|
// 接收远端消息
|
|
handleCustomMessage(event) {
|
|
console.log(`---收到 ${event.userId} 的 sei message: ${event.data}`)
|
|
},
|
|
|
|
// 关闭远端声音
|
|
async handleOffRemoteAudio(userId) {
|
|
console.log(userId, '---关闭远端声音')
|
|
try {
|
|
if (!userId){
|
|
this.audioRecordingSts = false;
|
|
this.remoteUsersViews = this.remoteUsersViews.map(item => {
|
|
item.microphone = false;
|
|
return {
|
|
...item,
|
|
microphone: false
|
|
}
|
|
})
|
|
}else {
|
|
this.remoteUsersViews = this.remoteUsersViews.map(item => {
|
|
if (item.userId == userId){
|
|
item.microphone = false;
|
|
return {
|
|
...item,
|
|
microphone: false
|
|
}
|
|
}
|
|
})
|
|
}
|
|
let json = {behavior: 'offAudio', userId: userId}
|
|
let data = {
|
|
destination: `/topic/video-room/${this.eventDialog.roomId}`,
|
|
body: JSON.stringify(json)
|
|
}
|
|
this.$stompSocket.publish(data)
|
|
|
|
// let jsonString = JSON.stringify({behavior: 'offAudio', userId: userId});
|
|
// let encoder = new TextEncoder();
|
|
// let encoded = encoder.encode(jsonString).buffer;
|
|
// console.log(encoded, '---关闭远端声音')
|
|
// let decoder = new TextDecoder();
|
|
// let decodedString = decoder.decode(encoded);
|
|
// let parsedObj = JSON.parse(decodedString);
|
|
// console.log(parsedObj, '---解析关闭远端声音');
|
|
// await this.trtc.sendCustomMessage({
|
|
// cmdId: 1,
|
|
// data: encoded
|
|
// });
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
},
|
|
// 开启远端声音
|
|
async handleOnRemoteAudio(userId) {
|
|
console.log(userId, '---开启远端声音')
|
|
try {
|
|
if (!userId){
|
|
this.audioRecordingSts = true;
|
|
this.remoteUsersViews = this.remoteUsersViews.map(item => {
|
|
item.microphone = true;
|
|
return {
|
|
...item,
|
|
microphone: true
|
|
}
|
|
})
|
|
}else {
|
|
this.remoteUsersViews = this.remoteUsersViews.map(item => {
|
|
if (item.userId == userId){
|
|
item.microphone = true;
|
|
return {
|
|
...item,
|
|
microphone: true
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
let json = {behavior: 'onAudio', userId: userId}
|
|
let data = {
|
|
destination: `/topic/video-room/${this.eventDialog.roomId}`,
|
|
body: JSON.stringify(json)
|
|
}
|
|
this.$stompSocket.publish(data)
|
|
// let jsonString = JSON.stringify({behavior: 'onAudio', userId: userId});
|
|
// let encoder = new TextEncoder();
|
|
// let encoded = encoder.encode(jsonString).buffer;
|
|
// await this.trtc.sendCustomMessage({
|
|
// cmdId: 2,
|
|
// data: encoded
|
|
// });
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
},
|
|
// 踢出远端用户
|
|
async handleKickOut(userId) {
|
|
console.log(userId, '---踢出远端用户')
|
|
try {
|
|
let json = {behavior: 'kickOut', userId: userId}
|
|
let data = {
|
|
destination: `/topic/video-room/${this.eventDialog.roomId}`,
|
|
body: JSON.stringify(json)
|
|
}
|
|
this.$stompSocket.publish(data)
|
|
// let jsonString = JSON.stringify({behavior: 'kickOut', userId: userId});
|
|
// let encoder = new TextEncoder();
|
|
// let encoded = encoder.encode(jsonString).buffer;
|
|
// await this.trtc.sendCustomMessage({
|
|
// cmdId: 3,
|
|
// data: encoded
|
|
// });
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
},
|
|
|
|
// 录制
|
|
updateTimerDisplay() {
|
|
if (!this.startTime) return;
|
|
const currentTime = performance.now();
|
|
this.duration = Math.floor((currentTime - this.startTime) / 1000); // 将毫秒转换为秒
|
|
},
|
|
handleVideoRecording(){
|
|
if (this.videoRecordingSts){
|
|
// clearInterval(this.timerId);
|
|
// this.timerId = null;
|
|
// this.videoRecordingSts = false;
|
|
// return
|
|
videoTelephone.stopRecord({id: this.eventDialog.id}).then((res) => {
|
|
console.log('---视频已停止录制')
|
|
clearInterval(this.timerId);
|
|
this.timerId = null;
|
|
this.videoRecordingSts = false;
|
|
});
|
|
}else {
|
|
// this.startTime = performance.now();
|
|
// this.updateTimerDisplay(); // 立即更新一次显示
|
|
// this.timerId = setInterval(() => this.updateTimerDisplay(), 1000); // 每秒更新一次
|
|
// this.videoRecordingSts = true;
|
|
// return
|
|
videoTelephone.startRecord({id: this.eventDialog.id}).then((res) => {
|
|
console.log('---视频已开始录制')
|
|
this.startTime = performance.now();
|
|
this.updateTimerDisplay(); // 立即更新一次显示
|
|
this.timerId = setInterval(() => this.updateTimerDisplay(), 1000); // 每秒更新一次
|
|
this.videoRecordingSts = true;
|
|
});
|
|
}
|
|
},
|
|
// 停止调解
|
|
handleStopMediate() {
|
|
this.$confirm("请确定是否结束调解?", "提示", {
|
|
confirmButtonText: "确定",
|
|
cancelButtonText: "取消",
|
|
type: "warning",
|
|
}).then(() => {
|
|
if(!this.$clickThrottle()) { return }//防止重复点击
|
|
let data = {id:this.eventDialog.id}
|
|
// if (this.videoRecordingSts){
|
|
// this.handleVideoRecording();
|
|
// } // 结束录制
|
|
videoTelephone.stopMediate(data).then((res) => {
|
|
this.handleClose();
|
|
this.$parent.visiblePopover = null
|
|
});
|
|
}).catch(() => {});
|
|
}
|
|
},
|
|
beforeDestroy() {
|
|
if (this.timerId) {
|
|
clearInterval(this.timerId);
|
|
}
|
|
if (this.trtc){
|
|
this.handleKickedOut();
|
|
}
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
.room-content{
|
|
background: linear-gradient(180deg, #F8E8FF 0%, #E7EAFE 100%);
|
|
border: 2px solid #FFFFFF;
|
|
top: 50%;
|
|
left: 50%;
|
|
position: absolute;
|
|
margin: 0 !important;
|
|
transform: translate(-50%, -50%);
|
|
user-select: none;
|
|
.room-top{
|
|
.room-top-btn{
|
|
padding: 6px 10px;
|
|
.tabs-svg{
|
|
width: 16px;
|
|
height: 16px;
|
|
}
|
|
}
|
|
}
|
|
.room-middle{
|
|
display: flex;
|
|
flex-wrap: wrap; /* 当子元素总宽度超过父容器时,子元素会自动换到下一行 */
|
|
|
|
.video-col{
|
|
aspect-ratio: 1 / 1; /* 宽度与高度的比例为1:1 */
|
|
//flex: 0 0 auto; /* 禁用子元素的伸缩性 */
|
|
.video-col-Graphics{
|
|
width: 100%;
|
|
height: 100%;
|
|
//background-color: #FFFFFF;
|
|
}
|
|
.video-col-btn{
|
|
position: absolute;
|
|
top: 11px;
|
|
right: 10px;
|
|
.tabs-svg{
|
|
width: 24px;
|
|
height: 24px;
|
|
}
|
|
}
|
|
.video-col-name{
|
|
position: absolute;
|
|
bottom: 0;
|
|
width: 100%;
|
|
height: 21px;
|
|
background-color: #00000059;
|
|
border-radius: 0 0 4px 4px;
|
|
}
|
|
}
|
|
}
|
|
.room-bottom{
|
|
position: absolute;
|
|
left: 24px;
|
|
bottom: 24px;
|
|
padding: 8px 16px;
|
|
width: calc(100% - 45px);
|
|
.tabs-svg{
|
|
width: 24px;
|
|
height: 24px;
|
|
}
|
|
.room-bottom-btn-finish{
|
|
background-color: #F53F3F;
|
|
padding: 10px 16px;
|
|
}
|
|
}
|
|
}
|
|
|
|
.room-content-big{
|
|
padding: 24px;
|
|
width: 536px;
|
|
height: 658px;
|
|
//left: calc(50% - 268px);
|
|
//bottom: 86px;
|
|
|
|
.room-middle{
|
|
padding: 16px 0;
|
|
width: 488px;
|
|
//height: 488px;
|
|
gap: 8px; /* 子元素之间的间隔 */
|
|
.w-100{
|
|
width: calc(100%);
|
|
//height: calc(100%);
|
|
}
|
|
.w-50{
|
|
width: calc(50% - 4px);
|
|
//height: calc(50% - 4px);
|
|
}
|
|
.w-33{
|
|
width: calc(33% - 5px);
|
|
//height: calc(33% - 5px);
|
|
}
|
|
}
|
|
}
|
|
|
|
.room-content-small{
|
|
padding: 12px 16px;
|
|
//width: 300px;
|
|
min-height: 140px;
|
|
//top: 0;
|
|
//left: 0;
|
|
.room-middle{
|
|
padding: 8px 0;
|
|
width: 272px;
|
|
gap: 4px; /* 子元素之间的间隔 */
|
|
.video-col{
|
|
width: 65px;
|
|
}
|
|
}
|
|
}
|
|
</style> |