rax-medical/src/views/remote-manage/remote-control.vue
2025-02-12 14:15:51 +08:00

1111 lines
43 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="remote-box" id="screenBox">
<div class="main-box">
<div class="left-box">
<h3>{{ currentRemote?.taskName }}</h3>
<chart-line ref="chartDom1" class="chart-line" :names="['BIS', 'HR']"
@exception-event="vitalExcepEvent"></chart-line>
<chart-line ref="chartDom2" class="chart-line" :names="['SBP', 'DBP']"
@exception-event="vitalExcepEvent"></chart-line>
<chart-line ref="chartDom3" class="chart-line" :names="['SPO2', 'TEMP']"
@exception-event="vitalExcepEvent"></chart-line>
<!-- <chart-ecg ref="chartDom4" class="chart-ecg" :name="['CH1', 'CH2']"
@exception-event="vitalExcepEvent"></chart-ecg>-->
</div>
<div class="center-box">
<div class="body-box">
<div class="body-img">
<img src="@/assets/imgs/main_body.png" style="width: 100%;height: 100%;"/>
<img class="lung-img" :class="{ 'shake_1': lungAlarm }"
:src="lungAlarm ? imgLungAlarm : imgLung">
<img class="heart-img" :class="{ 'shake_1': heartAlarm }"
:src="heartAlarm ? imgHeartAlarm : imgHeart">
</div>
</div>
<!-- <div class="btn-box">-->
<!-- <el-button class="start-btn" color="#F80000" @click="startAI">-->
<!-- 开始-->
<!-- </el-button>-->
<!-- <div class="right-btn-box">-->
<!-- <el-button :class="{ 'active': isAIDose }" size="small" @click="">AI给药</el-button>-->
<!-- <el-button :class="{ 'active': !isAIDose }" size="small">人工给药</el-button>-->
<!-- </div>-->
<!-- </div>-->
</div>
<div class="right-box">
<div class="top-btn-box">
<div class="top-left-btn-box">
<!-- <el-select v-model="database" filterable placeholder="Select" style="width: 100%;"-->
<!-- @change="selectDatabase">-->
<!-- <el-option v-for="item in databaseOptions" :key="item.value" :label="item.label"-->
<!-- :value="item.value"/>-->
<!-- </el-select>-->
<el-button color="#C77000" style="width: 200px;" @click="viewPatientInfo">患者信息</el-button>
<!-- <el-button color="#C77000" style="width: 150px;">已连接</el-button>-->
<!-- <el-button color="#C77000" >机器人运行正常</el-button>-->
</div>
<el-button color="#e0e0e0" @click="backRemote">
<el-icon>
<Back/>
</el-icon>
返回
</el-button>
</div>
<div class="monitoring-message">
<div class="left-box">
<span class="unusual-title">异常信息</span>
<ul ref="unusualMsgRef" class="unusual-box">
<li v-for="item in unusual" :key="item">{{ item }}</li>
</ul>
</div>
<div class="right-box">
<!-- <div class="video-box" @click="playPause">-->
<!-- <div class="icon-box">-->
<!-- <el-icon v-if="isVideoPlay">-->
<!-- <VideoPause/>-->
<!-- </el-icon>-->
<!-- <el-icon v-else>-->
<!-- <VideoPlay/>-->
<!-- </el-icon>-->
<!-- </div>-->
<!-- &lt;!&ndash; poster="@/assets/imgs/video_bck.png" &ndash;&gt;-->
<!-- <video ref="liveVideo">-->
<!-- <source src="@/assets/medical.mp4" type="video/mp4"/>-->
<!-- </video>-->
<!-- </div>-->
<!--聊天框 -->
<div class="message-box">
<ul ref="msgLog" class="message-log">
<li v-for="(item, index) in mssageList" :key="'msg-log-' + index"
:class="{ 'align-right': item.createUser == userInfo.account }">
<span>{{ item.msg }}</span>
</li>
</ul>
<div class="send-box">
<el-input v-model="msgVal" placeholder="请输入消息"/>
<el-button color="#006080" @click="sendMsg">发送消息</el-button>
</div>
</div>
<!-- 聊天框, 添加音频组件 -->
<!--<div class="message-box">-->
<!-- <ul ref="msgLog" class="message-log">-->
<!-- <li v-for="(item, index) in mssageList" :key="'msg-log-' + index"-->
<!-- :class="{ 'align-right': item.createUser == userInfo.account }">-->
<!-- <span v-if="item.msgType === 'msg'">{{ item.content }}</span>-->
<!-- <audio v-if="item.msgType === 'audio'" controls>-->
<!-- <source :src="'data:audio/mpeg;base64,' + item.content" type="audio/mpeg"/>-->
<!-- 您的浏览器不支持音频元素。-->
<!-- </audio>-->
<!-- </li>-->
<!-- </ul>-->
<!-- <div class="send-box">-->
<!-- <el-input style="width: 60%" v-model="msgVal" placeholder="请输入消息"/>-->
<!-- <el-button style="color: #006080; width: 20%; margin-left: 10px;" @click="sendMsg">发送消息</el-button>-->
<!-- <el-button style="color: #006080; width: 20%" class="mic-btn" @mousedown="startRecording" @mouseup="stopRecording"-->
<!-- @mouseleave="stopRecording">录音</el-button>-->
<!-- </div>-->
<!-- <div v-if="isRecording" class="mic-icon">-->
<!-- <i class="fa-solid fa-microphone"></i> &lt;!&ndash; 麦克风图标 &ndash;&gt;-->
<!-- 正在录音... {{ remainingTime }} 秒剩余-->
<!-- </div>-->
<!--</div>-->
</div>
</div>
<!-- table1 -->
<div class="table-box">
<el-table :data="varTableData" height="100%" style="width: 100%">
<el-table-column type="index" label="泵号" width="80" align="center"/>
<el-table-column prop="name" label="药物名称" align="center"/>
<el-table-column prop="speed" label="速度(ml/h)" width="120">
<!-- <template #header>
<el-dropdown @command="table1SpeedCommand">
<span style="color: white;font-size: 14px;line-height: 20px;">
{{ table1SpeedVal || '请选择速度' }}
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="速度(ug/kg/min)">速度(ug/kg/min)</el-dropdown-item>
<el-dropdown-item command="速度(ml/h)">速度(ml/h)</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template> -->
</el-table-column>
<el-table-column prop="total" label="累计药量(ml)" width="100"/>
<!-- <el-table-column prop="state" label="工作状态" width="150" align="center"/>-->
<!-- <el-table-column label="特殊情况人为干预" align="center">
<template #default="scope">
<div class="table-btn-box">
<el-button size="small" color="#006080" @click="tableItemPlus(scope)">
<el-icon>
<Plus/>
</el-icon>
</el-button>
<el-button size="small" color="#006080" :disabled="scope.row.speed <= 0"
@click="tableItemMinus(scope)">
<el-icon>
<Minus/>
</el-icon>
</el-button>
&lt;!&ndash; <el-button size="small" color="#006080" @click="tableItemConfirm(scope)"
:disabled="tableDataStore[scope.$index].speed === scope.row.speed">确定&ndash;&gt;-->
<!--<el-button size="small" color="#006080" @click="tableItemConfirm(scope, varTableData)">确定
</el-button>
<el-button size="small" color="#006080" @click="tableItemCancel(scope)">取消
</el-button>
</div>
</template>
</el-table-column> -->
</el-table>
</div>
<!-- table2 -->
<div class="table-box">
<el-table :data="fixedTableData" height="100%" style="width: 100%">
<el-table-column type="index" label="泵号" width="80" align="center"/>
<el-table-column prop="name" label="药物名称" align="center"/>
<el-table-column prop="speed" label="速度(ml/h)" width="100"/>
<el-table-column prop="total" label="累计药量(ml)" width="100"/>
<!-- <el-table-column prop="state" label="工作状态" width="150" align="center"/>-->
<!-- <el-table-column label="特殊情况人为干预" align="center">
<template #default="scope">
<div class="table-btn-box">
<el-button size="small" color="#006080" @click="tableItemPlus(scope)">
<el-icon>
<Plus/>
</el-icon>
</el-button>
<el-button size="small" color="#006080" :disabled="scope.row.speed <= 0"
@click="tableItemMinus(scope)">
<el-icon>
<Minus/>
</el-icon>
</el-button>
<el-button size="small" color="#006080" @click="tableItemConfirm(scope, fixedTableData)">确定
</el-button>
<el-button size="small" color="#006080" @click="tableItemCancel(scope)">取消
</el-button>
</div>
</template>
</el-table-column> -->
</el-table>
</div>
</div>
</div>
<el-dialog v-model="setDatabaseDialog" title="请选择需要查询的病人" width="300px" align-center>
<el-select v-model="database" filterable placeholder="Select" style="width: 100%;">
<el-option v-for="item in databaseOptions" :key="item.value" :label="item.label" :value="item.value"/>
</el-select>
<template #footer>
<span class="dialog-footer">
<el-button @click="setDatabaseDialog = false">取消</el-button>
<el-button type="primary" @click="setDatabase">确定</el-button>
</span>
</template>
</el-dialog>
<el-dialog v-model="isPatientDialog" title="患者信息" width="50%">
<PatientsForm ref="patientsFormRef" type="view" @close="isPatientDialog = false"/>
</el-dialog>
</div>
</template>
<script lang="ts" setup>
import {onMounted, onUnmounted, reactive, ref} from 'vue';
import {useRouter} from 'vue-router'
import {ElMessage} from 'element-plus';
import {dateFormater} from '@/utils/date-util';
import chartLine from './chart/chart-line.vue';
import chartEcg from './chart/chart-ecg.vue';
import PatientsForm from '@/views/patients-manage/form/patients-form.vue'
import imgLung from '@/assets/imgs/lung.png';
import imgHeart from '@/assets/imgs/heart.png';
import imgLungAlarm from '@/assets/imgs/lung_alarm.png';
import imgHeartAlarm from '@/assets/imgs/heart_alarm.png';
import {useRemoteWsStore} from "@/stores/remote-ws-store";
import {useUserStore} from "@/stores/user-info-store";
import {getPatientInfo, getPatientInfoM} from "@/api/patient";
import axios from "axios";
const router = useRouter()
const medicineCustom: any[] = [
{name: '丙泊酚', plus: 0.5, total: 50},
{name: '舒芬太尼', plus: 1, total: 100},
{name: '瑞芬太尼', plus: 0.05, total: 5},
{name: '顺阿曲库胺', plus: 0.02, total: 2},
{name: '尼卡地平', plus: 1, total: 100},
{name: '艾司洛尔', plus: 1, total: 100},
{name: '麻黄素', plus: 1, total: 100},
{name: '阿托品', plus: 1, total: 100},
{name: '罗库溴铵', plus: 0.1, total: 10}
]
const remoteWsStore = useRemoteWsStore()
const currentRemote = ref()
const userInfoStore = useUserStore()
const currentIndex = remoteWsStore.getCurrentTaskIndex()
const chartDom1 = ref(),
chartDom2 = ref(),
chartDom3 = ref(),
chartDom4 = ref(),
liveVideo = ref(),
msgLog = ref(),
unusualMsgRef = ref(),
patientsFormRef = ref()
const isPatientDialog = ref(false)
const database = ref('')
const databaseOptions = ref([] as { value: string, label: string }[])
const messageSum = ref(10)
const userInfo = ref(userInfoStore.getlogin())
const setDatabaseDialog = ref(false);
const featureTable = ref([] as any[]);
let chartNowData = reactive({ID: 0});
const lungAlarm = ref(false); // 肺部警告
const heartAlarm = ref(false); // 心脏警告
const isAIDose = ref(false); // 是否AI给药
const isVideoPlay = ref(false); // 视频是否播放
const videoSrc = ref('https://www.runoob.com/try/demo_source/mov_bbb.mp4');
const unusual = ref([] as any);
const fixedTableData = ref([] as any[]);
const varTableData = ref([] as any[]);
const table1SpeedVal = ref('');
let currentAIMedicine: any;
let currentDocMedicine: any;
const medicineSpeedTemp: any = {};
onMounted(() => {
currentRemote.value = remoteWsStore.getRemoteTask()[remoteWsStore.getCurrentTaskIndex()]
if (!currentRemote.value.isRemote) {
router.replace('/remote-manage/remote-manage');
return;
}
// msgLogScrollBottom();
msgLogScrollBottom();
initScale();
subscribeWS();
// setTableData();
});
onUnmounted(() => {
remoteWsStore.unsubscribeChat(currentRemote.value.patient, currentRemote.value.patientId, currentRemote.value.date, currentIndex);
// remoteWsStore.unsubscribeMedicine(currentRemote.value.patient, currentRemote.value.patientId, currentRemote.value.date, index);
remoteWsStore.unsubscribeVital(currentRemote.value.patient, currentRemote.value.patientId, currentRemote.value.date, currentIndex);
// remoteWsStore.disconnectChat(currentRemote.value.patient, currentRemote.value.patientId, currentRemote.value.date, currentIndex)
if (!router.currentRoute.value.path.startsWith("/remote-manage/")) {
const tasks: any = remoteWsStore.getRemoteTask()
tasks.forEach((task: any) => {
remoteWsStore.disconnect(task.patient, task.patientId, task.date, task.index)
})
}
})
function subscribeWS() {
subscribeVital()
subscribeChat()
/*remoteWsStore.subscribeMedicine(currentRemote.value.patient, currentRemote.value.patientId, currentRemote.value.date, index,
function (res: any) {
const data = JSON.parse(res.data);
if (data.status != 1) {
if (data.medicine) {
if (varTableData.value[data.medicine]) varTableData.value[data.medicine] = medicineSpeedTemp[data.medicine];
if (fixedTableData.value[data.medicine]) fixedTableData.value[data.medicine] = medicineSpeedTemp[data.medicine];
}
} else {
ElMessage.error(data.msg)
}
})*/
}
const subscribeVital = () => {
remoteWsStore.createVital(currentRemote.value.patient, currentRemote.value.patientId, currentRemote.value.date, currentIndex)
remoteWsStore.subscribeVital(currentRemote.value.patient, currentRemote.value.patientId, currentRemote.value.date, currentIndex,
function (res: any) {
const data = JSON.parse(res.data);
// 1 2 3
if (data.vitalSignsList != null) {
chartDom1.value.updateChartData(data.vitalSignsList);
chartDom2.value.updateChartData(data.vitalSignsList);
chartDom3.value.updateChartData(data.vitalSignsList);
// chartDom4.value.updateChartData(data.vitalSignsList);
// updateMedicineTable(data.aiMedicineList[0], data.docMedicineList[0]);
updateMedicineTable(data.aiMedicineList[0], undefined);
}
})
remoteWsStore.vitalOnclose(currentRemote.value.patient, currentRemote.value.patientId, currentRemote.value.date, currentIndex, () => {
setTimeout(() => {
ElMessage.info('远程控制' + currentIndex + ' 生命体征数据连接断开,正在尝试重连……')
subscribeVital()
}, 3000)
})
}
const subscribeChat = () => {
remoteWsStore.createChat(currentRemote.value.patient, currentRemote.value.patientId, currentRemote.value.date, currentIndex)
remoteWsStore.subscribeChat(currentRemote.value.patient, currentRemote.value.patientId, currentRemote.value.date, currentIndex,
function (res: any) {
const chatObj = JSON.parse(res.data);
if (chatObj.history) {
// mssageList.value = chatObj.history;
mssageList.value = chatObj;
} else {
mssageList.value.push(JSON.parse(res.data));
}
})
remoteWsStore.chatOnclose(currentRemote.value.patient, currentRemote.value.patientId, currentRemote.value.date, currentIndex, () => {
setTimeout(() => {
ElMessage.info('远程控制' + currentIndex + ' 通讯连接断开,正在尝试重连……')
subscribeChat()
}, 3000)
})
}
function initData() {
lungAlarm.value = false;
heartAlarm.value = false;
isAIDose.value = false;
unusual.value = [];
mssageList.value = [];
fixedTableData.value = [];
varTableData.value = [];
featureTable.value = [];
try {
msgLogScrollBottom();
} catch (error) {
}
}
function updateMedicineTable(aiMedicine: any, doctorMedicine: any) {
if (aiMedicine) {
delete aiMedicine._id;
delete aiMedicine.Time;
currentAIMedicine = aiMedicine;
// const keys = Object.keys(aiMedicine);
// console.log(keys);
// keys.forEach(key => {
// medicineSpeedTemp[key] = aiMedicine[key];
// })
if (varTableData.value.length > 0) {
varTableData.value = varTableData.value.filter(medicine => {
return medicine.name in aiMedicine; // 只保留存在于 aiMedicine 中的 medicine
});
varTableData.value.forEach((medicine: any) => {
medicine.speed = aiMedicine[medicine.name] ? Number(aiMedicine[medicine.name]).toFixed(2) : '0.0'
medicine.total = aiMedicine[medicine.name + "sum"] ? Number(aiMedicine[medicine.name + "sum"]).toFixed(2) : '0.0'
})
fixedTableData.value.forEach((medicine: any) => {
medicine.speed = aiMedicine[medicine.name] ? Number(aiMedicine[medicine.name]).toFixed(2) : '0.0'
medicine.total = aiMedicine[medicine.name + "sum"] ? Number(aiMedicine[medicine.name + "sum"]).toFixed(2) : '0.0'
})
// console.log(varTableData.value)
// console.log(fixedTableData.value)
} else {
const varTable: any = [];
const fixedTable: any = [];
remoteWsStore.varMedicine.forEach(key => {
const medicine = {
Phase: 0,
name: key,
speed: aiMedicine[key] ? Number(aiMedicine[key]).toFixed(2) : '0.0',
total: aiMedicine[key + "sum"] ? Number(aiMedicine[key + "sum"]).toFixed(2) : '0.0',
state: "正常"
}
varTable.push(medicine);
})
remoteWsStore.fixedMedicine.forEach(key => {
const medicine = {
Phase: 0,
name: key,
speed: aiMedicine[key] ? Number(aiMedicine[key]).toFixed(2) : '0.0',
total: aiMedicine[key + "sum"] ? Number(aiMedicine[key + "sum"]).toFixed(2) : '0.0',
state: "正常"
}
fixedTable.push(medicine);
})
varTableData.value = varTable;
fixedTableData.value = fixedTable;
}
}
if (doctorMedicine) {
delete doctorMedicine._id;
delete doctorMedicine.Time;
currentDocMedicine = doctorMedicine;
const keys = Object.keys(doctorMedicine);
keys.forEach(key => {
medicineSpeedTemp[key] = doctorMedicine[key];
})
if (varTableData.value.length > 0) {
varTableData.value.forEach((medicine: any) => {
medicine.speed = (Number(doctorMedicine[medicine.name]) + Number(aiMedicine[medicine.name])).toFixed(2);
medicine.total = (Number(doctorMedicine[medicine.name + "sum"]) + Number(aiMedicine[medicine.name + "sum"])).toFixed(2);
});
fixedTableData.value.forEach((medicine: any) => {
medicine.speed = (Number(doctorMedicine[medicine.name]) + Number(aiMedicine[medicine.name])).toFixed(2);
medicine.total = (Number(doctorMedicine[medicine.name + "sum"]) + Number(aiMedicine[medicine.name + "sum"])).toFixed(2);
})
} else {
const varTable: any = [];
const fixedTable: any = [];
keys.forEach(key => {
const medicine = {
Phase: 0,
name: key,
speed: Number(doctorMedicine[key]) + Number(aiMedicine[key]),
total: Number(doctorMedicine[key + "sum"]) + Number(aiMedicine[key + "sum"]),
state: "正常"
}
if (remoteWsStore.varMedicine.includes(key)) {
varTable.push(medicine);
} else {
fixedTable.push(medicine);
}
})
varTableData.value = varTable;
fixedTableData.value = fixedTable;
}
}
}
function vitalExcepEvent(data: any, time: any) {
logUpdate(data, time)
}
function logUpdate(msg: string, time: any) {
unusual.value.push(dateFormater('HH:mm:ss', time) + msg);
setTimeout(() => {
unusualMsgRef.value.scrollTo({
top: unusualMsgRef.value.scrollHeight,
behavior: 'smooth'
});
});
}
// table 速度选择
function table1SpeedCommand(e: any) {
table1SpeedVal.value = e
}
function keepFit(designWidth: number, designHeight: number, renderDomId: string) {
let width = designWidth || 1920,
height = designHeight || 1010;
let clientHeight = document.documentElement.clientHeight - 50;
let clientWidth = document.documentElement.clientWidth;
let scale = 1;
scale = (clientHeight / clientWidth) < (height / width) ? clientHeight / height : clientWidth / width;
// scale = clientHeight / height;
// scale = clientWidth / width;
const renderDom = document.getElementById(renderDomId);
if (renderDom) {
renderDom.style.height = clientHeight / scale + 'px';
renderDom.style.width = clientWidth / scale + 'px';
renderDom.style.transform = 'scale(' + scale + ')';
}
}
function initScale() {
let w = 1920,
h = 1010;
keepFit(w, h, 'screenBox');
window.addEventListener('resize', () => {
keepFit(w, h, 'screenBox');
});
}
const selectDatabase = (value: any) => {
initData();
};
const setDatabase = () => {
initData();
setDatabaseDialog.value = false;
};
const viewPatientInfo = () => {
isPatientDialog.value = true;
/*getPatientInfo(currentRemote.value.patient, currentRemote.value.patientId,
currentRemote.value.date).then(res => {
if (res.code == 0) {
patientsFormRef.value.resetData()
patientsFormRef.value.formData = JSON.parse(JSON.stringify(res.data))
}
})*/
getPatientInfoM(currentRemote.value.patient, currentRemote.value.patientId,
currentRemote.value.date).then(res => {
if (res.code == 0) {
patientsFormRef.value.resetData()
const formData = JSON.parse(JSON.stringify(res.data))
formData.性别 = formData.性别 == 'M' ? '男' : "女"
patientsFormRef.value.formData = formData
}
})
}
const backRemote = () => {
router.back();
}
const playPause = () => {
if (liveVideo.value.paused) {
liveVideo.value.play(); // 播放视频
isVideoPlay.value = true;
} else {
liveVideo.value.pause(); // 暂停视频
isVideoPlay.value = false;
}
}
const sendMsg = () => {
if (msgVal.value.trim() == '') return;
const index = remoteWsStore.getCurrentTaskIndex()
remoteWsStore.sendMsg(currentRemote.value.patient, currentRemote.value.patientId,
currentRemote.value.date, msgVal.value, index, function (res: any) {
if (res.code == 1) {
ElMessage.error(res.msg)
}
})
msgVal.value = '';
setTimeout(() => {
msgLogScrollBottom()
}, 0);
}
function msgLogScrollBottom() {
msgLog.value.scrollTo({
top: msgLog.value.scrollHeight,
behavior: 'smooth'
});
}
const tableItemPlus = (e: any) => {
const obj = medicineCustom.find(item => item.name === e.row.name) || {plus: 1};
e.row.speed += obj.plus;
e.row.speed = Number(e.row.speed.toFixed(2));
}
const tableItemMinus = (e: any) => {
const obj = medicineCustom.find(item => item.name === e.row.name) || {plus: 1};
if (!isAIDose.value && e.row.speed - obj.plus <= 0) return;
e.row.speed -= obj.plus;
if (e.row.speed < 0) e.row.speed = 0;
else e.row.speed = Number(e.row.speed.toFixed(2));
}
const tableItemConfirm = (e: any, tableData: any) => {
if (tableData.length < 1) return;
const params = {
name: currentRemote.value.patient,
id: currentRemote.value.patientId,
date: currentRemote.value.date,
flag: "1",
medicine: e.row.name,
value: e.row.speed
}
const index = remoteWsStore.getCurrentTaskIndex()
remoteWsStore.sendMedicine(params, index, function () {
});
}
const tableItemCancel = (e: any) => {
e.row.speed = medicineSpeedTemp[e.row.name];
}
function startAI() {
const params: any = {
name: currentRemote.value.patient,
id: currentRemote.value.patientId,
date: currentRemote.value.date,
flag: "0",
}
const index = remoteWsStore.getCurrentTaskIndex()
remoteWsStore.sendMedicine(params, index, function () {
});
}
/*
* 聊天室
*/
const msgVal = ref('');
const mssageList = ref([] as any);
</script>
<style lang="scss" scoped>
.remote-box {
width: 1920px;
height: 1010px;
background: #f1f3f5;
padding: 10px 0 20px 0;
transform-origin: top left;
overflow-y: auto;
.el-button {
color: white;
}
.main-box {
width: 100%;
height: 100%;
background: white;
padding: 20px;
box-sizing: border-box;
display: flex;
justify-content: space-between;
.left-box {
width: 37%;
height: 100%;
& > h3 {
font-size: 26px;
color: $main-color;
line-height: 30px;
margin-bottom: 20px;
font-weight: 600;
}
.chart-line {
width: 100%;
height: calc(25% - 30px);
height: calc(33.3% - 30px);
margin-bottom: 20px;
background: #e8f5f8;
border-top-left-radius: 20px;
border-top-right-radius: 20px;
// overflow: hidden;
}
.chart-ecg {
width: 100%;
height: calc(25% - 50px);
border-left: 1px solid #92b3c1;
border-bottom: 1px solid #92b3c1;
&::before {
content: '';
position: absolute;
width: 0;
height: 0;
top: 0;
left: -5px;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-bottom: 15px solid #285e7d;
border-top: 0;
}
&::after {
content: '';
position: absolute;
width: 0;
height: 0;
bottom: -5px;
right: 0;
border-left: 15px solid #285e7d;
border-right: 0;
border-bottom: 5px solid transparent;
border-top: 5px solid transparent;
}
}
//.chart-ecg {
// width: 100%;
// height: calc(25% - 50px);
// border-left: 1px solid #92b3c1;
// border-bottom: 1px solid #92b3c1;
//
// &::before {
// content: '';
// position: absolute;
// width: 0;
// height: 0;
// top: 0;
// left: -5px;
// border-left: 5px solid transparent;
// border-right: 5px solid transparent;
// border-bottom: 15px solid #285e7d;
// border-top: 0;
// }
//
// &::after {
// content: '';
// position: absolute;
// width: 0;
// height: 0;
// bottom: -5px;
// right: 0;
// border-left: 15px solid #285e7d;
// border-right: 0;
// border-bottom: 5px solid transparent;
// border-top: 5px solid transparent;
// }
//}
}
.center-box {
width: calc(100% - 1500px);
min-width: 500px;
height: 100%;
.body-box {
width: 100%;
height: calc(100% - 110px);
display: flex;
justify-content: center;
align-items: center;
.body-img {
position: relative;
// width: 400px;
// height: 650px;
margin-top: 80px;
width: 500px;
height: 812.5px;
min-height: 650px;
.lung-img {
position: absolute;
width: 500px;
height: auto;
top: 240px;
left: 0;
transition: all 2s;
}
.heart-img {
position: absolute;
width: 500px;
height: auto;
top: 420px;
left: 0;
transition: all 2s;
}
}
}
.btn-box {
position: relative;
width: 100%;
height: 110px;
display: flex;
justify-content: center;
align-items: center;
//.start-btn {
// width: 230px;
// height: 40px;
// font-size: 20px;
// border-radius: 16px;
// font-weight: 600;
//}
//.right-btn-box {
// position: absolute;
// width: 100px;
// height: 62px;
// top: calc(50% - 31px);
// right: 0;
// display: flex;
// flex-direction: column;
// justify-content: space-between;
//
// .el-button {
// width: 100%;
// padding: 0;
// height: 25px;
// line-height: 22px;
// border: 1px solid #e0e0e0;
// color: #616161;
//
// &.active {
// background: $main-color;
// color: white;
// }
//
// &:last-of-type {
// margin: 0;
// }
// }
//}
}
}
.right-box {
width: 36.5%;
height: 100%;
display: flex;
flex-direction: column;
.top-btn-box {
width: 100%;
height: 34px;
margin-bottom: 5px;
display: flex;
justify-content: space-between;
align-items: center;
.top-left-btn-box {
display: flex;
align-items: center;
.el-select {
margin-right: 10px;
}
}
.el-button {
border-radius: 16px;
height: 31px;
background-color: transparent;
color: #c77000;
}
& > .el-button {
border-radius: 4px;
background-color: #f2f3f5;
color: $main-color;
}
}
.monitoring-message {
width: 100%;
height: 41%;
padding-bottom: 10px;
display: flex;
justify-content: space-between;
& > .left-box {
position: relative;
width: 200px;
height: 100%;
.unusual-title {
display: block;
width: 100%;
line-height: 38px;
color: #C77000;
font-size: 20px;
text-align: center;
border: 1px dashed #C1C1C1;
border-radius: 10px;
}
.unusual-box {
width: 100%;
height: calc(100% - 45px);
// background: #F8F8F8;
border-left: 1px dashed #C1C1C1;
// border-radius: 4px;
margin-top: 5px;
padding: 8px 16px;
overflow-y: auto;
li {
color: #F80000;
font-size: 14px;
line-height: 22px;
}
}
}
& > .right-box {
width: calc(100% - 205px);
height: 100%;
// .video-box {
// position: relative;
// width: 100%;
// height: 270px;
// background: $main-color;
// /* background: url(@/assets/imgs/video_bck.png);
//background-size: 100% 100%; */
//
// &:hover {
// .icon-box {
// display: flex;
// }
// }
//
// .icon-box {
// display: none;
// position: absolute;
// top: 0;
// left: 0;
// bottom: 0;
// right: 0;
// font-size: 60px;
// color: white;
// background: rgba(black, .3);
// justify-content: center;
// align-items: center;
// }
//
// video {
// width: 100%;
// height: 100%;
// object-fit: cover;
// }
// }
.message-box {
width: 100%;
// height: 270px;
height: 100%;
// margin-bottom: 5px;
.message-log {
width: 100%;
height: 100%;
max-height: calc(100% - 35px);
padding: 16px 20px;
box-sizing: border-box;
border: 1px solid #c8c8c8;
background: #f8f8f8;
overflow-y: auto;
li {
width: 100%;
font-size: 14px;
line-height: 1.6;
margin: 5px 0;
&.align-right {
text-align: right;
span {
background: $main-color;
}
}
span {
display: inline-block;
max-width: 80%;
padding: 6px 8px;
box-sizing: border-box;
border-radius: 8px;
color: white;
letter-spacing: 1px;
background: $main-color;
background: #92b3c1;
text-align: left;
}
}
}
.send-box {
width: 100%;
height: 40px;
display: flex;
justify-content: space-between;
align-items: flex-end;
.el-input {
width: calc(100% - 110px);
height: 32px;
:deep(.el-input__wrapper) {
background-color: #F2F3F5;
border-color: #C1C1C1;
}
}
.el-button {
padding: 0;
width: 100px;
line-height: 30px;
}
}
}
}
}
.table-box {
width: 100%;
height: 29.5%;
margin-bottom: 20px;
flex-grow: 1;
:deep(.el-table__inner-wrapper) {
.el-table__cell {
padding: 6px 0;
}
.cell {
padding: 0 2px;
}
.el-table__header-wrapper {
tr {
background-color: $main-color;
}
th.el-table__cell {
color: white;
background-color: $main-color;
padding: 8px 0;
font-weight: 400;
}
}
}
//.table-btn-box {
// .el-button {
// padding: 0 7px;
// height: 24px;
// line-height: 22px;
//
// &:not(:first-of-type) {
// margin-left: 4px;
// }
// }
//}
}
}
}
}
// 麦克风图标样式
.send-box {
position: relative; /* 设置相对定位用于绝对定位子元素的参考 */
}
.mic-icon {
position: fixed; /* 使用固定定位 */
bottom: 20px; /* 距离底部20px */
left: 50%; /* 水平居中 */
transform: translateX(-50%); /* 使图标真正居中 */
background-color: rgba(255, 255, 255, 0.9); /* 背景颜色 */
border-radius: 5px; /* 圆角 */
padding: 10px; /* 内边距 */
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); /* 阴影效果 */
z-index: 1000; /* 确保图标在其他元素之上 */
display: flex; /* 使用 flexbox 布局 */
align-items: center; /* 垂直居中 */
}
.mic-icon .fa-microphone {
color: red; /* 麦克风图标颜色 */
font-size: 80px; /* 调整图标大小 */
margin-right: 5px; /* 图标与文本间的间距 */
}
</style>