|
@@ -1,15 +1,17 @@
|
|
|
import { defineComponent, Transition } from "vue";
|
|
|
-import { ElTag } from "element-plus";
|
|
|
+import { ElMessage, ElPopconfirm, ElTag } from "element-plus";
|
|
|
// import VirtualList from 'vue-virtual-list-v3';
|
|
|
// import VirtualList from 'vue3-virtual-list'
|
|
|
// import { RecycleScroller } from 'vue-virtual-scroller'
|
|
|
-import styles from './index.module.less'
|
|
|
-import request from '/src/helpers/request';
|
|
|
-import event, { LIVE_EVENT_MESSAGE } from '/src/components/live-broadcast/event';
|
|
|
-import { state } from '/src/state'
|
|
|
-import dayjs from 'dayjs';
|
|
|
+import styles from "./index.module.less";
|
|
|
+import request from "/src/helpers/request";
|
|
|
+import event, {
|
|
|
+ LIVE_EVENT_MESSAGE,
|
|
|
+} from "/src/components/live-broadcast/event";
|
|
|
+import { state } from "/src/state";
|
|
|
+import dayjs from "dayjs";
|
|
|
import Empty from "/src/components/empty";
|
|
|
-import runtime, * as RuntimeUtils from '/src/components/live-message/model/runtime'
|
|
|
+import runtime, * as RuntimeUtils from "/src/components/live-message/model/runtime";
|
|
|
import runtimeCast, * as RuntimeUtilCast from "/src/components/live-broadcast/runtime";
|
|
|
import { removeToken } from "/src/utils/auth";
|
|
|
|
|
@@ -18,18 +20,18 @@ export default defineComponent({
|
|
|
return {
|
|
|
messageList: [] as any[], // 回复学生列表
|
|
|
loadingMessage: false, // 观看列表状态
|
|
|
- }
|
|
|
+ };
|
|
|
},
|
|
|
mounted() {
|
|
|
- this.loadingMessage = true
|
|
|
+ this.loadingMessage = true;
|
|
|
event.on(LIVE_EVENT_MESSAGE["RC:TxtMsg"], this.onMessage);
|
|
|
// event.on(LIVE_EVENT_MESSAGE["RC:Chatroom:Like"], this.onLike)
|
|
|
- event.on(LIVE_EVENT_MESSAGE["RC:ForcedOffline"], this.onForcedOffline)
|
|
|
- event.on('MESSAGE:Change', this.scrollToBottom) // 添加消息
|
|
|
+ event.on(LIVE_EVENT_MESSAGE["RC:ForcedOffline"], this.onForcedOffline);
|
|
|
+ event.on("MESSAGE:Change", this.scrollToBottom); // 添加消息
|
|
|
setTimeout(() => {
|
|
|
this.loadingMessage = false;
|
|
|
}, 2000);
|
|
|
- this.scrollToBottom()
|
|
|
+ this.scrollToBottom();
|
|
|
},
|
|
|
beforeUnmount() {
|
|
|
event.off(LIVE_EVENT_MESSAGE["RC:TxtMsg"], this.onMessage);
|
|
@@ -39,20 +41,20 @@ export default defineComponent({
|
|
|
async onForcedOffline() {
|
|
|
// 强制退出登录
|
|
|
try {
|
|
|
- await RuntimeUtilCast.leaveIMRoom()
|
|
|
+ await RuntimeUtilCast.leaveIMRoom();
|
|
|
try {
|
|
|
- await request.post('/api-auth/exit', { data: {} });
|
|
|
+ await request.post("/api-auth/exit", { data: {} });
|
|
|
} catch {}
|
|
|
- RuntimeUtilCast.closeDevice('camera')
|
|
|
- RuntimeUtilCast.closeDevice('microphone')
|
|
|
- runtimeCast.syncLikeTimer && clearTimeout(runtimeCast.syncLikeTimer)
|
|
|
- state.user = null
|
|
|
+ RuntimeUtilCast.closeDevice("camera");
|
|
|
+ RuntimeUtilCast.closeDevice("microphone");
|
|
|
+ runtimeCast.syncLikeTimer && clearTimeout(runtimeCast.syncLikeTimer);
|
|
|
+ state.user = null;
|
|
|
removeToken();
|
|
|
(this as any).$router.push({
|
|
|
- path: '/login',
|
|
|
+ path: "/login",
|
|
|
query: {
|
|
|
- ...this.$route.query
|
|
|
- }
|
|
|
+ ...this.$route.query,
|
|
|
+ },
|
|
|
});
|
|
|
} catch (e) {
|
|
|
// TODO: handle error
|
|
@@ -60,73 +62,160 @@ export default defineComponent({
|
|
|
},
|
|
|
onLike(value: any) {
|
|
|
if (value && value.user) {
|
|
|
- const sendTime = dayjs(value.$EventMessage.sentTime || new Date()).format('HH:mm:ss')
|
|
|
- console.log(value, 'like')
|
|
|
+ const sendTime = dayjs(
|
|
|
+ value.$EventMessage.sentTime || new Date()
|
|
|
+ ).format("HH:mm:ss");
|
|
|
+ console.log(value, "like");
|
|
|
let tempObj = {
|
|
|
name: value.user?.name,
|
|
|
id: value.user.id,
|
|
|
isSelf: false,
|
|
|
- content: '给您点了' + value.counts + '个赞',
|
|
|
- sendTime
|
|
|
- }
|
|
|
+ content: "给您点了" + value.counts + "个赞",
|
|
|
+ sendTime,
|
|
|
+ };
|
|
|
RuntimeUtils.addMessage(tempObj);
|
|
|
- this.loadingMessage = false
|
|
|
+ this.loadingMessage = false;
|
|
|
}
|
|
|
- this.scrollToBottom()
|
|
|
+ this.scrollToBottom();
|
|
|
},
|
|
|
onMessage(value: any) {
|
|
|
if (value && value.user) {
|
|
|
- const sendTime = dayjs(value.$EventMessage.sentTime || new Date()).format('HH:mm:ss')
|
|
|
+ const sendTime = dayjs(
|
|
|
+ value.$EventMessage.sentTime || new Date()
|
|
|
+ ).format("HH:mm:ss");
|
|
|
|
|
|
let tempObj = {
|
|
|
name: value.user?.name,
|
|
|
id: value.user.id,
|
|
|
isSelf: false,
|
|
|
content: value.content,
|
|
|
- sendTime
|
|
|
- }
|
|
|
+ sendTime,
|
|
|
+ };
|
|
|
// 判断是否是主播
|
|
|
if (value.user.id === state.user.speakerId) {
|
|
|
- tempObj.isSelf = true
|
|
|
+ tempObj.isSelf = true;
|
|
|
}
|
|
|
// this.messageList.push(tempObj);
|
|
|
RuntimeUtils.addMessage(tempObj);
|
|
|
- this.loadingMessage = false
|
|
|
+ this.loadingMessage = false;
|
|
|
}
|
|
|
- this.scrollToBottom()
|
|
|
+ this.scrollToBottom();
|
|
|
},
|
|
|
scrollToBottom() {
|
|
|
// 默认滚动到底部
|
|
|
this.$nextTick(() => {
|
|
|
- document.querySelector('#tabList')?.scrollTo(0, document.querySelector('#messageList')?.scrollHeight || 0)
|
|
|
- })
|
|
|
- }
|
|
|
+ document
|
|
|
+ .querySelector("#tabList")
|
|
|
+ ?.scrollTo(
|
|
|
+ 0,
|
|
|
+ document.querySelector("#messageList")?.scrollHeight || 0
|
|
|
+ );
|
|
|
+ });
|
|
|
+ },
|
|
|
+ async confirmEvent(item: any) {
|
|
|
+ console.log(item, "item");
|
|
|
+ try {
|
|
|
+ const roomUid = sessionStorage.getItem("roomUid");
|
|
|
+ await request.post("/api-web/imLiveRoomBlack/add", {
|
|
|
+ requestType: "json",
|
|
|
+ data: {
|
|
|
+ userIdList: item.id,
|
|
|
+ roomUid,
|
|
|
+ },
|
|
|
+ });
|
|
|
+
|
|
|
+ ElMessage.success("拉黑成功");
|
|
|
+ } catch {}
|
|
|
+ },
|
|
|
},
|
|
|
render() {
|
|
|
return (
|
|
|
- <div style={{ minHeight: '100%', position: 'relative' }} id="messageList">
|
|
|
- {runtime.messageList.length > 0 ? runtime.messageList.map((item: any) => (
|
|
|
- <div class={[styles.itemContent, styles["slide-top-enter-active"]]}>
|
|
|
- <div class={styles.itemInfo}>
|
|
|
- <div class={styles.itemName}>
|
|
|
- <div class={styles.userName}>
|
|
|
- {item.isSelf ? <ElTag effect="dark" color="#01A79E">主讲人</ElTag> : null}
|
|
|
- <span class={styles['name-style']}>{item.name}{item.system ? null : ':'}</span>
|
|
|
- <span class={[styles.itemText, item.isSelf ? styles.active : null]}>
|
|
|
- {item.content}
|
|
|
- </span>
|
|
|
+ // <el-popconfirm
|
|
|
+ // confirm-button-text="Yes"
|
|
|
+ // cancel-button-text="No"
|
|
|
+ // :icon="InfoFilled"
|
|
|
+ // icon-color="#626AEF"
|
|
|
+ // title="Are you sure to delete this?"
|
|
|
+ // @confirm="confirmEvent"
|
|
|
+ // @cancel="cancelEvent"
|
|
|
+ // >
|
|
|
+ // <template #reference>
|
|
|
+ // <el-button>Delete</el-button>
|
|
|
+ // </template>
|
|
|
+ // </el-popconfirm>
|
|
|
+ <div style={{ minHeight: "100%", position: "relative" }} id="messageList">
|
|
|
+ {runtime.messageList.length > 0 ? (
|
|
|
+ runtime.messageList.map((item: any) => (
|
|
|
+ <div class={[styles.itemContent, styles["slide-top-enter-active"]]}>
|
|
|
+ <div class={styles.itemInfo}>
|
|
|
+ <div class={styles.itemName}>
|
|
|
+ <div class={styles.userName}>
|
|
|
+ {item.isSelf ? (
|
|
|
+ <ElTag effect="dark" color="#01A79E">
|
|
|
+ 主讲人
|
|
|
+ </ElTag>
|
|
|
+ ) : null}
|
|
|
+ <ElPopconfirm
|
|
|
+ confirmButtonText="确定"
|
|
|
+ cancelButtonText="取消"
|
|
|
+ title="加入黑名单后,学员无法发言和连麦?"
|
|
|
+ onConfirm={() => {
|
|
|
+ this.confirmEvent(item);
|
|
|
+ }}
|
|
|
+ v-slots={{
|
|
|
+ reference: () => (
|
|
|
+ <span class={styles["name-style"]}>
|
|
|
+ {item.name}
|
|
|
+ {item.system ? null : ":"}
|
|
|
+ </span>
|
|
|
+ ),
|
|
|
+ }}
|
|
|
+ ></ElPopconfirm>
|
|
|
+
|
|
|
+ <span
|
|
|
+ class={[
|
|
|
+ styles.itemText,
|
|
|
+ item.isSelf ? styles.active : null,
|
|
|
+ ]}
|
|
|
+ >
|
|
|
+ {item.content}
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ <p class={styles.rightTime}>{item.sendTime}</p>
|
|
|
</div>
|
|
|
- <p class={styles.rightTime}>{item.sendTime}</p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ ))
|
|
|
+ ) : this.loadingMessage ? (
|
|
|
+ <div class={styles.loadingStyle}>
|
|
|
+ <div
|
|
|
+ class="el-loading-mask"
|
|
|
+ style="background-color: rgba(0, 0, 0, 0.8);"
|
|
|
+ >
|
|
|
+ <div class="el-loading-spinner">
|
|
|
+ <svg class="circular" viewBox="25 25 50 50">
|
|
|
+ <circle
|
|
|
+ class="path"
|
|
|
+ cx="50"
|
|
|
+ cy="50"
|
|
|
+ r="20"
|
|
|
+ fill="none"
|
|
|
+ ></circle>
|
|
|
+ </svg>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- )) : (this.loadingMessage ? <div class={styles.loadingStyle}>
|
|
|
- <div class="el-loading-mask" style="background-color: rgba(0, 0, 0, 0.8);"><div class="el-loading-spinner"><svg class="circular" viewBox="25 25 50 50"><circle class="path" cx="50" cy="50" r="20" fill="none"></circle></svg></div></div>
|
|
|
- </div> : <Empty style={{ paddingTop: '120px' }} text="暂无学员互动!" icon="noData-no-message" />)}
|
|
|
+ ) : (
|
|
|
+ <Empty
|
|
|
+ style={{ paddingTop: "120px" }}
|
|
|
+ text="暂无学员互动!"
|
|
|
+ icon="noData-no-message"
|
|
|
+ />
|
|
|
+ )}
|
|
|
</div>
|
|
|
- )
|
|
|
- }
|
|
|
-})
|
|
|
+ );
|
|
|
+ },
|
|
|
+});
|
|
|
|
|
|
function source(source: any) {
|
|
|
throw new Error("Function not implemented.");
|