nuoyun
This commit is contained in:
@ -18,6 +18,14 @@ const router = createRouter({
|
|||||||
path: '/meeting/56',
|
path: '/meeting/56',
|
||||||
redirect: '/meeting/90'
|
redirect: '/meeting/90'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/meeting-ny/:meetingId',
|
||||||
|
name: "MeetingNy",
|
||||||
|
meta: {
|
||||||
|
source: 'nuoyun'
|
||||||
|
},
|
||||||
|
component: () => import("@/views/meeting-test.vue"),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "/appointment/56",
|
path: "/appointment/56",
|
||||||
redirect: "/appointment/90",
|
redirect: "/appointment/90",
|
||||||
@ -52,22 +60,22 @@ const router = createRouter({
|
|||||||
{
|
{
|
||||||
path: "/meeting/:meetingId",
|
path: "/meeting/:meetingId",
|
||||||
name: "Meeting",
|
name: "Meeting",
|
||||||
component: () => import("@/views/meeting.vue"),
|
component: () => import("@/views/meeting-test.vue"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/panelist/:meetingId",
|
path: "/panelist/:meetingId",
|
||||||
name: "Panelist",
|
name: "Panelist",
|
||||||
component: () => import("@/views/meeting.vue"),
|
component: () => import("@/views/meeting-test.vue"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/host/:meetingId/:createEmail/:pwd/:username/:nickname",
|
path: "/host/:meetingId/:createEmail/:pwd/:username/:nickname",
|
||||||
name: "Host",
|
name: "Host",
|
||||||
component: () => import("@/views/meeting.vue"),
|
component: () => import("@/views/meeting-test.vue"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/supervisor/:meetingId/:username",
|
path: "/supervisor/:meetingId/:username",
|
||||||
name: "Supervisor",
|
name: "Supervisor",
|
||||||
component: () => import("@/views/meeting.vue"),
|
component: () => import("@/views/meeting-test.vue"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/error",
|
path: "/error",
|
||||||
@ -92,6 +100,7 @@ const router = createRouter({
|
|||||||
router.beforeEach(async (to) => {
|
router.beforeEach(async (to) => {
|
||||||
await store.dispatch("getMeetingSettings");
|
await store.dispatch("getMeetingSettings");
|
||||||
// 判断会议信息是否存在,不存在则请求数据
|
// 判断会议信息是否存在,不存在则请求数据
|
||||||
|
|
||||||
if (!store.state.meeting.id && to.params.meetingId) {
|
if (!store.state.meeting.id && to.params.meetingId) {
|
||||||
await store.dispatch("getMeetingInfo", to.params.meetingId);
|
await store.dispatch("getMeetingInfo", to.params.meetingId);
|
||||||
}
|
}
|
||||||
@ -138,7 +147,7 @@ router.beforeEach(async (to) => {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// 如果要前往参会页面
|
// 如果要前往参会页面
|
||||||
else if (to.name === "Meeting") {
|
else if (to.name === "Meeting" || to.name === "MeetingNy") {
|
||||||
// 如果要去的页面会议号于 vuex中的不一样,则清除数据
|
// 如果要去的页面会议号于 vuex中的不一样,则清除数据
|
||||||
// if (to.params.meetingId !== store.state.joinUser.meetingId) {
|
// if (to.params.meetingId !== store.state.joinUser.meetingId) {
|
||||||
// store.commit("setJoinUser", {});
|
// store.commit("setJoinUser", {});
|
||||||
@ -153,7 +162,7 @@ router.beforeEach(async (to) => {
|
|||||||
store.commit("setLiked", false);
|
store.commit("setLiked", false);
|
||||||
store.commit("setMessagesList", []);
|
store.commit("setMessagesList", []);
|
||||||
store.commit("setJoinType", store.state.meeting.joinType);
|
store.commit("setJoinType", store.state.meeting.joinType);
|
||||||
return `/verify/${to.params.meetingId}`;
|
return `/verify/${to.params.meetingId}?redirect=${to.path}`;
|
||||||
}
|
}
|
||||||
if (store.state.meeting.joinType === "1") {
|
if (store.state.meeting.joinType === "1") {
|
||||||
// 如果是白名单模式
|
// 如果是白名单模式
|
||||||
@ -175,20 +184,20 @@ router.beforeEach(async (to) => {
|
|||||||
store.commit("setJoinUser", {});
|
store.commit("setJoinUser", {});
|
||||||
store.commit("setLiked", false);
|
store.commit("setLiked", false);
|
||||||
store.commit("setMessagesList", []);
|
store.commit("setMessagesList", []);
|
||||||
return `/verify/${to.params.meetingId}`;
|
return `/verify/${to.params.meetingId}?redirect=${to.path}`;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
store.commit("setJoinUser", {});
|
store.commit("setJoinUser", {});
|
||||||
store.commit("setLiked", false);
|
store.commit("setLiked", false);
|
||||||
store.commit("setMessagesList", []);
|
store.commit("setMessagesList", []);
|
||||||
return `/verify/${to.params.meetingId}`;
|
return `/verify/${to.params.meetingId}?redirect=${to.path}`;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (_.isEmpty(store.state.joinUser)) {
|
if (_.isEmpty(store.state.joinUser)) {
|
||||||
store.commit("setJoinUser", {});
|
store.commit("setJoinUser", {});
|
||||||
store.commit("setLiked", false);
|
store.commit("setLiked", false);
|
||||||
store.commit("setMessagesList", []);
|
store.commit("setMessagesList", []);
|
||||||
return `/verify/${to.params.meetingId}`;
|
return `/verify/${to.params.meetingId}?redirect=${to.path}`;
|
||||||
} else {
|
} else {
|
||||||
if (store.state.meeting.joinType === "2") {
|
if (store.state.meeting.joinType === "2") {
|
||||||
const { meetingPassword, email } = await registerJoinUser(
|
const { meetingPassword, email } = await registerJoinUser(
|
||||||
@ -262,6 +271,8 @@ router.beforeEach(async (to) => {
|
|||||||
});
|
});
|
||||||
store.commit("setPassword", meetingPassword);
|
store.commit("setPassword", meetingPassword);
|
||||||
return true;
|
return true;
|
||||||
|
} else if (to.name === "MeetingNy") {
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
560
src/views/meeting-test.vue
Normal file
560
src/views/meeting-test.vue
Normal file
@ -0,0 +1,560 @@
|
|||||||
|
<template>
|
||||||
|
<div id="app-container" ref="appContainerRef">
|
||||||
|
<div id="meeting-chat-row">
|
||||||
|
<div id="meeting-container" ref="meetingContainerRef">
|
||||||
|
<!-- v-if="route.name === 'MeetingNy'" -->
|
||||||
|
<iframe
|
||||||
|
ref="nuoyunIfrRef"
|
||||||
|
id="nuoyun-iframe"
|
||||||
|
src="https://console.nuoyun.tv/PlayerEmbed/PlayerEmbed.html?type=1&appid=451264724"
|
||||||
|
frameborder="0"
|
||||||
|
allowfullscreen
|
||||||
|
></iframe>
|
||||||
|
<div id="text-label-wrap">
|
||||||
|
<div
|
||||||
|
:id="`tag-${item.uniqId}`"
|
||||||
|
:key="item.uniqId"
|
||||||
|
class="text-tag"
|
||||||
|
v-for="item in labelList"
|
||||||
|
v-html="item.textLabel.content"
|
||||||
|
:style="{
|
||||||
|
left: `${item.textLabel.x}%`,
|
||||||
|
top: `${item.textLabel.y}%`,
|
||||||
|
backgroundColor: item.textLabel.backgroundColor,
|
||||||
|
visibility:
|
||||||
|
item.textLabel.visibility === '1' ? 'visible' : 'hidden',
|
||||||
|
}"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="chat-container" ref="chatContainerRef">
|
||||||
|
<Chat
|
||||||
|
:is-host="route.name === 'Host'"
|
||||||
|
place="right"
|
||||||
|
:account="joinName"
|
||||||
|
:message-list="messages"
|
||||||
|
@send="sendMessage"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div :class="`like-row`">
|
||||||
|
<like
|
||||||
|
:meeting-id="store.getters.meetingId"
|
||||||
|
:like="likeCount"
|
||||||
|
:online="onlineCount"
|
||||||
|
style="margin: 0 auto"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<el-tabs class="tabs" type="border-card">
|
||||||
|
<el-tab-pane label="会议介绍">
|
||||||
|
<div class="meeting-info meeting-note" v-html="meetingNote"></div>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane label="会议日程"
|
||||||
|
><div
|
||||||
|
class="meeting-info meeting-schedule"
|
||||||
|
v-html="meetingSchedule"
|
||||||
|
></div
|
||||||
|
></el-tab-pane>
|
||||||
|
<el-tab-pane label="专家介绍"
|
||||||
|
><div class="meeting-info expert-info" v-html="expertInfo"></div
|
||||||
|
></el-tab-pane>
|
||||||
|
<el-tab-pane label="聊天" class="chat-pane" v-if="screenWidth <= 768">
|
||||||
|
<Chat
|
||||||
|
:is-host="route.name === 'Host'"
|
||||||
|
place="bottom"
|
||||||
|
:account="joinName"
|
||||||
|
:message-list="messages"
|
||||||
|
@send="sendMessage"
|
||||||
|
/>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane
|
||||||
|
label="考核"
|
||||||
|
v-if="route.name === 'Meeting' || route.name === 'MeetingNy'"
|
||||||
|
>
|
||||||
|
<!-- // 签到、考试、问卷弹窗 -->
|
||||||
|
<el-row :gutter="10">
|
||||||
|
<el-col :span="12"
|
||||||
|
><el-button
|
||||||
|
type="primary"
|
||||||
|
:disabled="
|
||||||
|
!isDuringExamPeriod || store.state.joinUser.examSubmited
|
||||||
|
"
|
||||||
|
@click="showExamDialog = true"
|
||||||
|
style="width: 100%"
|
||||||
|
>考试</el-button
|
||||||
|
></el-col
|
||||||
|
>
|
||||||
|
<el-col :span="12"
|
||||||
|
><el-button
|
||||||
|
type="primary"
|
||||||
|
style="width: 100%"
|
||||||
|
@click="showQuestionnaireDialog = true"
|
||||||
|
:disabled="
|
||||||
|
!isDuringQuestionnairePeriod ||
|
||||||
|
store.state.joinUser.questionnaireSubmited
|
||||||
|
"
|
||||||
|
>问卷</el-button
|
||||||
|
></el-col
|
||||||
|
>
|
||||||
|
</el-row>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
|
||||||
|
<el-dialog
|
||||||
|
v-model="showSignDialog"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
title="签到"
|
||||||
|
width="30%"
|
||||||
|
:fullscreen="screenWidth < 900"
|
||||||
|
>
|
||||||
|
<span>是否确认签到</span>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button type="primary" @click="submitSign">确定</el-button>
|
||||||
|
<el-button type="primary" @click="showSignDialog = false"
|
||||||
|
>取消</el-button
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
<questions
|
||||||
|
mode="1"
|
||||||
|
@stage="getStageExamAnswer"
|
||||||
|
:questions-list="examQuestionsList"
|
||||||
|
v-if="showExamDialog && route.name !== 'Host'"
|
||||||
|
:showDialog="showExamDialog"
|
||||||
|
@close="showExamDialog = $event"
|
||||||
|
></questions>
|
||||||
|
|
||||||
|
<questions
|
||||||
|
mode="2"
|
||||||
|
@stage="getStageQuestionnaireAnswer"
|
||||||
|
:questions-list="questionnaireQuestionsList"
|
||||||
|
v-if="showQuestionnaireDialog && route.name !== 'Host'"
|
||||||
|
:showDialog="showQuestionnaireDialog"
|
||||||
|
@close="showQuestionnaireDialog = $event"
|
||||||
|
></questions>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { computed, nextTick, onMounted, reactive, ref } from "vue";
|
||||||
|
import { useRoute, useRouter } from "vue-router";
|
||||||
|
import { useStore } from "vuex";
|
||||||
|
import { uniqueId } from "lodash";
|
||||||
|
import ReconnectingWebSocket from "reconnecting-websocket";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import questions from "@/components/questions.vue";
|
||||||
|
import Chat from "@/components/chat.vue";
|
||||||
|
import like from "@/components/like.vue";
|
||||||
|
import { ElMessage, ElMessageBox } from "element-plus";
|
||||||
|
import {
|
||||||
|
signMeeting,
|
||||||
|
// generateSignature,
|
||||||
|
getOnlineUserTotalAndLikes,
|
||||||
|
getQuestionsList,
|
||||||
|
commitQuestionnaire,
|
||||||
|
commitExam,
|
||||||
|
} from "@/api/meeting";
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const store = useStore();
|
||||||
|
const router = useRouter();
|
||||||
|
const templateId = ref(0);
|
||||||
|
|
||||||
|
const meetingNote = computed(() => store.getters.meetingNote); // 会议介绍
|
||||||
|
const meetingSchedule = computed(() => store.getters.meetingSchedule); // 会议日程
|
||||||
|
const expertInfo = computed(() => store.getters.expertInfo); // 专家信息
|
||||||
|
const joinName = ref(""); // 显示聊天昵称
|
||||||
|
const joinAccount = ref(""); // 用于连接 websocket,提交考试
|
||||||
|
joinAccount.value =
|
||||||
|
store.getters.username ||
|
||||||
|
store.getters.icCard ||
|
||||||
|
store.getters.phone ||
|
||||||
|
store.getters.nickname;
|
||||||
|
joinName.value =
|
||||||
|
store.getters.nickname || store.getters.phone || store.getters.icCard;
|
||||||
|
|
||||||
|
const appContainerRef = ref(); // 应用容器
|
||||||
|
const meetingContainerRef = ref(); // 会议容器
|
||||||
|
const chatContainerRef = ref(); // 聊天容器
|
||||||
|
const nuoyunIfrRef = ref(); // 诺云iframe
|
||||||
|
const screenWidth = ref(0);
|
||||||
|
screenWidth.value = window.screen.width;
|
||||||
|
|
||||||
|
// 初始化尺寸
|
||||||
|
const initSize = () => {
|
||||||
|
const pageWidth = document.body.clientWidth;
|
||||||
|
appContainerRef.value.style.setProperty("--app-width", `${pageWidth}px`);
|
||||||
|
appContainerRef.value.style.setProperty(
|
||||||
|
"--meeting-container-width",
|
||||||
|
`${pageWidth * 0.8}px`
|
||||||
|
);
|
||||||
|
appContainerRef.value.style.setProperty(
|
||||||
|
"--chat-container-width",
|
||||||
|
`${pageWidth * 0.2}px`
|
||||||
|
);
|
||||||
|
};
|
||||||
|
onMounted(() => {
|
||||||
|
initSize();
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 加载、设置文本标签 */
|
||||||
|
const labelList = ref([]);
|
||||||
|
const loadTextLabelList = () => {
|
||||||
|
labelList.value = store.getters.textLabelList.map((el) => {
|
||||||
|
return {
|
||||||
|
...el,
|
||||||
|
textLabel: JSON.parse(el.textLabel),
|
||||||
|
uniqId: _.uniqueId(),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
loadTextLabelList();
|
||||||
|
|
||||||
|
/** 进入会议时获取点赞数量和在线人数 */
|
||||||
|
const onlineCount = ref(0);
|
||||||
|
const likeCount = ref(0);
|
||||||
|
const getLikeAndOnline = async () => {
|
||||||
|
const { data } = await getOnlineUserTotalAndLikes(store.getters.meetingId);
|
||||||
|
onlineCount.value = data.online;
|
||||||
|
likeCount.value = data.like;
|
||||||
|
};
|
||||||
|
getLikeAndOnline();
|
||||||
|
|
||||||
|
/** 从缓存中获取问题答案 */
|
||||||
|
const examQuestionsList = ref([]);
|
||||||
|
const getStageExamAnswer = (val) => {
|
||||||
|
examQuestionsList.value = val.map((el) => el);
|
||||||
|
};
|
||||||
|
const questionnaireQuestionsList = ref([]);
|
||||||
|
const getStageQuestionnaireAnswer = (val) => {
|
||||||
|
questionnaireQuestionsList.value = val.map((el) => el);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** websocket 连接、监听考试聊天消息 */
|
||||||
|
let socket = reactive({});
|
||||||
|
const initWebSocket = () => {
|
||||||
|
// 建立websocket连接
|
||||||
|
socket = new ReconnectingWebSocket(
|
||||||
|
`wss://meeting.chuhuankj.com/wss/websocket/meeting/${store.getters.meetingId}/${joinAccount.value}`
|
||||||
|
);
|
||||||
|
socket.addEventListener("open", () => {
|
||||||
|
console.log("websocket,已连接");
|
||||||
|
});
|
||||||
|
|
||||||
|
// 监听websocket消息
|
||||||
|
socket.addEventListener("message", async (event) => {
|
||||||
|
let data;
|
||||||
|
try {
|
||||||
|
data = JSON.parse(JSON.parse(event.data));
|
||||||
|
} catch (error) {
|
||||||
|
data = JSON.parse(event.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 会议信息更新时
|
||||||
|
if (data.type === "isRefreshMeeting") {
|
||||||
|
await store.dispatch("getMeetingInfo", store.getters.meetingId);
|
||||||
|
meetingContainerRef.value.style.background = `url(${
|
||||||
|
store.getters.templateBackgroundPic || store.getters.defaultBackground
|
||||||
|
}) 0% 0% / cover no-repeat`;
|
||||||
|
templateId.value = store.getters.templateId;
|
||||||
|
loadTextLabelList();
|
||||||
|
}
|
||||||
|
// 收到聊天消息时
|
||||||
|
else if (data.type === "isChat") {
|
||||||
|
messages.value.push({
|
||||||
|
...JSON.parse(data.content),
|
||||||
|
id: uniqueId(),
|
||||||
|
time: dayjs().format("YYYY-MM-DD HH:mm:ss"),
|
||||||
|
});
|
||||||
|
nextTick(() => {
|
||||||
|
document
|
||||||
|
.querySelector(".message-list .message-row:last-child")
|
||||||
|
.scrollIntoView({ behavior: "smooth" });
|
||||||
|
});
|
||||||
|
store.commit("setMessagesList", messages.value);
|
||||||
|
}
|
||||||
|
// 当检测到敏感词时
|
||||||
|
else if (data.type === "isSensitive") {
|
||||||
|
ElMessage.error(`消息未发送成功,因为包含违禁词:${data.content}。`);
|
||||||
|
}
|
||||||
|
// 开始签到时
|
||||||
|
else if (data.type === "isStartSign" && route.name === "Meeting") {
|
||||||
|
showSignDialog.value = true;
|
||||||
|
}
|
||||||
|
// 签到结束时
|
||||||
|
else if (data.type === "isEndSign" && route.name === "Meeting") {
|
||||||
|
showSignDialog.value = false;
|
||||||
|
}
|
||||||
|
// 开始考试时
|
||||||
|
else if (data.type === "isStartExam" && route.name === "Meeting") {
|
||||||
|
showExamDialog.value = true;
|
||||||
|
isDuringExamPeriod.value = true;
|
||||||
|
}
|
||||||
|
// 开始问卷时
|
||||||
|
else if (data.type === "isStartQuestionnaire" && route.name === "Meeting") {
|
||||||
|
showQuestionnaireDialog.value = true;
|
||||||
|
isDuringQuestionnairePeriod.value = true;
|
||||||
|
} else if (data.type === "isRefreshOnlineAndLike") {
|
||||||
|
getLikeAndOnline();
|
||||||
|
}
|
||||||
|
// 当检测到异地登陆时,强制退出登录,并清除数据
|
||||||
|
else if (data.type === "isRemoteLogin") {
|
||||||
|
ElMessageBox.alert("您的账号在异地登录,将被强制下线", "异地登录", {
|
||||||
|
type: "warning",
|
||||||
|
"show-close": false,
|
||||||
|
"show-confirm-button": false,
|
||||||
|
"show-cancel-button": false,
|
||||||
|
});
|
||||||
|
setTimeout(() => {
|
||||||
|
// leaveConference();
|
||||||
|
store.commit("setJoinUser", {});
|
||||||
|
store.commit("setPassword", "");
|
||||||
|
store.commit("setMessagesList", []);
|
||||||
|
store.commit("setLiked", false);
|
||||||
|
router.push(`/verify/${store.getters.meetingId}`);
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
|
// 会议结束时
|
||||||
|
else if (data.type === "isCloseMeeting") {
|
||||||
|
showExamDialog.value = false;
|
||||||
|
showQuestionnaireDialog.value = false;
|
||||||
|
isDuringExamPeriod.value = false;
|
||||||
|
isDuringQuestionnairePeriod.value = false;
|
||||||
|
ElMessageBox.alert("会议已结束");
|
||||||
|
socket.close();
|
||||||
|
if (route.name === "Meeting") {
|
||||||
|
if (store.getters.bankId && !store.state.joinUser.examSubmited) {
|
||||||
|
if (examQuestionsList.value.length === 0) {
|
||||||
|
examQuestionsList.value = await loadQuestionsList("1");
|
||||||
|
}
|
||||||
|
submitQuestion("1");
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
store.getters.questionnaireId &&
|
||||||
|
!store.state.joinUser.questionnaireSubmited
|
||||||
|
) {
|
||||||
|
if (questionnaireQuestionsList.value.length === 0) {
|
||||||
|
questionnaireQuestionsList.value = await loadQuestionsList("2");
|
||||||
|
}
|
||||||
|
submitQuestion("2");
|
||||||
|
}
|
||||||
|
} else if (route.name === "Host") {
|
||||||
|
meetingConfig.client.endMeeting();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
socket.addEventListener("close", (event) => {
|
||||||
|
console.log(event, "close");
|
||||||
|
});
|
||||||
|
socket.addEventListener("error", (event) => {
|
||||||
|
console.log(event, "error");
|
||||||
|
});
|
||||||
|
};
|
||||||
|
initWebSocket();
|
||||||
|
|
||||||
|
/** 聊天功能 */
|
||||||
|
const messages = ref([]); // 消息列表
|
||||||
|
messages.value = store.state.messagesList.map((msg) => msg); // 从缓存读取
|
||||||
|
|
||||||
|
const sendMessage = (msgObj) => {
|
||||||
|
// 发送消息
|
||||||
|
socket.send(
|
||||||
|
JSON.stringify({
|
||||||
|
account: joinName.value,
|
||||||
|
msg: msgObj.msg,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
messages.value.push(msgObj);
|
||||||
|
nextTick(() => {
|
||||||
|
document
|
||||||
|
.querySelector(".message-list .message-row:last-child")
|
||||||
|
.scrollIntoView({ behavior: "smooth" });
|
||||||
|
});
|
||||||
|
store.commit("setMessagesList", messages.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 签到功能 */
|
||||||
|
const showSignDialog = ref(false);
|
||||||
|
const submitSign = async () => {
|
||||||
|
// 提交签到
|
||||||
|
await signMeeting({
|
||||||
|
meetingId: store.getters.meetingId,
|
||||||
|
signTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
|
||||||
|
account: joinAccount.value,
|
||||||
|
});
|
||||||
|
showSignDialog.value = false;
|
||||||
|
store.commit("setJoinUser", {
|
||||||
|
...store.state.joinUser,
|
||||||
|
signSubmited: true,
|
||||||
|
});
|
||||||
|
ElMessage.success("签到成功");
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 考试功能 */
|
||||||
|
const showExamDialog = ref(false); //是否显示考试弹窗
|
||||||
|
const showQuestionnaireDialog = ref(false); //是否显示问卷弹窗
|
||||||
|
|
||||||
|
const isDuringExamPeriod = ref(false); // 是否在考试时间段内
|
||||||
|
const isDuringQuestionnairePeriod = ref(false); // 是否在问卷时间段内
|
||||||
|
isDuringExamPeriod.value = (() => {
|
||||||
|
const examStartTime = dayjs(store.state.meeting.examStartTime);
|
||||||
|
const meetingEndTime = dayjs(store.state.meeting.startTime).add(
|
||||||
|
store.state.meeting.duration,
|
||||||
|
"minute"
|
||||||
|
);
|
||||||
|
if (!examStartTime) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
const now = dayjs();
|
||||||
|
return now.isAfter(examStartTime) && now.isBefore(meetingEndTime);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
isDuringQuestionnairePeriod.value = (() => {
|
||||||
|
const questionnaireStartTime = dayjs(
|
||||||
|
store.state.meeting.questionnaireStartTime
|
||||||
|
);
|
||||||
|
const meetingEndTime = dayjs(store.state.meeting.startTime).add(
|
||||||
|
store.state.meeting.duration,
|
||||||
|
"minute"
|
||||||
|
);
|
||||||
|
if (!questionnaireStartTime) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
const now = dayjs();
|
||||||
|
return now.isAfter(questionnaireStartTime) && now.isBefore(meetingEndTime);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
/** 当考试和问卷弹框未能正确弹出时,(即考试开始时,未加入会议),加载题目列表 */
|
||||||
|
const loadQuestionsList = async (mode) => {
|
||||||
|
const { data } = await getQuestionsList({
|
||||||
|
meetingId: store.getters.meetingId,
|
||||||
|
type: mode,
|
||||||
|
});
|
||||||
|
return data.map((item) => {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
choiceAnswerIdStr: [],
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 当会议结束时,如果没有手动点击提交则自动提交试卷 */
|
||||||
|
const submitQuestion = async (mode) => {
|
||||||
|
if (mode == "1") {
|
||||||
|
await commitExam({
|
||||||
|
meetingId: store.getters.meetingId,
|
||||||
|
userAccount: joinAccount.value,
|
||||||
|
commitExamList: examQuestionsList.value.map((item) => {
|
||||||
|
return {
|
||||||
|
questionId: item.id,
|
||||||
|
choiceAnswerIdStr: item.choiceAnswerIdStr.join(",") + ",",
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
ElMessage.success("提交考试成功");
|
||||||
|
} else if (mode == "2") {
|
||||||
|
await commitQuestionnaire({
|
||||||
|
meetingId: store.getters.meetingId,
|
||||||
|
userAccount: joinAccount.value,
|
||||||
|
commitExamList: questionnaireQuestionsList.value.map((item) => {
|
||||||
|
return {
|
||||||
|
questionId: item.id,
|
||||||
|
choiceAnswerIdStr: item.choiceAnswerIdStr.join(",") + ",",
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
ElMessage.success("提交问卷成功");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
#app-container {
|
||||||
|
#meeting-chat-row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
#meeting-container {
|
||||||
|
position: relative;
|
||||||
|
width: var(--meeting-container-width);
|
||||||
|
height: calc(var(--meeting-container-width) * 9 / 16);
|
||||||
|
#nuoyun-iframe {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
#text-label-wrap {
|
||||||
|
pointer-events: none;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
:deep(.text-tag) {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 999;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 5px;
|
||||||
|
background-color: #fff;
|
||||||
|
* {
|
||||||
|
pointer-events: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#chat-container {
|
||||||
|
width: var(--chat-container-width);
|
||||||
|
height: calc(var(--meeting-container-width) * 9 / 16);
|
||||||
|
:deep(.chat-container .message-list) {
|
||||||
|
flex-grow: 1;
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.like-row {
|
||||||
|
padding-right: 20vw;
|
||||||
|
// background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
.tabs {
|
||||||
|
width: var(--app-width);
|
||||||
|
margin: 0 auto;
|
||||||
|
.chat-pane {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 手机样式
|
||||||
|
@media screen and (max-width: 768px) {
|
||||||
|
#app-container {
|
||||||
|
#meeting-chat-row {
|
||||||
|
#meeting-container {
|
||||||
|
width: 100vw;
|
||||||
|
height: calc(100vw * 9 / 16);
|
||||||
|
#nuoyun-iframe {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#chat-container {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.tabs {
|
||||||
|
width: 100vw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.like-row {
|
||||||
|
padding-right: 0;
|
||||||
|
// background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
.tabs {
|
||||||
|
.chat-pane {
|
||||||
|
display: initial;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -3,6 +3,7 @@
|
|||||||
id="app-container"
|
id="app-container"
|
||||||
:class="{
|
:class="{
|
||||||
isShare: templateId == 5 && inSharing && !isShareByme,
|
isShare: templateId == 5 && inSharing && !isShareByme,
|
||||||
|
useNuoyun: route.name === 'MeetingNy',
|
||||||
}"
|
}"
|
||||||
ref="appContainerRef"
|
ref="appContainerRef"
|
||||||
>
|
>
|
||||||
@ -18,8 +19,20 @@
|
|||||||
notInSharing: !inSharing,
|
notInSharing: !inSharing,
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<div class="text-label-container" ref="textLabelContainerRef"></div>
|
|
||||||
<div
|
<div
|
||||||
|
class="text-label-container"
|
||||||
|
ref="textLabelContainerRef"
|
||||||
|
v-if="route.name != 'MeetingNy'"
|
||||||
|
></div>
|
||||||
|
<iframe
|
||||||
|
class="nuoyun-ifr"
|
||||||
|
allowfullscreen
|
||||||
|
src="https://console.nuoyun.tv/PlayerEmbed/PlayerEmbed.html?type=1&appid=451264724"
|
||||||
|
frameborder="0"
|
||||||
|
v-if="route.name === 'MeetingNy'"
|
||||||
|
></iframe>
|
||||||
|
<div
|
||||||
|
v-else
|
||||||
id="video-element"
|
id="video-element"
|
||||||
:class="`layout-template-${templateId}`"
|
:class="`layout-template-${templateId}`"
|
||||||
ref="videoElementRef"
|
ref="videoElementRef"
|
||||||
@ -33,13 +46,13 @@
|
|||||||
style="position: absolute; bottom: 1vw; right: 6vw"
|
style="position: absolute; bottom: 1vw; right: 6vw"
|
||||||
/> -->
|
/> -->
|
||||||
<el-button
|
<el-button
|
||||||
v-if="!isFullScreen"
|
v-if="!isFullScreen && route.name !== 'MeetingNy'"
|
||||||
:icon="FullScreen"
|
:icon="FullScreen"
|
||||||
circle
|
circle
|
||||||
@click="setFullScreen"
|
@click="setFullScreen"
|
||||||
></el-button>
|
></el-button>
|
||||||
<el-button
|
<el-button
|
||||||
v-else
|
v-else-if="isFullScreen && route.name !== 'MeetingNy'"
|
||||||
:icon="CloseBold"
|
:icon="CloseBold"
|
||||||
circle
|
circle
|
||||||
@click="quitFullScreen"
|
@click="quitFullScreen"
|
||||||
@ -139,7 +152,7 @@
|
|||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<!-- <mediaCheck @close="startMeeting" /> -->
|
<!-- <mediaCheck @close="startMeeting" /> -->
|
||||||
<mediaCheck @close="startMeeting" />
|
<mediaCheck @close="startMeeting" v-if="route.name != `MeetingNy`" />
|
||||||
|
|
||||||
<questions
|
<questions
|
||||||
mode="1"
|
mode="1"
|
||||||
@ -185,7 +198,7 @@ import {
|
|||||||
generateSignature,
|
generateSignature,
|
||||||
getOnlineUserTotalAndLikes,
|
getOnlineUserTotalAndLikes,
|
||||||
} from "@/api/meeting";
|
} from "@/api/meeting";
|
||||||
import axios from "axios";
|
|
||||||
import Chat from "@/components/chat";
|
import Chat from "@/components/chat";
|
||||||
import mediaCheck from "@/components/mediaCheck.vue";
|
import mediaCheck from "@/components/mediaCheck.vue";
|
||||||
import like from "@/components/like.vue";
|
import like from "@/components/like.vue";
|
||||||
@ -195,7 +208,6 @@ import {
|
|||||||
commitQuestionnaire,
|
commitQuestionnaire,
|
||||||
commitExam,
|
commitExam,
|
||||||
} from "@/api/meeting";
|
} from "@/api/meeting";
|
||||||
// import CountDown from "@/components/countDown.vue";
|
|
||||||
|
|
||||||
const store = useStore();
|
const store = useStore();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
@ -356,26 +368,6 @@ const startMeeting = async () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// const setSize = () => {
|
|
||||||
// meetingWidth.value = meetingContainerRef.value.offsetWidth * 0.88;
|
|
||||||
// meetingHeight.value = (meetingWidth.value * 9) / 16;
|
|
||||||
|
|
||||||
// // videoElementRef.value.style.width = `${meetingWidth.value}px`;
|
|
||||||
// videoElementRef.value.style.height = `${meetingHeight.value + 42}px`;
|
|
||||||
|
|
||||||
// document.querySelector(
|
|
||||||
// "#video-element> div> .zmwebsdk-MuiPaper-root> .zmwebsdk-MuiPaper-root:nth-child(1)"
|
|
||||||
// ).style.width = `${meetingWidth.value}px`;
|
|
||||||
|
|
||||||
// document
|
|
||||||
// .querySelectorAll(
|
|
||||||
// 'div[id*="suspension-view-tabpanel"] > .zmwebsdk-MuiBox-root.zmwebsdk-MuiBox-root'
|
|
||||||
// )
|
|
||||||
// .forEach((el) => {
|
|
||||||
// el.style.height = `${meetingHeight.value}px`;
|
|
||||||
// });
|
|
||||||
// };
|
|
||||||
|
|
||||||
// 设置文本标签
|
// 设置文本标签
|
||||||
const setTextLabel = () => {
|
const setTextLabel = () => {
|
||||||
document.querySelectorAll(".text-tag").forEach((el) => {
|
document.querySelectorAll(".text-tag").forEach((el) => {
|
||||||
@ -455,7 +447,6 @@ setInterval(() => {
|
|||||||
`div[class*="zmwebsdk-makeStyles-inSharing"]`
|
`div[class*="zmwebsdk-makeStyles-inSharing"]`
|
||||||
);
|
);
|
||||||
inSharing.value = screenShareEl ? true : false;
|
inSharing.value = screenShareEl ? true : false;
|
||||||
// ------
|
|
||||||
|
|
||||||
// TODO:查找停止共享按钮元素,判断是否由自己共享,由自己共享则不应用 id 5 布局。
|
// TODO:查找停止共享按钮元素,判断是否由自己共享,由自己共享则不应用 id 5 布局。
|
||||||
if (templateId.value == 5) {
|
if (templateId.value == 5) {
|
||||||
@ -680,13 +671,10 @@ const initWebSocket = () => {
|
|||||||
|
|
||||||
// 监听websocket消息
|
// 监听websocket消息
|
||||||
socket.addEventListener("message", async (event) => {
|
socket.addEventListener("message", async (event) => {
|
||||||
console.log(JSON.parse(event.data));
|
|
||||||
console.log(event.data);
|
|
||||||
let data;
|
let data;
|
||||||
try {
|
try {
|
||||||
data = JSON.parse(JSON.parse(event.data));
|
data = JSON.parse(JSON.parse(event.data));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
|
||||||
data = JSON.parse(event.data);
|
data = JSON.parse(event.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -730,14 +718,13 @@ const initWebSocket = () => {
|
|||||||
// 开始考试时
|
// 开始考试时
|
||||||
else if (data.type === "isStartExam" && route.name === "Meeting") {
|
else if (data.type === "isStartExam" && route.name === "Meeting") {
|
||||||
showExamDialog.value = true;
|
showExamDialog.value = true;
|
||||||
isDuringExamPeriod.value = true;
|
// isDuringExamPeriod.value = true;
|
||||||
}
|
}
|
||||||
// 开始问卷时
|
// 开始问卷时
|
||||||
else if (data.type === "isStartQuestionnaire" && route.name === "Meeting") {
|
else if (data.type === "isStartQuestionnaire" && route.name === "Meeting") {
|
||||||
showQuestionnaireDialog.value = true;
|
showQuestionnaireDialog.value = true;
|
||||||
isDuringQuestionnairePeriod.value = true;
|
isDuringQuestionnairePeriod.value = true;
|
||||||
} else if (data.type === "isRefreshOnlineAndLike") {
|
} else if (data.type === "isRefreshOnlineAndLike") {
|
||||||
console.log(data.type);
|
|
||||||
getLikeAndOnline();
|
getLikeAndOnline();
|
||||||
}
|
}
|
||||||
// 当检测到异地登陆时,强制退出登录,并清除数据
|
// 当检测到异地登陆时,强制退出登录,并清除数据
|
||||||
@ -930,11 +917,10 @@ $meetingComponentHeight: $meetingComponentWitdh * 9 / 16;
|
|||||||
$meetingBackgroundWidth: 80vw; //会议背景宽度
|
$meetingBackgroundWidth: 80vw; //会议背景宽度
|
||||||
$meetingBackgroundHeight: 80vw * 9 / 16;
|
$meetingBackgroundHeight: 80vw * 9 / 16;
|
||||||
|
|
||||||
// @media screen and (max-width: 900px) {
|
|
||||||
.like-row.isShare {
|
.like-row.isShare {
|
||||||
margin-top: 42px;
|
margin-top: 42px;
|
||||||
}
|
}
|
||||||
// }
|
|
||||||
.isShare {
|
.isShare {
|
||||||
.text-label-container {
|
.text-label-container {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
@ -1064,6 +1050,7 @@ $meetingBackgroundHeight: 80vw * 9 / 16;
|
|||||||
padding-right: 20vw;
|
padding-right: 20vw;
|
||||||
background-color: #f5f5f5;
|
background-color: #f5f5f5;
|
||||||
}
|
}
|
||||||
|
|
||||||
#meeting-chat-row {
|
#meeting-chat-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
@ -1085,7 +1072,6 @@ $meetingBackgroundHeight: 80vw * 9 / 16;
|
|||||||
position: relative;
|
position: relative;
|
||||||
.text-label-container {
|
.text-label-container {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
// z-index: -1;
|
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: $meetingBackgroundWidth;
|
width: $meetingBackgroundWidth;
|
||||||
@ -1126,6 +1112,15 @@ $meetingBackgroundHeight: 80vw * 9 / 16;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#app-container.useNuoyun {
|
||||||
|
#meeting-container {
|
||||||
|
padding-top: 0 !important;
|
||||||
|
}
|
||||||
|
.nuoyun-ifr {
|
||||||
|
width: 80vw;
|
||||||
|
height: calc(80vw * 9 / 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
.layout-template-1 {
|
.layout-template-1 {
|
||||||
:deep(div[id*="suspension-view-tabpanel"]
|
:deep(div[id*="suspension-view-tabpanel"]
|
||||||
> .zmwebsdk-MuiBox-root.zmwebsdk-MuiBox-root
|
> .zmwebsdk-MuiBox-root.zmwebsdk-MuiBox-root
|
||||||
|
|||||||
@ -628,19 +628,21 @@ const submitVerify = async (newJoinUserRef) => {
|
|||||||
ElMessage.error("请勾选同意用户协议");
|
ElMessage.error("请勾选同意用户协议");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log(meeting.value.joinType);
|
|
||||||
if (meeting.value.joinType === "1") {
|
|
||||||
store.commit("setJoinUser", newJoinUser.value);
|
store.commit("setJoinUser", newJoinUser.value);
|
||||||
router.push(`/meeting/${meetingId.value}`);
|
router.push(route.query.redirect);
|
||||||
} else if (meeting.value.joinType === "2") {
|
// console.log(meeting.value.joinType);
|
||||||
store.commit("setJoinUser", newJoinUser.value);
|
// if (meeting.value.joinType === "1") {
|
||||||
router.push(`/meeting/${meetingId.value}`);
|
// store.commit("setJoinUser", newJoinUser.value);
|
||||||
} else if (meeting.value.joinType === "3") {
|
// router.push(`/meeting/${meetingId.value}`);
|
||||||
// const { data } = await visitorJoinUser(newJoinUser.value);
|
// } else if (meeting.value.joinType === "2") {
|
||||||
// store.commit("setPassword", data);
|
// store.commit("setJoinUser", newJoinUser.value);
|
||||||
store.commit("setJoinUser", newJoinUser.value);
|
// router.push(`/meeting/${meetingId.value}`);
|
||||||
router.push(`/meeting/${meetingId.value}`);
|
// } else if (meeting.value.joinType === "3") {
|
||||||
}
|
// // const { data } = await visitorJoinUser(newJoinUser.value);
|
||||||
|
// // store.commit("setPassword", data);
|
||||||
|
// store.commit("setJoinUser", newJoinUser.value);
|
||||||
|
// router.push(`/meeting/${meetingId.value}`);
|
||||||
|
// }
|
||||||
};
|
};
|
||||||
const refreshPage = () => {
|
const refreshPage = () => {
|
||||||
const state = meeting.value.status == 1 ? true : false;
|
const state = meeting.value.status == 1 ? true : false;
|
||||||
|
|||||||
Reference in New Issue
Block a user