mirror of
https://gitee.com/xiongmao1988/rax-medical.git
synced 2025-08-24 04:54:58 +08:00
1111 lines
43 KiB
Vue
1111 lines
43 KiB
Vue
<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>-->
|
||
<!-- <!– poster="@/assets/imgs/video_bck.png" –>-->
|
||
<!-- <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> <!– 麦克风图标 –>-->
|
||
<!-- 正在录音... {{ 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>
|
||
<!– <el-button size="small" color="#006080" @click="tableItemConfirm(scope)"
|
||
:disabled="tableDataStore[scope.$index].speed === scope.row.speed">确定–>-->
|
||
<!--<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>
|