commit: 一期-final

This commit is contained in:
republicline 2025-06-18 09:15:00 +08:00
parent 198ae7d820
commit 263c91f66c
24 changed files with 961 additions and 530 deletions

2
.env
View File

@ -2,4 +2,4 @@ VITE_PWD_ENC_KEY='thanks,rax4cloud'
VITE_OAUTH2_PASSWORD_CLIENT='rax:rax'
VITE_RAX_BASE_URL='/api'
VITE_RAX_BASE_URL='/api'

View File

@ -81,7 +81,7 @@ const getDatabases = () => app.post('/getdatabases', function (req, res) {
// con.connect();
con.query("SHOW DATABASES", function (error, results, fields) {
if (error) {
console.log(`${nowTime()} 错误:${JSON.stringify(error)}`);
// console.log(`${nowTime()} 错误:${JSON.stringify(error)}`);
return res.status(500).send(error);
} else {
res.send(results);
@ -97,16 +97,16 @@ const mysqlQuery = (res, database, sql) => {
connection(database).connect();
connection(database).query(sql, (error, results, fields) => {
if (error) {
console.log(`${nowTime()} 错误:${JSON.stringify(error)}`);
// console.log(`${nowTime()} 错误:${JSON.stringify(error)}`);
return res.status(500).send(error);
} else {
res.send(results);
}
connection(database).end();
});
} catch (error) {
console.log(error);
// console.log(error);
return res.status(500).send('连接失败', error);
}
}
@ -123,4 +123,4 @@ export default {
nowTime,
dateFormater,
getDatabases
};
};

View File

@ -288,4 +288,4 @@ body {
font-size: 16px !important;
}
}
}
}

View File

