123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801 |
- <template>
- <div id="detailInfo">
- <el-row>
- <el-col :span="24" class="info">
- <el-col :span="4" class="left">
- <el-col :span="24" class="leftTop">
- <el-image :src="roomdetail.filedir"></el-image>
- <p>{{ roomdetail.title }}</p>
- <p>{{ roomdetail.content }}</p>
- </el-col>
- <el-col :span="24" class="leftDown">
- <el-col :span="8" class="btn" @click.native="shexiangBtn()">
- <i class="iconfont iconshexiangtou"></i>
- <p>摄像头</p>
- </el-col>
- <el-col :span="8" class="btn" @click.native="tianchongBtn()">
- <i class="iconfont iconmaikefeng-tianchong"></i>
- <p>麦克风</p>
- </el-col>
- <el-col :span="8" class="btn" @click.native="chatBtn()">
- <i class="el-icon-user"></i>
- <p>聊天</p>
- </el-col>
- </el-col>
- <el-col :span="24" class="leftDown">
- <el-col :span="8" class="btn" @click.native="lookuserBtn()">
- <i class="el-icon-user"></i>
- <p>成员</p>
- </el-col>
- <el-col :span="8" class="btn" @click.native="queBtn()">
- <i class="el-icon-question"></i>
- <p>问卷</p>
- </el-col>
- <el-col :span="8" class="btn" @click.native="queCloseBtn()">
- <i class="el-icon-circle-close"></i>
- <p>停卷</p>
- </el-col>
- </el-col>
- </el-col>
- <el-col :span="20" class="right">
- <el-col :span="24" class="rightTop">
- <span @click="liveon"><i class="iconfont iconshexiangtou"></i>直播</span>
- <span v-show="zjrshow" @click="livezhuchi"><i class="iconfont iconshexiangtou"></i>主持</span>
- <span @click="liveclose"><i class="el-icon-switch-button"></i>关闭直播</span>
- <span @click="shareon"><i class="iconfont iconfenxiang"></i>屏幕</span>
- <span @click="shareclose"><i class="iconfont iconfenxiang"></i>关闭分享</span>
- <span><el-switch @change="recordclick" v-model="isrecord" active-text="录制" inactive-text="停录"> </el-switch></span>
- <span @click="dismissroomClick"><i class="iconfont iconfenxiang"></i>解散房间</span>
- </el-col>
- <el-col :span="2" class="noVideo"> </el-col>
- <el-col :span="20" class="video">
- <el-col :span="24" class="videoMeet">
- <el-col :span="18" class="one">
- <div id="main-video" class="video-box col-div" style="justify-content: flex-end"></div>
- </el-col>
- <el-col :span="6" class="two">
- <el-col v-show="zjrshow" :span="24" class="twoOne" v-for="(item, index) in zjrList" :key="index">
- <el-col :span="14">
- <div :id="forOtherId(item.zjrid)" class="video-box col-div othevideo" style="justify-content: flex-end"></div>
- </el-col>
- <el-col :span="10">
- <p>
- <span>{{ item.zjrname }}</span>
- <span>
- <el-button type="danger" size="mini" @click="zjrChange(item.zjrid)">主讲</el-button>
- </span>
- </p>
- </el-col>
- </el-col>
- </el-col>
- </el-col>
- </el-col>
- <el-col :span="2" class="noVideo"></el-col>
- <el-col :span="24" class="rightDown">
- <!-- 开始直播 -->
- </el-col>
- </el-col>
- </el-col>
- </el-row>
- <el-dialog title="摄像头" :visible.sync="shexiangDia" width="30%" :before-close="handleClose">
- <el-select @change="cameraChange" v-model="cameraId" filterable placeholder="请选择摄像头">
- <el-option v-for="item in cameras" :key="item.deviceId" :label="item.label" :value="item.deviceId"> </el-option>
- </el-select>
- </el-dialog>
- <el-dialog title="麦克风" :visible.sync="tianchongDia" width="30%" :before-close="handleClose">
- <el-select @change="micrChange" v-model="microphoneId" filterable placeholder="请选择麦克风">
- <el-option v-for="item in microphones" :key="item.deviceId" :label="item.label" :value="item.deviceId"> </el-option>
- </el-select>
- </el-dialog>
- <el-dialog title="讨论" :visible.sync="chatDia" width="50%" :before-close="handleClose">
- <el-row>
- <el-col :span="24" class="chatList">
- <el-col :span="24" class="list" v-for="(item, index) in dataList" :key="index">
- <p>
- <span :class="item.sendname == user.name ? 'selfColor' : ''">{{ item.sendname }}</span>
- <span>{{ item.content }}</span>
- </p>
- </el-col>
- </el-col>
- <el-col :span="24" class="chatInput">
- <el-col :span="19" class="input">
- <el-input type="textarea" maxlength="5000" show-word-limit v-model="content"></el-input>
- </el-col>
- <el-col :span="5" class="btn">
- <el-button type="primary" size="mini" @click="chatCreate">发送</el-button>
- </el-col>
- </el-col>
- </el-row>
- </el-dialog>
- <el-dialog title="问卷" :visible.sync="queDia" width="38%" :before-close="handleClose">
- <el-row>
- <el-col :span="24">
- <el-col :span="12">
- <el-select v-model="queid" filterable placeholder="请选择问卷">
- <el-option v-for="item in questList" :key="item.id" :label="item.name" :value="item.id"> </el-option>
- </el-select>
- </el-col>
- <el-col :span="12" class="btn">
- <el-button type="primary" size="mini" @click="queCreate">发送</el-button>
- </el-col>
- </el-col>
- </el-row>
- </el-dialog>
- <el-dialog title="成员" :visible.sync="lookuserDia" width="60%" height="450px" :before-close="handleClose" :close-on-click-modal="(clo = false)">
- <el-row>
- <el-col :span="24" class="sudoku_row">
- <el-col :span="24" class="sudoku_item" v-for="(item, index) in userList" :key="index">
- <div :id="forId(item.userid)" class="video-box col-div lookvideo" style="justify-content: flex-end"></div>
- <p>
- <i class="el-icon-user"></i>
- <span class="selfColor">{{ item.username }}({{ item.isonline === '1' ? '在线' : '离线' }})</span>
- <span v-if="item.switchrole === 'anchor'">
- <el-button type="danger" size="mini" @click="lookuserUpdate(item.id, 'audience')">移除</el-button>
- <el-button type="primary" size="mini" @click="roomshangmai(item.userid)">主讲</el-button>
- </span>
- <span v-else><el-button type="primary" size="mini" @click="lookuserUpdate(item.id, 'anchor')">连麦</el-button></span>
- </p>
- </el-col>
- </el-col>
- </el-row>
- </el-dialog>
- </div>
- </template>
- <script>
- import Vue from 'vue';
- import { mapState, createNamespacedHelpers } from 'vuex';
- const { mapActions: gensign } = createNamespacedHelpers('gensign');
- const { mapActions: chat } = createNamespacedHelpers('chat');
- const { mapActions: room } = createNamespacedHelpers('room');
- const { mapActions: lookuser } = createNamespacedHelpers('lookuser');
- const { mapActions: roomuser } = createNamespacedHelpers('roomuser');
- import TRTC from 'trtc-js-sdk';
- export default {
- name: 'detailInfo',
- props: {
- roomInfo: null,
- },
- components: {},
- data: function() {
- return {
- // 摄像头
- shexiangDia: false,
- cameraId: '',
- cameras: [],
- // 麦克风
- tianchongDia: false,
- chatDia: false,
- queDia: false,
- questList: [],
- queid: '',
- microphoneId: '',
- microphones: [],
- client_: '',
- localStream_: '',
- shareClient_: '',
- shareStream_: '',
- sdkAppId_: '1400414461',
- userId_: '',
- userMainId_: '',
- open_: false,
- content: '',
- dataList: [],
- isrecord: false,
- shareid: '',
- userList: [],
- lookuserDia: false,
- index_: 0,
- ov1: '',
- ov2: '',
- ov3: '',
- ov4: '',
- ov5: '',
- ov6: '',
- ov7: '',
- showbtn_: false,
- roomdetail: {},
- zjrList: [],
- zjrshow: false,
- };
- },
- created() {
- this.getRoomInfo();
- this.initclient();
- this.getDevices();
- this.chatSearch();
- },
- mounted() {
- this.channel();
- },
- methods: {
- ...gensign(['gensignFetch']),
- ...chat(['query', 'create', 'fetch']),
- ...room({
- roomfetch: 'fetch',
- startrecord: 'startrecord',
- stoprecord: 'stoprecord',
- roomquest: 'roomquest',
- roomquestclose: 'roomquestclose',
- questquery: 'questquery',
- updateanchor: 'updateanchor',
- updateshmai: 'updateshmai',
- switchzjr: 'switchzjr',
- switchzb: 'switchzb',
- switchzp: 'switchzp',
- dismissroom: 'dismissroom',
- }),
- ...lookuser(['lookquery', 'lookupdate']),
- ...roomuser({ roomuserfetch: 'fetch' }),
- // 解散房间
- async dismissroomClick() {
- const info = { roomid: this.id, roomname: this.name };
- let res = await this.dismissroom({ ...info });
- if (this.$checkRes(res)) {
- console.log(res.data);
- this.$message({
- message: '操作成功',
- type: 'success',
- });
- }
- },
- async livezp() {
- const data = {};
- data.id = this.id;
- data.uid = this.user.uid;
- const res = await this.switchzb(data);
- if (this.$checkRes(res)) {
- console.log(res.data);
- this.$message({
- message: '操作成功',
- type: 'success',
- });
- }
- },
- async livezhuchi() {
- const data = {};
- data.id = this.id;
- data.uid = this.user.uid;
- const res = await this.switchzb(data);
- if (this.$checkRes(res)) {
- console.log(res.data);
- this.$message({
- message: '操作成功',
- type: 'success',
- });
- this.localStream_.unmuteVideo();
- this.localStream_.unmuteAudio();
- }
- },
- async zjrChange(zjrid) {
- const data = {};
- data.id = this.id;
- data.switchzjr = zjrid;
- const res = await this.switchzjr(data);
- if (this.$checkRes(res)) {
- console.log(res.data);
- this.$message({
- message: '操作成功',
- type: 'success',
- });
- this.localStream_.muteVideo();
- this.localStream_.muteAudio();
- }
- },
- async getRoomInfo() {
- const res = await this.roomfetch(this.id);
- if (this.$checkRes(res)) {
- console.log(res.data);
- this.$set(this, `roomdetail`, res.data);
- if (res.data.anchorid === this.user.uid) {
- this.zjrshow = true;
- }
- for (const elm of res.data.zjr) {
- const ru = await this.roomuserfetch(elm);
- if (this.$checkRes(ru)) {
- const newdata = { zjrid: elm, zjrname: ru.data.name };
- this.zjrList.push(newdata);
- }
- }
- }
- },
- async roomshangmai(dataid) {
- const data = {};
- data.id = this.id;
- data.shmaiid = dataid;
- const res = await this.updateshmai(data);
- if (this.$checkRes(res)) {
- console.log(res.data);
- this.$message({
- message: '操作成功',
- type: 'success',
- });
- }
- },
- async queCreate() {
- const data = {};
- data.roomid = this.id;
- data.queid = this.queid;
- const res = await this.roomquest(data);
- if (this.$checkRes(res)) {
- console.log(res.data);
- this.$message({
- message: '操作成功',
- type: 'success',
- });
- }
- },
- async lookuserBtn() {
- this.lookuserDia = true;
- this.lookuserSearch();
- },
- async lookuserSearch({ skip = 0, limit = 1000 } = {}) {
- const info = { roomid: this.id };
- let res = await this.lookquery({ skip, limit, ...info });
- console.log(res.data);
- this.$set(this, `userList`, res.data);
- },
- async lookuserUpdate(_id, _switchrole) {
- console.log(_id);
- let data = {};
- data.id = _id;
- data.switchrole = _switchrole;
- const res = await this.lookupdate(data);
- if (this.$checkRes(res)) {
- console.log(res.data);
- this.$message({
- message: '操作成功',
- type: 'success',
- });
- this.lookuserSearch();
- } else {
- this.$message.error(res.errmsg);
- }
- },
- async recordclick() {
- console.log(this.isrecord);
- if (this.isrecord) {
- const info = { roomid: this.id, roomname: this.name, shareid: this.shareid };
- let res = await this.startrecord({ ...info });
- } else {
- const info = { roomid: this.id, roomname: this.name };
- let res = await this.stoprecord({ ...info });
- }
- },
- async chatSearch({ skip = 0, limit = 1000 } = {}) {
- const info = { roomid: this.id };
- let res = await this.query({ skip, limit, ...info });
- this.$set(this, `dataList`, res.data);
- },
- async questSearch({ skip = 0, limit = 1000 } = {}) {
- const info = { status: '1' };
- let res = await this.questquery({ skip, limit, ...info });
- console.log(res);
- if (this.$checkRes(res)) {
- this.$set(this, `questList`, res.data);
- }
- },
- async chatCreate() {
- let data = {};
- data.roomid = this.id;
- data.type = '0';
- data.content = this.content;
- data.sendid = this.user.uid;
- data.sendname = this.user.name;
- const res = await this.create(data);
- if (this.$checkRes(res)) {
- console.log(res.data);
- this.content = '';
- }
- },
- channel() {
- console.log('in function:');
- this.$stomp({
- [`/exchange/public_chat_` + this.id]: this.onMessage,
- });
- },
- onMessage(message) {
- // console.log('receive a message: ', message.body);
- let body = _.get(message, 'body');
- if (body) {
- body = JSON.parse(body);
- this.dataList.push(body);
- this.content = '';
- }
- // const { content, contenttype, sendid, sendname, icon, groupid, sendtime, type } = message.headers;
- // let object = { content, contenttype, sendid, sendname, icon, groupid, sendtime, type };
- // this.list.push(object);
- },
- async getDevices() {
- this.cameras = await TRTC.getCameras();
- this.microphones = await TRTC.getMicrophones();
- },
- async initclient() {
- console.log(this.user.uid);
- this.userId_ = this.user.uid;
- if (this.anchorid === this.user.uid) {
- this.showbtn_ = true;
- this.userMainId_ = 'mainr-' + this.user.uid;
- } else {
- this.userMainId_ = 'other-' + this.user.uid;
- }
- const res = await this.gensignFetch({ userid: this.userMainId_ });
- if (this.$checkRes(res)) {
- console.log(res.data);
- this.client_ = TRTC.createClient({
- mode: 'live',
- sdkAppId: this.sdkAppId_,
- userId: this.userMainId_,
- userSig: res.data,
- });
- }
- },
- async liveon() {
- this.open_ = true;
- console.log('8888--' + this.userId_);
- if (this.cameraId === '' || this.microphoneId === '') {
- this.$message({
- message: '请选择摄像头和麦克风',
- type: 'warning',
- });
- return;
- }
- await this.client_.join({ roomId: this.name, role: 'anchor' });
- this.localStream_ = await TRTC.createStream({
- audio: true,
- video: true,
- cameraId: this.cameraId,
- microphoneId: this.microphoneId,
- userId: this.userMainId_,
- });
- this.localStream_.setVideoProfile('480p');
- await this.localStream_.initialize();
- console.log('initialize local stream success');
- // publish the local stream
- await this.client_.publish(this.localStream_);
- this.localStream_.play('main-video');
- //$('#mask_main').appendTo($('#player_' + this.localStream_.getId()));
- // 订阅其他用户音视频
- this.client_.on('stream-subscribed', event => {
- const remoteStream = event.stream;
- // 远端流订阅成功,播放远端音视频流
- const usertempid_ = remoteStream.getUserId();
- console.log('111' + remoteStream.getUserId());
- if (usertempid_) {
- const usersplit_ = usertempid_.substring(0, 5);
- if (usersplit_ === 'other') {
- const id_ = 'othe-video-' + usertempid_;
- remoteStream.play(id_);
- } else if (usersplit_ === 'wxxcx') {
- const id_ = 'look-video-' + usertempid_;
- remoteStream.play(id_);
- } else if (usersplit_ === 'meetu') {
- const id_ = 'look-video-' + usertempid_;
- remoteStream.play(id_);
- }
- }
- });
- // 监听远端流增加事件
- this.client_.on('stream-added', event => {
- const remoteStream = event.stream;
- console.log('222' + remoteStream.getType());
- // 订阅远端音频和视频流
- this.client_.subscribe(remoteStream, { audio: true, video: true }).catch(e => {
- console.error('failed to subscribe remoteStream');
- });
- });
- this.client_.on('stream-removed', event => {
- const remoteStream = event.stream;
- console.log('stop----');
- const usertempid_ = remoteStream.getUserId();
- if (usertempid_) {
- const usersplit_ = usertempid_.substring(0, 5);
- if (usersplit_ === 'other') {
- this.index_ = this.index_ - 1;
- }
- }
- remoteStream.stop();
- });
- this.client_.on('mute-video', event => {
- const remoteStream = event.stream;
- // 订阅远端音频和视频流
- const usertempid_ = remoteStream.getUserId();
- if (usertempid_) {
- const usersplit_ = usertempid_.substring(0, 4);
- if (usersplit_ === 'othe') {
- this.index_ = this.index_ - 1;
- }
- }
- });
- },
- async shareon() {
- const shareId = 'share-' + this.userId_;
- this.shareid = shareId;
- const res = await this.gensignFetch({ userid: shareId });
- if (this.$checkRes(res)) {
- const shareClient = TRTC.createClient({
- mode: 'videoCall',
- sdkAppId: this.sdkAppId_,
- userId: shareId,
- userSig: res.data,
- });
- this.shareClient_ = shareClient;
- shareClient.setDefaultMuteRemoteStreams(true);
- await shareClient.join({ roomId: this.name });
- const localStream = TRTC.createStream({ audio: false, screen: true });
- //localStream.setScreenProfile({ width: 200, height: 200, float: 'left', frameRate: 5, bitrate: 1600 /* kbps */ });
- await localStream.initialize();
- this.shareStream_ = localStream;
- console.log('initialize share stream success');
- await shareClient.publish(localStream);
- this.client_.on('stream-added', event => {
- const remoteStream = event.stream;
- const remoteUserId = remoteStream.getUserId();
- if (remoteUserId === shareId) {
- // 取消订阅自己的屏幕分享流
- this.client_.unsubscribe(remoteStream);
- } else {
- // 订阅其他一般远端流
- this.client_.subscribe(remoteStream);
- }
- });
- }
- },
- async liveclose() {
- // 关闭视频通话
- console.log(this.open_);
- if (this.open_) {
- const videoTrack = this.localStream_.getVideoTrack();
- if (videoTrack) {
- this.localStream_.removeTrack(videoTrack).then(() => {
- console.log('remove video call success');
- // 关闭摄像头
- videoTrack.stop();
- this.client_.unpublish(this.localStream_).then(() => {
- // 取消发布本地流成功
- });
- this.localStream_.close();
- });
- }
- }
- },
- async shareclose() {
- this.shareClient_;
- if (this.shareClient_) {
- this.shareClient_.unpublish(this.shareStream_).then(() => {
- // 关闭屏幕分享流
- this.shareStream_.close();
- });
- }
- },
- async cameraChange() {
- //await this.localStream_.switchDevice('video', this.cameraId);
- },
- async micrChange() {
- //await this.localStream_.switchDevice('audio', this.microphoneId);
- },
- // 选择打开摄像头
- shexiangBtn() {
- this.shexiangDia = true;
- },
- // 选择打开麦克风
- tianchongBtn() {
- this.tianchongDia = true;
- },
- chatBtn() {
- this.chatDia = true;
- },
- async queBtn() {
- this.queDia = true;
- this.questSearch();
- },
- async queCloseBtn() {
- // 关闭问卷
- const data = {};
- data.roomid = this.id;
- const res = await this.roomquestclose(data);
- if (this.$checkRes(res)) {
- this.$message({
- message: '操作成功',
- type: 'success',
- });
- }
- },
- forId(itemid) {
- return 'look-video-wxxcx-' + itemid;
- },
- forOtherId(itemid) {
- return 'othe-video-other-' + itemid;
- },
- // 关闭摄像头&麦克风
- handleClose(done) {
- done();
- },
- },
- computed: {
- ...mapState(['user']),
- id() {
- return this.$route.query.id;
- },
- name() {
- return this.$route.query.name;
- },
- anchorid() {
- return this.$route.query.anchorid;
- },
- pageTitle() {
- return `${this.$route.meta.title}`;
- },
- },
- metaInfo() {
- return { title: this.$route.meta.title };
- },
- };
- </script>
- <style lang="less" scoped>
- .info {
- background-color: #2a2b30;
- min-height: 840px;
- .left {
- .leftTop {
- min-height: 540px;
- padding: 0 15px;
- margin: 20px 0;
- p {
- color: #ccc;
- }
- p:nth-child(2) {
- padding: 10px 0;
- }
- p:nth-child(3) {
- line-height: 25px;
- }
- }
- .leftDown {
- padding: 10px 0 0 0;
- border-top: 1px solid #000;
- .btn {
- margin: 0 0 15px 0;
- color: #cccccc;
- text-align: center;
- }
- .btn:hover {
- cursor: pointer;
- }
- }
- }
- .right {
- .rightTop {
- height: 100px;
- background-color: #232428;
- text-align: right;
- color: #ccc;
- line-height: 100px;
- span {
- margin: 0 10px 0 0;
- }
- span:hover {
- cursor: pointer;
- color: #409eff;
- }
- }
- .video {
- min-height: 640px;
- background-color: #000;
- overflow: hidden;
- position: relative;
- .videoMeet {
- .one {
- height: 480px;
- overflow: hidden;
- }
- .two {
- height: 480px;
- overflow: hidden;
- background-color: white;
- .twoOne {
- height: 80px;
- width: 100%;
- overflow: hidden;
- span:first-child {
- width: 100%;
- text-align: center;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- // font-weight: bold;
- }
- span:last-child {
- width: 100%;
- }
- }
- }
- .three {
- height: 160px;
- overflow: hidden;
- }
- }
- }
- .noVideo {
- min-height: 640px;
- background-color: #151618;
- }
- .rightDown {
- height: 100px;
- background-color: #232428;
- }
- }
- }
- /deep/.el-dialog__body {
- min-height: 100px;
- }
- #main-video {
- float: left;
- width: 100%;
- height: 640px;
- min-height: 600px;
- grid-area: 1/1/3/4;
- }
- .chatList {
- height: 400px;
- padding: 5px 5px 5px 0px;
- overflow-y: auto;
- .list {
- margin: 0 0 10px 0;
- span:first-child {
- float: left;
- width: 15%;
- text-align: center;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- // font-weight: bold;
- }
- span:last-child {
- float: right;
- width: 84%;
- }
- }
- }
- .chatInput {
- position: absolute;
- bottom: 0;
- .el-button {
- width: 100%;
- padding: 20px 0;
- }
- }
- .sudoku_row {
- display: flex;
- align-items: center;
- width: 100%;
- height: 430px;
- flex-wrap: wrap;
- overflow-y: auto;
- }
- .sudoku_item {
- display: flex;
- justify-content: center;
- align-items: center;
- flex-direction: column;
- width: 30%;
- padding: 10px 10px 10px 10px;
- }
- .lookvideo {
- width: 100%;
- height: 160px;
- min-height: 160px;
- background-color: black;
- grid-area: 1/1/3/4;
- }
- .othevideo {
- margin: 10px 10px 10px 10px;
- width: 80px;
- height: 80px;
- min-height: 80px;
- background-color: black;
- grid-area: 1/1/3/4;
- }
- </style>
|