海信医疗-远程超声管理平台-信创国产化
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

653 lines
17 KiB

<template>
<div class="meeting-container">
<!-- 顶部导航栏 -->
<header class="top-bar">
<div class="logo">
<img src="@/assets/logo/logo.png" />
<span>信联</span>
</div>
<div class="title">{{ queryParams.name }}</div>
<div class="window-controls">
<i class="el-icon-minus" @click="minimizeWindow"></i>
<i class="el-icon-close" @click="closeWindow"></i>
</div>
</header>
<!-- 主画面区域2x2网格布局 -->
<main class="main-content">
<div class="video-grid" v-for="(item, index) in list" :key="index">
<div class="video-box">
<!-- 空状态加号靠右垂直居中 -->
<div v-if="!item.user || !item.user.id" class="empty-state">
<button class="add-user-btn" @click="handleUpdate(index)">
<i class="el-icon-plus"></i>
</button>
</div>
<!-- 有用户时显示内容 -->
<div v-else class="user-state">
<!-- 单元格顶部行:左音量、中姓名、右取消质控 -->
<div class="cell-top-bar">
<div class="signal-icon">
<i
v-for="n in 5"
:key="n"
class="bar"
:class="{ active: n <= item.signalLevel }"
/>
</div>
<div class="grid-top-name">{{ item.user.name }}</div>
<div class="cancel-qc" @click="handleDelete(item, index, form)">
取消质控
</div>
</div>
<!-- 中间横向:头像 + 名字 + 离线按钮 -->
<div class="user-info">
<img
v-if="item.user.avatar"
:src="getAvatarUrl(item.user.avatar)"
class="user-avatar"
/>
<div v-else class="default-avatar">
{{ item.user.name.charAt(0) || "?" }}
</div>
<span class="user-name">{{ item.user.name }}</span>
<span class="offline-tag">离线</span>
</div>
</div>
</div>
</div>
</main>
<!-- 底部控制栏 -->
<!-- <footer class="bottom-bar">
<div class="control-left">
<button class="control-btn" @click="toggleMute">
<i v-if="!isMuted" class="el-icon-microphone"></i>
<i v-else class="el-icon-microphone-off"></i>
<span>{{ isMuted ? "取消静音" : "静音" }}</span>
</button>
</div>
<div class="control-center">
<span class="meeting-status" :class="{ joined: isJoined }">
{{ isJoined ? "已进入房间" : "未进入房间" }}
</span>
</div>
<div class="control-right">
<button class="control-btn secondary" @click="leaveRoom">
<i class="el-icon-log-out"></i>
<span>退出会议</span>
</button>
<button class="control-btn danger" @click="stopMeeting">
<i class="el-icon-stop"></i>
<span>结束会议</span>
</button>
</div>
</footer> -->
<!-- 添加或邀请修改邀请公告对话框 -->
<CreateGroupDialog
ref="createGroupDialogRef"
title="选择人员"
:min-select-count="1"
@confirm="submitForm"
/>
</div>
</template>
<script>
import CreateGroupDialog from "@/views/message/components/CreateGroupDialog";
import {
postQualityCreate,
postQualityInvite,
postUserInfo,
postQualityQuit,
postQualityStop,
} from "@/api/videoCommunication";
export default {
name: "qualityControl",
components: {
CreateGroupDialog,
},
data() {
return {
loading: true,
total: 0,
list: [
{ signalLevel: 5, user: {} },
{ signalLevel: 4, user: {} },
{ signalLevel: 3, user: {} },
{ signalLevel: 2, user: {} },
],
queryParams: {
name: "测试部门的云质控",
room_id: "6689110",
},
index: 0,
form: {},
// 语音会议相关状态
// isJoined: false,
// isMuted: false,
// storageKey: "HiWebRTC",
// serviceID: "90f4d5a954ab449e9b6aac92",
// serviceKey: "2c17c6393771ee3048ae34d6b380c5ec",
// BasicRoomServiceToken: "https://121.36.105.19:7080/v1/auth/token",
// userID: "",
// joinRetry: 0,
// maxRetry: 3,
};
},
mounted() {
this.$store.dispatch("app/toggleSideBarHide", true);
this.$store.dispatch("settings/changeSetting", {
key: "fixedHeader",
value: false,
});
this.$store.dispatch("settings/changeSetting", {
key: "tagsView",
value: false,
});
this.getList();
// this.initRTC();
},
// beforeUnmount() {
// this.leaveRoom();
// this.unbindEvent();
// },
methods: {
// 初始化RTC SDK
// initRTC() {
// let localData = window.localStorage.getItem(this.storageKey);
// if (localData) {
// localData = JSON.parse(localData);
// this.serviceID = localData.serviceID;
// this.serviceKey = localData.serviceKey;
// this.BasicRoomServiceToken = localData.BasicRoomServiceToken;
// }
// if (window.hirtcwebsdk) {
// window.hirtcwebsdk.init({
// leaveBeforeUnload: false,
// debug: false,
// forceArea: true,
// });
// this.bindEvent();
// this.userID =
// this.$store.state.user.userInfo.id ||
// new Date().getTime().toString(16).split("").reverse().join("");
// }
// },
// // 绑定事件
// bindEvent() {
// if (!window.hirtcwebsdk) return;
// window.hirtcwebsdk.on("joined", (users) => {
// this.handleJoined(users);
// });
// window.hirtcwebsdk.on("leave", () => {
// this.handleLeave();
// });
// window.hirtcwebsdk.on("error", (errorCode, detail) => {
// this.handleError(errorCode, detail);
// });
// window.hirtcwebsdk.on("someoneJoin", (userID) => {
// this.handleSomeoneJoin(userID);
// });
// window.hirtcwebsdk.on("someoneLeave", (userID) => {
// this.handleSomeoneLeave(userID);
// });
// },
// // 解绑事件
// unbindEvent() {
// if (!window.hirtcwebsdk) return;
// window.hirtcwebsdk.off("joined");
// window.hirtcwebsdk.off("leave");
// window.hirtcwebsdk.off("error");
// window.hirtcwebsdk.off("someoneJoin");
// window.hirtcwebsdk.off("someoneLeave");
// },
// // 进入房间
// joinRoom() {
// if (!window.hirtcwebsdk) {
// this.$message.error("RTC SDK 未初始化");
// return;
// }
// window.hirtcwebsdk.join({
// serviceID: this.serviceID,
// serviceKey: this.serviceKey,
// BasicRoomServiceToken: this.BasicRoomServiceToken,
// userID: this.userID.toString(),
// roomID: this.queryParams.room_id,
// joinConfig: {
// audio: true,
// video: false,
// },
// });
// },
// // 离开房间
// leaveRoom() {
// if (!window.hirtcwebsdk || !this.isJoined) return;
// window.hirtcwebsdk.leave();
// },
// // 结束会议
// stopMeeting() {
// this.$confirm("确定要结束本次会议吗?", "提示", {
// type: "warning",
// confirmButtonText: "确定",
// cancelButtonText: "取消",
// })
// .then(() => {
// // 调用后端接口结束质控
// postQualityStop({
// quality_id: this.form.quality_id,
// })
// .then(() => {
// this.$modal.msgSuccess("会议已结束");
// this.leaveRoom();
// this.closeWindow();
// })
// .catch(() => {
// this.$modal.msgError("结束会议失败");
// });
// })
// .catch(() => {});
// },
// // 切换麦克风
// toggleMute() {
// if (!window.hirtcwebsdk || !this.isJoined) {
// this.$message.warning("请先进入房间");
// return;
// }
// if (this.isMuted) {
// // 取消静音
// window.hirtcwebsdk.unmuteAudio();
// this.isMuted = false;
// this.$message.success("麦克风已开启");
// } else {
// // 静音
// window.hirtcwebsdk.muteAudio();
// this.isMuted = true;
// this.$message.success("麦克风已关闭");
// }
// },
// // 进房成功回调
// handleJoined(users) {
// this.joinRetry = 0;
// this.isJoined = true;
// this.$message.success("已进入语音房间");
// // 自动开启麦克风
// if (window.hirtcwebsdk) {
// window.hirtcwebsdk.unmuteAudio();
// }
// },
// // 离开房间回调
// handleLeave() {
// this.isJoined = false;
// this.isMuted = false;
// this.$message.info("已离开房间");
// },
// // 错误处理
// handleError(errorCode, detail) {
// if (errorCode === window.hirtcwebsdk?.ErrorCode.JoinError) {
// if (this.joinRetry < this.maxRetry) {
// this.joinRetry++;
// this.joinRoom();
// } else {
// this.joinRetry = 0;
// this.$message.error("进房失败,请检查网络");
// }
// }
// },
// // 有人进入
// handleSomeoneJoin(userID) {
// this.$message.info(`${userID} 进入了房间`);
// },
// // 有人离开
// handleSomeoneLeave(userID) {
// this.$message.info(`${userID} 离开了房间`);
// },
minimizeWindow() {
this.$router.push("/video/index");
},
closeWindow() {
this.$confirm("确定要退出本次质控吗?", "提示", {
type: "warning",
confirmButtonText: "确定",
cancelButtonText: "取消",
})
.then(() => {
// this.leaveRoom();
this.$store.dispatch("app/toggleSideBarHide", false);
this.$store.dispatch("settings/changeSetting", {
key: "fixedHeader",
value: true,
});
this.$store.dispatch("settings/changeSetting", {
key: "tagsView",
value: true,
});
this.$router.push("/");
})
.catch(() => {});
},
getList() {
this.loading = true;
postQualityCreate({
avatar: "",
init_users: [],
invite_code: "1234",
name: this.queryParams.name,
room_id: this.queryParams.room_id,
}).then((response) => {
this.form = response.data;
this.loading = false;
// 创建质控成功后自动进入语音房间
// this.joinRoom();
});
},
getAvatarUrl(avatar) {
return this.$store.getters.config.MINIO_ENDPOINT_HTTPS + avatar;
},
handleUpdate(index) {
this.index = index;
this.$refs.createGroupDialogRef.show();
},
submitForm(selectedMembers) {
const inviteArr = selectedMembers.map((item) => item.id);
postQualityInvite({
invite_users: inviteArr,
quality_id: this.form.quality_id,
}).then(() => {
this.$modal.msgSuccess("邀请成功");
this.handleViewData({ user_id: selectedMembers[0].id });
});
},
handleViewData(row) {
postUserInfo(row).then((response) => {
this.list[this.index].user = { ...response.data };
});
},
handleDelete(row, index, form) {
const that = this;
this.$modal
.confirm("确定要取消该成员的质控吗?")
.then(function () {
return postQualityQuit({
invite_type_detail: 9,
quality_id: form.quality_id,
user_id: row.user.id,
});
})
.then(() => {
that.list[index].user = {};
that.$modal.msgSuccess("取消质控成功");
})
.catch(() => {});
},
},
};
</script>
<style lang="scss">
.meeting-container {
display: flex;
flex-direction: column;
height: 100vh;
background-color: #004d40;
color: #ffffff;
.top-bar {
height: 40px;
background: #00695c;
display: flex;
align-items: center;
padding: 0 15px;
justify-content: space-between;
.logo {
display: flex;
align-items: center;
font-weight: 600;
img {
width: 28px;
margin-right: 8px;
}
}
.title {
position: absolute;
left: 50%;
transform: translateX(-50%);
font-size: 18px;
color: #ffffff;
font-weight: 500;
}
.window-controls {
display: flex;
align-items: center;
i {
margin-left: 15px;
cursor: pointer;
font-size: 20px;
color: #ffffff;
}
}
}
.main-content {
flex: 1;
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-rows: repeat(2, 1fr);
gap: 1px;
background-color: #00796b;
.video-grid {
background-color: #004d40;
position: relative;
.video-box {
width: 100%;
height: 100%;
position: relative;
.empty-state {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
.add-user-btn {
width: 90px;
height: 90px;
border-radius: 14px;
background-color: #00897b;
border: none;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
i {
font-size: 42px;
color: #ffffff;
}
}
}
.user-state {
width: 100%;
height: 100%;
position: relative;
.cell-top-bar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 10px;
border-bottom: 1px solid #00695c;
.signal-icon {
display: flex;
align-items: flex-end;
gap: 2px;
height: 14px;
z-index: 10;
.bar {
width: 3px;
background: #666;
border-radius: 1px;
&:nth-child(1) {
height: 4px;
}
&:nth-child(2) {
height: 7px;
}
&:nth-child(3) {
height: 10px;
}
&:nth-child(4) {
height: 13px;
}
&:nth-child(5) {
height: 16px;
}
&.active {
background: #4cd964;
}
}
}
.grid-top-name {
font-size: 18px;
}
.cancel-qc {
background: #fff;
color: #333;
padding: 4px 12px;
border-radius: 3px;
font-size: 15px;
cursor: pointer;
}
}
.user-info {
height: calc(100% - 45px);
display: flex;
align-items: center;
justify-content: center;
gap: 16px;
.user-avatar {
width: 90px;
height: 90px;
border-radius: 14px;
object-fit: cover;
}
.default-avatar {
width: 90px;
height: 90px;
display: flex;
align-items: center;
justify-content: center;
font-size: 26px;
}
.user-name {
font-size: 18px;
}
.offline-tag {
background: #00897b;
padding: 8px 22px;
border-radius: 6px;
font-size: 16px;
}
}
}
}
}
}
.bottom-bar {
height: 60px;
background: #00695c;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 20px;
border-top: 1px solid #00796b;
.control-left {
display: flex;
gap: 10px;
}
.control-center {
.meeting-status {
padding: 8px 20px;
border-radius: 20px;
background: #004d40;
color: #fff;
font-size: 14px;
&.joined {
background: #4cd964;
color: #000;
}
}
}
.control-right {
display: flex;
gap: 10px;
}
.control-btn {
display: flex;
align-items: center;
gap: 6px;
padding: 8px 20px;
border-radius: 20px;
border: none;
cursor: pointer;
font-size: 14px;
transition: all 0.3s ease;
background: #00897b;
color: #fff;
&:hover {
background: #00a085;
}
&.secondary {
background: #546e7a;
&:hover {
background: #607d8b;
}
}
&.danger {
background: #ef5350;
&:hover {
background: #e53935;
}
}
i {
font-size: 16px;
}
}
}
}
</style>