@ -67,7 +67,6 @@ const importData = () => {
function handleUpload(options: any) {
handleHttpUploadUrl(options, props.importUrl)
.then((res: any) => {
console.log(res)
if (res === 'Request failed with status code 403') {
ElMessage.error('上传失败,请检查权限信息')
return

View File

@ -13,12 +13,12 @@
</div>
<el-form ref="formRef" :model="formData" :rules="rules" label-width="60">
<template v-if="tabActive === 0">
<el-upload action="#" :limit="1" :http-request="handleUpload" ref="uploadRef"
:show-file-list="false" :on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload">
<img v-if="formData.avatar" :src="'/api' + formData.avatar" class="avatar"/>
<img v-else src="@/assets/imgs/home/avatar.png" class="avatar"/>
</el-upload>
<!--<el-upload action="#" :limit="1" :http-request="handleUpload" ref="uploadRef"-->
<!-- :show-file-list="false" :on-success="handleAvatarSuccess"-->
<!-- :before-upload="beforeAvatarUpload">-->
<!-- <img v-if="formData.avatar" :src="'/api' + formData.avatar" class="avatar"/>-->
<!-- <img v-else src="@/assets/imgs/home/avatar.png" class="avatar"/>-->
<!--</el-upload>-->
<el-form-item label="用户名" prop="account">
<el-input v-model="formData.account" disabled></el-input>
</el-form-item>
@ -26,11 +26,11 @@
<el-input v-model="formData.phone" placeholder="请输入手机号"></el-input>
</el-form-item>
<el-form-item label="姓名" prop="name">
<el-input v-model="formData.name" placeholder="请输入姓名"></el-input>
</el-form-item>
<el-form-item label="邮箱" prop="mailbox">
<el-input v-model="formData.mailbox" placeholder="请输入邮箱"></el-input>
<el-input v-model="formData.name" placeholder="请输入姓名(2-6个汉字)"></el-input>
</el-form-item>
<!--<el-form-item label="邮箱" prop="mailbox">-->
<!-- <el-input v-model="formData.mailbox" placeholder="请输入邮箱"></el-input>-->
<!--</el-form-item>-->
</template>
<template v-else>
<el-form-item label="密码" prop="password" label-width="100">
@ -118,11 +118,9 @@ const rules = reactive({
phone: [
{required: true, validator: validatorPhone, trigger: 'blur'},
],
name: [
{required: true, message: '请输入姓名', trigger: 'blur'},
],
mailbox: [
{type: 'email', message: '邮箱格式不正确', trigger: ['blur', 'change']},
{required: true, message: '请输入邮箱', trigger: ['blur', 'change']},
{pattern: /^[^@]+@[^@]+$/ , message: '邮箱格式不正确'}
],
password: [
{required: true, validator: validatorPassword, trigger: 'change'},
@ -135,8 +133,19 @@ const rules = reactive({
{required: true, message: '请输入密码', trigger: 'change'},
{required: true, validator: validatorPassword, trigger: 'change'},
{validator: validatePassword, trigger: 'blur'}
]
],
name: [
{required: true, message: '请输入姓名', trigger: ['blur', 'change']},
{pattern: /^[\u4E00-\u9FA5]{2,6}$/ , message: '请输入2-6个汉字'}
],
// mailbox: [
// {required: true, message: '', trigger: ['blur', 'change']},
// {validator: '^[^@]+@[^@]+$', message: '', trigger: ['blur', 'change']}
// ]
})
const tabActive = ref(0)
const formData = ref({
avatar: '',
@ -206,6 +215,7 @@ const submitForm = async () => {
updateUserInfo(param).then((res: any) => {
if (res && res.code == 0) {
ElMessage.success('更新成功')
window.location.reload();
close()
} else {
ElMessage.error(res.msg)

View File

@ -9,5 +9,7 @@ export enum LogTypeEnum {
export enum REGEXP {
PASSWORD = '^[a-zA-Z0-9]{8,16}$',
ACCOUNT = '^[a-zA-Z0-9]{2,16}$',
MOBILE = '^[1][3,4,5,6.7,8,9][0-9]{9}$'
}
MOBILE = '^[1][3,4,5,6.7,8,9][0-9]{9}$',
EMAIL = '^[^@]+@[^@]+$',
NAME = '^[\u4E00-\u9FA5]{2,6}$'
}

View File

@ -1,36 +1,40 @@
import {defineStore} from "pinia";
import {Session} from "@/utils/storage";
import {ElMessage} from "element-plus";
import {ElMessage, ElMessageBox} from "element-plus";
// 本地调试版本:
const vitalUrl = "ws://" + window.location.host + "/socket.io/admin/rax/vitalSignsMedicine?token=" + Session.getToken()
// const medicineUrl = "ws://" + window.location.host + "/socket.io/admin/rax/addMedicine?token=" + Session.getToken()
const chatUrl = "ws://" + window.location.host + "/socket.io/admin/rax/chatRoom?token=" + Session.getToken()
// 服务器部署版本
// const vitalUrl = "wss://" + window.location.host + "/socket.io/admin/rax/vitalSignsMedicine?token=" + Session.getToken()
// // const medicineUrl = "wss://" + window.location.host + "/socket.io/admin/rax/addMedicine?token=" + Session.getToken()
// const chatUrl = "wss://" + window.location.host + "/socket.io/admin/rax/chatRoom?token=" + Session.getToken()
// 测试echars
// const vitalUrl = "wss://" + "110.41.142.124" + "/socket.io/admin/rax/vitalSignsMedicine?token=" + Session.getToken()
// const medicineUrl = "wss://" + "110.41.142.124" + "/socket.io/admin/rax/addMedicine?token=" + Session.getToken()
// const chatUrl = "wss://" + "110.41.142.124" + "/socket.io/admin/rax/chatRoom?token=" + Session.getToken()
export const useRemoteWsStore = defineStore("remoteWs", {
state: () => {
return {
patient: {} as any,
remoteTasks: [] as any,
remoteTasksCap: 10,
currentTaskIndex: -1,
varMedicine: ["丙泊酚", "舒芬太尼", "瑞芬太尼", "顺阿曲库胺", "罗库溴铵"],
fixedMedicine: ["尼卡地平", "艾司洛尔", "麻黄素", "阿托品"],
exceptionType: ["BIS_except", "DBP_except", "EtCO2_except", "HR_except", "SBP_except", "ST_except"],
// varMedicine: ["丙泊酚", "舒芬太尼", "瑞芬太尼", "顺阿曲库铵", "罗库溴铵"],
varMedicine: ["丙泊酚", "舒芬太尼", "瑞芬太尼", "顺阿曲库铵"],
fixedMedicine: ["尼卡地平", "艾司洛尔", "麻黄碱", "阿托品"],
exceptionType: ["BIS_except", "TOF_except", "HR_except", "SBP_except", "DBP_except", "MAP_except"],
exceptionMsg: {
"BIS_except": "脑电双频指数异常", "DBP_except": "舒张压异常", "EtCO2_except": "呼气末二氧化碳异常",
"HR_except": "心率异常", "SBP_except": "收缩压异常", "ST_except": "ST异常"
"BIS_except": "脑电双频指数异常",
"TOF_except": "TOF异常",
"HR_except": "心率异常",
"SBP_except": "收缩压异常",
"DBP_except": "舒张压异常",
"MAP_except": "平均动脉压异常",
// "EtCO2_except": "呼气末二氧化碳异常",
// "ST_except": "ST异常",
} as any,
closeStatus: {} as any
}
@ -105,6 +109,9 @@ export const useRemoteWsStore = defineStore("remoteWs", {
setRemoteLog(log: any, i: number) {
this.remoteTasks[i].log.push(log)
},
getRemoteLog(i: number) {
return this.remoteTasks[i].log
},
getCloseStatus() {
return this.closeStatus
},
@ -192,7 +199,7 @@ export const useRemoteWsStore = defineStore("remoteWs", {
if (patient && !patient['vitalWS']) {
patient['vitalWS'] = new WebSocket(vitalUrl)
patient['vitalWS'].onopen = function () {
ElMessage.info("远程控制" + (index + 1) + ",生命体征数据连接成功")
ElMessage.info("远程查看" + (index + 1) + ",生命体征数据连接成功")
patient['vitalWS'].send(JSON.stringify({
patientName: name,
idNum: id,
@ -236,6 +243,7 @@ export const useRemoteWsStore = defineStore("remoteWs", {
patient.vitalWS.onmessage = undefined;
}
},
sendMsg(name: string, id: string, date: string, msg: string, index: number, cb: any) {
const patient: any = this.patient[name + id + date + index]
if (patient) {
@ -257,7 +265,6 @@ export const useRemoteWsStore = defineStore("remoteWs", {
})
}
},
sendAudio(name: string, id: string, date: string, audio: any, index: number, cb: any) {
const patient: any = this.patient[name + id + date + index]
if (patient) {
@ -280,7 +287,6 @@ export const useRemoteWsStore = defineStore("remoteWs", {
}
},
disconnectVital(name: string, id: string, date: string, index: number) {
const patient: any = this.patient[name + id + date + index]
if (patient && patient.vitalWS) {
@ -294,17 +300,23 @@ export const useRemoteWsStore = defineStore("remoteWs", {
if (patient && !patient['chatWS']) {
patient['chatWS'] = new WebSocket(chatUrl)
patient['chatWS'].onopen = function () {
ElMessage.info("远程控制" + (index + 1) + ",通讯连接成功")
ElMessage.info("远程查看" + (index + 1) + ",通讯连接成功")
patient['chatWS'].send(JSON.stringify({
patientName: name,
idNum: id,
date: date,
msgType: "init"
}))
patient['chatWS'].send(JSON.stringify({
patientName: name,
idNum: id,
date: date,
msgType: "historyChat"
}))
}
patient['chatWS'].onerror = () => {
ElMessage.error("远程控制" + (index + 1) + "通讯出错")
ElMessage.error("远程查看" + (index + 1) + "通讯出错")
}
delete this.closeStatus[name + id + date + index + 'chatWS']
}
@ -314,7 +326,7 @@ export const useRemoteWsStore = defineStore("remoteWs", {
patient.chatWS.onmessage = (e: any) => {
if (e && e.data) {
const data = JSON.parse(e.data);
if (data.msgType == "msg" || data.msgType == "audio") {
if (data.msgType == "msg" || data.msgType == "audio" || data.msgType == "historyChat" || data.msgType == "destroy") {
cb(e)
} else {
patient.chatWS.send(JSON.stringify({msgType: "heartbeat"}))
@ -322,6 +334,15 @@ export const useRemoteWsStore = defineStore("remoteWs", {
}
}
},
getHistoryChat(name: string, id: string, date: string, index: number) {
const patient: any = this.patient[name + id + date + index]
patient.chatWS.send(JSON.stringify({
patientName: name,
idNum: id,
date: date,
msgType: "historyChat"
}))
},
chatOnclose(name: string, id: string, date: string, index: number, cb: any) {
const patient: any = this.patient[name + id + date + index]
patient.chatWS.onclose = () => {
@ -405,4 +426,4 @@ export const useRemoteWsStore = defineStore("remoteWs", {
patient.medicineWS.onmessage = undefined;
}
}
})
})

View File

@ -129,9 +129,9 @@
</div>
</div>
<div class="model">
<p>软件名称智娃全身麻醉智能泵注系统软件<br>
型号规格ZW-AA-001-SWI<br>
发布版本号SWI V0&nbsp;&nbsp;&nbsp;完整版本号SWI V0.1.00.001</p>
<p>软件名称智娃远程管理系统软件<br>
型号规格ZW-AA-001-RMS<br>
发布版本号RMS V0&nbsp;&nbsp;&nbsp;完整版本号RMS V0.1.00.001</p>
</div>
</div>
</div>
@ -181,7 +181,7 @@ const loginRules = reactive({
{required: true, message: '请输入用户名', trigger: 'change'},
],
password: [
{required: true, message: '请输入用户名', trigger: 'change'},
{required: true, message: '请输入密码', trigger: 'change'},
],
phone: [
{required: true, validator: validatorPhone, trigger: 'blur'},
@ -205,7 +205,7 @@ const registerRules = reactive({
],
name: [
{required: true, message: '请输入真实姓名', trigger: 'blur'},
{pattern: /^[\u4E00-\u9FA5]{2,6}$/, message: '请输入2-6个汉字'}
{pattern: /^[\u4E00-\u9FA5]{2,6}$/ , message: '请输入2-6个汉字'}
],
phone: [
{required: true, validator: validatorPhone, trigger: 'change'},

View File

@ -27,7 +27,7 @@
<el-table ref="tableRef" v-loading="loading" :data="tableData" height="100%" border show-overflow-tooltip
@row-click="tableRowClick">
<!-- <el-table-column type="selection" width="55"/>-->
<el-table-column type="index" label="#" width="55" align="center"/>
<el-table-column type="index" label="编号" width="55" align="center"/>
<el-table-column property="住院号" label="住院号" width="120" align="center"/>
<el-table-column property="姓名" label="姓名" width="120" align="center"/>
<el-table-column label="手机号" width="220" align="center">

View File

@ -2,8 +2,8 @@
<div class="table-page">
<div class="search-part" v-show="isSearch">
<div class="search-cell">
<span class="label">用户</span>
<el-input v-model="queryParams.userName" placeholder="请输入用户名"></el-input>
<span class="label"></span>
<el-input v-model="queryParams.userName" placeholder="请输入名"></el-input>
</div>
<el-button type="primary" icon="Search" @click="searchData()">查询</el-button>
<el-button icon="Refresh" @click="resetSearch()">重置</el-button>
@ -11,49 +11,124 @@
<div class="button-part" style="justify-content: space-between;">
<div>
<el-button type="primary" icon="FirstAidKit" @click="addData">新增</el-button>
<el-button icon="FirstAidKit" @click="importData">导入</el-button>
<!--<el-button icon="FirstAidKit" @click="importData">导入</el-button>-->
<el-button icon="Delete" @click="removeData()">删除</el-button>
</div>
<TableAbility @searchBtn="isSearch = !isSearch" @refreshBtn="updateData()"
@downloadBtn="exportData('医生数据', tableData)"></TableAbility>
<!--<TableAbility @searchBtn="isSearch = !isSearch" @refreshBtn="updateData()"-->
<!-- @downloadBtn="exportData('医生数据', tableData)"></TableAbility>-->
</div>
<!--<div class="table-part">-->
<!-- <el-table ref="tableRef" v-loading="loading" :data="tableData" height="100%" border show-overflow-tooltip-->
<!-- :row-class-name="({ row }: any) => row.lockFlag == 1 && 'disable'" @row-click="tableRowClick">-->
<!-- <el-table-column type="selection" width="55"/>-->
<!-- <el-table-column type="index" label="编号" width="70" align="center"/>-->
<!-- <el-table-column property="name" label="姓名" width="120" align="center"/>-->
<!-- <el-table-column label="手机号" width="220" align="center">-->
<!-- <template #default="scope">-->
<!-- <div v-if="scope.row.phone">-->
<!-- {{-->
<!-- scope.row.phone.slice(0, 3) + '****' + scope.row.phone.slice(7)-->
<!-- }}-->
<!-- </div>-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- <el-table-column label="角色" width="220" align="center">-->
<!-- <template #default="scope">-->
<!-- <span v-for="(item, index) in scope.row.roleList" :key="index">-->
<!-- {{ item.roleName }} {{ (scope.row.roleList.length - 1) == index ? '' : '' }}-->
<!-- </span>-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- <el-table-column label="锁定" width="120" align="center">-->
<!-- <template #default="scope">-->
<!-- <span><el-switch v-model="scope.row.lockFlag" @click="enableChange(scope.row)"/></span>-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- <el-table-column label="操作" align="center">-->
<!-- <template #default="scope">-->
<!-- <span @click.stop>-->
<!-- <el-button link icon="RefreshLeft" @click="resetPassword(scope.row)"-->
<!-- :disabled="scope.row.lockFlag == 1">密码</el-button>-->
<!-- <el-button link icon="EditPen" @click="editData(scope.row)"-->
<!-- :disabled="scope.row.lockFlag == 1">修改</el-button>-->
<!-- <el-button link icon="Delete" @click="removeData([scope.row])"-->
<!-- :disabled="scope.row.lockFlag == 1">删除</el-button>-->
<!-- </span>-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- </el-table>-->
<!--</div>-->
<div class="table-part">
<el-table ref="tableRef" v-loading="loading" :data="tableData" height="100%" border show-overflow-tooltip
:row-class-name="({ row }: any) => row.lockFlag == 1 && 'disable'" @row-click="tableRowClick">
<el-table-column type="selection" width="55"/>
<el-table-column type="index" label="#" width="55" align="center"/>
<el-table
ref="tableRef"
v-loading="loading"
:data="tableData"
height="100%"
border
show-overflow-tooltip
:row-class-name="({ row }) => row.lockFlag == 1 && 'disable'"
@selection-change="handleSelectionChange"
>
<!-- 复选框列 -->
<el-table-column
type="selection"
width="55"
:selectable="isSelectable"
/>
<el-table-column type="index" label="编号" width="70" align="center"/>
<el-table-column property="name" label="姓名" width="120" align="center"/>
<el-table-column label="手机号" width="220" align="center">
<template #default="scope">
<div v-if="scope.row.phone">
{{
scope.row.phone.slice(0, 3) + '****' + scope.row.phone.slice(7)
}}
{{ scope.row.phone.slice(0, 3) + '****' + scope.row.phone.slice(7) }}
</div>
</template>
</el-table-column>
<el-table-column label="角色" width="220" align="center">
<template #default="scope">
<span v-for="(item, index) in scope.row.roleList" :key="index">
{{ item.roleName }} {{ (scope.row.roleList.length - 1) == index ? '' : '' }}
</span>
<span v-for="(item, index) in scope.row.roleList" :key="index">
{{ item.roleName }}
{{ scope.row.roleList.length - 1 == index ? '' : '' }}
</span>
</template>
</el-table-column>
<el-table-column label="锁定" width="120" align="center">
<template #default="scope">
<span><el-switch v-model="scope.row.lockFlag" @click="enableChange(scope.row)"/></span>
<span>
<el-switch v-model="scope.row.lockFlag" @click="enableChange(scope.row)"/>
</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center">
<template #default="scope">
<span @click.stop>
<el-button link icon="RefreshLeft" @click="resetPassword(scope.row)"
:disabled="scope.row.lockFlag == 1">密码</el-button>
<el-button link icon="EditPen" @click="editData(scope.row)"
:disabled="scope.row.lockFlag == 1">修改</el-button>
<el-button link icon="Delete" @click="removeData([scope.row])"
:disabled="scope.row.lockFlag == 1">删除</el-button>
</span>
<span @click.stop>
<el-button
link
icon="RefreshLeft"
@click="resetPassword(scope.row)"
:disabled="scope.row.lockFlag == 1"
>
密码
</el-button>
<el-button
link
icon="EditPen"
@click="editData(scope.row)"
:disabled="scope.row.lockFlag == 1"
>
修改
</el-button>
<!-- 删除按钮根据角色动态隐藏 -->
<el-button
v-if="!isAdmin(scope.row)"
link
icon="Delete"
@click="removeData([scope.row])"
:disabled="scope.row.lockFlag == 1"
>
删除
</el-button>
</span>
</template>
</el-table-column>
</el-table>
@ -63,15 +138,26 @@
</div>
</div>
<el-dialog v-model="psDialogVisible" title="密码重置" width="500" draggable>
<el-form ref="formRef" :model="formData" :rules="rules" label-width="60">
<el-form-item label="密码" prop="password" label-width="100">
<el-input v-model="formData.password" type="password" show-password
placeholder="8~16位字母或数字区分大小写"></el-input>
<el-form ref="formRef" :model="formData" :rules="rules" label-width="100">
<!--<el-form-item label="新密码" prop="password" label-width="100">-->
<!-- <el-input v-model="formData.password" type="password" show-password-->
<!-- placeholder="8~16位字母或数字区分大小写"></el-input>-->
<!--</el-form-item>-->
<!--<el-form-item label="确认密码" prop="confirmPassword" label-width="100">-->
<!-- <el-input v-model="formData.confirmPassword" type="password" show-password-->
<!-- placeholder="确认密码"></el-input>-->
<!--</el-form-item>-->
<el-form-item label="新密码" prop="resetPassword">
<el-input v-model="formData.resetPassword" placeholder="8~16位字母或数字(区分大小写)"
type="password" show-password></el-input>
</el-form-item>
<el-form-item label="确认密码" prop="confirmPassword" label-width="100">
<el-input v-model="formData.confirmPassword" type="password" show-password
placeholder="确认密码"></el-input>
<el-form-item label="确认密码" prop="confirmPassword" style="width: 100%;">
<el-input v-model="formData.confirmPassword" placeholder="确认密码"
type="password" show-password></el-input>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
@ -93,7 +179,7 @@
</template>
<script lang='ts' setup>
import {reactive, ref} from 'vue'
import {computed, reactive, ref} from 'vue'
import {ElMessage, ElMessageBox} from 'element-plus'
import {exportData, tableRemoveRow} from '@/utils/table-util'
import CommonPagination from '@/components/common-pagination.vue'
@ -128,12 +214,19 @@ const validatePassword = (rule: any, value: any, callback: any) => {
}
}
const validateConsistent = (rule: any, value: any, callback: any) => {
if (formData.value.password != formData.value.confirmPassword) {
callback('两次密码不一致')
} else {
callback()
}
//
const isAdmin = (row: any) => {
return row.roleList.some((role: any) => role.roleName === '高级管理员');
};
//
const isSelectable = (row: any) => {
return !isAdmin(row);
};
//
const handleSelectionChange = (val: tableData.value) => {
tableRef.value = val
}
const rules = ref({
@ -141,13 +234,30 @@ const rules = ref({
{required: true, message: '请输入密码', trigger: ['blur', 'change']},
{validator: validatePassword, trigger: ['blur', 'change']},
],
resetPassword: [
{required: true, message: '请输入密码', trigger: ['blur', 'change']},
{validator: validatePass2, trigger: ['blur', 'change']}
],
confirmPassword: [
{required: true, message: '请输入密码', trigger: ['blur', 'change']},
{validator: validatePassword, trigger: ['blur', 'change']},
{validator: validateConsistent, trigger: ['blur', 'change']}
{validator: validatePass2, trigger: ['blur', 'change']}
],
name: [
{required: true, message: '请输入姓名', trigger: 'blur'},
{pattern: /^[\u4E00-\u9FA5]{2,6}$/ , message: '请输入2-6个汉字'}
]
})
function validatePass2(rule: any, value: any, callback: any) {
if (!(new RegExp(REGEXP.PASSWORD).test(value))) {
callback("8~16位字母或数字区分大小写");
} else if (value !== formData.value.resetPassword) {
callback(new Error('两次密码不一致'));
} else {
callback()
}
}
queryData()
function searchData() {
@ -168,7 +278,10 @@ function queryData() {
}).then((res: any) => {
loading.value = false
total.value = res.data.total
tableData.value = res.data.records
tableData.value = res.data.records.map((item: any) => ({
...item,
lockFlag: item.lockFlag === "1" //
}));
}).catch(error => {
loading.value = false
})
@ -234,12 +347,14 @@ const resetPassword = (e: any) => {
})
}
const sbPs = () => {
formRef.value.validate((valid: any, fields: any) => {
if (valid) {
modifyPw({
username: formData.value.username,
password: formData.value.password
password: formData.value.resetPassword,
}).then((res: any) => {
if (res.code == 0) {
ElMessage.success('重置成功!')
@ -247,11 +362,15 @@ const sbPs = () => {
} else {
ElMessage.error(res.msg)
}
}).catch((error: any) => {
ElMessage.error('请求发生错误,请稍后重试。')
})
}
})
}
const editData = (e: any) => {
isFormDialog.value = true
formDialogTitle.value = '修改'
@ -260,14 +379,17 @@ const editData = (e: any) => {
const val = JSON.parse(JSON.stringify(e));
val.role = []
val.roleList.forEach((role: any) => {
val.role.push(role.roleId)
val.role.push(role)
})
doctorFormRef.value.formData = val
doctorFormRef.value.formData.role=doctorFormRef.value.formData.role[0].roleId
}, 0)
}
const tableRowClick = (row: any) => {
tableRef.value.toggleRowSelection(row)
tableRef.value.toggleRowSelection(row, isAdmin(row))
}
const doctorFormSave = (data: any, type: string) => {
updateData()
}
@ -278,4 +400,11 @@ const paginationChange = (page: number, s: number) => {
}
</script>
<style lang='scss' scoped></style>
<style lang='scss' scoped>
.disable {
opacity: 0.6;
pointer-events: none;
}
</style>

View File

@ -1,59 +1,100 @@
<template>
<el-form ref="formRef" :model="formData" :rules="rules" label-width="80">
<el-form ref="formRef" :model="formData" :rules="rules" label-width="100">
<el-row>
<el-col :span="12">
<el-form-item label="用户名" prop="username">
<template #label>
<span style="color: red;">*</span> 用户名
</template>
<el-input v-model="formData.username" placeholder="2~16位字母或数字区分大小写"
:disabled="type === 'edit'"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="姓名" prop="name">
<el-input v-model="formData.name" placeholder="请输入姓名"></el-input>
<template #label>
<span style="color: red;">*</span> 姓名
</template>
<el-input v-model="formData.name" placeholder="请输入姓名(2-6个汉字)"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="角色" prop="role">
<el-select v-model="formData.role" placeholder="请选择角色" multiple>
<el-option v-for="item in roleOption" :key="item.roleId" :label="item.roleName"
:value="item.roleId"/>
<template #label>
<span style="color: red;">*</span> 角色
</template>
<el-select v-model="formData.role" placeholder="请选择角色">
<el-option
v-for="item in roleOption"
:key="item.roleId"
:label="item.roleName"
:value="item.roleId"
/>
</el-select>
</el-form-item>
</el-col>
<!--<el-col :span="12">-->
<!-- <el-form-item label="邮箱" prop="email">-->
<!-- <template #label>-->
<!-- <span style="color: red;">*</span> 邮箱-->
<!-- </template>-->
<!-- <el-input v-model="formData.email" placeholder="请输入邮箱"></el-input>-->
<!-- </el-form-item>-->
<!--</el-col>-->
<el-col :span="12">
<el-form-item label="邮箱" prop="email">
<el-input v-model="formData.email" placeholder="请输入邮箱"></el-input>
<el-form-item label="电话" prop="phone">
<template #label>
<span style="color: red;">*</span> 电话
</template>
<el-input v-model="formData.phone" placeholder="请输入电话"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="电话" prop="phone">
<el-input v-model="formData.phone" placeholder="请输入电话"></el-input>
</el-form-item>
</el-col>
<!--<el-col :span="12">-->
<!-- <el-form-item label="电话" prop="phone">-->
<!-- <template #label>-->
<!-- <span style="color: red;">*</span> 电话-->
<!-- </template>-->
<!-- <el-input v-model="formData.phone" placeholder="请输入电话"></el-input>-->
<!-- </el-form-item>-->
<!--</el-col>-->
<el-col :span="12" v-if="type != 'edit'">
<el-form-item label="锁定" prop="lockFlag">
<template #label>
<span style="color: red;">*</span> 锁定
</template>
<el-radio-group v-model="formData.lockFlag">
<el-radio :label="'0'" border>解锁</el-radio>
<el-radio :label="'1'" border>锁定</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row v-if="type != 'edit'">
<el-col :span="12">
<el-form-item label="密码" prop="password">
<el-input v-model="formData.password" placeholder="8~16位字母或数字区分大小写"
<template #label>
<span style="color: red;">*</span> 密码
</template>
<el-input v-model="formData.password" placeholder="8~16位字母或数字(区分大小写)"
:disabled="type === 'edit'" type="password" show-password></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="确认密码" prop="confirmPassword">
<el-form-item label="确认密码" prop="confirmPassword" style="width: auto;" >
<template #label>
<span style="color: red;">*</span>确认密码
</template>
<el-input v-model="formData.confirmPassword" placeholder="确认密码"
:disabled="type === 'edit'" type="password" show-password></el-input>
:disabled="type === 'edit'" type="password" show-password> </el-input>
</el-form-item>
</el-col>
</el-row>
@ -89,16 +130,24 @@ const validatorPhone = (rule: any, value: any, callback: any) => {
} else {
callback();
}
}
const validateEmail = (rule: any, value: any, callback: any) => {
if (!new RegExp(REGEXP.EMAIL).test(value)) {
callback(new Error('请输入合法邮箱'));
}
callback();
}
const rules = reactive({
username: [
{required: true, message: '请输入用户名', trigger: ['blur', 'change']},
{validator: validateAccount, trigger: ['blur', 'change']}
],
name: [
{required: true, message: '请输入姓名', trigger: ['blur', 'change']},
{required: true, message: '请输入姓名', trigger: 'blur'},
{pattern: /^[\u4E00-\u9FA5]{2,6}$/ , message: '请输入2-6个汉字'}
],
role: [
{required: true, message: '请选择角色', trigger: ['blur', 'change']},
@ -111,8 +160,12 @@ const rules = reactive({
{validator: validatePass2, trigger: ['blur', 'change']}
],
confirmPassword: [
{required: true, message: '请输入密码', trigger: ['blur', 'change']},
{required: true, message: '请确认密码', trigger: ['blur', 'change']},
{validator: validatePass2, trigger: ['blur', 'change']}
],
email: [
{required: false, message: '请输入邮箱', trigger: ['blur', 'change']},
{validator: validateEmail, trigger: ['blur', 'change']}
]
})
@ -121,12 +174,14 @@ const formData = ref({
id: '',
username: '',
name: '',
role: [],
// role: [], //,
role: '', //
email: '',
phone: '',
password: '',
confirmPassword: '',
lockFlag: '0',
roleName:''
} as any)
onMounted(() => {
@ -175,7 +230,8 @@ function resetData() {
id: '',
username: '',
name: '',
role: [],
// role: [],
role: '',
email: '',
phone: '',
password: '',
@ -186,9 +242,20 @@ function resetData() {
const saveData = async () => {
await formRef.value.validate((valid: any, fields: any) => {
const userInfo = {
id: formData.value.id,
userId: formData.value.userId,
username: formData.value.username,
name: formData.value.name,
role: Array.of(formData.value.role),
email: formData.value.email,
phone: formData.value.phone,
password: formData.value.password,
lockFlag: formData.value.lockFlag
}
if (valid) {
if (props.type == "add") {
addUser(formData.value).then((data: any) => {
addUser(userInfo).then((data: any) => {
if (data.code == 0) {
ElMessage.success('保存成功!')
emit('save', formData.value, props.type)
@ -202,7 +269,7 @@ const saveData = async () => {
userId: formData.value.userId,
username: formData.value.username,
name: formData.value.name,
role: formData.value.role,
role: Array.of(formData.value.role),
email: formData.value.email,
phone: formData.value.phone
}).then((data: any) => {

View File

@ -11,17 +11,17 @@
<div class="button-part" style="justify-content: space-between;">
<div>
<el-button type="primary" icon="FirstAidKit" @click="addData">新增</el-button>
<el-button icon="FirstAidKit" @click="importData">导入</el-button>
<!--<el-button icon="FirstAidKit" @click="importData">导入</el-button>-->
<el-button icon="Delete" @click="removeData()">删除</el-button>
</div>
<TableAbility @searchBtn="isSearch = !isSearch" @refreshBtn="init"
@downloadBtn="exportData('角色数据', tableData)"></TableAbility>
<!--<TableAbility @searchBtn="isSearch = !isSearch" @refreshBtn="init"-->
<!-- @downloadBtn="exportData('角色数据', tableData)"></TableAbility>-->
</div>
<div class="table-part">
<el-table ref="tableRef" v-loading="loading" :data="tableData" height="100%" border show-overflow-tooltip
@row-click="tableRowClick">
<el-table-column type="selection" width="55"/>
<el-table-column type="index" label="#" width="55" align="center"/>
<el-table-column type="index" label="编号" width="70" align="center"/>
<el-table-column property="roleName" label="角色名称" width="120" align="center"/>
<el-table-column property="roleCode" label="角色标识" width="180" align="center"/>
<el-table-column property="roleDesc" label="角色描述" width="120" align="center"/>
@ -53,9 +53,9 @@
<el-dialog v-model="isFormDialog" :title="formDialogTitle" width="30%">
<RoleForm ref="RoleFormRef" :type="formDialogTitle === '添加' ? 'add' : 'edit'" @close="isFormDialog = false"/>
</el-dialog>
<ImportDialog ref="importDialogRef" title="角色导入" templateUrl="/admin/sys-file/local/file/role.xlsx"
importUrl="/admin/role/import" @success="importSuccessEvent"/>
<EmpowerDialog ref="empowerDialogRef"/>
<!--<ImportDialog ref="importDialogRef" title="角色导入" templateUrl="/admin/sys-file/local/file/role.xlsx"-->
<!-- importUrl="/admin/role/import" @success="importSuccessEvent"/>-->
<!--<EmpowerDialog ref="empowerDialogRef"/>-->
</template>
<script lang='ts' setup>

View File

@ -1,7 +1,7 @@
<template>
<div class="chart-dom-box">
<div ref="chartDom" style="width: 100%; height: 100%"></div>
</div>
<div class="chart-dom-box">
<div ref="chartDom" style="width: 100%; height: 100%"></div>
</div>
</template>
<script lang="ts" setup>
@ -12,215 +12,251 @@ import {useRemoteWsStore} from "@/stores/remote-ws-store";
const chartDom = ref();
const props = withDefaults(defineProps<{
names: any
names: any
}>(), {
names: ['BIS', 'HR']
names: ['BIS', 'HR']
});
defineExpose({
updateChartData
updateChartData
});
const emit = defineEmits(["exceptionEvent"]);
let chart: any;
const xData: any = [];
const series: any = [];
const legendData: any = [];
const colors = ['#00AAB7', '#C77000'];
const colors = ['#00AAB7', '#C77000','#191919'];
let currentNode: any;
const remoteWsStore = useRemoteWsStore();
onMounted(() => {
chartInit();
chartInit();
});
function updateChartData(data: any) {
if (data) {
// if (currentNode && currentNode.Time == data[0].Time) {
if (currentNode && currentNode.Time == data.Time) {
return;
} else {
currentNode = data;
if (data) {
// if (currentNode && currentNode.Time == data[0].Time) {
if (currentNode && currentNode.Time == data.Time) {
return;
} else {
currentNode = data;
// if (currentNode.surgery_status){
// emit("exceptionEvent", remoteWsStore.exceptionMsg.surgery_status, currentNode.Time)
// }
}
// for (let i = (data.length - 1); i >= 0; i--) {
// const item = data[i];
const item = data;
if (xData.indexOf(dateFormater("HH:mm:ss", item.Time)) == -1) {
xData.shift();
xData.push(dateFormater("HH:mm:ss", item.Time));
series.forEach((serie: any) => {
serie.data.shift();
serie.data.push(item[serie.name])
if (item[serie.name + '_except']) {
emit("exceptionEvent", remoteWsStore.exceptionMsg[serie.name + '_except'], item.Time);
}
})
chart.setOption({
xAxis: {
data: xData,
},
series,
})
}
// }
//
}
// for (let i = (data.length - 1); i >= 0; i--) {
// const item = data[i];
const item = data;
if (xData.indexOf(dateFormater("HH:mm:ss", item.Time)) == -1) {
xData.shift();
xData.push(dateFormater("HH:mm:ss", item.Time));
series.forEach((serie: any) => {
serie.data.shift();
serie.data.push(item[serie.name])
if (item[serie.name + '_except']) {
emit("exceptionEvent", remoteWsStore.exceptionMsg[serie.name + '_except'], item.Time);
}
})
chart.setOption({
xAxis: {
data: xData,
},
series,
})
}
// }
}
}
function chartInit() {
chart = echarts.init(chartDom.value as HTMLElement);
chart.clear();
getSeries();
getXData();
getLegendData();
const option: any = {
color: colors,
tooltip: {
trigger: 'axis',
formatter: (params: any) => {
let str = '';
str += params[0].axisValue;
str += '<br>';
props.names.forEach((item: any, index: any) => {
str += params[index].marker;
str += params[index].seriesName + ' ';
switch (item) {
case 'BIS':
str += `脑电双频指数<麻醉深度>${params[index].value}`;
break;
case 'HR':
str += `心率:${params[index].value} 次/分`;
break;
case 'SBP':
str += `收缩压:${params[index].value} mmHg`;
break;
case 'DBP':
str += `舒张压:${params[index].value} mmHg`;
break;
case 'SPO2':
str += `体温:${params[index].value}`;
break;
case 'TEMP':
str += `氧饱和度:${params[index].value}`;
break;
default:
break;
}
str += index === 0 ? '<br>' : '';
});
return str;
},
},
legend: {
type: 'plain',
show: true,
top: 0,
right: 15,
itemGap: 30,
itemWidth: 20,
itemHeight: 3,
icon: 'rect',
textStyle: {
fontSize: 16,
fontWeight: 600,
lineHeight: 30,
},
formatter: (params: string) => {
const index = props.names.findIndex((item: any) => item === params);
let str = params + ' ';
switch (params) {
case 'BIS':
str += `${series[index].data[series[index].data.length - 1]}`;
break;
case 'HR':
str += `${series[index].data[series[index].data.length - 1]} 次/分`;
break;
case 'SBP':
str += `${series[index].data[series[index].data.length - 1]} mmHg`;
break;
case 'DBP':
str += `${series[index].data[series[index].data.length - 1]} mmHg`;
break;
case 'SPO2':
str += `${series[index].data[series[index].data.length - 1]}`;
break;
case 'TEMP':
str += `${series[index].data[series[index].data.length - 1]}`;
break;
default:
break;
}
return str;
},
data: legendData
},
grid: {
left: 5,
right: 25,
bottom: 5,
top: 40,
containLabel: true,
},
xAxis: {
show: true,
type: 'category',
boundaryGap: false,
data: [],
axisLine: {lineStyle: {color: '#006080'}}
},
yAxis: {
show: true,
type: 'value',
axisLabel: {
formatter: `{value} ${props.names[0] === 'BIS' ? '次/分' : props.names[0] === 'SBP' ? 'mmHg' : ''}`
},
axisLine: {show: true, lineStyle: {color: '#006080'}},
splitLine: {lineStyle: {color: '#C0C4CC', width: 1, type: 'dashed'}},
},
series,
};
if (props.names[0] !== 'BIS'
) {
option.yAxis.max = (value: any) => value.max + 20;
}
chart.setOption(option);
chart.resize();
window.addEventListener('resize', () => {
chart = echarts.init(chartDom.value as HTMLElement);
chart.clear();
getSeries();
getXData();
getLegendData();
const option: any = {
color: colors,
tooltip: {
trigger: 'axis',
formatter: (params: any) => {
let str = '';
str += params[0].axisValue;
str += '<br>';
props.names.forEach((item: any, index: any) => {
str += params[index].marker;
str += params[index].seriesName + ' ';
switch (item) {
case 'BIS':
str += `脑电双频指数<麻醉深度>${params[index].value}`;
break;
case 'HR':
str += `心率:${params[index].value} `;
break;
case 'SBP':
// str += `${params[index].value} mmHg`;
str += `收缩压:${params[index].value} `;
break;
case 'MAP':
// str += `${params[index].value} mmHg`;
str += `平均动脉压:${params[index].value} `;
break;
case 'DBP':
str += `舒张压:${params[index].value} `;
break;
case 'SPO2':
str += `${params[index].value}`;
break;
case 'TOF':
str += `${params[index].value}`;
break;
case 'ST':
str += `${params[index].value}`;
break;
case 'EtCO2':
str += `${params[index].value}`;
break;
case 'TEMP':
str += `${params[index].value}`;
break;
default:
break;
}
str += '<br>';
// str += index === 0 ? '<br>' : '';
// str += index === 0 ? '<br>' : '';
});
return str;
},
},
legend: {
type: 'plain',
show: true,
top: 0,
right: 15,
itemGap: 30,
itemWidth: 20,
itemHeight: 3,
icon: 'rect',
textStyle: {
fontSize: 16,
fontWeight: 600,
lineHeight: 30,
},
formatter: (params: string) => {
const index = props.names.findIndex((item: any) => item === params);
let str = params + ' ';
switch (params) {
case 'BIS':
str += `${series[index].data[series[index].data.length - 1]}`;
break;
case 'HR':
str += `${series[index].data[series[index].data.length - 1]}`;
break;
case 'SBP':
// str += `${series[index].data[series[index].data.length - 1]} mmHg`;
str += `${series[index].data[series[index].data.length - 1]} `;
break;
case 'DBP':
str += `${series[index].data[series[index].data.length - 1]} `;
break;
case 'MAP':
str += `${series[index].data[series[index].data.length - 1]} `;
break;
case 'SPO2':
str += `${series[index].data[series[index].data.length - 1]}`;
break;
case 'TOF':
str += `${series[index].data[series[index].data.length - 1]}`;
break;
case 'ST':
str += `${series[index].data[series[index].data.length - 1]}`;
break;
case 'EtCO2':
str += `${series[index].data[series[index].data.length - 1]}`;
break;
case 'TEMP':
str += `${series[index].data[series[index].data.length - 1]}`;
break;
default:
break;
}
return str;
},
data: legendData
},
grid: {
left: 5,
right: 25,
bottom: 5,
top: 40,
containLabel: true,
},
xAxis: {
show: true,
type: 'category',
boundaryGap: false,
data: [],
axisLine: {lineStyle: {color: '#006080'}}
},
yAxis: {
show: true,
type: 'value',
axisLabel: {
// formatter: `{value} ${props.names[0] === 'BIS' ? '/' : props.names[0] === 'SBP' ? 'mmHg' : ''}`
// formatter: `{value} ${props.names[0] === 'BIS' ? '/' : props.names[0] === 'SBP' ? 'mmHg' : ''}`
},
axisLine: {show: true, lineStyle: {color: '#006080'}},
splitLine: {lineStyle: {color: '#C0C4CC', width: 1, type: 'dashed'}},
},
series,
};
if (props.names[0] !== 'BIS'
) {
option.yAxis.max = (value: any) => value.max + 20;
}
chart.setOption(option);
chart.resize();
});
window.addEventListener('resize', () => {
chart.resize();
});
}
function getSeries() {
props.names.forEach((name: any) => {
const serie = {
name,
type: 'line',
symbol: 'none',
smooth: true,
data: [] as number[],
};
for (let i = 0; i < 10; i++) {
serie.data.push(0);
}
series.push(serie)
});
props.names.forEach((name: any) => {
const serie = {
name,
type: 'line',
symbol: 'none',
smooth: true,
data: [] as number[],
};
for (let i = 0; i < 10; i++) {
serie.data.push(0);
}
series.push(serie)
});
}
function getXData() {
for (let i = 0; i < 10; i++) {
xData.push(0);
}
for (let i = 0; i < 10; i++) {
xData.push(0);
}
}
function getLegendData() {
props.names.forEach((name: any, index: any) => {
legendData.push({
name,
textStyle: {color: colors[index]},
props.names.forEach((name: any, index: any) => {
legendData.push({
name,
textStyle: {color: colors[index]},
});
});
});
}
</script>
<style lang="scss" scoped>
.chart-dom-box {
position: relative;
position: relative;
}
</style>

View File

@ -1,8 +1,10 @@
<template>
<!--缩略图页面的消息列表-->
<div class="message-item-part">
<div class="tag-index">{{ index + 1 }}</div>
<ul ref="listRef">
<li v-for="(item, i) in remoteWsStore.remoteTasks[index]?.log || []" :key="i">
<!--<li v-for="(item, i) in remoteWsStore.remoteTasks[index]?.log || []" :key="i">-->
<li v-for="(item, i) in remoteWsStore.getRemoteLog(index) || []" :key="i">
<span>{{ dateFormater('yyyy-MM-dd HH:mm:ss', item.time) }}</span>
<span>{{ item.taskName }}</span>
<span>{{ item.state }}</span>
@ -30,12 +32,18 @@ defineExpose({
})
function scrollToBottom() {
setTimeout(() => {
listRef.value.scrollTo({
top: listRef.value.scrollHeight,
behavior: 'smooth'
})
}, 0)
// setTimeout(() => {
// listRef.value.scrollTo({
// top: listRef.value.scrollHeight,
// behavior: 'smooth'
// })
// }, 0)
setTimeout(() => {
listRef.value.scrollTo({
top: listRef.value.scrollHeight,
behavior: 'smooth'
});
});
}
</script>

View File

@ -1,18 +1,26 @@
<template>
<div class="message-part">
<div class="title">
<span>消息通知</span>
</div>
<div ref="listRef" class="content">
<el-timeline>
<el-timeline-item v-for="(item, index) in remoteWsStore.remoteTasks[remoteWsStore.currentTaskIndex]?.log || []" :key="index"
:timestamp="dateFormater('yyyy-MM-dd HH:mm:ss', item.time)"
:class="{ 'alarm': item.state === '连接失败' || item.state === '异常' }">
{{ item.taskName + ' ' + item.state }}
</el-timeline-item>
</el-timeline>
</div>
</div>
<div class="message-part">
<div class="title">
<span>消息通知</span>
</div>
<div ref="listRef" class="content">
<el-timeline>
<el-timeline-item v-for="(item, index) in remoteWsStore.remoteTasks[remoteWsStore.currentTaskIndex]?.log || []" :key="index"
:timestamp="dateFormater('yyyy-MM-dd HH:mm:ss', item.time)"
:class="{ 'alarm': item.state === '连接失败' || item.state === '异常' }">
{{ item.taskName + ' ' + item.state}}
</el-timeline-item>
</el-timeline>
<!--<el-timeline>-->
<!-- <el-timeline-item v-for="(item, i) in remoteWsStore.remoteTasks[remoteWsStore.currentTaskIndex]?.log || []" :key="i">-->
<!-- <span>{{ dateFormater('yyyy-MM-dd HH:mm:ss', item.time) }}</span>-->
<!-- <span>{{ item.taskName }}</span>-->
<!-- <span>{{ item.state }}</span>-->
<!-- </el-timeline-item>-->
<!--</el-timeline>-->
</div>
</div>
</template>
<script lang='ts' setup>
@ -22,67 +30,76 @@ import {useRemoteWsStore} from "@/stores/remote-ws-store";
defineExpose({
setData,
scrollToBottom
// setData,
scrollToBottom
})
const remoteWsStore = useRemoteWsStore()
const listRef = ref()
function setData(e: any, index: number) {
remoteWsStore.setRemoteLog(e, index)
}
// function setData(e: any, index: number) {
// remoteWsStore.setRemoteLog(e, index)
// }
function scrollToBottom() {
setTimeout(() => {
listRef.value.scrollTo({
top: listRef.value.scrollHeight,
behavior: 'smooth'
})
}, 0)
// setTimeout(() => {
// listRef.value.scrollTo({
// top: listRef.value.scrollHeight,
// behavior: 'smooth'
// })
// }, 0)
setTimeout(() => {
listRef.value.scrollTo({
top: listRef.value.scrollHeight,
behavior: 'smooth'
})
// console.log(remoteWsStore.remoteTasks[remoteWsStore.currentTaskIndex]?.log)
})
}
</script>
<style lang='scss' scoped>
.message-part {
width: 100%;
height: 100%;
border: 1px solid $border-color;
.title {
width: 100%;
height: 40px;
font-size: 20px;
text-align: center;
line-height: 40px;
font-weight: 600;
color: white;
background: $main-color;
}
height: 100%;
border: 1px solid $border-color;
.content {
width: 100%;
height: calc(100% - 100px);
margin-top: 40px;
padding: 0 20px;
overflow-x: hidden;
overflow-y: auto;
:deep(.el-timeline-item) {
color: red;
.el-timeline-item__content,
.el-timeline-item__timestamp {
color: inherit;
}
&.alarm {
color: red;
.el-timeline-item__node {
background: red;
}
}
.title {
width: 100%;
height: 40px;
font-size: 20px;
text-align: center;
line-height: 40px;
font-weight: 600;
color: white;
background: $main-color;
}
.content {
width: 100%;
height: calc(100% - 100px);
margin-top: 40px;
padding: 0 20px;
overflow-x: hidden;
overflow-y: auto;
:deep(.el-timeline-item) {
color: red;
.el-timeline-item__content,
.el-timeline-item__timestamp {
color: inherit;
}
&.alarm {
color: red;
.el-timeline-item__node {
background: red;
}
}
}
}
}
}</style>

View File

@ -4,16 +4,16 @@
<img src="@/assets/imgs/remote/remote_bck.png">
<el-form class="info">
<h3>连接服务器</h3>
<h3>连接服务器</h3>
<br>
<el-form-item>云服务器连接状态{{ patientInfo.isRemote ? '已连接' : '未连接' }}</el-form-item>
<!--<el-form-item>云服务器连接状态{{ patientInfo.isRemote ? '已连接' : '未连接' }}</el-form-item>-->
<!-- <p>输入用户名{{ patientInfo.serverun }}</p>
<p>密码*********</p>
<br>-->
<el-form-item class="input-box" ><span>输入病人姓名</span>
<el-form-item class="input-box" ><span>输入患者姓名</span>
<el-input v-model="patientInfo.patient"></el-input>
</el-form-item>
<el-form-item class="input-box" ><span>输入病人证件号</span>
<el-form-item class="input-box" ><span>输入证件号</span>
<el-input v-model="patientInfo.patientId"></el-input>
</el-form-item>
<!-- <p class="input-box"><span>请选择手术时间</span>-->
@ -165,6 +165,6 @@ const unsubscribeLastTask = () => {
height: auto;
margin-bottom: 15px;
}
}
</style>

View File

@ -1,4 +1,5 @@
<template>
<!--缩略图-->
<div class="remote-item-part">
<div class="title">
<span>{{ remoteTask.taskName || '远程查看' }}</span>
@ -7,7 +8,7 @@
<div class="left-box">
<div class="info-box">
<div class="row-item">
<span class="label">病人名称</span>
<span class="label">患者姓名</span>
<span class="input-value">{{ remoteTask.patient }}</span>
</div>
<div class="row-item">
@ -30,23 +31,41 @@
<span class="label">BIS</span>
<span class="value">{{ patientInfo.BIS }}</span>
</div>
<div class="row-item yellow" :class="{ 'alarm': patientInfo.HR_except }">
<span class="label">HR</span>
<span class="value">{{ patientInfo.HR }}
<!--<span class="unit">/</span>-->
</span>
</div>
<div class="row-item yellow" :class="{ 'alarm': patientInfo.TOF_except }">
<span class="label">TOF</span>
<span class="value">{{ patientInfo.TOF }}</span>
</div>
<div class="row-item" :class="{ 'alarm': patientInfo.SBP_except }">
<span class="label">SBP</span>
<span class="value">{{ patientInfo.SBP }}<span class="unit">mmHg</span></span>
<span class="value">{{ patientInfo.SBP }}</span>
</div>
<div class="row-item yellow" :class="{ 'alarm': patientInfo.DBP_except }">
<span class="label">DBP</span>
<span class="value">{{ patientInfo.DBP }}</span>
</div>
<div class="row-item yellow" :class="{ 'alarm': patientInfo.MAP_except }">
<span class="label">MAP</span>
<span class="value">{{ patientInfo.MAP }}</span>
</div>
<div class="row-item">
<span class="label">SPO2</span>
<span class="value">{{ patientInfo.SPO2 }}</span>
</div>
<div class="row-item yellow" :class="{ 'alarm': patientInfo.DBP_except }">
<span class="label">DBP</span>
<span class="value">{{ patientInfo.DBP }}<span class="unit">mmHg</span></span>
</div>
<div class="row-item yellow" :class="{ 'alarm': patientInfo.HR_except }">
<span class="label">HR</span>
<span class="value">{{ patientInfo.HR }}<span class="unit">/</span></span>
</div>
<div class="row-item yellow">
<span class="label">ST</span>
<span class="value">{{ patientInfo.ST }}</span>
</div>
<div class="row-item yellow" >
<span class="label">EtCO2</span>
<span class="value">{{ patientInfo.EtCO2 }}</span>
</div>
<div class="row-item yellow" >
<span class="label">TEMP</span>
<span class="value">{{ patientInfo.TEMP }}</span>
</div>
@ -90,13 +109,27 @@ function initData() {
function subscribeVital() {
remoteWsStore.subscribeVital(remoteTask.value.patient, remoteTask.value.patientId, remoteTask.value.date, props.index, (res: any) => {
const data = JSON.parse(res.data);
if (data.vitalSignsList && data.vitalSignsList.length > 0) {
Object.assign(patientInfo.value, data.vitalSignsList[0]);
patientInfo.value.state = (patientInfo.value.BIS_except || patientInfo.value.SBP_except ||
patientInfo.value.DBP_except || patientInfo.value.HR_except);
setLog(patientInfo.value, props.index)
emit('addLogAfter', props.index)
// const data = JSON.parse(res.data);
// if (data.vitalSignsList && data.vitalSignsList.length > 0) {
// Object.assign(patientInfo.value, data.vitalSignsList[0]);
// patientInfo.value.state = (patientInfo.value.BIS_except || patientInfo.value.SBP_except ||
// patientInfo.value.DBP_except || patientInfo.value.HR_except || patientInfo.value.ST_except
// ||patientInfo.value.EtCO2_except);
// setLog(patientInfo.value, props.index)
// emit('addLogAfter', props.index)
// }
if (res && res.data) {
const data = JSON.parse(res.data);
// if (data.vitalSignsList && data.vitalSignsList.length > 0) {
if (data.vitalSignsList) {
Object.assign(patientInfo.value, data.vitalSignsList);
patientInfo.value.state = (patientInfo.value.BIS_except || patientInfo.value.SBP_except ||
patientInfo.value.DBP_except || patientInfo.value.HR_except || patientInfo.value.ST_except
|| patientInfo.value.EtCO2_except || patientInfo.value.TOF_except);
// patient.vitalWS.send(JSON.stringify({msgType: "heartbeat"}))
setLog(patientInfo.value, props.index)
emit('addLogAfter', props.index)
}
}
})
@ -105,16 +138,38 @@ function subscribeVital() {
function wsClose() {
remoteWsStore.vitalOnclose(remoteTask.value.patient, remoteTask.value.patientId, remoteTask.value.date, props.index, () => {
setTimeout(() => {
ElMessage.info('远程控制' + props.index + ' 生命体征数据连接断开,正在尝试重连……')
ElMessage.info('远程查看' + props.index + ' 生命体征数据连接断开,正在尝试重连……')
initData()
}, 3000)
})
}
// const lastTime = ref([])
//
// function setLog(data: any, index: number) {
// // if (currentException[index]?.Time != data.Time) {
// if (lastTime[index].value != data.Time)
// remoteWsStore.exceptionType.forEach((item: any) => {
// if (data[item]) {
// const msg: any = remoteWsStore.exceptionMsg[item];
// remoteWsStore.setRemoteLog({
// state: msg,
// taskName: remoteTask.value.taskName,
// time: data.Time,
// type: "exception"
// }, index);
// }
// })
// // currentException[index] = data
// // }
// }
const lastTimes:any = ref([]); // 使lastTime
function setLog(data: any, index: number) {
if (currentException[index]?.Time != data.Time) {
currentException[index] = data
console.log(lastTimes.value[index], data.Time);
if (data.Time != lastTimes.value[index]) {
remoteWsStore.exceptionType.forEach((item: any) => {
if (data[item]) {
const msg: any = remoteWsStore.exceptionMsg[item];
@ -125,7 +180,8 @@ function setLog(data: any, index: number) {
type: "exception"
}, index);
}
})
});
lastTimes.value[index] = data.Time; // lastTime
}
}

View File

@ -4,12 +4,13 @@
<span>{{ remoteItem?.taskName || '远程查看' }}</span>
<el-button v-if="remoteItem?.taskName" class="break-btn" @click="breakRemote">断开连接</el-button>
</div>
<!-- 小分辨率 -->
<div v-if="mediaMini800" class="content mini" :class="{ 'is-total': remoteItem?.isRemote }">
<div class="left-box">
<div class="info-box">
<div class="row-item">
<span class="label">病人名称</span>
<span class="label">患者姓名</span>
<span class="input-value">{{ remoteItem.patient }}</span>
</div>
<div class="row-item">
@ -32,21 +33,39 @@
<span class="label">BIS</span>
<span class="value">{{ patientInfo.BIS }}</span>
</div>
<div class="row-item yellow" :class="{ 'alarm': patientInfo.HR_except }">
<span class="label">HR</span>
<span class="value">{{ patientInfo.HR }}
<!--<span class="unit">/</span>-->
</span>
</div>
<div class="row-item yellow" :class="{ 'alarm': patientInfo.TOF_except }">
<span class="label">TOF</span>
<span class="value">{{ patientInfo.TOF }}</span>
</div>
<div class="row-item" :class="{ 'alarm': patientInfo.SBP_except }">
<span class="label">SBP</span>
<span class="value">{{ patientInfo.SBP }}<span class="unit">mmHg</span></span>
<span class="value">{{ patientInfo.SBP }}</span>
</div>
<div class="row-item yellow" :class="{ 'alarm': patientInfo.DBP_except }">
<span class="label">DBP</span>
<span class="value">{{ patientInfo.DBP }}</span>
</div>
<div class="row-item yellow" :class="{ 'alarm': patientInfo.MAP_except }">
<span class="label">MAP</span>
<span class="value">{{ patientInfo.MAP }}</span>
</div>
<div class="row-item">
<span class="label">SPO2</span>
<span class="value">{{ patientInfo.SPO2 }}</span>
</div>
<div class="row-item yellow" :class="{ 'alarm': patientInfo.DBP_except }">
<span class="label">DBP</span>
<span class="value">{{ patientInfo.DBP }}<span class="unit">mmHg</span></span>
<div class="row-item yellow">
<span class="label">ST</span>
<span class="value">{{ patientInfo.ST }}</span>
</div>
<div class="row-item yellow" :class="{ 'alarm': patientInfo.HR_except }">
<span class="label">HR</span>
<span class="value">{{ patientInfo.HR }}<span class="unit">/</span></span>
<div class="row-item yellow">
<span class="label">EtCO2</span>
<span class="value">{{ patientInfo.EtCO2 }}</span>
</div>
<div class="row-item yellow">
<span class="label">TEMP</span>
@ -57,11 +76,15 @@
<img src="@/assets/imgs/main_body_intact.png">
</div>
</div>
<!-- 十个任务主页面的 -->
<div v-else class="content" :class="{ 'is-total': remoteItem?.isRemote }">
<!--<div :class="{ 'is-total': remoteItem?.isRemote }">-->
<div class="left-box">
<div class="info-box">
<div class="row-item">
<span class="label">病人名称</span>
<span class="label">患者姓名</span>
<span class="input-value">{{ remoteItem?.patient }}</span>
</div>
<div class="row-item">
@ -73,13 +96,23 @@
<span class="label">BIS</span>
<span class="value">{{ patientInfo.BIS }}</span>
</div>
<div class="row-item" :class="{ 'alarm': patientInfo.SBP_except }">
<span class="label">SBP</span>
<span class="value">{{ patientInfo.SBP }}<span class="unit">mmHg</span></span>
<div class="row-item" :class="{ 'alarm': patientInfo.HR_except }">
<span class="label">HR</span>
<span class="value">{{ patientInfo.HR }}
<!--<span class="unit">mmHg</span>-->
</span>
</div>
<div class="row-item">
<span class="label">SPO2</span>
<span class="value">{{ patientInfo.SPO2 }}</span>
<div class="row-item" :class="{ 'alarm': patientInfo.DBP_except }">
<span class="label">DBP</span>
<span class="value">{{ patientInfo.DBP }}</span>
</div>
<div class="row-item" :class="{ 'alarm': patientInfo.TEMP_except }">
<span class="label">TEMP</span>
<span class="value">{{ patientInfo.TEMP }}</span>
</div>
<div class="row-item" :class="{ 'alarm': patientInfo.ST_except }">
<span class="label">ST</span>
<span class="value">{{ patientInfo.ST }}</span>
</div>
</div>
<div class="center-box">
@ -99,17 +132,29 @@
<span class="tag-value" :class="{ 'alarm': patientInfo.state }">异常</span>
</div>
</div>
<div class="row-item" :class="{ 'alarm': patientInfo.DBP_except }">
<span class="label">DBP</span>
<span class="value">{{ patientInfo.DBP }}<span class="unit">mmHg</span></span>
<div class="row-item" :class="{ 'alarm': patientInfo.TOF_except }">
<span class="label">TOF</span>
<span class="value">{{ patientInfo.TOF }}
<!--<span class="unit">mmHg</span>-->
</span>
</div>
<div class="row-item" :class="{ 'alarm': patientInfo.HR_except }">
<span class="label">HR</span>
<span class="value">{{ patientInfo.HR }}<span class="unit">/</span></span>
<div class="row-item" :class="{ 'alarm': patientInfo.SBP_except }">
<span class="label">SBP</span>
<span class="value">{{ patientInfo.SBP }}
<!--<span class="unit">/</span>-->
</span>
</div>
<div class="row-item">
<span class="label">TEMP</span>
<span class="value">{{ patientInfo.TEMP }}</span>
<div class="row-item " :class="{ 'alarm': patientInfo.MAP_except }">
<span class="label">MAP</span>
<span class="value">{{ patientInfo.MAP }}</span>
</div>
<div class="row-item " :class="{'alarm': patientInfo.SPO2_except}">
<span class="label">SPO2</span>
<span class="value">{{ patientInfo.SPO2 }}</span>
</div>
<div class="row-item " :class="{'alarm': patientInfo.EtCO2_except}">
<span class="label">EtCO2</span>
<span class="value">{{ patientInfo.EtCO2 }}</span>
</div>
</div>
</div>
@ -159,6 +204,7 @@ function showData(i: any) {
currentException = {}
if (remoteItem.value && remoteItem.value.patient) {
remoteWsStore.createVital(remoteItem.value.patient, remoteItem.value.patientId, remoteItem.value.date, currentIndex)
remoteWsStore.createChat(remoteItem.value.patient, remoteItem.value.patientId, remoteItem.value.date, currentIndex)
}
getData()
}
@ -171,11 +217,19 @@ function initData() {
remoteWsStore.createVital(remoteItem.value.patient, remoteItem.value.patientId, remoteItem.value.date, currentIndex)
remoteWsStore.vitalOnclose(remoteItem.value.patient, remoteItem.value.patientId, remoteItem.value.date, currentIndex, () => {
setTimeout(() => {
ElMessage.info('远程控制' + (currentIndex + 1) + ' 生命体征数据连接断开,正在尝试重连……')
ElMessage.info('远程查看' + (currentIndex + 1) + ' 生命体征数据连接断开,正在尝试重连……')
remoteWsStore.createVital(remoteItem.value.patient, remoteItem.value.patientId, remoteItem.value.date, currentIndex)
initData()
}, 3000)
})
remoteWsStore.createChat(remoteItem.value.patient, remoteItem.value.patientId, remoteItem.value.date, currentIndex)
remoteWsStore.chatOnclose(remoteItem.value.patient, remoteItem.value.patientId, remoteItem.value.date, currentIndex, () => {
setTimeout(() => {
// ElMessage.info('' + (currentIndex + 1) + ' ')
remoteWsStore.createChat(remoteItem.value.patient, remoteItem.value.patientId, remoteItem.value.date, currentIndex)
initData()
}, 3000)
})
getData()
}
}
@ -189,8 +243,8 @@ function getData() {
// if (data.vitalSignsList && data.vitalSignsList.length > 0) {
if (data.vitalSignsList) {
Object.assign(patientInfo.value, data.vitalSignsList);
patientInfo.value.state = (patientInfo.value.BIS_except || patientInfo.value.SBP_except ||
patientInfo.value.DBP_except || patientInfo.value.HR_except);
patientInfo.value.state = (patientInfo.value.BIS_except || patientInfo.value.SBP_except || patientInfo.value.MAP_except
|| patientInfo.value.DBP_except || patientInfo.value.HR_except || patientInfo.value.TOF_except);
setLog(patientInfo.value)
emit('addLogAfter')
}
@ -199,20 +253,24 @@ function getData() {
}
}
const lastTime = ref(0)
// ,
function setLog(data: any) {
if (currentException?.Time != data.Time) {
currentException = data
// console.log(lastTime.value, data.Time)
if (data.Time != lastTime.value) {
remoteWsStore.exceptionType.forEach((item: any) => {
if (data[item]) {
const msg: any = remoteWsStore.exceptionMsg[item];
remoteWsStore.setRemoteLog({
state: msg,
taskName: remoteItem.value.taskName,
time: item.Time,
time: data.Time,
type: "exception"
}, currentIndex);
}
})
lastTime.value = data.Time
}
}
@ -224,6 +282,7 @@ const breakRemote = () => {
emit('breakRemote')
}
</script>
<style lang='scss' scoped>

View File

@ -3,12 +3,16 @@
<div class="main-box">
<div class="left-box">
<h3>{{ currentRemote?.taskName }}</h3>
<chart-line ref="chartDom1" class="chart-line" :names="['BIS', 'HR']"
<chart-line ref="chartDom1" class="chart-line" :names="['BIS', 'HR','TOF']"
@exception-event="vitalExcepEvent"></chart-line>
<chart-line ref="chartDom2" class="chart-line" :names="['SBP', 'DBP']"
<chart-line ref="chartDom2" class="chart-line" :names="['SBP', 'DBP','MAP']"
@exception-event="vitalExcepEvent"></chart-line>
<chart-line ref="chartDom3" class="chart-line" :names="['SPO2', 'TEMP']"
<chart-line ref="chartDom3" class="chart-line" :names="['TEMP','ST']"
@exception-event="vitalExcepEvent"></chart-line>
<chart-line ref="chartDom4" class="chart-line" :names="['SPO2', 'EtCO2']"
@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>
@ -79,8 +83,9 @@
<!--聊天框 -->
<div class="message-box">
<ul ref="msgLog" class="message-log">
<li v-for="(item, index) in mssageList" :key="'msg-log-' + index"
<li v-for="(item, index) in messageList" :key="'msg-log-' + index"
:class="{ 'align-right': item.createUser == userInfo.account }">
<div>{{ item.createUser }}</div>
<span>{{ item.msg }}</span>
</li>
</ul>
@ -120,7 +125,7 @@
<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">
<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;">
@ -135,7 +140,7 @@
</el-dropdown>
</template> -->
</el-table-column>
<el-table-column prop="total" label="累计药量(ml)" 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">
@ -165,10 +170,10 @@
<!-- 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 type="index" label="泵号" width="80" align="center" :index="5"/>
<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="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">
@ -196,17 +201,17 @@
</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="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>
@ -214,9 +219,9 @@
</template>
<script lang="ts" setup>
import {onMounted, onUnmounted, reactive, ref} from 'vue';
import {onMounted, onUnmounted, onUpdated, reactive, ref} from 'vue';
import {useRouter} from 'vue-router'
import {ElMessage} from 'element-plus';
import {ElMessage, ElMessageBox} from 'element-plus';
import {dateFormater} from '@/utils/date-util';
import chartLine from './chart/chart-line.vue';
import chartEcg from './chart/chart-ecg.vue';
@ -230,7 +235,6 @@ import {useUserStore} from "@/stores/user-info-store";
import {getPatientInfo, getPatientInfoM} from "@/api/patient";
import axios from "axios";
const router = useRouter()
const medicineCustom: any[] = [
@ -240,9 +244,9 @@ const medicineCustom: any[] = [
{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: 1, total: 100},
{name: '罗库溴铵', plus: 0.1, total: 10}
// {name: '', plus: 0.1, total: 10}
]
const remoteWsStore = useRemoteWsStore()
const currentRemote = ref()
@ -278,6 +282,12 @@ const table1SpeedVal = ref('');
let currentAIMedicine: any;
let currentDocMedicine: any;
const medicineSpeedTemp: any = {};
/*
* 聊天室
*/
const msgVal = ref('');
const messageList = ref([] as any);
const historyMsg = ref([] as any);
onMounted(() => {
currentRemote.value = remoteWsStore.getRemoteTask()[remoteWsStore.getCurrentTaskIndex()]
@ -292,8 +302,9 @@ onMounted(() => {
// setTableData();
});
onUnmounted(() => {
remoteWsStore.unsubscribeChat(currentRemote.value.patient, currentRemote.value.patientId, currentRemote.value.date, currentIndex);
// 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)
@ -328,19 +339,19 @@ const subscribeVital = () => {
remoteWsStore.subscribeVital(currentRemote.value.patient, currentRemote.value.patientId, currentRemote.value.date, currentIndex,
function (res: any) {
const data = JSON.parse(res.data);
// 1 2 3
// 1 2 3 4
if (data.vitalSignsList != null) {
updateMedicineTable(data.aiMedicineList[0], undefined);
chartDom1.value.updateChartData(data.vitalSignsList);
chartDom2.value.updateChartData(data.vitalSignsList);
chartDom3.value.updateChartData(data.vitalSignsList);
// chartDom4.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 + ' 生命体征数据连接断开,正在尝试重连……')
ElMessage.info('远程查看' + currentIndex + ' 生命体征数据连接断开,正在尝试重连……')
subscribeVital()
}, 3000)
})
@ -350,28 +361,45 @@ 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));
// const chatObj = JSON.parse(res.data);
// if (chatObj.history) {
// // mssageList.value = chatObj.history;
// console.log("2131231")
// mssageList.value = chatObj;
// } else {
const msg = JSON.parse(res.data);
if (msg.msgType === 'msg') {
messageList.value.push(msg);
}
if (msg.msgType === 'historyChat') {
messageList.value = msg.history;
}
if (msg.msgType == "destroy") {
ElMessageBox.confirm('远程查看' + currentIndex + '已断开与手术室连接', '提示', {
confirmButtonText: '确认',
type: 'info'
}).then(() => {
}).catch(() => {
});
}
})
remoteWsStore.chatOnclose(currentRemote.value.patient, currentRemote.value.patientId, currentRemote.value.date, currentIndex, () => {
setTimeout(() => {
ElMessage.info('远程控制' + currentIndex + ' 通讯连接断开,正在尝试重连……')
ElMessage.info('远程查看' + currentIndex + ' 通讯连接断开,正在尝试重连……')
subscribeChat()
}, 3000)
})
}
function initData() {
lungAlarm.value = false;
heartAlarm.value = false;
isAIDose.value = false;
unusual.value = [];
mssageList.value = [];
messageList.value = [];
fixedTableData.value = [];
varTableData.value = [];
featureTable.value = [];
@ -387,16 +415,14 @@ function updateMedicineTable(aiMedicine: any, doctorMedicine: any) {
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
});
// todo
// 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'
@ -408,7 +434,7 @@ function updateMedicineTable(aiMedicine: any, doctorMedicine: any) {
// console.log(varTableData.value)
// console.log(fixedTableData.value)
} else {
} else { //
const varTable: any = [];
const fixedTable: any = [];
remoteWsStore.varMedicine.forEach(key => {
@ -483,7 +509,7 @@ function vitalExcepEvent(data: any, time: any) {
}
function logUpdate(msg: string, time: any) {
unusual.value.push(dateFormater('HH:mm:ss', time) + msg);
unusual.value.push(dateFormater('HH:mm:ss', time) + '- ' + msg);
setTimeout(() => {
unusualMsgRef.value.scrollTo({
top: unusualMsgRef.value.scrollHeight,
@ -633,12 +659,6 @@ function startAI() {
}
/*
* 聊天室
*/
const msgVal = ref('');
const mssageList = ref([] as any);
</script>
<style lang="scss" scoped>
@ -678,8 +698,10 @@ const mssageList = ref([] as any);
.chart-line {
width: 100%;
//height: calc(25% - 30px);
//height: calc(33.3% - 30px);
height: calc(25% - 30px);
height: calc(33.3% - 30px);
//height: calc(33.3% - 30px);
margin-bottom: 20px;
background: #e8f5f8;
border-top-left-radius: 20px;

View File

@ -32,6 +32,7 @@ import RemoteDialog from './part/remote-dialog.vue'
import RemotePart from './part/remote-part.vue'
import MessagePart from './part/message-part.vue'
import {useRemoteWsStore} from "@/stores/remote-ws-store";
import {ElMessage} from "element-plus";
const router = useRouter()
const remotePartRef = ref()
@ -68,6 +69,7 @@ const editTask = (item: any) => {
// content
if (item.isRemote) {
remotePartRef.value.showData(item.index)
remoteWsStore.getHistoryChat(item.patient, item.patientId, item.date, item.index)
} else {
remoteDialogRef.value.open(item.index)
}
@ -79,7 +81,6 @@ const toRemoteControl = (item: any) => {
remoteWsStore.setCurrentTaskIndex(item.index)
router.push('/remote-manage/remote-control')
} else {
remoteDialogRef.value.open(item.index)
}
}
//
@ -100,6 +101,7 @@ const addLogAfter = () => {
messagePartRef.value.scrollToBottom()
}
</script>
<style lang='scss' scoped>

View File

@ -26,11 +26,11 @@
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="邮箱" prop="mailbox">
<el-input v-model="formData.mailbox" placeholder="请输入邮箱"></el-input>
</el-form-item>
</el-col>
<!--<el-col :span="12">-->
<!-- <el-form-item label="邮箱" prop="mailbox">-->
<!-- <el-input v-model="formData.mailbox" placeholder="请输入邮箱"></el-input>-->
<!-- </el-form-item>-->
<!--</el-col>-->
</el-row>
<el-row>
<el-col :span="12">

View File

@ -20,7 +20,7 @@
<el-table ref="tableRef" v-loading="loading" :data="tableData" height="100%" border show-overflow-tooltip
@row-click="tableRowClick">
<el-table-column type="selection" width="55"/>
<el-table-column type="index" label="#" width="55" align="center"/>
<el-table-column type="index" label="编号" width="55" align="center"/>
<el-table-column property="name" label="医院名称" width="200" align="center"/>
<el-table-column property="code" label="编码" width="60" align="center"/>
<el-table-column label="高级管理员" width="200" align="center">

View File

@ -16,7 +16,7 @@
<el-table ref="tableRef" v-loading="loading" :data="tableData" height="100%" border show-overflow-tooltip
:row-class-name="({ row }: any) => row.lockFlag == 1 && 'disable'" @row-click="tableRowClick">
<!--<el-table-column type="selection" width="55"/>-->
<el-table-column type="index" label="#" width="55" align="center" />
<el-table-column type="index" label="编号" width="70" align="center" />
<!--<el-table-column property="hospital" label="医院名称" width="200" align="center"/>-->
<el-table-column property="name" label="姓名" width="120" align="center" />
<el-table-column label="手机号" width="220" align="center">
@ -25,13 +25,13 @@
}}
</template>
</el-table-column>
<el-table-column label="角色" width="220" align="center">
<template #default="scope">
<span v-for="(item, index) in scope.row.roleList" :key="index">
{{ item.roleName }} {{ (scope.row.roleList.length - 1) == index ? '' : '' }}
</span>
</template>
</el-table-column>
<!--<el-table-column label="角色" width="220" align="center">-->
<!-- <template #default="scope">-->
<!-- <span v-for="(item, index) in scope.row.roleList" :key="index">-->
<!-- {{ item.roleName }} {{ (scope.row.roleList.length - 1) == index ? '' : '' }}-->
<!-- </span>-->
<!-- </template>-->
<!--</el-table-column>-->
<el-table-column label="锁定" width="120" align="center">
<template #default="scope">
<span @click.stop>

View File

@ -1,41 +1,44 @@
import { fileURLToPath, URL } from 'node:url'
import {fileURLToPath, URL} from 'node:url'
import { defineConfig } from 'vite'
import {defineConfig} from 'vite'
import vue from '@vitejs/plugin-vue'
import fs from 'fs';
import path from 'path';
// https://vitejs.dev/config/
export default defineConfig({
// base: '/medical/',
plugins: [vue()],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
// base: '/medical/',
plugins: [vue()],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
},
css: {
preprocessorOptions: {
scss: {
additionalData: '@import "./src/assets/css/variable.scss";' //引入scss文件
}
}
},
server: {
proxy: {
'/api': {
target: 'http://127.0.0.1:6679', // 目标服务器地址
// target: 'http://110.41.142.124:6679', // 目标服务器地址
ws: true, // 是否启用 WebSocket
changeOrigin: true, // 是否修改请求头中的 Origin 字段
rewrite: (path) => path.replace(/^\/api/, ''),
},
'/socket.io': {
target: 'ws://127.0.0.1:6679',
// target: 'ws://110.41.142.124:6679',
ws: true,
changeOrigin: true,
rewrite: (path) => path.replace(/^\/socket.io/, ''),
},
}
}
},
css:{
preprocessorOptions:{
scss:{
additionalData: '@import "./src/assets/css/variable.scss";' //引入scss文件
}
}
},
server: {
proxy: {
'/api': {
target: 'http://127.0.0.1:6679', // 目标服务器地址
// target: 'http://110.41.142.124:6679', // 目标服务器地址
ws: true, // 是否启用 WebSocket
changeOrigin: true, // 是否修改请求头中的 Origin 字段
rewrite: (path) => path.replace(/^\/api/, ''),
},
'/socket.io': {
target: 'ws://127.0.0.1:6679',
// target: 'ws://110.41.142.124:6679',
ws: true,
changeOrigin: true,
rewrite: (path) => path.replace(/^\/socket.io/, ''),
},
}
}
})