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.
414 lines
9.6 KiB
414 lines
9.6 KiB
|
1 month ago
|
<template>
|
||
|
|
<div class="quality-control-container">
|
||
|
|
<!-- 顶部导航栏 -->
|
||
|
|
<div class="header-bar">
|
||
|
|
<div class="header-left">
|
||
|
|
<span class="logo-text">信联</span>
|
||
|
|
</div>
|
||
|
|
<div class="header-center">
|
||
|
|
<span class="title">超声事业部的云质控</span>
|
||
|
|
</div>
|
||
|
|
<div class="header-right">
|
||
|
|
<el-button
|
||
|
|
icon="el-icon-minus"
|
||
|
|
type="text"
|
||
|
|
class="min-btn"
|
||
|
|
@click="minimize"
|
||
|
|
></el-button>
|
||
|
|
<el-button
|
||
|
|
icon="el-icon-close"
|
||
|
|
type="text"
|
||
|
|
class="close-btn"
|
||
|
|
@click="close"
|
||
|
|
></el-button>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- 2x2 分屏视频区域 -->
|
||
|
|
<div class="grid-container">
|
||
|
|
<div v-for="(slot, index) in gridSlots" :key="index" class="grid-slot">
|
||
|
|
<!-- 有成员时的状态 -->
|
||
|
|
<template v-if="slot.user">
|
||
|
|
<!-- 左上角信号强度 -->
|
||
|
|
<div class="signal-icon">
|
||
|
|
<i
|
||
|
|
v-for="n in 5"
|
||
|
|
:key="n"
|
||
|
|
class="bar"
|
||
|
|
:class="{ active: n <= slot.signalLevel }"
|
||
|
|
></i>
|
||
|
|
</div>
|
||
|
|
<!-- 顶部用户名称 -->
|
||
|
|
<div class="slot-name">{{ slot.user.name }}</div>
|
||
|
|
<!-- 取消质控按钮 -->
|
||
|
|
<el-button
|
||
|
|
class="cancel-btn"
|
||
|
|
type="info"
|
||
|
|
size="mini"
|
||
|
|
@click="cancelQualityControl(index)"
|
||
|
|
>
|
||
|
|
取消质控
|
||
|
|
</el-button>
|
||
|
|
<!-- 有成员时的用户信息 -->
|
||
|
|
<div class="user-btn" @click="showUserDetail(slot.user)">
|
||
|
|
<el-avatar :size="56" :src="slot.user.avatar" class="user-avatar">
|
||
|
|
<span class="avatar-text">{{ slot.user.name.charAt(0) }}</span>
|
||
|
|
</el-avatar>
|
||
|
|
<div class="user-info-text">
|
||
|
|
<span class="user-name">{{ slot.user.name }}</span>
|
||
|
|
<span :class="['status-dot', slot.user.status === '在线' ? 'online' : 'offline']"></span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</template>
|
||
|
|
|
||
|
|
<!-- 无成员时的添加按钮 -->
|
||
|
|
<div v-else class="add-btn" @click="openAddUserDialog(index)">
|
||
|
|
<i class="el-icon-plus"></i>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- 添加质控成员弹窗 -->
|
||
|
|
<CreateGroupDialog
|
||
|
|
title="邀请参加人员"
|
||
|
|
:visible.sync="showAddDialog"
|
||
|
|
:recent-contacts="recentContacts"
|
||
|
|
:recent-groups="recentGroups"
|
||
|
|
:min-select-count="1"
|
||
|
|
confirm-text="确定"
|
||
|
|
@create-success="handleAddMembers"
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
</template>
|
||
|
|
|
||
|
|
<script>
|
||
|
|
import CreateGroupDialog from "@/views/message/components/CreateGroupDialog";
|
||
|
|
|
||
|
|
export default {
|
||
|
|
name: "CloudQualityControl",
|
||
|
|
components: {
|
||
|
|
CreateGroupDialog,
|
||
|
|
},
|
||
|
|
data() {
|
||
|
|
return {
|
||
|
|
// 分屏数据(4个位置)
|
||
|
|
gridSlots: [
|
||
|
|
{
|
||
|
|
index: 0,
|
||
|
|
signalLevel: 5,
|
||
|
|
user: {
|
||
|
|
name: "基层医生",
|
||
|
|
status: "在线",
|
||
|
|
avatar: "https://img.icons8.com/fluency/96/doctor-male.png",
|
||
|
|
},
|
||
|
|
},
|
||
|
|
{
|
||
|
|
index: 1,
|
||
|
|
signalLevel: 0,
|
||
|
|
user: null,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
index: 2,
|
||
|
|
signalLevel: 5,
|
||
|
|
user: {
|
||
|
|
name: "于春晓",
|
||
|
|
status: "离线",
|
||
|
|
avatar: "https://img.icons8.com/fluency/96/doctor-male.png",
|
||
|
|
},
|
||
|
|
},
|
||
|
|
{
|
||
|
|
index: 3,
|
||
|
|
signalLevel: 0,
|
||
|
|
user: null,
|
||
|
|
},
|
||
|
|
],
|
||
|
|
// 添加弹窗状态
|
||
|
|
showAddDialog: false,
|
||
|
|
currentAddIndex: null,
|
||
|
|
// 联系人数据
|
||
|
|
recentContacts: [
|
||
|
|
{ id: "1", name: "基层医生(在线)", avatar: "" },
|
||
|
|
{ id: "2", name: "于春晓", avatar: "" },
|
||
|
|
{ id: "3", name: "郭君", avatar: "" },
|
||
|
|
{ id: "4", name: "张医生", avatar: "" },
|
||
|
|
{ id: "5", name: "李护士", avatar: "" },
|
||
|
|
{ id: "6", name: "王主任", avatar: "" },
|
||
|
|
],
|
||
|
|
recentGroups: [
|
||
|
|
{
|
||
|
|
id: "group1",
|
||
|
|
name: "医疗专家组",
|
||
|
|
avatar: "",
|
||
|
|
expanded: false,
|
||
|
|
members: [
|
||
|
|
{ id: "m1", name: "张医生", avatar: "", selected: false },
|
||
|
|
{ id: "m2", name: "李护士", avatar: "", selected: false },
|
||
|
|
{ id: "m3", name: "王主任", avatar: "", selected: false },
|
||
|
|
],
|
||
|
|
},
|
||
|
|
{
|
||
|
|
id: "group2",
|
||
|
|
name: "超声科团队",
|
||
|
|
avatar: "",
|
||
|
|
expanded: false,
|
||
|
|
members: [
|
||
|
|
{ id: "m4", name: "陈医生", avatar: "", selected: false },
|
||
|
|
{ id: "m5", name: "刘医生", avatar: "", selected: false },
|
||
|
|
],
|
||
|
|
},
|
||
|
|
],
|
||
|
|
};
|
||
|
|
},
|
||
|
|
mounted() {
|
||
|
|
this.$store.dispatch("app/toggleSideBarHide", true);
|
||
|
|
this.$store.dispatch("settings/changeSetting", {
|
||
|
|
key: "fixedHeader",
|
||
|
|
value: false,
|
||
|
|
});
|
||
|
|
},
|
||
|
|
methods: {
|
||
|
|
// 取消质控
|
||
|
|
cancelQualityControl(index) {
|
||
|
|
this.$confirm("确定要取消该成员的质控吗?", "提示", {
|
||
|
|
confirmButtonText: "确定",
|
||
|
|
cancelButtonText: "取消",
|
||
|
|
type: "warning",
|
||
|
|
})
|
||
|
|
.then(() => {
|
||
|
|
this.gridSlots[index].user = null;
|
||
|
|
this.gridSlots[index].signalLevel = 0;
|
||
|
|
this.$message({
|
||
|
|
type: "success",
|
||
|
|
message: "已取消质控",
|
||
|
|
});
|
||
|
|
})
|
||
|
|
.catch(() => {});
|
||
|
|
},
|
||
|
|
// 打开添加用户弹窗
|
||
|
|
openAddUserDialog(index) {
|
||
|
|
this.currentAddIndex = index;
|
||
|
|
this.showAddDialog = true;
|
||
|
|
},
|
||
|
|
// 显示用户详情
|
||
|
|
showUserDetail(user) {
|
||
|
|
this.$message.info(`用户: ${user.name}`)
|
||
|
|
},
|
||
|
|
// 添加成员成功回调
|
||
|
|
handleAddMembers(members) {
|
||
|
|
// 找到第一个空的位置添加成员
|
||
|
|
const emptySlots = this.gridSlots
|
||
|
|
.map((slot, index) => ({ slot, index }))
|
||
|
|
.filter((item) => !item.slot.user);
|
||
|
|
|
||
|
|
members.forEach((member, idx) => {
|
||
|
|
if (emptySlots[idx]) {
|
||
|
|
this.gridSlots[emptySlots[idx].index].user = {
|
||
|
|
name: member.name,
|
||
|
|
status: "在线",
|
||
|
|
avatar:
|
||
|
|
member.avatar ||
|
||
|
|
"https://img.icons8.com/fluency/96/doctor-male.png",
|
||
|
|
};
|
||
|
|
this.gridSlots[emptySlots[idx].index].signalLevel = 5;
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
this.showAddDialog = false;
|
||
|
|
this.$message({
|
||
|
|
type: "success",
|
||
|
|
message: `已添加 ${members.length} 位质控成员`,
|
||
|
|
});
|
||
|
|
},
|
||
|
|
// 窗口最小化(仅占位)
|
||
|
|
minimize() {
|
||
|
|
this.$message.info("窗口最小化");
|
||
|
|
},
|
||
|
|
// 关闭窗口
|
||
|
|
close() {
|
||
|
|
this.$confirm("确定要退出此次云质控吗?", "提示", {
|
||
|
|
confirmButtonText: "确定",
|
||
|
|
cancelButtonText: "取消",
|
||
|
|
type: "warning",
|
||
|
|
})
|
||
|
|
.then(() => {
|
||
|
|
this.$message({
|
||
|
|
type: "success",
|
||
|
|
message: "已退出云质控",
|
||
|
|
});
|
||
|
|
})
|
||
|
|
.catch(() => {});
|
||
|
|
},
|
||
|
|
},
|
||
|
|
};
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<style scoped>
|
||
|
|
/* 整体容器 */
|
||
|
|
.quality-control-container {
|
||
|
|
width: 100vw;
|
||
|
|
height: 100vh;
|
||
|
|
background-color: #00413d;
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
color: #fff;
|
||
|
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
||
|
|
"Helvetica Neue", Arial, sans-serif;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* 顶部导航栏 */
|
||
|
|
.header-bar {
|
||
|
|
height: 30px;
|
||
|
|
background-color: #00615c;
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: space-between;
|
||
|
|
padding: 0 10px;
|
||
|
|
}
|
||
|
|
.logo-text {
|
||
|
|
color: #fff;
|
||
|
|
font-weight: bold;
|
||
|
|
font-size: 14px;
|
||
|
|
}
|
||
|
|
.header-center {
|
||
|
|
color: #fff;
|
||
|
|
font-size: 12px;
|
||
|
|
}
|
||
|
|
.header-right .el-button {
|
||
|
|
color: #fff;
|
||
|
|
padding: 0 5px;
|
||
|
|
font-size: 12px;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* 2x2 网格布局 */
|
||
|
|
.grid-container {
|
||
|
|
flex: 1;
|
||
|
|
display: grid;
|
||
|
|
grid-template-columns: 1fr 1fr;
|
||
|
|
grid-template-rows: 1fr 1fr;
|
||
|
|
gap: 2px;
|
||
|
|
background-color: #007570;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* 单个分屏 */
|
||
|
|
.grid-slot {
|
||
|
|
background-color: #00413d;
|
||
|
|
position: relative;
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: center;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* 信号强度图标 */
|
||
|
|
.signal-icon {
|
||
|
|
position: absolute;
|
||
|
|
top: 8px;
|
||
|
|
left: 8px;
|
||
|
|
display: flex;
|
||
|
|
align-items: flex-end;
|
||
|
|
gap: 2px;
|
||
|
|
height: 14px;
|
||
|
|
}
|
||
|
|
.signal-icon .bar {
|
||
|
|
width: 3px;
|
||
|
|
background: #666;
|
||
|
|
border-radius: 1px;
|
||
|
|
}
|
||
|
|
.signal-icon .bar:nth-child(1) {
|
||
|
|
height: 4px;
|
||
|
|
}
|
||
|
|
.signal-icon .bar:nth-child(2) {
|
||
|
|
height: 7px;
|
||
|
|
}
|
||
|
|
.signal-icon .bar:nth-child(3) {
|
||
|
|
height: 10px;
|
||
|
|
}
|
||
|
|
.signal-icon .bar:nth-child(4) {
|
||
|
|
height: 13px;
|
||
|
|
}
|
||
|
|
.signal-icon .bar:nth-child(5) {
|
||
|
|
height: 16px;
|
||
|
|
}
|
||
|
|
.signal-icon .bar.active {
|
||
|
|
background: #4cd964;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* 顶部用户名 */
|
||
|
|
.slot-name {
|
||
|
|
position: absolute;
|
||
|
|
top: 8px;
|
||
|
|
left: 50%;
|
||
|
|
transform: translateX(-50%);
|
||
|
|
font-size: 12px;
|
||
|
|
color: #fff;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* 取消质控按钮 */
|
||
|
|
.cancel-btn {
|
||
|
|
position: absolute;
|
||
|
|
top: 8px;
|
||
|
|
right: 8px;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* 添加质控按钮 */
|
||
|
|
.add-btn {
|
||
|
|
width: 56px;
|
||
|
|
height: 56px;
|
||
|
|
background-color: #007570;
|
||
|
|
border-radius: 10px;
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: center;
|
||
|
|
cursor: pointer;
|
||
|
|
transition: background 0.2s;
|
||
|
|
}
|
||
|
|
.add-btn:hover {
|
||
|
|
background-color: #00918a;
|
||
|
|
}
|
||
|
|
.add-btn .el-icon-plus {
|
||
|
|
font-size: 26px;
|
||
|
|
color: #fff;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* 有成员时的用户按钮 */
|
||
|
|
.user-btn {
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
align-items: center;
|
||
|
|
gap: 6px;
|
||
|
|
cursor: pointer;
|
||
|
|
}
|
||
|
|
.user-avatar {
|
||
|
|
width: 56px;
|
||
|
|
height: 56px;
|
||
|
|
border-radius: 10px;
|
||
|
|
background-color: #00b3ad;
|
||
|
|
transition: background 0.2s;
|
||
|
|
}
|
||
|
|
.user-avatar:hover {
|
||
|
|
background-color: #00d4cd;
|
||
|
|
}
|
||
|
|
.avatar-text {
|
||
|
|
font-size: 20px;
|
||
|
|
color: #fff;
|
||
|
|
}
|
||
|
|
.user-info-text {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 4px;
|
||
|
|
}
|
||
|
|
.user-info-text .user-name {
|
||
|
|
font-size: 12px;
|
||
|
|
color: #fff;
|
||
|
|
}
|
||
|
|
.status-dot {
|
||
|
|
width: 8px;
|
||
|
|
height: 8px;
|
||
|
|
border-radius: 50%;
|
||
|
|
}
|
||
|
|
.status-dot.online {
|
||
|
|
background-color: #4cd964;
|
||
|
|
}
|
||
|
|
.status-dot.offline {
|
||
|
|
background-color: #999;
|
||
|
|
}
|
||
|
|
</style>
|