mirror of
https://gitee.com/xiongmao1988/rax-medical.git
synced 2025-08-23 20:44:58 +08:00
Merge branch 'refs/heads/dev'
# Conflicts: # src/views/login/login.vue # src/views/remote-manage/part/remote-dialog.vue
This commit is contained in:
commit
198b34f732
|
@ -12,7 +12,7 @@
|
|||
"dependencies": {
|
||||
"@stomp/stompjs": "^7.0.0",
|
||||
"axios": "^1.3.3",
|
||||
"crypto-js": "4.2.0",
|
||||
"crypto-js": "^4.2.0",
|
||||
"echarts": "^5.4.1",
|
||||
"element-plus": "2.3.1",
|
||||
"js-cookie": "^3.0.5",
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
import request from "@/utils/request";
|
||||
|
||||
const addDailyPlanUrl = "/admin/dailyPlan/saveOrUpdate";
|
||||
const getDailyPlanListUrl = "/admin/dailyPlan/getListByDate";
|
||||
const deleteByIdUrl = "/admin/dailyPlan/deleteById";
|
||||
const getPlanDateListUrl = "/admin/dailyPlan/getPlanDateList";
|
||||
const getTodoCountByDateUrl = "/admin/dailyPlan/getTodoCountByDate";
|
||||
|
||||
export function saveOrUpdate(param: any) {
|
||||
return new Promise((resolve, reject) => {
|
||||
request.postForm(addDailyPlanUrl, param).then((res: any) => {
|
||||
resolve(res.data);
|
||||
}).catch(err => {
|
||||
reject(err);
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export function getDailyPlanList(date: string) {
|
||||
return new Promise((resolve, reject) => {
|
||||
request.postForm(getDailyPlanListUrl, {date}).then((res: any) => {
|
||||
resolve(res.data);
|
||||
}).catch(err => {
|
||||
reject(err);
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export function deleteById(id: string) {
|
||||
return new Promise((resolve, reject) => {
|
||||
request.postForm(deleteByIdUrl, {id}).then((res: any) => {
|
||||
resolve(res.data);
|
||||
}).catch(err => {
|
||||
reject(err);
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export function getPlanDateList(startDate: string, endDate: string) {
|
||||
return new Promise((resolve, reject) => {
|
||||
request.postForm(getPlanDateListUrl, {startDate, endDate}).then((res: any) => {
|
||||
resolve(res.data);
|
||||
}).catch(err => {
|
||||
reject(err);
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export function getTodoCountByDate(date: string) {
|
||||
return new Promise((resolve, reject) => {
|
||||
request.postForm(getTodoCountByDateUrl, {date}).then((res: any) => {
|
||||
resolve(res.data);
|
||||
}).catch(err => {
|
||||
reject(err);
|
||||
})
|
||||
});
|
||||
}
|
|
@ -1,21 +1,32 @@
|
|||
import request, {CommonHeaderEnum} from "@/utils/request";
|
||||
|
||||
const getMonthlyLogCountUrl = '/admin/log/getMonthlyLogCount'
|
||||
const getPageUrl = "/admin/log/page";
|
||||
|
||||
export function getMonthlyLogCount(startTime: string, endTime: string) {
|
||||
return new Promise(resolve => {
|
||||
request({
|
||||
url: getMonthlyLogCountUrl,
|
||||
method: 'post',
|
||||
data: {
|
||||
startTime,
|
||||
endTime
|
||||
},
|
||||
headers: {
|
||||
'Content-Type': CommonHeaderEnum.FORM_CONTENT_TYPE,
|
||||
},
|
||||
}).then(res => {
|
||||
resolve(res.data);
|
||||
})
|
||||
})
|
||||
return new Promise(resolve => {
|
||||
request({
|
||||
url: getMonthlyLogCountUrl,
|
||||
method: 'post',
|
||||
data: {
|
||||
startTime,
|
||||
endTime
|
||||
},
|
||||
headers: {
|
||||
'Content-Type': CommonHeaderEnum.FORM_CONTENT_TYPE,
|
||||
},
|
||||
}).then(res => {
|
||||
resolve(res.data);
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export function getPage(current: number, size: number) {
|
||||
return new Promise((resolve, reject) => {
|
||||
request.get(getPageUrl + `?current=${current}&size=${size}`).then((res: any) => {
|
||||
resolve(res.data);
|
||||
}).catch(err => {
|
||||
reject(err);
|
||||
})
|
||||
})
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
import request from "@/utils/request";
|
||||
|
||||
const patientInfoUrl = "/admin/medicine/getPatientInfo";
|
||||
|
||||
export function getPatientInfo(name: string, id: string, date: string) {
|
||||
return new Promise((resolve, reject) => {
|
||||
request.postForm(patientInfoUrl, {
|
||||
patientName: name,
|
||||
idNum: id,
|
||||
date: date
|
||||
}).then((res: any) => {
|
||||
resolve(res.data);
|
||||
}).catch(error => {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -1,23 +1,28 @@
|
|||
<template>
|
||||
<el-timeline>
|
||||
<el-timeline-item v-for="(item, index) in activities" :key="index" :timestamp="item.time">
|
||||
{{ item.title + '-' + item.ip }}
|
||||
<el-timeline-item v-for="(item, index) in activities" :key="index" :timestamp="item.createTime">
|
||||
{{ item.title + '-' + item.remoteAddr }}
|
||||
</el-timeline-item>
|
||||
</el-timeline>
|
||||
</template>
|
||||
|
||||
<script lang='ts' setup>
|
||||
import { onMounted, reactive, ref, toRefs, watch } from 'vue'
|
||||
import { dateFormater } from '@/utils/date-util';
|
||||
import {onMounted, ref} from 'vue'
|
||||
import * as logManageApi from "@/api/log-manage";
|
||||
|
||||
const activities: any = []
|
||||
const activities = ref([] as any);
|
||||
|
||||
while (activities.length < 10) {
|
||||
activities.push({
|
||||
time: dateFormater('yyyy-MM-dd HH:mm:ss'),
|
||||
title: '登录成功',
|
||||
ip: '127.0.0.1'
|
||||
})
|
||||
onMounted(function () {
|
||||
getLogList();
|
||||
});
|
||||
|
||||
function getLogList() {
|
||||
logManageApi.getPage(0, 100).then((res: any) => {
|
||||
if (res.code == 0) {
|
||||
activities.value = res.data.records;
|
||||
console.log(activities.value)
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,82 +1,100 @@
|
|||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import { useLoginStore } from '@/stores/user-info-store'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { constantRoute } from './routes'
|
||||
import {createRouter, createWebHistory} from 'vue-router'
|
||||
import {useLoginStore} from '@/stores/user-info-store'
|
||||
import {ElMessage} from 'element-plus'
|
||||
import {constantRoute} from './routes'
|
||||
import {decrypt, decryption, encrypt, encryption, isBase64} from "@/utils/other";
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(import.meta.env.BASE_URL),
|
||||
routes: constantRoute,
|
||||
history: createWebHistory(import.meta.env.BASE_URL),
|
||||
routes: constantRoute,
|
||||
stringifyQuery: stringifyQuery,
|
||||
parseQuery: parseQuery,
|
||||
})
|
||||
|
||||
const kk = "raxipnenttlewe";
|
||||
|
||||
router.beforeEach((to, from, next) => {
|
||||
const loginInfo = useLoginStore().getlogin()
|
||||
const isLogin = loginInfo.isLogin
|
||||
// 普通用户
|
||||
const commonUser = [
|
||||
'/login',
|
||||
'/home',
|
||||
'/patients-manage',
|
||||
'/patients-manage/patients-manage',
|
||||
'/patients-manage/surgery-info'
|
||||
]
|
||||
// 中级管理员
|
||||
const IntermediateAdmin = [
|
||||
'/login',
|
||||
'/home',
|
||||
'/patients-manage',
|
||||
'/patients-manage/patients-manage',
|
||||
'/patients-manage/surgery-info',
|
||||
'/remote-manage',
|
||||
'/remote-manage/remote-manage',
|
||||
'/remote-manage/remote-control'
|
||||
]
|
||||
// 高级管理员
|
||||
const SeniorAdmin = [
|
||||
'/login',
|
||||
'/home',
|
||||
'/patients-manage',
|
||||
'/patients-manage/patients-manage',
|
||||
'/patients-manage/surgery-info',
|
||||
'/remote-manage',
|
||||
'/remote-manage/remote-manage',
|
||||
'/remote-manage/remote-control',
|
||||
'/permissions-manage',
|
||||
'/permissions-manage/doctor-manage',
|
||||
'/permissions-manage/role-manage',
|
||||
'/permissions-manage/menu-manage',
|
||||
'/logs-manage',
|
||||
'/logs-manage/message-manage',
|
||||
'/logs-manage/logs-manage'
|
||||
]
|
||||
const isViewRoute = () => {
|
||||
let release = false
|
||||
switch (loginInfo.permissions) {
|
||||
case '超级管理员':
|
||||
release = true
|
||||
break;
|
||||
case '高级管理员':
|
||||
release = SeniorAdmin.some((p: string) => p === to.path)
|
||||
break;
|
||||
case '中级管理员':
|
||||
release = IntermediateAdmin.some((p: string) => p === to.path)
|
||||
break;
|
||||
case '普通用户':
|
||||
release = commonUser.some((p: string) => p === to.path)
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return release
|
||||
}
|
||||
if(to.fullPath ==='/login') {
|
||||
next()
|
||||
return
|
||||
}
|
||||
if (!isLogin) next('/login') // 重定向登录页
|
||||
else if(!isViewRoute()) {
|
||||
ElMessage.error('无权访问!')
|
||||
next(from.fullPath)
|
||||
}else next()
|
||||
const loginInfo = useLoginStore().getlogin()
|
||||
// const isLogin = loginInfo.isLogin
|
||||
// 普通用户
|
||||
const commonUser = [
|
||||
'/login',
|
||||
'/home',
|
||||
'/patients-manage',
|
||||
'/patients-manage/patients-manage',
|
||||
'/patients-manage/surgery-info'
|
||||
]
|
||||
// 中级管理员
|
||||
const IntermediateAdmin = [
|
||||
'/login',
|
||||
'/home',
|
||||
'/patients-manage',
|
||||
'/patients-manage/patients-manage',
|
||||
'/patients-manage/surgery-info',
|
||||
'/remote-manage',
|
||||
'/remote-manage/remote-manage',
|
||||
'/remote-manage/remote-control'
|
||||
]
|
||||
// 高级管理员
|
||||
const SeniorAdmin = [
|
||||
'/login',
|
||||
'/home',
|
||||
'/patients-manage',
|
||||
'/patients-manage/patients-manage',
|
||||
'/patients-manage/surgery-info',
|
||||
'/remote-manage',
|
||||
'/remote-manage/remote-manage',
|
||||
'/remote-manage/remote-control',
|
||||
'/permissions-manage',
|
||||
'/permissions-manage/doctor-manage',
|
||||
'/permissions-manage/role-manage',
|
||||
'/permissions-manage/menu-manage',
|
||||
'/logs-manage',
|
||||
'/logs-manage/message-manage',
|
||||
'/logs-manage/logs-manage'
|
||||
]
|
||||
const isViewRoute = () => {
|
||||
let release = true
|
||||
/*switch (loginInfo.permissions) {
|
||||
case '超级管理员':
|
||||
release = true
|
||||
break;
|
||||
case '高级管理员':
|
||||
release = SeniorAdmin.some((p: string) => p === to.path)
|
||||
break;
|
||||
case '中级管理员':
|
||||
release = IntermediateAdmin.some((p: string) => p === to.path)
|
||||
break;
|
||||
case '普通用户':
|
||||
release = commonUser.some((p: string) => p === to.path)
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}*/
|
||||
return release
|
||||
}
|
||||
if (to.fullPath === '/login') {
|
||||
next()
|
||||
return
|
||||
}
|
||||
/*if (!isLogin) next('/login') // 重定向登录页
|
||||
else */
|
||||
if (!isViewRoute()) {
|
||||
ElMessage.error('无权访问!')
|
||||
next(from.fullPath)
|
||||
} else next()
|
||||
});
|
||||
|
||||
function stringifyQuery(query: any) {
|
||||
return btoa(encrypt(JSON.stringify(query), kk));
|
||||
}
|
||||
|
||||
function parseQuery(query: any) {
|
||||
if (isBase64(query)) {
|
||||
return JSON.parse(decrypt(atob(query), kk));
|
||||
} else {
|
||||
return query;
|
||||
}
|
||||
}
|
||||
|
||||
export default router
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
export const constantRoute=[
|
||||
|
||||
{ path: '/:pathMatch(.*)*', name: 'not-found', redirect: '/home' },
|
||||
{ path: '/:pathMatch(.*)*', name: 'not-found', redirect: '/login' },
|
||||
{
|
||||
path: '/login',
|
||||
name: '登录',
|
||||
|
@ -8,7 +8,7 @@ export const constantRoute=[
|
|||
},
|
||||
{
|
||||
path: '/',
|
||||
redirect: '/home',
|
||||
redirect: '/login',
|
||||
component: () => import('@/views/index.vue'),
|
||||
children: [
|
||||
{
|
||||
|
|
|
@ -0,0 +1,214 @@
|
|||
import {defineStore} from "pinia";
|
||||
import {Session} from "@/utils/storage";
|
||||
|
||||
const vitalUrl = "ws://localhost:5173/socket.io/admin/rax/vitalSignsMedicine?token=" + Session.getToken()
|
||||
const medicineUrl = "ws://localhost:5173/socket.io/admin/rax/addMedicine?token=" + Session.getToken()
|
||||
const chatUrl = "ws://localhost:5173/socket.io/admin/rax/chatRoom?token=" + Session.getToken()
|
||||
|
||||
export const useRemoteWsStore = defineStore("remoteWs", {
|
||||
state: () => {
|
||||
return {
|
||||
patient: {} as any,
|
||||
remoteTasks: [] as any,
|
||||
remoteTasksCap: 10,
|
||||
currentTaskIndex: 0,
|
||||
varMedicine: ["丙泊酚", "舒芬太尼", "瑞芬太尼", "顺阿曲库胺"],
|
||||
fixedMedicine: ["尼卡地平", "艾司洛尔", "麻黄素", "阿托品"],
|
||||
exceptionType: ["BIS_except", "DBP_except", "EtCO2_except", "HR_except", "SBP_except", "ST_except"],
|
||||
exceptionMsg: {
|
||||
"BIS_except": "脑电双频指数异常", "DBP_except": "舒张压异常", "EtCO2_except": "呼气末二氧化碳异常",
|
||||
"HR_except": "心率异常", "SBP_except": "收缩压异常", "ST_except": "ST异常"
|
||||
},
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
initRemoteTask() {
|
||||
if (this.remoteTasks.length <= 0) {
|
||||
for (let i = 0; i < 10; i++) {
|
||||
this.remoteTasks.push({
|
||||
isRemote: false,
|
||||
isException: false,
|
||||
taskName: "",
|
||||
server: "",
|
||||
serverun: "",
|
||||
serverps: "",
|
||||
patient: "",
|
||||
patientId: "",
|
||||
date: "",
|
||||
log: [],
|
||||
index: i
|
||||
})
|
||||
}
|
||||
}
|
||||
return this.remoteTasks
|
||||
},
|
||||
resetRemoteTask(i: number) {
|
||||
this.remoteTasks[i] = Object.assign(this.remoteTasks[i], {
|
||||
isRemote: false,
|
||||
isException: false,
|
||||
taskName: "",
|
||||
server: "",
|
||||
serverun: "",
|
||||
serverps: "",
|
||||
patient: "",
|
||||
patientId: "",
|
||||
date: "",
|
||||
log: [],
|
||||
index: i,
|
||||
message: []
|
||||
})
|
||||
},
|
||||
getActiveRemoteTask() {
|
||||
for (let i = 0; i < this.remoteTasks.length; i++) {
|
||||
if (this.remoteTasks[i].isRemote) return i
|
||||
}
|
||||
},
|
||||
setRemoteLog(log: any, i: number) {
|
||||
this.remoteTasks[i].log.push(log)
|
||||
},
|
||||
createConnect(name: string, id: string, date: string) {
|
||||
if (!this.patient[name + id + date]) {
|
||||
const vitalWS = new WebSocket(vitalUrl)
|
||||
const medicineWS = new WebSocket(medicineUrl)
|
||||
const chatWS = new WebSocket(chatUrl)
|
||||
vitalWS.onopen = function () {
|
||||
vitalWS.send(JSON.stringify({
|
||||
patientName: name,
|
||||
idNum: id,
|
||||
date: date
|
||||
}))
|
||||
}
|
||||
medicineWS.onopen = function () {
|
||||
medicineWS.send(JSON.stringify({
|
||||
patientName: name,
|
||||
idNum: id,
|
||||
date: date
|
||||
}))
|
||||
}
|
||||
chatWS.onopen = function () {
|
||||
chatWS.send(JSON.stringify({
|
||||
patientName: name,
|
||||
idNum: id,
|
||||
date: date
|
||||
}))
|
||||
}
|
||||
this.patient[name + id + date] = {
|
||||
vitalWS,
|
||||
medicineWS,
|
||||
chatWS
|
||||
}
|
||||
}
|
||||
},
|
||||
disconnect(name: string, id: string, date: string) {
|
||||
const patient: any = this.patient[name + id + date]
|
||||
if (patient) {
|
||||
patient.vitalWS.close()
|
||||
patient.medicineWS.close()
|
||||
patient.chatWS.close()
|
||||
delete this.patient[name + id + date]
|
||||
}
|
||||
},
|
||||
subscribeVital(name: string, id: string, date: string, cb: any) {
|
||||
const patient: any = this.patient[name + id + date]
|
||||
if (patient) {
|
||||
patient.vitalWS.onmessage = cb
|
||||
patient.vitalCB = cb
|
||||
} else {
|
||||
cb({
|
||||
status: 1,
|
||||
msg: "已断开连接"
|
||||
})
|
||||
}
|
||||
},
|
||||
unsubscribeVital(name: string, id: string, date: string) {
|
||||
const patient: any = this.patient[name + id + date]
|
||||
if (patient && patient.vitalWS) {
|
||||
patient.vitalWS.onmessage = undefined;
|
||||
patient.vitalCB = undefined;
|
||||
}
|
||||
},
|
||||
sendMsg(name: string, id: string, date: string, msg: string, cb: any) {
|
||||
const patient: any = this.patient[name + id + date]
|
||||
if (patient) {
|
||||
const params = {
|
||||
patientName: name,
|
||||
idNum: id,
|
||||
date: date,
|
||||
msg
|
||||
}
|
||||
patient.chatWS.send(JSON.stringify(params))
|
||||
cb({
|
||||
status: 0
|
||||
})
|
||||
} else {
|
||||
cb({
|
||||
status: 1,
|
||||
msg: "已断开连接"
|
||||
})
|
||||
}
|
||||
},
|
||||
subscribeChat(name: string, id: string, date: string, cb: any) {
|
||||
const patient: any = this.patient[name + id + date]
|
||||
if (patient) {
|
||||
patient.chatCB = cb
|
||||
patient.chatWS.onmessage = cb
|
||||
} else {
|
||||
cb({
|
||||
status: 1,
|
||||
msg: "已断开连接"
|
||||
})
|
||||
}
|
||||
},
|
||||
unsubscribeChat(name: string, id: string, date: string) {
|
||||
const patient: any = this.patient[name + id + date]
|
||||
patient.chatCB = undefined;
|
||||
patient.chatWS.onmessage = undefined;
|
||||
},
|
||||
sendMedicine(args: {
|
||||
name: string,
|
||||
id: string,
|
||||
date: string,
|
||||
flag: string,
|
||||
medicine: string,
|
||||
value: string
|
||||
}, cb: any) {
|
||||
const patient: any = this.patient[args.name + args.id + args.date]
|
||||
if (patient) {
|
||||
const params = {
|
||||
patientName: args.name,
|
||||
idNum: args.id,
|
||||
date: args.date,
|
||||
flag: args.flag,
|
||||
medicine: args.medicine,
|
||||
value: args.value
|
||||
}
|
||||
patient.medicineWS.send(JSON.stringify(params))
|
||||
cb({
|
||||
status: 0
|
||||
})
|
||||
} else {
|
||||
cb({
|
||||
status: 1,
|
||||
msg: "已断开连接"
|
||||
})
|
||||
}
|
||||
},
|
||||
subscribeMedicine(name: string, id: string, date: string, cb: any) {
|
||||
const patient = this.patient[name + id + date]
|
||||
if (patient) {
|
||||
patient.medicineCB = cb
|
||||
patient.medicineWS.onmessage = cb
|
||||
} else {
|
||||
cb({
|
||||
status: 1,
|
||||
msg: "已断开连接"
|
||||
})
|
||||
}
|
||||
},
|
||||
unsubscribeMedicine(name: string, id: string, date: string) {
|
||||
const patient: any = this.patient[name + id + date]
|
||||
patient.medicineCB = undefined;
|
||||
patient.medicineWS.onmessage = undefined;
|
||||
}
|
||||
}
|
||||
})
|
|
@ -4,7 +4,6 @@ export const useLoginStore = defineStore('login', {
|
|||
state: () => {
|
||||
return {
|
||||
login: {
|
||||
isLogin: false,
|
||||
account: '',
|
||||
name: '',
|
||||
/**
|
||||
|
@ -13,7 +12,6 @@ export const useLoginStore = defineStore('login', {
|
|||
* 医院中级管理员: 首页、患者管理、远程管理
|
||||
* 医院普通用户: 首页、患者管理
|
||||
*/
|
||||
permissions: '',
|
||||
hospital: ''
|
||||
} as any
|
||||
}
|
||||
|
|
|
@ -22,55 +22,68 @@ export function dateFormater(formater: string, time?: any) {
|
|||
|
||||
/**
|
||||
* 获取指定月份天数
|
||||
* @param {*} time
|
||||
* @returns
|
||||
* @param {*} time
|
||||
* @returns
|
||||
*/
|
||||
export function getMonthDays(time: any) {
|
||||
if (!time) time = new Date();
|
||||
const now = new Date(time);
|
||||
const year = now.getFullYear();
|
||||
const month = now.getMonth() + 1;
|
||||
if (!time) time = new Date();
|
||||
const now = new Date(time);
|
||||
const year = now.getFullYear();
|
||||
const month = now.getMonth() + 1;
|
||||
|
||||
const isLeapYear = (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
|
||||
const isLeapYear = (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
|
||||
|
||||
const daysInMonth = month === 2
|
||||
? isLeapYear ? 29 : 28
|
||||
: month === 4 || month === 6 || month === 9 || month === 11
|
||||
? 30
|
||||
: 31;
|
||||
const daysInMonth = month === 2
|
||||
? isLeapYear ? 29 : 28
|
||||
: month === 4 || month === 6 || month === 9 || month === 11
|
||||
? 30
|
||||
: 31;
|
||||
|
||||
return daysInMonth;
|
||||
return daysInMonth;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前日期的周几 i:1,2,3,4,5,6,7
|
||||
* @returns
|
||||
*/
|
||||
export function getFirstDayOfWeek(date: Date, i: number) {
|
||||
if (i < 1 || i > 7) {
|
||||
return null;
|
||||
}
|
||||
const day = date.getDay() || 7;
|
||||
return new Date(date.getFullYear(), date.getMonth(), date.getDate() + i - day);
|
||||
export function getFirstDayOfWeek(date: string | Date | number, i: number) {
|
||||
let temp: any;
|
||||
if (!(date instanceof Date)) {
|
||||
if (typeof date == "number") {
|
||||
temp = new Date(date);
|
||||
} else {
|
||||
const s = date.replace(/-/g, "/");
|
||||
temp = new Date(s);
|
||||
}
|
||||
} else {
|
||||
temp = new Date(date.getTime())
|
||||
}
|
||||
if (i < 1 || i > 7) {
|
||||
return null;
|
||||
}
|
||||
const day = temp.getDay() || 7;
|
||||
return new Date(temp.getFullYear(), temp.getMonth(), temp.getDate() + i - day);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前日期是周几
|
||||
* @returns
|
||||
*/
|
||||
const weekArray = ['周天', '周一', '周二', '周三', '周四', '周五', '周六'];
|
||||
export function getCurrentDate(date: any) {
|
||||
let myDate = new Date();
|
||||
if (date) {
|
||||
if (date instanceof Date) {
|
||||
myDate = date;
|
||||
} else {
|
||||
date = date.replace(/-/g, '/');
|
||||
myDate = new Date(date);
|
||||
}
|
||||
}
|
||||
|
||||
const days = myDate.getDay();
|
||||
return weekArray[days];
|
||||
export function getCurrentDate(date: any) {
|
||||
let myDate = new Date();
|
||||
if (date) {
|
||||
if (date instanceof Date) {
|
||||
myDate = date;
|
||||
} else {
|
||||
date = date.replace(/-/g, '/');
|
||||
myDate = new Date(date);
|
||||
}
|
||||
}
|
||||
|
||||
const days = myDate.getDay();
|
||||
return weekArray[days];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -78,17 +91,20 @@ export function getCurrentDate(date: any) {
|
|||
* @returns
|
||||
*/
|
||||
export function getDays(date: any, days: number) {
|
||||
if (date) {
|
||||
if (!(date instanceof Date)) {
|
||||
date = date.replace(/-/g, '/');
|
||||
date = new Date(date);
|
||||
}
|
||||
if (date) {
|
||||
let temp: any;
|
||||
if (!(date instanceof Date)) {
|
||||
date = date.replace(/-/g, '/');
|
||||
temp = new Date(date);
|
||||
} else {
|
||||
temp = new Date(date.getTime());
|
||||
}
|
||||
|
||||
const time = date.setDate(date.getDate() + days); // 天数
|
||||
return new Date(time);
|
||||
}
|
||||
const time = temp.setDate(temp.getDate() + days);
|
||||
return new Date(time);
|
||||
}
|
||||
}
|
||||
|
||||
export function getEndOfMonth(year: number, month: number) {
|
||||
return new Date(year, month, 0).getDate()
|
||||
return new Date(year, month, 0).getDate()
|
||||
}
|
|
@ -5,29 +5,47 @@ import * as CryptoJS from 'crypto-js';
|
|||
*加密处理
|
||||
*/
|
||||
export function encryption(src: string, keyWord: string) {
|
||||
const key = CryptoJS.enc.Utf8.parse(keyWord);
|
||||
// 加密
|
||||
let encrypted = CryptoJS.AES.encrypt(src, key, {
|
||||
iv: key,
|
||||
mode: CryptoJS.mode.CBC,
|
||||
padding: CryptoJS.pad.Pkcs7,
|
||||
});
|
||||
return encrypted.toString();
|
||||
const key = CryptoJS.enc.Utf8.parse(keyWord);
|
||||
// 加密
|
||||
const encrypted = CryptoJS.AES.encrypt(src, key, {
|
||||
iv: key,
|
||||
mode: CryptoJS.mode.CBC,
|
||||
padding: CryptoJS.pad.Pkcs7,
|
||||
});
|
||||
return encrypted.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 解密
|
||||
* @param {*} params 参数列表
|
||||
* @returns 明文
|
||||
* @param src
|
||||
* @param keyWord
|
||||
*/
|
||||
export function decryption(src: string, keyWord: string) {
|
||||
const key = CryptoJS.enc.Utf8.parse(keyWord);
|
||||
// 解密逻辑
|
||||
let decryptd = CryptoJS.AES.decrypt(src, key, {
|
||||
iv: key,
|
||||
mode: CryptoJS.mode.CBC,
|
||||
padding: CryptoJS.pad.Pkcs7,
|
||||
});
|
||||
const key = keyWord;
|
||||
// 解密逻辑
|
||||
const decryptd = CryptoJS.AES.decrypt(src, key, {
|
||||
iv: key,
|
||||
mode: CryptoJS.mode.CBC,
|
||||
padding: CryptoJS.pad.Pkcs7,
|
||||
});
|
||||
|
||||
return decryptd.toString(CryptoJS.enc.Utf8);
|
||||
return decryptd.toString(CryptoJS.enc.Utf8);
|
||||
}
|
||||
|
||||
export function encrypt(src: string, key: string) {
|
||||
return CryptoJS.AES.encrypt(src, key).toString()
|
||||
}
|
||||
|
||||
export function decrypt(src: string, key: string) {
|
||||
return CryptoJS.AES.decrypt(src, key).toString(CryptoJS.enc.Utf8)
|
||||
}
|
||||
|
||||
export function isBase64(s: string) {
|
||||
if (s == "" || s.trim() == "") return false;
|
||||
try {
|
||||
return window.btoa(window.atob(s)) == s;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,72 +1,75 @@
|
|||
<template>
|
||||
<div class="home-page">
|
||||
<div class="background-box">
|
||||
<div class="left-content">
|
||||
<div class="message-box">
|
||||
<el-carousel height="32px" direction="vertical" indicator-position="none" autoplay>
|
||||
<el-carousel-item v-for="(item, index) in messages" :key="'message-' + index">
|
||||
<p class="text-row-1" style="line-height: 32px;" :class="{'is-link': item.link}" @click="() => {item.link && router.push(item.link)}">【{{ item.type }}】 {{ item.content }}</p>
|
||||
</el-carousel-item>
|
||||
</el-carousel>
|
||||
</div>
|
||||
<div class="header-box">
|
||||
<div class="header-item">
|
||||
<span class="main-color f20" style="font-weight: 600;">{{ userInfo.name }}</span>
|
||||
<span class="text2-color f14">{{ userInfo.permissions }}</span>
|
||||
</div>
|
||||
<div class="header-item">
|
||||
<el-icon class="text1-color" style="font-size: 26px;margin-right: 20px;">
|
||||
<Calendar />
|
||||
</el-icon>
|
||||
<div>
|
||||
<p class="text1-color f14">待办任务</p>
|
||||
<p class="main-color f20">{{ total }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="echart-box">
|
||||
<div class="echart-item">
|
||||
<NumberChart />
|
||||
</div>
|
||||
<div class="echart-item">
|
||||
<NumberPieChart />
|
||||
</div>
|
||||
<div class="echart-item">
|
||||
<TimeChart />
|
||||
</div>
|
||||
<div class="echart-item">
|
||||
<TimeBarChart />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right-content">
|
||||
<div class="week-calendar">
|
||||
<WeekCalendar />
|
||||
</div>
|
||||
<div class="system-logs">
|
||||
<div class="title">
|
||||
<span>系统日志</span>
|
||||
<span class="f14" style="cursor: pointer;" @click="router.push('./logs-manage/logs-manage')">更多</span>
|
||||
</div>
|
||||
<div class="content">
|
||||
<SystemLogs />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="home-page">
|
||||
<div class="background-box">
|
||||
<div class="left-content">
|
||||
<div class="message-box">
|
||||
<el-carousel height="32px" direction="vertical" indicator-position="none" autoplay>
|
||||
<el-carousel-item v-for="(item, index) in messages" :key="'message-' + index">
|
||||
<p class="text-row-1" style="line-height: 32px;" :class="{'is-link': item.link}"
|
||||
@click="() => {item.link && router.push(item.link)}">【{{ item.type }}】 {{ item.content }}</p>
|
||||
</el-carousel-item>
|
||||
</el-carousel>
|
||||
</div>
|
||||
<div class="header-box">
|
||||
<div class="header-item">
|
||||
<span class="main-color f20" style="font-weight: 600;">{{ userInfo.name }}</span>
|
||||
<span class="text2-color f14">{{ userInfo.permissions }}</span>
|
||||
</div>
|
||||
<div class="header-item">
|
||||
<el-icon class="text1-color" style="font-size: 26px;margin-right: 20px;">
|
||||
<Calendar/>
|
||||
</el-icon>
|
||||
<div>
|
||||
<p class="text1-color f14">待办任务</p>
|
||||
<p class="main-color f20">{{ total }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="echart-box">
|
||||
<div class="echart-item">
|
||||
<NumberChart/>
|
||||
</div>
|
||||
<div class="echart-item">
|
||||
<NumberPieChart/>
|
||||
</div>
|
||||
<div class="echart-item">
|
||||
<TimeChart/>
|
||||
</div>
|
||||
<div class="echart-item">
|
||||
<TimeBarChart/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right-content">
|
||||
<div class="week-calendar">
|
||||
<WeekCalendar/>
|
||||
</div>
|
||||
<div class="system-logs">
|
||||
<div class="title">
|
||||
<span>系统日志</span>
|
||||
<span class="f14" style="cursor: pointer;" @click="router.push('./logs-manage/logs-manage')">更多</span>
|
||||
</div>
|
||||
<div class="content">
|
||||
<SystemLogs/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang='ts' setup>
|
||||
import { onMounted, reactive, ref, toRefs, watch } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useLoginStore } from '@/stores/user-info-store'
|
||||
import {onMounted, ref} from 'vue'
|
||||
import {useRouter} from 'vue-router'
|
||||
import {useLoginStore} from '@/stores/user-info-store'
|
||||
import NumberChart from "./number-chart.vue";
|
||||
import NumberPieChart from "./number-pie-chart.vue";
|
||||
import TimeChart from "./time-chart.vue";
|
||||
import TimeBarChart from "./time-bar-chart.vue";
|
||||
import WeekCalendar from "./week-calendar.vue";
|
||||
import SystemLogs from "@/components/system-logs.vue";
|
||||
import * as dailyPlanApi from "@/api/daily-plan";
|
||||
import {dateFormater} from "@/utils/date-util";
|
||||
|
||||
|
||||
const router = useRouter()
|
||||
|
@ -75,127 +78,153 @@ const userInfo = useLoginStore().getlogin()
|
|||
const messages = ref([] as any)
|
||||
const total = ref(0) // 日历添加的记录提醒统计
|
||||
|
||||
messages.value.push({type: '通知', content: '测试测试测试测试测试测试测试测试测试测试', link: '/system-manage/system-home'})
|
||||
messages.value.push({type: '公告', content: '公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试'})
|
||||
messages.value.push({
|
||||
type: '通知',
|
||||
content: '测试测试测试测试测试测试测试测试测试测试',
|
||||
link: '/system-manage/system-home'
|
||||
})
|
||||
messages.value.push({
|
||||
type: '公告',
|
||||
content: '公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试公告测试'
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
getTodoCount();
|
||||
})
|
||||
|
||||
function getTodoCount() {
|
||||
dailyPlanApi.getTodoCountByDate(dateFormater("yyyy-MM-dd", new Date())).then((res: any) => {
|
||||
if (res.code == 0) {
|
||||
total.value = res.data;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.home-page {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 15px;
|
||||
overflow-y: auto;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 15px;
|
||||
overflow-y: auto;
|
||||
|
||||
.background-box {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: white;
|
||||
padding: 20px 35px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
min-height: 900px;
|
||||
.background-box {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: white;
|
||||
padding: 20px 35px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
min-height: 900px;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.left-content {
|
||||
width: calc(100% - 350px);
|
||||
height: 100%;
|
||||
.message-box {
|
||||
height: 34px;
|
||||
background: #f8f8f8;
|
||||
color: $text-color;
|
||||
padding: 0 30px;
|
||||
border: 1px solid $border1-color;
|
||||
margin-bottom: 20px;
|
||||
.is-link {
|
||||
cursor: pointer;
|
||||
color: $main-color;
|
||||
}
|
||||
}
|
||||
.header-box {
|
||||
width: 100%;
|
||||
height: 90px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
.left-content {
|
||||
width: calc(100% - 350px);
|
||||
height: 100%;
|
||||
|
||||
.header-item {
|
||||
width: calc(60% - 20px);
|
||||
height: 100%;
|
||||
border: 1px solid $border-color;
|
||||
border-radius: 5px;
|
||||
box-shadow: 1px 1px 5px $border2-color;
|
||||
padding: 0 90px;
|
||||
line-height: 1.5;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
.message-box {
|
||||
height: 34px;
|
||||
background: #f8f8f8;
|
||||
color: $text-color;
|
||||
padding: 0 30px;
|
||||
border: 1px solid $border1-color;
|
||||
margin-bottom: 20px;
|
||||
|
||||
&~.header-item {
|
||||
width: 40%;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
.is-link {
|
||||
cursor: pointer;
|
||||
color: $main-color;
|
||||
}
|
||||
}
|
||||
|
||||
.echart-box {
|
||||
width: 100%;
|
||||
height: calc(100% - 164px);
|
||||
margin-top: 20px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
.header-box {
|
||||
width: 100%;
|
||||
height: 90px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.echart-item {
|
||||
width: calc(60% - 20px);
|
||||
height: calc(50% - 10px);
|
||||
border: 1px solid $border-color;
|
||||
border-radius: 5px;
|
||||
padding: 20px;
|
||||
box-shadow: 1px 1px 5px $border2-color;
|
||||
|
||||
&:nth-child(even) {
|
||||
width: 40%;
|
||||
}
|
||||
&:nth-child(n + 3) {
|
||||
margin-top: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.header-item {
|
||||
width: calc(60% - 20px);
|
||||
height: 100%;
|
||||
border: 1px solid $border-color;
|
||||
border-radius: 5px;
|
||||
box-shadow: 1px 1px 5px $border2-color;
|
||||
padding: 0 90px;
|
||||
line-height: 1.5;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
|
||||
.right-content {
|
||||
width: 330px;
|
||||
height: 100%;
|
||||
.week-calendar {
|
||||
width: 100%;
|
||||
height: 50%;
|
||||
}
|
||||
.system-logs {
|
||||
width: 100%;
|
||||
height: calc(50% - 20px);
|
||||
margin-top: 20px;
|
||||
overflow: hidden;
|
||||
& ~ .header-item {
|
||||
width: 40%;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
padding: 0 20px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.echart-box {
|
||||
width: 100%;
|
||||
height: calc(100% - 164px);
|
||||
margin-top: 20px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
|
||||
.content {
|
||||
width: 100%;
|
||||
height: calc(100% - 50px);
|
||||
margin-top: 10px;
|
||||
border: 1px solid $border-color;
|
||||
padding: 30px;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
.echart-item {
|
||||
width: calc(60% - 20px);
|
||||
height: calc(50% - 10px);
|
||||
border: 1px solid $border-color;
|
||||
border-radius: 5px;
|
||||
padding: 20px;
|
||||
box-shadow: 1px 1px 5px $border2-color;
|
||||
|
||||
&:nth-child(even) {
|
||||
width: 40%;
|
||||
}
|
||||
|
||||
&:nth-child(n + 3) {
|
||||
margin-top: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.right-content {
|
||||
width: 330px;
|
||||
height: 100%;
|
||||
|
||||
.week-calendar {
|
||||
width: 100%;
|
||||
height: 50%;
|
||||
}
|
||||
|
||||
.system-logs {
|
||||
width: 100%;
|
||||
height: calc(50% - 20px);
|
||||
margin-top: 20px;
|
||||
overflow: hidden;
|
||||
|
||||
.title {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
padding: 0 20px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 100%;
|
||||
height: calc(100% - 50px);
|
||||
margin-top: 10px;
|
||||
border: 1px solid $border-color;
|
||||
padding: 30px;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}</style>
|
||||
|
|
|
@ -1,146 +1,173 @@
|
|||
<template>
|
||||
<el-form ref="formRef" :model="formData" :rules="rules" label-width="100">
|
||||
<el-form-item label="标题" prop="title">
|
||||
<el-input v-model="formData.title" placeholder="请输入标题"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="类型" prop="type">
|
||||
<el-select v-model="formData.type" placeholder="请选择类型">
|
||||
<el-option v-for="item in typeOption" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="state" placeholder="请选择状态">
|
||||
<el-select v-model="formData.state">
|
||||
<el-option v-for="item in stateOption" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="日期" prop="date">
|
||||
<el-date-picker v-model="formData.date" type="date" placeholder="请输入日期" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="时间" prop="time">
|
||||
<el-time-picker v-model="formData.time" placeholder="请输入时间" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="内容" prop="content">
|
||||
<el-input v-model="formData.content" type="textarea" :rows="10" placeholder="请输入内容"></el-input>
|
||||
</el-form-item>
|
||||
<div style="text-align: right;" >
|
||||
<el-button v-if="formData.isSaveBtn" class="f18" type="primary" @click="saveData">保存</el-button>
|
||||
<el-button v-if="formData.isRemoveBtn" class="f18" @click="removeData">删除</el-button>
|
||||
</div>
|
||||
</el-form>
|
||||
<el-form ref="formRef" :model="formData" :rules="rules" label-width="100">
|
||||
<el-form-item label="标题" prop="title">
|
||||
<el-input v-model="formData.title" placeholder="请输入标题"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="类型" prop="type">
|
||||
<el-select v-model="formData.type" placeholder="请选择类型">
|
||||
<el-option v-for="item in typeOption" :key="item.value" :label="item.label" :value="item.value"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status" placeholder="请选择状态">
|
||||
<el-select v-model="formData.status">
|
||||
<el-option v-for="item in stateOption" :key="item.value" :label="item.label" :value="item.value"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="日期" prop="date">
|
||||
<el-date-picker v-model="formData.date" type="date" placeholder="请输入日期"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="时间" prop="time">
|
||||
<el-time-picker v-model="formData.time" placeholder="请输入时间"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="内容" prop="content">
|
||||
<el-input v-model="formData.content" type="textarea" :rows="10" placeholder="请输入内容"></el-input>
|
||||
</el-form-item>
|
||||
<div style="text-align: right;">
|
||||
<el-button v-if="isSaveBtn" class="f18" type="primary" @click="saveData">保存</el-button>
|
||||
<el-button v-if="isRemoveBtn" class="f18" @click="removeData">删除</el-button>
|
||||
</div>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script lang='ts' setup>
|
||||
import { onMounted, reactive, ref, toRefs, watch } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
|
||||
const emit = defineEmits(['close', 'saveData'])
|
||||
import {onMounted, reactive, ref} from 'vue'
|
||||
import {ElMessage, ElMessageBox} from 'element-plus'
|
||||
import {dateFormater} from "@/utils/date-util";
|
||||
import * as dailyPlanApi from "@/api/daily-plan";
|
||||
|
||||
const emit = defineEmits(['close', 'saveData', "removeEvent"])
|
||||
defineExpose({
|
||||
resetData
|
||||
})
|
||||
const typeOption = [
|
||||
{ label: '手术', value: '手术' },
|
||||
{ label: '会议', value: '会议' },
|
||||
{label: '手术', value: '手术'},
|
||||
{label: '会议', value: '会议'},
|
||||
]
|
||||
const stateOption = [
|
||||
{ label: '已处理', value: '已处理' },
|
||||
{ label: '未处理', value: '未处理' },
|
||||
{label: '已处理', value: '已处理'},
|
||||
{label: '未处理', value: '未处理'},
|
||||
]
|
||||
const rules = reactive({
|
||||
title: [
|
||||
{ required: true, message: '请输入标题', trigger: 'blur' },
|
||||
],
|
||||
type: [
|
||||
{ required: true, message: '请选择类型', trigger: 'blur' },
|
||||
],
|
||||
state: [
|
||||
{ required: true, message: '请选择状态', trigger: 'blur' },
|
||||
],
|
||||
date: [
|
||||
{ required: true, message: '请输入日期', trigger: 'blur' },
|
||||
],
|
||||
time: [
|
||||
{ required: true, message: '请输入时间', trigger: 'blur' },
|
||||
],
|
||||
content: [
|
||||
{ required: true, message: '请输入内容', trigger: 'blur' },
|
||||
]
|
||||
title: [
|
||||
{required: true, message: '请输入标题', trigger: 'blur'},
|
||||
],
|
||||
type: [
|
||||
{required: true, message: '请选择类型', trigger: 'blur'},
|
||||
],
|
||||
status: [
|
||||
{required: true, message: '请选择状态', trigger: 'blur'},
|
||||
],
|
||||
date: [
|
||||
{required: true, message: '请输入日期', trigger: 'blur'},
|
||||
],
|
||||
time: [
|
||||
{required: true, message: '请输入时间', trigger: 'blur'},
|
||||
],
|
||||
content: [
|
||||
{required: true, message: '请输入内容', trigger: 'blur'},
|
||||
]
|
||||
})
|
||||
|
||||
const formRef = ref()
|
||||
const formData = ref({
|
||||
id: '',
|
||||
title: '',
|
||||
type: '',
|
||||
state: '',
|
||||
date: '',
|
||||
time: '',
|
||||
content: '',
|
||||
isSaveBtn: true,
|
||||
isRemoveBtn: true
|
||||
id: '',
|
||||
title: '',
|
||||
type: '',
|
||||
status: '',
|
||||
date: '',
|
||||
time: '',
|
||||
content: '',
|
||||
})
|
||||
|
||||
const isSaveBtn = ref(true);
|
||||
const isRemoveBtn = ref(true);
|
||||
|
||||
onMounted(() => {
|
||||
formData.value = {
|
||||
id: '',
|
||||
title: '',
|
||||
type: '',
|
||||
state: '',
|
||||
date: '',
|
||||
time: '',
|
||||
content: '',
|
||||
isSaveBtn: true,
|
||||
isRemoveBtn: true
|
||||
}
|
||||
formData.value = {
|
||||
id: '',
|
||||
title: '',
|
||||
type: '',
|
||||
status: '',
|
||||
date: '',
|
||||
time: '',
|
||||
content: '',
|
||||
}
|
||||
})
|
||||
|
||||
defineExpose({
|
||||
formData,
|
||||
resetData,
|
||||
})
|
||||
function close() {
|
||||
emit('close')
|
||||
emit('close')
|
||||
}
|
||||
function resetData() {
|
||||
formRef.value.resetFields()
|
||||
Object.assign(formData.value, {
|
||||
id: '',
|
||||
title: '',
|
||||
type: '',
|
||||
state: '',
|
||||
date: '',
|
||||
time: '',
|
||||
content: ''
|
||||
})
|
||||
|
||||
function resetData(hasRmBtn: boolean, date?: string, form?: any) {
|
||||
formRef.value.resetFields()
|
||||
if (form) {
|
||||
const tempForm = Object.assign({}, form);
|
||||
const planDate = new Date(tempForm.date + " " + tempForm.time);
|
||||
tempForm.date = planDate;
|
||||
tempForm.time = planDate;
|
||||
formData.value = tempForm;
|
||||
} else {
|
||||
Object.assign(formData.value, {
|
||||
id: '',
|
||||
title: '',
|
||||
type: '',
|
||||
status: '',
|
||||
date: date ? date : '',
|
||||
time: '',
|
||||
content: ''
|
||||
})
|
||||
}
|
||||
isRemoveBtn.value = hasRmBtn;
|
||||
}
|
||||
const saveData = async () => {
|
||||
await formRef.value.validate((valid: any, fields: any) => {
|
||||
if (valid) {
|
||||
ElMessage.success('保存成功!')
|
||||
emit('saveData', formData.value)
|
||||
close()
|
||||
} else {
|
||||
// console.log('error submit!', fields)
|
||||
}
|
||||
})
|
||||
|
||||
const saveData = () => {
|
||||
formRef.value.validate((valid: any, fields: any) => {
|
||||
if (valid) {
|
||||
const form = JSON.parse(JSON.stringify(formData.value));
|
||||
form.time = dateFormater("HH:mm:ss", new Date(form.time));
|
||||
form.date = dateFormater("yyyy-MM-dd", new Date(form.date));
|
||||
dailyPlanApi.saveOrUpdate(form).then((res: any) => {
|
||||
if (res.code == 0) {
|
||||
ElMessage.success('保存成功!');
|
||||
emit('saveData', form);
|
||||
close();
|
||||
} else {
|
||||
ElMessage.error(res.msg);
|
||||
}
|
||||
}).catch(error => {
|
||||
ElMessage.error("服务端异常");
|
||||
})
|
||||
} else {
|
||||
// console.log('error submit!', fields)
|
||||
}
|
||||
})
|
||||
}
|
||||
const removeData = () => {
|
||||
ElMessageBox.confirm(
|
||||
'是否确认删除?',
|
||||
{
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
draggable: true
|
||||
}
|
||||
).then(() => {
|
||||
ElMessage.success('删除成功!')
|
||||
close()
|
||||
}).catch(() => { })
|
||||
ElMessageBox.confirm(
|
||||
'是否确认删除?',
|
||||
{
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
draggable: true
|
||||
}
|
||||
).then(() => {
|
||||
dailyPlanApi.deleteById(formData.value.id).then((res: any) => {
|
||||
if (res.code == 0) {
|
||||
ElMessage.success('删除成功!');
|
||||
close();
|
||||
emit("removeEvent");
|
||||
} else {
|
||||
ElMessage.error(res.msg);
|
||||
}
|
||||
});
|
||||
}).catch(() => {
|
||||
ElMessage.error("服务器异常");
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,304 +1,334 @@
|
|||
<template>
|
||||
<div class="week-calendar-part">
|
||||
<div class="header-box">
|
||||
<el-icon @click="setWeek('up')">
|
||||
<ArrowLeft />
|
||||
</el-icon>
|
||||
<div class="date-block">
|
||||
<span @click="handleOpen">{{ formatDate(month) }}</span>
|
||||
<el-date-picker ref="datePicker" popper-class="week-calendar-picker" class="month-date-pick" v-model="month"
|
||||
type="month" @change="setWeek()" />
|
||||
</div>
|
||||
<el-icon @click="setWeek('down')">
|
||||
<ArrowRight />
|
||||
</el-icon>
|
||||
</div>
|
||||
<div class="week-box">
|
||||
<table>
|
||||
<tr class="text1-color">
|
||||
<th v-for="item in weekEn" :key="item">{{ item }}</th>
|
||||
</tr>
|
||||
<tr v-if="week.length > 0" class="">
|
||||
<td v-for="item in week" :key="item" :class="{
|
||||
'record-mark': recordWeek.some((r: any) => dateFormater('yyyy-MM-dd', r.date) === dateFormater('yyyy-MM-dd', item)),
|
||||
'active': dateFormater('yyyy-MM-dd', item) === dateFormater('yyyy-MM-dd', currentDate)
|
||||
}">
|
||||
<div class="week-calendar-part">
|
||||
<div class="header-box">
|
||||
<el-icon @click="minusWeek()">
|
||||
<ArrowLeft/>
|
||||
</el-icon>
|
||||
<div class="date-block">
|
||||
<span @click="handleDatePickerOpen">{{ getMonthTitle() }}</span>
|
||||
<el-date-picker ref="datePickerRef"
|
||||
popper-class="week-calendar-picker"
|
||||
class="month-date-pick"
|
||||
v-model="month"
|
||||
type="month"
|
||||
@change="setMonthWeek()"/>
|
||||
</div>
|
||||
<el-icon @click="addWeek()">
|
||||
<ArrowRight/>
|
||||
</el-icon>
|
||||
</div>
|
||||
<div class="week-box">
|
||||
<table>
|
||||
<tr class="text1-color">
|
||||
<th v-for="item in weekCn" :key="item">{{ item }}</th>
|
||||
</tr>
|
||||
<tr v-if="week.length > 0" class="">
|
||||
<td v-for="item in week" :key="item"
|
||||
:class="{
|
||||
'record-mark': recordWeek.some((r: any) => r == dateFormater('yyyy-MM-dd', item)),
|
||||
'active':
|
||||
dateFormater('yyyy-MM-dd', item) == dateFormater('yyyy-MM-dd', currentDate)}">
|
||||
<span :class="{
|
||||
'text2-color': item.getDate() > week[6].getDate()
|
||||
}" @click="setDate(item)">{{ dateFormater('dd', item) }}</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<el-button text icon="Plus" style="width: 100%;margin-bottom: 5px;" @click="addRecord()">新建</el-button>
|
||||
<div class="record-box ">
|
||||
<el-empty v-if="record.length < 1" :description="dateFormater('MM月dd日', currentDate) + '没有任何记录'" style="padding: 0;" />
|
||||
<div class="record-item" v-for="(item, index) in record" :key="'record-' + index" @click="viewRecord(item)">
|
||||
<div class="icon-box">
|
||||
<i class="icon-RectangleCopy"></i>
|
||||
</div>
|
||||
<div class="text-box">
|
||||
<p class="main-color" style="font-weight: 600;cursor: pointer;">{{
|
||||
item.title }}</p>
|
||||
<p p class=" text2-color font14">{{ dateFormater('yyyy-MM-dd HH:mm:ss', item.time) }}</p>
|
||||
</div>
|
||||
<el-icon class="remove-icon" @click.stop="remoteRecord(item, index)">
|
||||
<Close />
|
||||
</el-icon>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<el-button text icon="Plus" style="width: 100%;margin-bottom: 5px;" @click="addRecord()">新建</el-button>
|
||||
<div class="record-box ">
|
||||
<el-empty v-if="record.length < 1" :description="dateFormater('MM月dd日', currentDate) + '没有任何记录'"
|
||||
style="padding: 0;"/>
|
||||
<div class="record-item" v-for="(item, index) in record" :key="'record-' + index" @click="viewRecord(item)">
|
||||
<div class="icon-box">
|
||||
<i class="icon-RectangleCopy"></i>
|
||||
</div>
|
||||
<div class="text-box">
|
||||
<p class="main-color" style="font-weight: 600;cursor: pointer;">{{
|
||||
item.title
|
||||
}}</p>
|
||||
<p p class=" text2-color font14">{{ item.date + " " + item.time }}</p>
|
||||
</div>
|
||||
<el-icon class="remove-icon" @click.stop="remoteRecord(item, index)">
|
||||
<Close/>
|
||||
</el-icon>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-dialog v-model="isRecordDialog" title="详情">
|
||||
<RecordForm ref="recordFormRef" @close="isRecordDialog = false" @saveData="saveData" />
|
||||
</el-dialog>
|
||||
</div>
|
||||
<el-dialog v-model="isRecordDialog" title="详情">
|
||||
<RecordForm ref="recordFormRef" @remove-event="planRemoveEvent" @close="isRecordDialog = false"
|
||||
@saveData="saveData"/>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang='ts' setup>
|
||||
import { onMounted, reactive, ref, toRefs, watch } from 'vue'
|
||||
import {onMounted, ref} from 'vue'
|
||||
import RecordForm from './record-form.vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { dateFormater, getFirstDayOfWeek, getDays } from '@/utils/date-util'
|
||||
import {ElMessage, ElMessageBox} from 'element-plus'
|
||||
import {dateFormater, getDays, getFirstDayOfWeek} from '@/utils/date-util'
|
||||
import * as dailyPlanApi from "@/api/daily-plan";
|
||||
|
||||
const monthCn = ['一', '二', '三', '四', '五', '六', '七', '八', '九', '十', '十一', '十二'];
|
||||
const weekCn = ['周一', '周二', '周三', '周四', '周五', '周六', '周日'];
|
||||
const datePickerRef = ref();
|
||||
const recordFormRef = ref();
|
||||
const isRecordDialog = ref(false);
|
||||
const month = ref(new Date());
|
||||
const week = ref([] as any);
|
||||
const recordWeek = ref([] as any);
|
||||
const record = ref([] as any);
|
||||
const currentDate = ref<Date>(new Date());
|
||||
|
||||
const monthEn = ['一', '二', '三', '四', '五', '六', '七', '八', '九', '十', '十一', '十二']
|
||||
const weekEn = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
|
||||
onMounted(init)
|
||||
|
||||
const datePicker = ref()
|
||||
const recordFormRef = ref()
|
||||
const isRecordDialog = ref(false)
|
||||
const month = ref(new Date())
|
||||
const week = ref([] as any)
|
||||
const recordWeek = ref([] as any)
|
||||
const record = ref([] as any)
|
||||
const currentDate = ref<Date>(new Date())
|
||||
|
||||
setWeek()
|
||||
|
||||
function formatDate(date: any) {
|
||||
return monthEn[new Date(date).getMonth()] + '月 ' + new Date(date).getFullYear()
|
||||
function init() {
|
||||
setMonthWeek();
|
||||
}
|
||||
|
||||
function getMonthTitle() {
|
||||
return monthCn[new Date(month.value).getMonth()] + '月 ' + new Date(month.value).getFullYear();
|
||||
}
|
||||
|
||||
function addWeek() {
|
||||
const date: any = getDays(month.value, 7);
|
||||
month.value = date;
|
||||
setWeek(date);
|
||||
}
|
||||
|
||||
function minusWeek() {
|
||||
const date: any = getDays(month.value, -7);
|
||||
month.value = date;
|
||||
setWeek(date);
|
||||
}
|
||||
|
||||
function setMonthWeek() {
|
||||
setWeek(month.value);
|
||||
setDate(month.value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置周
|
||||
* @param type
|
||||
* @param type
|
||||
* 获取一周的数据,然后给每天打 record-mark 标记
|
||||
*/
|
||||
function setWeek(type?: 'up' | 'down') {
|
||||
const date = (type && getDays(month.value, type === 'up' ? -7 : 7)) || month.value
|
||||
currentDate.value = date
|
||||
const e = date
|
||||
week.value = []
|
||||
recordWeek.value = []
|
||||
recordWeek.value = [
|
||||
{
|
||||
id: '1',
|
||||
title: '月度会议',
|
||||
type: '',
|
||||
state: '',
|
||||
date: getFirstDayOfWeek(e, 1),
|
||||
time: getFirstDayOfWeek(e, 1),
|
||||
content: '测试测试'
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
title: '手术提醒',
|
||||
type: '',
|
||||
state: '',
|
||||
date: getFirstDayOfWeek(e, 4),
|
||||
time: getFirstDayOfWeek(e, 4),
|
||||
content: '测试测试'
|
||||
}
|
||||
]
|
||||
// 定时器等待动画执行
|
||||
setTimeout(() => {
|
||||
for (let i = 0; i < 7; i++) {
|
||||
week.value.push(getFirstDayOfWeek(date, i + 1))
|
||||
}
|
||||
}, 0)
|
||||
setDate(currentDate.value)
|
||||
function setWeek(date: any) {
|
||||
week.value = [];
|
||||
setTimeout(() => {
|
||||
for (let i = 0; i < 7; i++) {
|
||||
week.value.push(getFirstDayOfWeek(date, i + 1));
|
||||
}
|
||||
getWeekPlanList(week.value[0], week.value[6]);
|
||||
}, 0)
|
||||
}
|
||||
|
||||
const handleOpen = () => {
|
||||
datePicker.value.handleOpen()
|
||||
function getWeekPlanList(startDate: any, endDate: any) {
|
||||
recordWeek.value = [];
|
||||
dailyPlanApi.getPlanDateList(dateFormater("yyyy-MM-dd", startDate),
|
||||
dateFormater("yyyy-MM-dd", endDate)).then((res: any) => {
|
||||
if (res.code == 0) {
|
||||
recordWeek.value = res.data;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const handleDatePickerOpen = () => {
|
||||
datePickerRef.value.handleOpen();
|
||||
}
|
||||
|
||||
function setDate(e: Date) {
|
||||
currentDate.value = e
|
||||
record.value = recordWeek.value.filter((r: any) => dateFormater('yyyy-MM-dd', r.date) === dateFormater('yyyy-MM-dd', e))
|
||||
currentDate.value = e
|
||||
getWeekPlanList(week.value[0], week.value[6]);
|
||||
getDatePlanList();
|
||||
}
|
||||
|
||||
function getDatePlanList() {
|
||||
dailyPlanApi.getDailyPlanList(dateFormater("yyyy-MM-dd", currentDate.value)).then((res: any) => {
|
||||
if (res.code == 0) {
|
||||
record.value = res.data;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const addRecord = () => {
|
||||
const e = currentDate.value || new Date()
|
||||
isRecordDialog.value = true
|
||||
setTimeout(() => {
|
||||
recordFormRef.value.resetData()
|
||||
recordFormRef.value.formData.date = e
|
||||
recordFormRef.value.formData.isRemoveBtn = false
|
||||
}, 0)
|
||||
const e = currentDate.value || new Date()
|
||||
isRecordDialog.value = true
|
||||
setTimeout(() => {
|
||||
recordFormRef.value.resetData(false, dateFormater("yyyy-MM-dd", e));
|
||||
}, 0)
|
||||
}
|
||||
const viewRecord = (e: any) => {
|
||||
isRecordDialog.value = true
|
||||
setTimeout(() => {
|
||||
recordFormRef.value.resetData()
|
||||
recordFormRef.value.formData = Object.assign({}, recordFormRef.value.formData, e)
|
||||
recordFormRef.value.formData.isRemoveBtn = true
|
||||
// console.log(recordFormRef.value.formData)
|
||||
}, 0)
|
||||
isRecordDialog.value = true
|
||||
setTimeout(() => {
|
||||
recordFormRef.value.resetData(true, null, e);
|
||||
}, 0)
|
||||
}
|
||||
const remoteRecord = (item: any, index: number) => {
|
||||
ElMessageBox.confirm(
|
||||
'是否确认删除?',
|
||||
{
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
draggable: true
|
||||
}
|
||||
).then(() => {
|
||||
ElMessage.success('删除成功!')
|
||||
recordWeek.value = recordWeek.value.filter((r: any) => r.id !== item.id)
|
||||
setDate(item.date)
|
||||
}).catch(() => { })
|
||||
ElMessageBox.confirm(
|
||||
'是否确认删除?',
|
||||
{
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
draggable: true
|
||||
}
|
||||
).then(() => {
|
||||
dailyPlanApi.deleteById(item.id).then((res: any) => {
|
||||
if (res.code == 0) {
|
||||
ElMessage.success('删除成功!');
|
||||
setDate(item.date);
|
||||
} else {
|
||||
ElMessage.error(res.msg);
|
||||
}
|
||||
}).catch(err => {
|
||||
ElMessage.error("服务器异常");
|
||||
})
|
||||
})
|
||||
}
|
||||
const saveData = (e: any) => {
|
||||
recordWeek.value.push(e)
|
||||
setDate(e.date)
|
||||
setDate(new Date(e.date));
|
||||
}
|
||||
|
||||
const planRemoveEvent = () => {
|
||||
setDate(currentDate.value)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.week-calendar-part {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
|
||||
.header-box {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
.header-box {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.el-icon {
|
||||
cursor: pointer;
|
||||
}
|
||||
.el-icon {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.date-block {
|
||||
position: relative;
|
||||
.date-block {
|
||||
position: relative;
|
||||
|
||||
&>span {
|
||||
cursor: pointer;
|
||||
}
|
||||
& > span {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
:deep(.month-date-pick) {
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
:deep(.month-date-pick) {
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.week-box {
|
||||
width: 100%;
|
||||
height: 80px;
|
||||
border-top: 1px solid $border-color;
|
||||
.week-box {
|
||||
width: 100%;
|
||||
height: 80px;
|
||||
border-top: 1px solid $border-color;
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
height: 80px;
|
||||
text-align: center;
|
||||
table {
|
||||
width: 100%;
|
||||
height: 80px;
|
||||
text-align: center;
|
||||
|
||||
tr {
|
||||
td {
|
||||
font-weight: 600;
|
||||
color: black;
|
||||
tr {
|
||||
td {
|
||||
font-weight: 600;
|
||||
color: black;
|
||||
|
||||
span {
|
||||
cursor: pointer;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border: 2px solid transparent;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
margin: 0 auto;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
transition: all .3s;
|
||||
span {
|
||||
cursor: pointer;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border: 2px solid transparent;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
margin: 0 auto;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
transition: all .3s;
|
||||
|
||||
&:hover {
|
||||
background: rgba($main-color, .1);
|
||||
transition: all .3s;
|
||||
}
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
background: rgba($main-color, .1);
|
||||
transition: all .3s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.record-mark {
|
||||
color: $main-color;
|
||||
.record-mark {
|
||||
color: $main-color;
|
||||
|
||||
span {
|
||||
border-color: $main-color;
|
||||
}
|
||||
}
|
||||
span {
|
||||
border-color: $main-color;
|
||||
}
|
||||
}
|
||||
|
||||
.active {
|
||||
color: white;
|
||||
.active {
|
||||
color: white;
|
||||
|
||||
span {
|
||||
color: white;
|
||||
border-color: $main-color;
|
||||
background: $main-color;
|
||||
span {
|
||||
color: white;
|
||||
border-color: $main-color;
|
||||
background: $main-color;
|
||||
|
||||
&:hover {
|
||||
background: rgba($main-color, .8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
background: rgba($main-color, .8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.record-box {
|
||||
width: 100%;
|
||||
height: calc(100% - 170px);
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
.record-box {
|
||||
width: 100%;
|
||||
height: calc(100% - 170px);
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
|
||||
.record-item {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px 20px;
|
||||
transition: all .6s;
|
||||
.record-item {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px 20px;
|
||||
transition: all .6s;
|
||||
|
||||
&:hover {
|
||||
background: rgba($main-color, .1);
|
||||
transition: all .6s;
|
||||
}
|
||||
&:hover {
|
||||
background: rgba($main-color, .1);
|
||||
transition: all .6s;
|
||||
}
|
||||
|
||||
.icon-box {
|
||||
flex-shrink: 0;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 8px;
|
||||
background: rgba($main-color, .1);
|
||||
color: $main-color;
|
||||
font-size: 32px;
|
||||
text-align: center;
|
||||
line-height: 50px;
|
||||
margin-right: 15px;
|
||||
}
|
||||
.icon-box {
|
||||
flex-shrink: 0;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 8px;
|
||||
background: rgba($main-color, .1);
|
||||
color: $main-color;
|
||||
font-size: 32px;
|
||||
text-align: center;
|
||||
line-height: 50px;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.remove-icon {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
font-size: 20px;
|
||||
top: calc(50% - 10px);
|
||||
right: 20px;
|
||||
color: $text3-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
.remove-icon {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
font-size: 20px;
|
||||
top: calc(50% - 10px);
|
||||
right: 20px;
|
||||
color: $text3-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -82,32 +82,37 @@ getHospitalsData().then((res: any) => {
|
|||
|
||||
const menus = [] as any
|
||||
switch (userInfo.permissions) {
|
||||
case '超级管理员':
|
||||
menus.push({label: '首页', path: '/home', icon: 'icon-shouye'})
|
||||
menus.push({label: '权限管理', path: '/permissions-manage', icon: 'icon-users'})
|
||||
menus.push({label: '患者管理', path: '/patients-manage', icon: 'icon-renyuanguanli'})
|
||||
menus.push({label: '远程管理', path: '/remote-manage', icon: 'icon-anquanbaozhang'})
|
||||
menus.push({label: '后台管理', path: '/system-manage', icon: 'icon-houtaiguanli'})
|
||||
menus.push({label: '系统管理', path: '/logs-manage', icon: 'icon-setting'})
|
||||
break;
|
||||
case '高级管理员':
|
||||
menus.push({label: '首页', path: '/home', icon: 'icon-shouye'})
|
||||
menus.push({label: '权限管理', path: '/permissions-manage', icon: 'icon-users'})
|
||||
menus.push({label: '患者管理', path: '/patients-manage', icon: 'icon-renyuanguanli'})
|
||||
menus.push({label: '远程管理', path: '/remote-manage', icon: 'icon-anquanbaozhang'})
|
||||
menus.push({label: '系统管理', path: '/logs-manage', icon: 'icon-setting'})
|
||||
break;
|
||||
case '中级管理员':
|
||||
menus.push({label: '首页', path: '/home', icon: 'icon-shouye'})
|
||||
menus.push({label: '患者管理', path: '/patients-manage', icon: 'icon-renyuanguanli'})
|
||||
menus.push({label: '远程管理', path: '/remote-manage', icon: 'icon-anquanbaozhang'})
|
||||
break;
|
||||
case '普通用户':
|
||||
menus.push({label: '首页', path: '/home', icon: 'icon-shouye'})
|
||||
menus.push({label: '患者管理', path: '/patients-manage', icon: 'icon-renyuanguanli'})
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
case '超级管理员':
|
||||
menus.push({label: '首页', path: '/home', icon: 'icon-shouye'})
|
||||
menus.push({label: '权限管理', path: '/permissions-manage', icon: 'icon-users'})
|
||||
menus.push({label: '患者管理', path: '/patients-manage', icon: 'icon-renyuanguanli'})
|
||||
menus.push({label: '远程管理', path: '/remote-manage', icon: 'icon-anquanbaozhang'})
|
||||
menus.push({label: '后台管理', path: '/system-manage', icon: 'icon-houtaiguanli'})
|
||||
menus.push({label: '系统管理', path: '/logs-manage', icon: 'icon-setting'})
|
||||
break;
|
||||
case '高级管理员':
|
||||
menus.push({label: '首页', path: '/home', icon: 'icon-shouye'})
|
||||
menus.push({label: '权限管理', path: '/permissions-manage', icon: 'icon-users'})
|
||||
menus.push({label: '患者管理', path: '/patients-manage', icon: 'icon-renyuanguanli'})
|
||||
menus.push({label: '远程管理', path: '/remote-manage', icon: 'icon-anquanbaozhang'})
|
||||
menus.push({label: '系统管理', path: '/logs-manage', icon: 'icon-setting'})
|
||||
break;
|
||||
case '中级管理员':
|
||||
menus.push({label: '首页', path: '/home', icon: 'icon-shouye'})
|
||||
menus.push({label: '患者管理', path: '/patients-manage', icon: 'icon-renyuanguanli'})
|
||||
menus.push({label: '远程管理', path: '/remote-manage', icon: 'icon-anquanbaozhang'})
|
||||
break;
|
||||
case '普通用户':
|
||||
menus.push({label: '首页', path: '/home', icon: 'icon-shouye'})
|
||||
menus.push({label: '患者管理', path: '/patients-manage', icon: 'icon-renyuanguanli'})
|
||||
break;
|
||||
default:
|
||||
menus.push({label: '首页', path: '/home', icon: 'icon-shouye'})
|
||||
menus.push({label: '权限管理', path: '/permissions-manage', icon: 'icon-users'})
|
||||
menus.push({label: '患者管理', path: '/patients-manage', icon: 'icon-renyuanguanli'})
|
||||
menus.push({label: '远程管理', path: '/remote-manage', icon: 'icon-anquanbaozhang'})
|
||||
menus.push({label: '后台管理', path: '/system-manage', icon: 'icon-houtaiguanli'})
|
||||
menus.push({label: '系统管理', path: '/logs-manage', icon: 'icon-setting'})
|
||||
}
|
||||
|
||||
const isShowUserInfoDrawer = ref(false)
|
||||
|
|
|
@ -8,120 +8,120 @@
|
|||
</el-select>
|
||||
</div>
|
||||
|
||||
<img v-show="!isShowRegister" class="logo move_2" src="@/assets/imgs/logo.png">
|
||||
<div v-if="!isShowRegister" class="login-block move_2">
|
||||
<div class="login-way">
|
||||
<span :class="passwordLogin && 'active'" @click="passwordLogin = true">密码登录</span>
|
||||
<span :class="!passwordLogin && 'active'" @click="passwordLogin = false">验证码登录</span>
|
||||
</div>
|
||||
<el-form ref="loginFormRef" :model="loginParams" :rules="loginRules" label-width="0" size="small">
|
||||
<div class="login-form password-login" v-if="passwordLogin">
|
||||
<el-form-item prop="account">
|
||||
<el-input v-model="loginParams.account" placeholder="请输入用户名">
|
||||
<template #prepend>
|
||||
<el-icon>
|
||||
<User/>
|
||||
</el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="password">
|
||||
<el-input v-model="loginParams.password" type="password" show-password placeholder="请输入密码">
|
||||
<template #prepend>
|
||||
<el-icon>
|
||||
<Lock/>
|
||||
</el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-button :loading="loading" class="login-btn" type="primary" @click="login('password')">登录</el-button>
|
||||
<span class="register-btn" @click="getCaptchaCode()">注册账号</span>
|
||||
</div>
|
||||
<div class="login-form code-login" v-else>
|
||||
<el-form-item prop="phone">
|
||||
<el-input v-model="loginParams.phone" placeholder="请输入手机号">
|
||||
<template #prepend>
|
||||
<div @click.stop style="display: flex;align-items: center;">
|
||||
<el-dropdown @command="selectPhoneArea">
|
||||
<img v-show="!isShowRegister" class="logo move_2" src="@/assets/imgs/logo.png">
|
||||
<div v-if="!isShowRegister" class="login-block move_2">
|
||||
<div class="login-way">
|
||||
<span :class="passwordLogin && 'active'" @click="passwordLogin = true">密码登录</span>
|
||||
<span :class="!passwordLogin && 'active'" @click="passwordLogin = false">验证码登录</span>
|
||||
</div>
|
||||
<el-form ref="loginFormRef" :model="loginParams" :rules="loginRules" label-width="0" size="small">
|
||||
<div class="login-form password-login" v-if="passwordLogin">
|
||||
<el-form-item prop="account">
|
||||
<el-input v-model="loginParams.account" placeholder="请输入用户名">
|
||||
<template #prepend>
|
||||
<el-icon>
|
||||
<User/>
|
||||
</el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="password">
|
||||
<el-input v-model="loginParams.password" type="password" show-password placeholder="请输入密码">
|
||||
<template #prepend>
|
||||
<el-icon>
|
||||
<Lock/>
|
||||
</el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-button :loading="loading" class="login-btn" type="primary" @click="login('password')">登录</el-button>
|
||||
<span class="register-btn" @click="getCaptchaCode()">注册账号</span>
|
||||
</div>
|
||||
<div class="login-form code-login" v-else>
|
||||
<el-form-item prop="phone">
|
||||
<el-input v-model="loginParams.phone" placeholder="请输入手机号">
|
||||
<template #prepend>
|
||||
<div @click.stop style="display: flex;align-items: center;">
|
||||
<el-dropdown @command="selectPhoneArea">
|
||||
<span style="color: #909399;">{{ loginParams.phoneArea }}<el-icon>
|
||||
<DCaret/>
|
||||
</el-icon></span>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item v-for="item in phoneAreas" :command="item">{{
|
||||
item
|
||||
}}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="code">
|
||||
<el-input v-model="loginParams.code" placeholder="请输入6位短信验证码">
|
||||
<template #append>
|
||||
<span class="send-btn" @click="sendCode">{{ loginParams.sendText }}</span>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-button class="login-btn" type="primary" @click="login('code')">登录</el-button>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
<div v-else class="register-block move_2">
|
||||
<div class="header-box">
|
||||
<span class="title">新用户申请</span>
|
||||
<el-icon @click="isShowRegister = false">
|
||||
<Close/>
|
||||
</el-icon>
|
||||
</div>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item v-for="item in phoneAreas" :command="item">{{
|
||||
item
|
||||
}}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="code">
|
||||
<el-input v-model="loginParams.code" placeholder="请输入6位短信验证码">
|
||||
<template #append>
|
||||
<span class="send-btn" @click="sendCode">{{ loginParams.sendText }}</span>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-button class="login-btn" type="primary" @click="login('code')">登录</el-button>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
<div v-else class="register-block move_2">
|
||||
<div class="header-box">
|
||||
<span class="title">新用户申请</span>
|
||||
<el-icon @click="isShowRegister = false">
|
||||
<Close/>
|
||||
</el-icon>
|
||||
</div>
|
||||
|
||||
<el-form ref="registerFormRef" :model="registerParams" :rules="registerRules" label-width="100">
|
||||
<el-form-item label="用户名" prop="username">
|
||||
<el-input v-model="registerParams.username" placeholder="请输入用户名"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="密码" prop="password">
|
||||
<el-input v-model="registerParams.password" type="password" show-password
|
||||
placeholder="请输入密码"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="姓名" prop="name">
|
||||
<el-input v-model="registerParams.name" placeholder="请输入姓名"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="手机号" prop="phone">
|
||||
<el-input v-model="registerParams.phone" placeholder="请输入手机号"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="医院" prop="hospital">
|
||||
<el-select v-model="registerParams.hospital" style="width: 100%;">
|
||||
<el-option v-for="item in hospitals" :key="item.id" :label="item.name"
|
||||
:value="item.id"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="性别" prop="sex">
|
||||
<el-radio-group v-model="registerParams.sex">
|
||||
<el-radio label="男"/>
|
||||
<el-radio label="女"/>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="验证码" prop="code">
|
||||
<el-input v-model="registerParams.code" placeholder="请输入验证码"
|
||||
style="width: calc(100% - 110px);"></el-input>
|
||||
<img width="100" height="32" style="margin-left: 10px;" :src="captchaImgUrl"/>
|
||||
<a class="change_img" @click="refreshImg" href="#">看不清?</a>
|
||||
</el-form-item>
|
||||
<el-form ref="registerFormRef" :model="registerParams" :rules="registerRules" label-width="100">
|
||||
<el-form-item label="用户名" prop="username">
|
||||
<el-input v-model="registerParams.username" placeholder="请输入用户名"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="密码" prop="password">
|
||||
<el-input v-model="registerParams.password" type="password" show-password
|
||||
placeholder="请输入密码"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="姓名" prop="name">
|
||||
<el-input v-model="registerParams.name" placeholder="请输入姓名"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="手机号" prop="phone">
|
||||
<el-input v-model="registerParams.phone" placeholder="请输入手机号"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="医院" prop="hospital">
|
||||
<el-select v-model="registerParams.hospital" style="width: 100%;">
|
||||
<el-option v-for="item in hospitals" :key="item.id" :label="item.name"
|
||||
:value="item.id"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="性别" prop="sex">
|
||||
<el-radio-group v-model="registerParams.sex">
|
||||
<el-radio label="男"/>
|
||||
<el-radio label="女"/>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="验证码" prop="code">
|
||||
<el-input v-model="registerParams.code" placeholder="请输入验证码"
|
||||
style="width: calc(100% - 110px);"></el-input>
|
||||
<img width="100" height="32" style="margin-left: 10px;" :src="captchaImgUrl"/>
|
||||
<a class="change_img" @click="refreshImg" href="#">看不清?</a>
|
||||
</el-form-item>
|
||||
|
||||
</el-form>
|
||||
<div class="footer-box">
|
||||
<el-button type="primary" @click="register">注 册</el-button>
|
||||
<span @click="isShowRegister = false">已有账号?</span>
|
||||
</div>
|
||||
</div>
|
||||
</el-form>
|
||||
<div class="footer-box">
|
||||
<el-button type="primary" @click="register">注 册</el-button>
|
||||
<span @click="isShowRegister = false">已有账号?</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<SliderVerify v-model:isShowSelf="sliderVConf.isShowSelf" :width="sliderVConf.width" :imgUrl="sliderImgUrl"
|
||||
:height="sliderVConf.height" @success="sliderSuccess" @close="sliderClose"></SliderVerify>
|
||||
</div>
|
||||
</div>
|
||||
<SliderVerify v-model:isShowSelf="sliderVConf.isShowSelf" :width="sliderVConf.width" :imgUrl="sliderImgUrl"
|
||||
:height="sliderVConf.height" @success="sliderSuccess" @close="sliderClose"></SliderVerify>
|
||||
</template>
|
||||
|
||||
<script lang='ts' setup>
|
||||
|
@ -313,21 +313,20 @@ const sendCode = () => {
|
|||
}, 1000);
|
||||
}
|
||||
const login = async (type: string) => {
|
||||
//加载效果:开始加载
|
||||
loading.value=true;
|
||||
const obj = loginParams.value
|
||||
if (!currentHospital.value) {
|
||||
ElMessage.warning('请在右上角选择院区')
|
||||
return
|
||||
}
|
||||
//加载效果:开始加载
|
||||
loading.value = true;
|
||||
//保证全部表单正常再发请求
|
||||
await loginFormRef.value.validate((valid: any, fields: any) => {
|
||||
if (valid) {
|
||||
sliderVConf.value.isShowSelf = true;
|
||||
}
|
||||
})
|
||||
//加载效果:开始加载
|
||||
loading.value = true;
|
||||
/*if (!currentHospital.value) {
|
||||
ElMessage.warning('请在右上角选择院区')
|
||||
return
|
||||
}*/
|
||||
//加载效果:开始加载
|
||||
loading.value = true;
|
||||
//保证全部表单正常再发请求
|
||||
await loginFormRef.value.validate((valid: any, fields: any) => {
|
||||
if (valid) {
|
||||
sliderVConf.value.isShowSelf = true;
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
@ -353,50 +352,28 @@ function sliderSuccess() {
|
|||
loading.value = false
|
||||
} else {
|
||||
// 存储token 信息
|
||||
Session.set('token', data.access_token);
|
||||
Session.set('refresh_token', data.refresh_token);
|
||||
console.log(data)
|
||||
toHome()
|
||||
}
|
||||
})
|
||||
console.log(data)
|
||||
ElNotification({
|
||||
type: 'success',
|
||||
message: '欢迎回来',
|
||||
title: `HI,${getTime()}好`
|
||||
});
|
||||
loginPost(data)
|
||||
router.push('/home')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function sliderClose() {
|
||||
loading.value = false
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
const toHome = () => {
|
||||
|
||||
ElNotification({
|
||||
type: 'success',
|
||||
message: '欢迎回来',
|
||||
title: `HI,${getTime()}好`
|
||||
});
|
||||
|
||||
const getPermissions = () => {
|
||||
let permissions = '普通用户'
|
||||
switch (loginParams.value.account) {
|
||||
|
||||
case 'admin':
|
||||
permissions = '超级管理员'
|
||||
break;
|
||||
case 'dev1':
|
||||
permissions = '高级管理员'
|
||||
break;
|
||||
case 'dev2':
|
||||
permissions = '中级管理员'
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return permissions
|
||||
}
|
||||
useLoginStore().setlogin('isLogin', true)
|
||||
useLoginStore().setlogin('account', loginParams.value.account)
|
||||
useLoginStore().setlogin('name', loginParams.value.name || '暂未设置姓名')
|
||||
useLoginStore().setlogin('hospital', currentHospital.value)
|
||||
useLoginStore().setlogin('permissions', getPermissions())
|
||||
router.push('/home')
|
||||
const loginPost = (data: any) => {
|
||||
Session.set('token', data.access_token);
|
||||
Session.set('refresh_token', data.refresh_token);
|
||||
useLoginStore().setlogin('account', data.username)
|
||||
console.log(data)
|
||||
useLoginStore().setlogin('name', data.user_info.name || '暂未设置姓名')
|
||||
}
|
||||
|
||||
</script>
|
||||
|
|
|
@ -1,197 +1,181 @@
|
|||
<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>
|
||||
import { onMounted, ref } from 'vue';
|
||||
import {onMounted, ref} from 'vue';
|
||||
import * as echarts from 'echarts';
|
||||
import { dateFormater } from '@/utils/date-util';
|
||||
import {dateFormater} from '@/utils/date-util';
|
||||
import {useRemoteWsStore} from "@/stores/remote-ws-store";
|
||||
|
||||
const chartDom = ref();
|
||||
|
||||
interface Props {
|
||||
names?: string[];
|
||||
chartData: any[];
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
names: () => ['CH1', 'CH2'],
|
||||
chartData: () => [] as any[],
|
||||
});
|
||||
|
||||
// const emit = defineEmits(['updateData']);
|
||||
|
||||
let chart: any;
|
||||
const names = props.names; // 类型名称
|
||||
const color = ['#00AAB7', '#C77000'];
|
||||
let xData = [] as any[]; // x时间轴
|
||||
let series = [] as any[];
|
||||
|
||||
// 更新图表
|
||||
function updateChart(num: number, time?: string) {
|
||||
xData.shift();
|
||||
xData.push(dateFormater('HH:mm:ss', time));
|
||||
// const values = [] as number[];
|
||||
series.forEach((item, index) => {
|
||||
item.data.shift();
|
||||
// item.data.push(index === 0 ? num - 0.2 : index === 2 ? num + 0.2 : num);
|
||||
// item.data.push(index === 0 ? -Math.floor(Math.random() * 50 + 40) : Math.floor(Math.random() * 50 + 40));
|
||||
item.data.push(Math.floor(Math.random() * 160 + -80));
|
||||
// values.push(item.data[item.data.length - 1]);
|
||||
});
|
||||
// emit('updateData', values); // 传值
|
||||
chart.setOption({
|
||||
xAxis: {
|
||||
data: xData,
|
||||
},
|
||||
series,
|
||||
});
|
||||
}
|
||||
// 格式化数据
|
||||
function formatterData() {
|
||||
xData = [];
|
||||
series = [];
|
||||
for (let i = 0; i < 50; i++) {
|
||||
if (props.chartData[i]) xData.push(dateFormater('HH:mm:ss', props.chartData[i].Time || props.chartData[i].TIME));
|
||||
else xData.unshift(0);
|
||||
}
|
||||
names.forEach((item, index) => {
|
||||
const obj = {
|
||||
name: item,
|
||||
type: 'line',
|
||||
symbol: 'none',
|
||||
lineStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 1, 1, [
|
||||
{
|
||||
offset: 0,
|
||||
color: 'rgba(40,94,125,0)',
|
||||
},
|
||||
{
|
||||
offset: 0.3,
|
||||
color: color[index],
|
||||
},
|
||||
{
|
||||
offset: 0.5,
|
||||
color: color[index],
|
||||
},
|
||||
{
|
||||
offset: 0.7,
|
||||
color: color[index],
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: 'rgba(40,94,125,0)',
|
||||
},
|
||||
]),
|
||||
width: 1,
|
||||
},
|
||||
data: [] as number[],
|
||||
};
|
||||
for (let i = 0; i < 50; i++) {
|
||||
if (props.chartData[i]) {
|
||||
const num = props.chartData[i].ST;
|
||||
// obj.data.push(index === 0 ? num - 0.2 : index === 2 ? num + 0.2 : num);
|
||||
// obj.data.push(index === 0 ? -Math.floor(Math.random() * 50 + 40) : Math.floor(Math.random() * 50 + 40));
|
||||
obj.data.push(Math.floor(Math.random() * 160 + -80));
|
||||
} else obj.data.unshift(0);
|
||||
}
|
||||
series.push(obj);
|
||||
});
|
||||
}
|
||||
// 渲染图表 父组件调用
|
||||
function chartSet() {
|
||||
formatterData();
|
||||
if (chart) chart.setOption({
|
||||
xAxis: {
|
||||
data: xData,
|
||||
},
|
||||
series,
|
||||
});
|
||||
}
|
||||
// 图表初始化
|
||||
function chartInit() {
|
||||
chart = echarts.init(chartDom.value as HTMLElement);
|
||||
chart.clear();
|
||||
const option = {
|
||||
color: color,
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
formatter: (params: any) => {
|
||||
let str = params[0].axisValue;
|
||||
str += `<br>`;
|
||||
names.forEach((item, index) => {
|
||||
str += params[index].marker;
|
||||
str += params[index].seriesName + ' ';
|
||||
str += `${params[index].value} HZ`;
|
||||
str += index === 0 ? '<br>' : '';
|
||||
});
|
||||
return str;
|
||||
},
|
||||
},
|
||||
grid: {
|
||||
left: 1,
|
||||
right: 20,
|
||||
bottom: 5,
|
||||
top: 20,
|
||||
containLabel: true,
|
||||
},
|
||||
xAxis: {
|
||||
show: true,
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
axisLine: { show: false, lineStyle: { color: '#006080' } },
|
||||
axisTick: { show: false },
|
||||
axisLabel: { show: false },
|
||||
splitLine: { show: true, lineStyle: { color: '#D4E8F0', width: 1, type: 'solid' } },
|
||||
data: xData,
|
||||
},
|
||||
yAxis: {
|
||||
show: true,
|
||||
type: 'value',
|
||||
min: function (value: any) {
|
||||
return value.min - 40
|
||||
},
|
||||
max: function (value: any) {
|
||||
return value.max + 40
|
||||
},
|
||||
axisLabel: {
|
||||
formatter: `{value} HZ`
|
||||
},
|
||||
axisLine: { show: false, lineStyle: { color: '#006080' } },
|
||||
splitLine: { lineStyle: { color: '#D4E8F0', width: 1, type: 'solid' } },
|
||||
},
|
||||
series,
|
||||
};
|
||||
chart.setOption(option);
|
||||
chart.resize();
|
||||
window.addEventListener('resize', () => {
|
||||
chart.resize();
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
chartInit();
|
||||
const props = withDefaults(defineProps<{ names?: string[] }>(), {
|
||||
names: ['CH1', 'CH2']
|
||||
});
|
||||
defineExpose({
|
||||
updateChart,
|
||||
chartSet
|
||||
updateChartData
|
||||
});
|
||||
const emit = defineEmits(["exceptionEvent"]);
|
||||
let chart: any;
|
||||
const color = ['#00AAB7', '#C77000'];
|
||||
const xData = [] as any[]; // x时间轴
|
||||
const series = [] as any[];
|
||||
let currentNode: any;
|
||||
const remoteWsStore = useRemoteWsStore();
|
||||
|
||||
onMounted(() => {
|
||||
chartInit();
|
||||
});
|
||||
|
||||
function updateChartData(data: any) {
|
||||
if (data) {
|
||||
if (currentNode && currentNode.Time == data.Time) {
|
||||
return;
|
||||
} else {
|
||||
currentNode = data;
|
||||
}
|
||||
xData.shift();
|
||||
xData.push(dateFormater("HH:mm:ss", data.Time ? data.Time - 8 * 60 * 60 * 1000 : ""));
|
||||
series.forEach(serie => {
|
||||
serie.data.shift();
|
||||
serie.data.push(data[serie] ? data[serie] : 0);
|
||||
if (data[serie.name + '_except']) {
|
||||
emit("exceptionEvent", remoteWsStore.exceptionMsg[serie.name + '_except']);
|
||||
}
|
||||
})
|
||||
chart.setOption({
|
||||
xAxis: {
|
||||
data: xData,
|
||||
},
|
||||
series
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 图表初始化
|
||||
function chartInit() {
|
||||
chart = echarts.init(chartDom.value as HTMLElement);
|
||||
chart.clear();
|
||||
getXData();
|
||||
getSeries();
|
||||
const option = {
|
||||
color: color,
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
formatter: (params: any) => {
|
||||
let str = params[0].axisValue;
|
||||
str += `<br>`;
|
||||
props.names.forEach((item, index) => {
|
||||
str += params[index].marker;
|
||||
str += params[index].seriesName + ' ';
|
||||
str += `${params[index].value} HZ`;
|
||||
str += index === 0 ? '<br>' : '';
|
||||
});
|
||||
return str;
|
||||
},
|
||||
},
|
||||
grid: {
|
||||
left: 1,
|
||||
right: 20,
|
||||
bottom: 5,
|
||||
top: 20,
|
||||
containLabel: true,
|
||||
},
|
||||
xAxis: {
|
||||
show: true,
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
axisLine: {show: false, lineStyle: {color: '#006080'}},
|
||||
axisTick: {show: false},
|
||||
axisLabel: {show: false},
|
||||
splitLine: {show: true, lineStyle: {color: '#D4E8F0', width: 1, type: 'solid'}},
|
||||
data: xData,
|
||||
},
|
||||
yAxis: {
|
||||
show: true,
|
||||
type: 'value',
|
||||
min: function (value: any) {
|
||||
return value.min - 40
|
||||
},
|
||||
max: function (value: any) {
|
||||
return value.max + 40
|
||||
},
|
||||
axisLabel: {
|
||||
formatter: `{value} HZ`
|
||||
},
|
||||
axisLine: {show: false, lineStyle: {color: '#006080'}},
|
||||
splitLine: {lineStyle: {color: '#D4E8F0', width: 1, type: 'solid'}},
|
||||
},
|
||||
series,
|
||||
};
|
||||
chart.setOption(option);
|
||||
chart.resize();
|
||||
window.addEventListener('resize', () => {
|
||||
chart.resize();
|
||||
});
|
||||
}
|
||||
|
||||
function getXData() {
|
||||
for (let i = 0; i < 50; i++) {
|
||||
xData.push(0);
|
||||
}
|
||||
}
|
||||
|
||||
function getSeries() {
|
||||
props.names.forEach((name, index) => {
|
||||
const serie = {
|
||||
name,
|
||||
type: 'line',
|
||||
symbol: 'none',
|
||||
lineStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 1, 1, [
|
||||
{
|
||||
offset: 0,
|
||||
color: 'rgba(40,94,125,0)',
|
||||
},
|
||||
{
|
||||
offset: 0.3,
|
||||
color: color[index],
|
||||
},
|
||||
{
|
||||
offset: 0.5,
|
||||
color: color[index],
|
||||
},
|
||||
{
|
||||
offset: 0.7,
|
||||
color: color[index],
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: 'rgba(40,94,125,0)',
|
||||
},
|
||||
]),
|
||||
width: 1,
|
||||
},
|
||||
data: [],
|
||||
};
|
||||
for (let i = 0; i < 50; i++) {
|
||||
serie.data.push(0);
|
||||
}
|
||||
series.push(serie);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.chart-dom-box {
|
||||
position: relative;
|
||||
position: relative;
|
||||
|
||||
.chart-rate {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
left: 30px;
|
||||
color: #285e7d;
|
||||
font-size: 16px;
|
||||
line-height: 30px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.chart-rate {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
left: 30px;
|
||||
color: #285e7d;
|
||||
font-size: 16px;
|
||||
line-height: 30px;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -5,102 +5,73 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref } from 'vue';
|
||||
import {onMounted, ref} from 'vue';
|
||||
import * as echarts from 'echarts';
|
||||
import { dateFormater } from '@/utils/date-util';
|
||||
import {dateFormater} from '@/utils/date-util';
|
||||
import {useRemoteWsStore} from "@/stores/remote-ws-store";
|
||||
|
||||
const chartDom = ref();
|
||||
const props = withDefaults(defineProps<{
|
||||
names: string[]
|
||||
}>(), {
|
||||
names: ['BIS', 'HR']
|
||||
});
|
||||
defineExpose({
|
||||
updateChartData
|
||||
});
|
||||
const emit = defineEmits(["exceptionEvent"]);
|
||||
let chart: any;
|
||||
const xData: any = [];
|
||||
const series: any = [];
|
||||
const legendData: any = [];
|
||||
const colors = ['#00AAB7', '#C77000'];
|
||||
let currentNode: any;
|
||||
const remoteWsStore = useRemoteWsStore();
|
||||
|
||||
interface Props {
|
||||
names: string[];
|
||||
chartData: any[];
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
names: () => ['BIS', 'HR'],
|
||||
chartData: () => [] as any[],
|
||||
onMounted(() => {
|
||||
chartInit();
|
||||
});
|
||||
|
||||
// const emit = defineEmits(['updateData']);
|
||||
|
||||
let chart: any;
|
||||
const names = props.names; // 类型名称
|
||||
const color = ['#00AAB7', '#C77000'];
|
||||
let legendData = [] as any[];
|
||||
let xData = [] as any[]; // x时间轴
|
||||
let series = [] as any[];
|
||||
|
||||
|
||||
// 更新图表
|
||||
function updateChart(ary: number[], time?: string) {
|
||||
xData.shift();
|
||||
xData.push(dateFormater('HH:mm:ss', time));
|
||||
// const values: number[] = [];
|
||||
series.forEach((item, index) => {
|
||||
item.data.shift();
|
||||
item.data.push(ary[index]);
|
||||
// values.push(item.data[item.data.length - 1]);
|
||||
});
|
||||
// emit('updateData', [values]); // 传值
|
||||
chart.setOption({
|
||||
xAxis: {
|
||||
data: xData,
|
||||
},
|
||||
series,
|
||||
});
|
||||
function updateChartData(data: any) {
|
||||
if (data) {
|
||||
if (currentNode && currentNode.Time == data.Time) {
|
||||
return;
|
||||
} else {
|
||||
currentNode = data;
|
||||
}
|
||||
xData.shift();
|
||||
xData.push(dateFormater("HH:mm:ss", data.Time ? data.Time - 8 * 60 * 60 * 1000 : ''));
|
||||
series.forEach(serie => {
|
||||
serie.data.shift();
|
||||
serie.data.push(data[serie.name]);
|
||||
if (data[serie.name + '_except']) {
|
||||
emit("exceptionEvent", remoteWsStore.exceptionMsg[serie.name + '_except']);
|
||||
}
|
||||
})
|
||||
chart.setOption({
|
||||
xAxis: {
|
||||
data: xData,
|
||||
},
|
||||
series,
|
||||
})
|
||||
}
|
||||
}
|
||||
// 格式化数据
|
||||
function formatterData() {
|
||||
legendData = [];
|
||||
xData = [];
|
||||
series = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
if (props.chartData[i]) xData.push(dateFormater('HH:mm:ss', props.chartData[i].Time || props.chartData[i].TIME));
|
||||
else xData.unshift(0);
|
||||
}
|
||||
names.forEach((item, index) => {
|
||||
const obj = {
|
||||
name: item,
|
||||
type: 'line',
|
||||
symbol: 'none',
|
||||
smooth: true,
|
||||
data: [] as number[],
|
||||
};
|
||||
for (let i = 0; i < 10; i++) {
|
||||
if (props.chartData[i]) obj.data.push(props.chartData[i][item]);
|
||||
else obj.data.unshift(0);
|
||||
}
|
||||
legendData.push({
|
||||
name: item,
|
||||
textStyle: { color: color[index] },
|
||||
});
|
||||
series.push(obj);
|
||||
});
|
||||
}
|
||||
// 渲染图表 父组件调用
|
||||
function chartSet() {
|
||||
formatterData();
|
||||
if (chart) chart.setOption({
|
||||
xAxis: {
|
||||
data: xData,
|
||||
},
|
||||
series,
|
||||
});
|
||||
}
|
||||
// 图表初始化
|
||||
|
||||
function chartInit() {
|
||||
chart = echarts.init(chartDom.value as HTMLElement);
|
||||
chart.clear();
|
||||
formatterData();
|
||||
const option : any = {
|
||||
color,
|
||||
getSeries();
|
||||
getXData();
|
||||
getLegendData();
|
||||
const option: any = {
|
||||
color: colors,
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
formatter: (params: any) => {
|
||||
let str = '';
|
||||
str += params[0].axisValue;
|
||||
str += '<br>';
|
||||
names.forEach((item, index) => {
|
||||
props.names.forEach((item, index) => {
|
||||
str += params[index].marker;
|
||||
str += params[index].seriesName + ' ';
|
||||
switch (item) {
|
||||
|
@ -145,7 +116,7 @@ function chartInit() {
|
|||
lineHeight: 30,
|
||||
},
|
||||
formatter: (params: string) => {
|
||||
const index = names.findIndex((item) => item === params);
|
||||
const index = props.names.findIndex((item) => item === params);
|
||||
let str = params + ' ';
|
||||
switch (params) {
|
||||
case 'BIS':
|
||||
|
@ -171,7 +142,7 @@ function chartInit() {
|
|||
}
|
||||
return str;
|
||||
},
|
||||
data: legendData,
|
||||
data: legendData
|
||||
},
|
||||
grid: {
|
||||
left: 5,
|
||||
|
@ -184,21 +155,22 @@ function chartInit() {
|
|||
show: true,
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
data: xData,
|
||||
axisLine: { lineStyle: { color: '#006080' } }
|
||||
data: [],
|
||||
axisLine: {lineStyle: {color: '#006080'}}
|
||||
},
|
||||
yAxis: {
|
||||
show: true,
|
||||
type: 'value',
|
||||
axisLabel: {
|
||||
formatter: `{value} ${names[0] === 'BIS' ? '次/分' : 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' } },
|
||||
axisLine: {show: true, lineStyle: {color: '#006080'}},
|
||||
splitLine: {lineStyle: {color: '#C0C4CC', width: 1, type: 'dashed'}},
|
||||
},
|
||||
series,
|
||||
};
|
||||
if(names[0] !== 'BIS') {
|
||||
if (props.names[0] !== 'BIS'
|
||||
) {
|
||||
option.yAxis.max = (value: any) => value.max + 20;
|
||||
}
|
||||
chart.setOption(option);
|
||||
|
@ -208,13 +180,36 @@ function chartInit() {
|
|||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
chartInit();
|
||||
});
|
||||
defineExpose({
|
||||
updateChart,
|
||||
chartSet
|
||||
});
|
||||
function getSeries() {
|
||||
props.names.forEach(name => {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
function getLegendData() {
|
||||
props.names.forEach((name, index) => {
|
||||
legendData.push({
|
||||
name,
|
||||
textStyle: {color: colors[index]},
|
||||
});
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
@ -1,51 +1,41 @@
|
|||
<template>
|
||||
<div class="message-item-part">
|
||||
<div class="tag-index">{{ index + 1 }}</div>
|
||||
<ul ref="listRef">
|
||||
<li v-for="(item, index) in logs" :key="index">
|
||||
<span>{{ dateFormater('HH:mm:ss', item.time) }}</span>
|
||||
<span>{{ item.title }}</span>
|
||||
<span>{{ item.state }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<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">
|
||||
<span>{{ dateFormater('yyyy-MM-dd HH:mm:ss', item.time) }}</span>
|
||||
<span>{{ item.taskName }}</span>
|
||||
<span>{{ item.state }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang='ts' setup>
|
||||
import { onMounted, reactive, ref, toRefs, watch } from 'vue'
|
||||
import type { RemoteLogItem, RemoteItem } from '@/utils/public-interface'
|
||||
import { useRemoteStore } from '@/stores/remote-info-store'
|
||||
import { dateFormater } from '@/utils/date-util'
|
||||
|
||||
interface Props {
|
||||
index: number
|
||||
logs: Array<RemoteLogItem>
|
||||
}
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
index: () => 0,
|
||||
logs: () => [] as Array<RemoteLogItem>
|
||||
})
|
||||
import {ref} from 'vue';
|
||||
import {useRemoteWsStore} from "@/stores/remote-ws-store";
|
||||
import {dateFormater} from "@/utils/date-util";
|
||||
|
||||
const remoteWsStore = useRemoteWsStore();
|
||||
const props = withDefaults(defineProps<{
|
||||
index: number
|
||||
}>(),
|
||||
{
|
||||
index: () => 0
|
||||
})
|
||||
const listRef = ref()
|
||||
const remoteTasks: any = ref([] as Array<RemoteItem>)
|
||||
|
||||
defineExpose({
|
||||
scrollToBottom,
|
||||
scrollToBottom
|
||||
})
|
||||
|
||||
remoteTasks.value = useRemoteStore().remoteTasks
|
||||
// 监听 useRemoteStore() 值变化
|
||||
// useRemoteStore().$subscribe((mutation: any, state: any) => {
|
||||
// console.log(mutation, state)
|
||||
// })
|
||||
|
||||
function scrollToBottom() {
|
||||
setTimeout(() => {
|
||||
listRef.value.scrollTo({
|
||||
top: listRef.value.scrollHeight,
|
||||
behavior: 'smooth'
|
||||
})
|
||||
}, 0)
|
||||
setTimeout(() => {
|
||||
listRef.value.scrollTo({
|
||||
top: listRef.value.scrollHeight,
|
||||
behavior: 'smooth'
|
||||
})
|
||||
}, 0)
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,47 +1,45 @@
|
|||
<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 remoteStore.currentRemote.log || []" :key="index"
|
||||
:timestamp="dateFormater('yyyy-MM-dd HH:mm:ss', item.time)"
|
||||
:class="{ 'alarm': item.state === '连接失败' || item.state === '异常' }">
|
||||
{{ item.title + ' ' + 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>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang='ts' setup>
|
||||
import { onMounted, reactive, ref, toRefs, watch } from 'vue'
|
||||
import type { RemoteLogItem, RemoteItem } from '@/utils/public-interface'
|
||||
import { useRemoteStore } from '@/stores/remote-info-store'
|
||||
import { dateFormater } from '@/utils/date-util'
|
||||
import {ref} from 'vue'
|
||||
import {dateFormater} from '@/utils/date-util'
|
||||
import {useRemoteWsStore} from "@/stores/remote-ws-store";
|
||||
|
||||
|
||||
defineExpose({
|
||||
setData,
|
||||
scrollToBottom
|
||||
setData,
|
||||
scrollToBottom
|
||||
})
|
||||
|
||||
const remoteStore = useRemoteStore()
|
||||
const remoteWsStore = useRemoteWsStore()
|
||||
const listRef = ref()
|
||||
|
||||
function setData(e: RemoteLogItem, index: number) {
|
||||
remoteStore.setRemoteLog(e, index)
|
||||
remoteStore.$patch({currentRemote: remoteStore.remoteTasks[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)
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,73 +1,101 @@
|
|||
<template>
|
||||
<el-dialog class="header-none" v-model="dialogVisible" :width="700" :show-close="false">
|
||||
<div class="content-box">
|
||||
<img src="@/assets/imgs/remote/remote_bck.png">
|
||||
<div class="info">
|
||||
<h3>连接云服务器</h3>
|
||||
<br>
|
||||
<p><strong>云服务器连接状态:{{ patientInfo.isRemote ? '已连接' : '未连接' }}</strong></p>
|
||||
<p>输入用户名:{{ patientInfo.serverUser }}</p>
|
||||
<p>密码:*********</p>
|
||||
<br>
|
||||
<p class="input-box"><span>输入病人姓名:</span><el-input v-model="patientInfo.patientName"></el-input></p>
|
||||
<p class="input-box"><span>输入病人住院号:</span><el-input v-model="patientInfo.patientCode"></el-input></p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="btn-box">
|
||||
<el-button class="f18" type="primary" @click="confirmRemote">确定连接</el-button>
|
||||
<!-- <el-button class="f18" @click="breakRemote">断开连接</el-button> -->
|
||||
<el-button class="f18" style="margin-left: 50px;" @click="dialogVisible = false">返回</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
<el-dialog class="header-none" v-model="dialogVisible" :width="700" :show-close="false">
|
||||
<div class="content-box">
|
||||
<img src="@/assets/imgs/remote/remote_bck.png">
|
||||
<div class="info">
|
||||
<h3>连接云服务器</h3>
|
||||
<br>
|
||||
<p>云服务器连接状态:{{ patientInfo.isRemote ? '已连接' : '未连接' }}</p>
|
||||
<!-- <p>输入用户名:{{ patientInfo.serverun }}</p>
|
||||
<p>密码:*********</p>
|
||||
<br>-->
|
||||
<p class="input-box"><span>输入病人姓名:</span>
|
||||
<el-input v-model="patientInfo.patient"></el-input>
|
||||
</p>
|
||||
<p class="input-box"><span>输入病人身份证号:</span>
|
||||
<el-input v-model="patientInfo.patientId"></el-input>
|
||||
</p>
|
||||
<p class="input-box"><span>请选择手术时间:</span>
|
||||
<el-date-picker
|
||||
v-model="patientInfo.date"
|
||||
type="date"
|
||||
placeholder="请选择日期"
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btn-box">
|
||||
<el-button class="f18" type="primary" @click="confirmRemote">确定连接</el-button>
|
||||
<!-- <el-button class="f18" @click="breakRemote">断开连接</el-button> -->
|
||||
<el-button class="f18" style="margin-left: 50px;" @click="dialogVisible = false">返回</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script lang='ts' setup>
|
||||
import { onMounted, reactive, ref, toRefs, watch } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useRemoteStore } from '@/stores/remote-info-store';
|
||||
import type { RemoteItem } from '@/utils/public-interface';
|
||||
|
||||
const router = useRouter()
|
||||
import {ref} from 'vue'
|
||||
import {ElMessage} from 'element-plus'
|
||||
import {useRemoteWsStore} from "@/stores/remote-ws-store";
|
||||
import {dateFormater} from "@/utils/date-util";
|
||||
|
||||
const emit = defineEmits(['confirmRemote', 'errorRemote', 'breakRemote'])
|
||||
|
||||
const dialogVisible = ref(false)
|
||||
const patientInfo = ref({} as RemoteItem)
|
||||
const patientInfo = ref({} as any)
|
||||
const remoteWsStore = useRemoteWsStore();
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
close,
|
||||
})
|
||||
onMounted(() => {
|
||||
|
||||
open,
|
||||
close,
|
||||
})
|
||||
|
||||
function open(e: RemoteItem) {
|
||||
patientInfo.value = JSON.parse(JSON.stringify(e))
|
||||
dialogVisible.value = true
|
||||
function open(e: number) {
|
||||
patientInfo.value = remoteWsStore.remoteTasks[e]
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
function close() {
|
||||
dialogVisible.value = false
|
||||
dialogVisible.value = false
|
||||
}
|
||||
|
||||
const confirmRemote = () => {
|
||||
if(patientInfo.value.patientCode) {
|
||||
ElMessage.success('连接成功!')
|
||||
patientInfo.value.isRemote = true
|
||||
patientInfo.value.title = '远程控制' + (patientInfo.value.index + 1)
|
||||
emit('confirmRemote', patientInfo.value)
|
||||
close()
|
||||
}else{
|
||||
ElMessage.error('连接失败!')
|
||||
emit('errorRemote', patientInfo.value)
|
||||
}
|
||||
if (patientInfo.value.patientId && patientInfo.value.patient) {
|
||||
ElMessage.success('连接成功!')
|
||||
patientInfo.value.isRemote = true
|
||||
patientInfo.value.taskName = '远程控制' + (patientInfo.value.index + 1)
|
||||
patientInfo.value.date = dateFormater("yyyy-MM-dd", patientInfo.value.date)
|
||||
unsubscribeLastTask();
|
||||
remoteWsStore.$patch({currentTaskIndex: patientInfo.value.index})
|
||||
remoteWsStore.setRemoteLog({
|
||||
time: new Date(),
|
||||
taskName: patientInfo.value.taskName,
|
||||
state: '连接成功',
|
||||
type: "normal"
|
||||
}, remoteWsStore.currentTaskIndex)
|
||||
emit('confirmRemote', patientInfo.value)
|
||||
close()
|
||||
} else {
|
||||
remoteWsStore.setRemoteLog({
|
||||
time: new Date(),
|
||||
taskName: patientInfo.value.taskName,
|
||||
state: '连接失败'
|
||||
}, patientInfo.value.index)
|
||||
ElMessage.error('连接失败!')
|
||||
emit('errorRemote', patientInfo.value)
|
||||
}
|
||||
}
|
||||
const breakRemote = () => {
|
||||
ElMessage.info('连接已断开!')
|
||||
emit('breakRemote', patientInfo.value)
|
||||
close()
|
||||
ElMessage.info('连接已断开!')
|
||||
emit('breakRemote', patientInfo.value)
|
||||
close()
|
||||
}
|
||||
|
||||
const unsubscribeLastTask = () => {
|
||||
const lastTaskIndex = remoteWsStore.currentTaskIndex;
|
||||
const lastTask: any = remoteWsStore.remoteTasks[lastTaskIndex];
|
||||
if (lastTask) {
|
||||
remoteWsStore.unsubscribeVital(lastTask.patient, lastTask.patientId, lastTask.date);
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
@ -116,6 +144,7 @@ const breakRemote = () => {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn-box {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
|
|
@ -1,122 +1,114 @@
|
|||
<template>
|
||||
<div class="remote-item-part">
|
||||
<div class="title">
|
||||
<span>{{ remoteTask.title || '远程控制' }}</span>
|
||||
</div>
|
||||
<div class="content mini" :class="{ 'is-total': remoteTask.isRemote }">
|
||||
<div class="left-box">
|
||||
<div class="info-box">
|
||||
<div class="row-item">
|
||||
<span class="label">病人名称</span>
|
||||
<span class="input-value">{{ patientInfo.name }}</span>
|
||||
</div>
|
||||
<div class="row-item">
|
||||
<span class="label">住院号</span>
|
||||
<span class="input-value">{{ patientInfo.code }}</span>
|
||||
</div>
|
||||
<div class="row-item">
|
||||
<span class="label">手术时间</span>
|
||||
<span class="input-value">{{ patientInfo.time && dateFormater('yyyy-MM-dd HH:mm:ss', patientInfo.time)
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="row-item">
|
||||
<span class="label">手术状态</span>
|
||||
<span class="tag-value" :class="{ 'normal': !patientInfo.state }">正常</span>
|
||||
<span class="tag-value" :class="{ 'alarm': patientInfo.state }">异常</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-item" :class="{ 'alarm': patientInfo.BIS < 40 || patientInfo.BIS > 60 }">
|
||||
<span class="label">BIS</span>
|
||||
<span class="value">{{ patientInfo.BIS }}</span>
|
||||
</div>
|
||||
<div class="row-item" :class="{ 'alarm': patientInfo.SBP < 90 || patientInfo.SBP > 120 }">
|
||||
<span class="label">SBP</span>
|
||||
<span class="value">{{ patientInfo.SBP }}<span class="unit">mmHg</span></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 < 60 || patientInfo.DBP > 90 }">
|
||||
<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 < 50 || patientInfo.HR > 80 }">
|
||||
<span class="label">HR</span>
|
||||
<span class="value">{{ patientInfo.HR }}<span class="unit">次/分</span></span>
|
||||
</div>
|
||||
<div class="row-item yellow">
|
||||
<span class="label">TEMP</span>
|
||||
<span class="value">{{ patientInfo.TEMP }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="center-box">
|
||||
<img src="@/assets/imgs/main_body_intact.png">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="remote-item-part">
|
||||
<div class="title">
|
||||
<span>{{ remoteTask.taskName || '远程控制' }}</span>
|
||||
</div>
|
||||
<div class="content mini" :class="{ 'is-total': remoteTask.isRemote }">
|
||||
<div class="left-box">
|
||||
<div class="info-box">
|
||||
<div class="row-item">
|
||||
<span class="label">病人名称</span>
|
||||
<span class="input-value">{{ remoteTask.patient }}</span>
|
||||
</div>
|
||||
<div class="row-item">
|
||||
<span class="label">住院号</span>
|
||||
<span class="input-value">{{ remoteTask.patientId }}</span>
|
||||
</div>
|
||||
<div class="row-item">
|
||||
<span class="label">手术时间</span>
|
||||
<span class="input-value">{{
|
||||
remoteTask.date
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="row-item">
|
||||
<span class="label">手术状态</span>
|
||||
<span class="tag-value" :class="{ 'normal': !patientInfo.state }">正常</span>
|
||||
<span class="tag-value" :class="{ 'alarm': patientInfo.state }">异常</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-item" :class="{ 'alarm': patientInfo.BIS_except }">
|
||||
<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>
|
||||
<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">TEMP</span>
|
||||
<span class="value">{{ patientInfo.TEMP }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="center-box">
|
||||
<img src="@/assets/imgs/main_body_intact.png">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang='ts' setup>
|
||||
import { onMounted, onBeforeUnmount, reactive, ref, toRefs, watch } from 'vue'
|
||||
import type { RemoteItem, PatientInfoItem, RemoteLogItem } from '@/utils/public-interface'
|
||||
import { useRemoteStore } from '@/stores/remote-info-store'
|
||||
import { dateFormater } from '@/utils/date-util'
|
||||
import { setRemoteLog } from '@/static-data/core'
|
||||
import {onMounted, onUnmounted, ref} from 'vue'
|
||||
import {useRemoteWsStore} from "@/stores/remote-ws-store";
|
||||
|
||||
interface Props {
|
||||
index: number
|
||||
}
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
index: () => 0
|
||||
const props = withDefaults(defineProps<{ index: number }>(), {
|
||||
index: () => 0
|
||||
})
|
||||
|
||||
const emit = defineEmits(['addLogAfter'])
|
||||
|
||||
const remoteStore = useRemoteStore()
|
||||
const remoteTask = remoteStore.remoteTasks[props.index]
|
||||
let timer = 0
|
||||
const patientInfo = ref({} as PatientInfoItem)
|
||||
const remoteWsStore = useRemoteWsStore();
|
||||
const remoteTask = ref(remoteWsStore.remoteTasks[props.index]);
|
||||
const patientInfo = ref({} as any)
|
||||
|
||||
onMounted(() => {
|
||||
clearInterval(timer)
|
||||
// 连接成功执行查询
|
||||
if (remoteTask.isRemote) {
|
||||
timer = setInterval(() => {
|
||||
initData()
|
||||
}, 2000)
|
||||
}
|
||||
// 连接成功执行查询
|
||||
if (remoteTask.value.isRemote) {
|
||||
initData()
|
||||
}
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
// 页面卸载后清楚定时器
|
||||
clearInterval(timer)
|
||||
onUnmounted(() => {
|
||||
remoteWsStore.unsubscribeVital(remoteTask.value.patient, remoteTask.value.patientId, remoteTask.value.date);
|
||||
})
|
||||
|
||||
function initData() {
|
||||
remoteTask.dataAlarm = false
|
||||
const obj = {
|
||||
name: remoteTask.patientName,
|
||||
code: '',
|
||||
time: new Date(),
|
||||
state: false,
|
||||
BIS: Number((Math.random() * 100).toFixed(2)),
|
||||
SBP: Number((Math.random() * 100).toFixed(2)),
|
||||
SPO2: Number((Math.random() * 100).toFixed(2)),
|
||||
DBP: Number((Math.random() * 100).toFixed(2)),
|
||||
HR: Number((Math.random() * 100).toFixed(2)),
|
||||
TEMP: Number((Math.random() * 100).toFixed(2))
|
||||
}
|
||||
setRemoteLog(obj, (title: string, size: string) => {
|
||||
obj.state = true
|
||||
remoteTask.dataAlarm = true
|
||||
remoteStore.setRemoteLog({
|
||||
time: new Date(),
|
||||
title,
|
||||
state: '异常'
|
||||
}, props.index)
|
||||
subscribeVital();
|
||||
}
|
||||
|
||||
function subscribeVital() {
|
||||
remoteWsStore.subscribeVital(remoteTask.value.patient, remoteTask.value.patientId, remoteTask.value.date, (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)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function setLog(data: any, index: number) {
|
||||
remoteWsStore.exceptionType.forEach((item: any) => {
|
||||
if (data[item]) {
|
||||
const msg: any = remoteWsStore.exceptionMsg[item];
|
||||
remoteWsStore.setRemoteLog({
|
||||
state: msg,
|
||||
taskName: remoteTask.value.taskName,
|
||||
time: new Date(),
|
||||
type: "exception"
|
||||
}, index);
|
||||
}
|
||||
})
|
||||
Object.assign(patientInfo.value, obj)
|
||||
emit('addLogAfter', props.index)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
|
|
@ -1,377 +1,415 @@
|
|||
<template>
|
||||
<div class="remote-part">
|
||||
<div class="title">
|
||||
<span>{{ remoteItem?.title || '远程控制' }}</span>
|
||||
<el-button v-if="remoteItem" 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="input-value">{{ patientInfo.name }}</span>
|
||||
</div>
|
||||
<div class="row-item">
|
||||
<span class="label">住院号</span>
|
||||
<span class="input-value">{{ patientInfo.code }}</span>
|
||||
</div>
|
||||
<div class="row-item">
|
||||
<span class="label">手术时间</span>
|
||||
<span class="input-value">{{ patientInfo.time && dateFormater('yyyy-MM-dd HH:mm:ss', patientInfo.time) }}</span>
|
||||
</div>
|
||||
<div class="row-item">
|
||||
<span class="label">手术状态</span>
|
||||
<span class="tag-value" :class="{'normal': !patientInfo.state}">正常</span>
|
||||
<span class="tag-value" :class="{'alarm': patientInfo.state}">异常</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-item" :class="{'alarm': patientInfo.BIS < 40 || patientInfo.BIS > 60}">
|
||||
<span class="label">BIS</span>
|
||||
<span class="value">{{ patientInfo.BIS }}</span>
|
||||
</div>
|
||||
<div class="row-item" :class="{'alarm': patientInfo.SBP < 90 || patientInfo.SBP > 120}">
|
||||
<span class="label">SBP</span>
|
||||
<span class="value">{{ patientInfo.SBP }}<span class="unit">mmHg</span></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 < 60 || patientInfo.DBP > 90}">
|
||||
<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 < 50 || patientInfo.HR > 80}">
|
||||
<span class="label">HR</span>
|
||||
<span class="value">{{ patientInfo.HR }}<span class="unit">次/分</span></span>
|
||||
</div>
|
||||
<div class="row-item yellow">
|
||||
<span class="label">TEMP</span>
|
||||
<span class="value">{{ patientInfo.TEMP }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="center-box">
|
||||
<img src="@/assets/imgs/main_body_intact.png">
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="content" :class="{'is-total': remoteItem?.isRemote}">
|
||||
<div class="left-box">
|
||||
<div class="info-box">
|
||||
<div class="row-item">
|
||||
<span class="label">病人名称</span>
|
||||
<span class="input-value">{{ patientInfo.name }}</span>
|
||||
</div>
|
||||
<div class="row-item">
|
||||
<span class="label">住院号</span>
|
||||
<span class="input-value">{{ patientInfo.code }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-item" :class="{'alarm': patientInfo.BIS < 40 || patientInfo.BIS > 60}">
|
||||
<span class="label">BIS</span>
|
||||
<span class="value">{{ patientInfo.BIS }}</span>
|
||||
</div>
|
||||
<div class="row-item" :class="{'alarm': patientInfo.SBP < 90 || patientInfo.SBP > 120}">
|
||||
<span class="label">SBP</span>
|
||||
<span class="value">{{ patientInfo.SBP }}<span class="unit">mmHg</span></span>
|
||||
</div>
|
||||
<div class="row-item">
|
||||
<span class="label">SPO2</span>
|
||||
<span class="value">{{ patientInfo.SPO2 }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="center-box">
|
||||
<img src="@/assets/imgs/main_body_intact.png">
|
||||
</div>
|
||||
<div class="right-box">
|
||||
<div class="info-box">
|
||||
<div class="row-item">
|
||||
<span class="label">手术时间</span>
|
||||
<span class="input-value">{{ patientInfo.time && dateFormater('yyyy-MM-dd HH:mm:ss', patientInfo.time) }}</span>
|
||||
</div>
|
||||
<div class="row-item">
|
||||
<span class="label">手术状态</span>
|
||||
<span class="tag-value" :class="{'normal': !patientInfo.state}">正常</span>
|
||||
<span class="tag-value" :class="{'alarm': patientInfo.state}">异常</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-item" :class="{'alarm': patientInfo.DBP < 60 || patientInfo.DBP > 90}">
|
||||
<span class="label">DBP</span>
|
||||
<span class="value">{{ patientInfo.DBP }}<span class="unit">mmHg</span></span>
|
||||
</div>
|
||||
<div class="row-item" :class="{'alarm': patientInfo.HR < 50 || patientInfo.HR > 80}">
|
||||
<span class="label">HR</span>
|
||||
<span class="value">{{ patientInfo.HR }}<span class="unit">次/分</span></span>
|
||||
</div>
|
||||
<div class="row-item">
|
||||
<span class="label">TEMP</span>
|
||||
<span class="value">{{ patientInfo.TEMP }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="remote-part">
|
||||
<div class="title">
|
||||
<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="input-value">{{ remoteItem.patient }}</span>
|
||||
</div>
|
||||
<div class="row-item">
|
||||
<span class="label">住院号</span>
|
||||
<span class="input-value">{{ remoteItem.patientId }}</span>
|
||||
</div>
|
||||
<div class="row-item">
|
||||
<span class="label">手术时间</span>
|
||||
<span class="input-value">{{
|
||||
remoteItem.date
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="row-item">
|
||||
<span class="label">手术状态</span>
|
||||
<span class="tag-value" :class="{'normal': !patientInfo.state}">正常</span>
|
||||
<span class="tag-value" :class="{'alarm': patientInfo.state}">异常</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-item" :class="{'alarm': patientInfo.BIS_except}">
|
||||
<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>
|
||||
<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">TEMP</span>
|
||||
<span class="value">{{ patientInfo.TEMP }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="center-box">
|
||||
<img src="@/assets/imgs/main_body_intact.png">
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="content" :class="{'is-total': remoteItem?.isRemote}">
|
||||
<div class="left-box">
|
||||
<div class="info-box">
|
||||
<div class="row-item">
|
||||
<span class="label">病人名称</span>
|
||||
<span class="input-value">{{ remoteItem.patient }}</span>
|
||||
</div>
|
||||
<div class="row-item">
|
||||
<span class="label">住院号</span>
|
||||
<span class="input-value">{{ remoteItem.patientId }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-item" :class="{'alarm': patientInfo.BIS_except}">
|
||||
<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>
|
||||
<div class="row-item">
|
||||
<span class="label">SPO2</span>
|
||||
<span class="value">{{ patientInfo.SPO2 }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="center-box">
|
||||
<img src="@/assets/imgs/main_body_intact.png">
|
||||
</div>
|
||||
<div class="right-box">
|
||||
<div class="info-box">
|
||||
<div class="row-item">
|
||||
<span class="label">手术时间</span>
|
||||
<span class="input-value">{{
|
||||
remoteItem.date
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="row-item">
|
||||
<span class="label">手术状态</span>
|
||||
<span class="tag-value" :class="{'normal': !patientInfo.state}">正常</span>
|
||||
<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>
|
||||
<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>
|
||||
<div class="row-item">
|
||||
<span class="label">TEMP</span>
|
||||
<span class="value">{{ patientInfo.TEMP }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang='ts' setup>
|
||||
import { onMounted, onBeforeUnmount, reactive, ref, toRefs, watch } from 'vue'
|
||||
import { dateFormater } from '@/utils/date-util'
|
||||
import { useRemoteStore } from '@/stores/remote-info-store';
|
||||
import type { RemoteItem, PatientInfoItem } from '@/utils/public-interface'
|
||||
import { setRemoteLog } from '@/static-data/core'
|
||||
import {onUnmounted, ref} from 'vue'
|
||||
import {useRemoteWsStore} from "@/stores/remote-ws-store";
|
||||
|
||||
const emit = defineEmits(['addLogAfter', 'breakRemote'])
|
||||
|
||||
const remoteStore = useRemoteStore()
|
||||
let timer = 0
|
||||
const mediaMini800 = ref(false)
|
||||
const remoteItem = ref<RemoteItem>({} as RemoteItem)
|
||||
const patientInfo = ref({} as PatientInfoItem)
|
||||
|
||||
initData(remoteStore.currentRemote)
|
||||
const remoteItem = ref({} as any)
|
||||
const patientInfo = ref({} as any)
|
||||
const remoteWsStore = useRemoteWsStore()
|
||||
|
||||
defineExpose({
|
||||
initData
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
// 页面卸载后清楚定时器
|
||||
clearInterval(timer)
|
||||
})
|
||||
|
||||
window.addEventListener('resize', () => {
|
||||
mediaMini800.value = Boolean(window.innerWidth < 801)
|
||||
initData, showData
|
||||
});
|
||||
|
||||
function initData(e?: RemoteItem) {
|
||||
const obj = e || {} as RemoteItem
|
||||
remoteItem.value = obj
|
||||
patientInfo.value.state = obj.dataAlarm
|
||||
patientInfo.value.name = obj.patientName || ''
|
||||
patientInfo.value.code = 'XXXXXX'
|
||||
clearInterval(timer)
|
||||
if(!patientInfo.value.name) return
|
||||
timer = setInterval(() => {
|
||||
getData()
|
||||
}, 2000)
|
||||
window.addEventListener('resize', () => {
|
||||
mediaMini800.value = Boolean(window.innerWidth < 801)
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
remoteWsStore.unsubscribeVital(remoteItem.value.patient, remoteItem.value.patientId, remoteItem.value.date);
|
||||
})
|
||||
|
||||
function showData(i: number) {
|
||||
const lastTaskIndex = remoteWsStore.currentTaskIndex;
|
||||
const lastTask: any = remoteWsStore.remoteTasks[lastTaskIndex];
|
||||
if (lastTask) {
|
||||
remoteWsStore.unsubscribeVital(lastTask.patient, lastTask.patientId, lastTask.date);
|
||||
}
|
||||
remoteWsStore.currentTaskIndex = i
|
||||
remoteItem.value = remoteWsStore.remoteTasks[remoteWsStore.currentTaskIndex]
|
||||
getData()
|
||||
}
|
||||
|
||||
function initData() {
|
||||
remoteItem.value = remoteWsStore.remoteTasks[remoteWsStore.currentTaskIndex]
|
||||
remoteWsStore.createConnect(remoteItem.value.patient, remoteItem.value.patientId, remoteItem.value.date)
|
||||
getData()
|
||||
}
|
||||
|
||||
function getData() {
|
||||
remoteItem.value.dataAlarm = false
|
||||
const obj = {
|
||||
state: false,
|
||||
BIS: Math.ceil(Math.random() * 100),
|
||||
SBP: Math.ceil(Math.random() * 100),
|
||||
SPO2: Math.ceil(Math.random() * 100),
|
||||
DBP: Math.ceil(Math.random() * 100),
|
||||
HR: Math.ceil(Math.random() * 100),
|
||||
TEMP: Math.ceil(Math.random() * 100),
|
||||
} as PatientInfoItem
|
||||
patientInfo.value.time = new Date()
|
||||
setRemoteLog(obj, (title: string, size: string) => {
|
||||
obj.state = true
|
||||
remoteItem.value.dataAlarm = true
|
||||
remoteStore.setRemoteLog({
|
||||
time: new Date(),
|
||||
title,
|
||||
state: '异常'
|
||||
}, remoteItem.value.index)
|
||||
})
|
||||
remoteStore.setRemoteDataAlarm(remoteItem.value.dataAlarm, remoteItem.value.index)
|
||||
remoteStore.$patch({currentRemote: remoteStore.remoteTasks[remoteItem.value.index]})
|
||||
Object.assign(patientInfo.value, obj)
|
||||
emit('addLogAfter')
|
||||
remoteWsStore.unsubscribeVital(remoteItem.value.patient, remoteItem.value.patientId, remoteItem.value.date);
|
||||
remoteWsStore.subscribeVital(remoteItem.value.patient, remoteItem.value.patientId, remoteItem.value.date, (res: any) => {
|
||||
if (res && res.data) {
|
||||
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)
|
||||
emit('addLogAfter')
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function setLog(data: any) {
|
||||
remoteWsStore.exceptionType.forEach((item: any) => {
|
||||
if (data[item]) {
|
||||
const msg: any = remoteWsStore.exceptionMsg[item];
|
||||
remoteWsStore.setRemoteLog({
|
||||
state: msg,
|
||||
taskName: remoteItem.value.taskName,
|
||||
time: new Date(),
|
||||
type: "exception"
|
||||
}, remoteWsStore.currentTaskIndex);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const breakRemote = () => {
|
||||
remoteItem.value.isRemote = false
|
||||
emit('breakRemote', remoteItem.value)
|
||||
remoteWsStore.disconnect(remoteItem.value.patient, remoteItem.value.patientId, remoteItem.value.date)
|
||||
remoteWsStore.resetRemoteTask(remoteWsStore.currentTaskIndex)
|
||||
if (remoteWsStore.getActiveRemoteTask()) {
|
||||
showData(remoteWsStore.getActiveRemoteTask())
|
||||
}
|
||||
emit('breakRemote')
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.remote-part {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 1px solid $border-color;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 1px solid $border-color;
|
||||
|
||||
.title {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
font-size: 20px;
|
||||
text-align: center;
|
||||
line-height: 40px;
|
||||
font-weight: 600;
|
||||
color: white;
|
||||
background: $main-color;
|
||||
.break-btn {
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
right: 20px;
|
||||
}
|
||||
}
|
||||
.content {
|
||||
width: 100%;
|
||||
height: calc(100% - 40px);
|
||||
padding: 20px 50px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
.common-box {
|
||||
width: 30%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-evenly;
|
||||
align-items: center;
|
||||
}
|
||||
.left-box {
|
||||
@extend .common-box;
|
||||
|
||||
.label {
|
||||
background: $main-color;
|
||||
}
|
||||
}
|
||||
.center-box {
|
||||
@extend .common-box;
|
||||
img {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
}
|
||||
.right-box {
|
||||
@extend .common-box;
|
||||
.label {
|
||||
background: $main-color;
|
||||
}
|
||||
}
|
||||
.row-item {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
.label {
|
||||
flex-shrink: 0;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
color: white;
|
||||
font-size: 18px;
|
||||
line-height: 40px;
|
||||
text-align: center;
|
||||
border-radius: 5px;
|
||||
}
|
||||
}
|
||||
.info-box, .row-item .value {
|
||||
display: none;
|
||||
}
|
||||
&.is-total {
|
||||
.info-box, .row-item .value {
|
||||
display: block;
|
||||
}
|
||||
.label {
|
||||
width: calc(50% - 10px);
|
||||
}
|
||||
.value {
|
||||
width: 50%;
|
||||
height: 40px;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
text-align: center;
|
||||
border-radius: 5px;
|
||||
color: $main-color;
|
||||
border-color: $main-color;
|
||||
font-size: 22px;
|
||||
line-height: 40px;
|
||||
font-weight: 600;
|
||||
.unit {
|
||||
font-size: 16px;
|
||||
font-family: 400;
|
||||
}
|
||||
}
|
||||
.right-box .value {
|
||||
color: $main-color;
|
||||
border-color: $main-color;
|
||||
}
|
||||
.row-item.alarm {
|
||||
.label {
|
||||
background: red !important;
|
||||
}
|
||||
.value {
|
||||
color: red !important;
|
||||
border-color: red !important;
|
||||
}
|
||||
}
|
||||
.info-box {
|
||||
width: 100%;
|
||||
.row-item {
|
||||
padding: 10px 0;
|
||||
height: 40px;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
.label {
|
||||
width: 70px;
|
||||
height: 20px;
|
||||
background: transparent;
|
||||
color: $main-color;
|
||||
font-size: 16px;
|
||||
line-height: 20px;
|
||||
font-weight: 600;
|
||||
text-align: left;
|
||||
}
|
||||
.input-value {
|
||||
width: 100%;
|
||||
height: 21px;
|
||||
line-height: 20px;
|
||||
font-size: 16px;
|
||||
color: $main-color;
|
||||
border-bottom: 1px solid $border2-color;
|
||||
}
|
||||
.tag-value {
|
||||
margin-left: 30px;
|
||||
padding: 0 20px;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
font-size: 18px;
|
||||
color: white;
|
||||
font-weight: 600;
|
||||
background: $border2-color;
|
||||
border-radius: 8px;
|
||||
&.normal {
|
||||
background: $main-color;
|
||||
}
|
||||
&.alarm {
|
||||
background: red;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
&.mini {
|
||||
padding: 20px;
|
||||
.left-box {
|
||||
width: 240px;
|
||||
}
|
||||
.center-box {
|
||||
width: calc(100% - 250px);
|
||||
}
|
||||
&.is-total {
|
||||
.left-box {
|
||||
.info-box {
|
||||
display: block;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.row-item.yellow {
|
||||
.label {
|
||||
background: $main-color;
|
||||
}
|
||||
.value {
|
||||
color:$main-color;
|
||||
border-color: $main-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
.title {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
font-size: 20px;
|
||||
text-align: center;
|
||||
line-height: 40px;
|
||||
font-weight: 600;
|
||||
color: white;
|
||||
background: $main-color;
|
||||
|
||||
.break-btn {
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
right: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 100%;
|
||||
height: calc(100% - 40px);
|
||||
padding: 20px 50px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.common-box {
|
||||
width: 30%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-evenly;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.left-box {
|
||||
@extend .common-box;
|
||||
|
||||
.label {
|
||||
background: $main-color;
|
||||
}
|
||||
}
|
||||
|
||||
.center-box {
|
||||
@extend .common-box;
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.right-box {
|
||||
@extend .common-box;
|
||||
|
||||
.label {
|
||||
background: $main-color;
|
||||
}
|
||||
}
|
||||
|
||||
.row-item {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.label {
|
||||
flex-shrink: 0;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
color: white;
|
||||
font-size: 18px;
|
||||
line-height: 40px;
|
||||
text-align: center;
|
||||
border-radius: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.info-box, .row-item .value {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&.is-total {
|
||||
.info-box, .row-item .value {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.label {
|
||||
width: calc(50% - 10px);
|
||||
}
|
||||
|
||||
.value {
|
||||
width: 50%;
|
||||
height: 40px;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
text-align: center;
|
||||
border-radius: 5px;
|
||||
color: $main-color;
|
||||
border-color: $main-color;
|
||||
font-size: 22px;
|
||||
line-height: 40px;
|
||||
font-weight: 600;
|
||||
|
||||
.unit {
|
||||
font-size: 16px;
|
||||
font-family: 400;
|
||||
}
|
||||
}
|
||||
|
||||
.right-box .value {
|
||||
color: $main-color;
|
||||
border-color: $main-color;
|
||||
}
|
||||
|
||||
.row-item.alarm {
|
||||
.label {
|
||||
background: red !important;
|
||||
}
|
||||
|
||||
.value {
|
||||
color: red !important;
|
||||
border-color: red !important;
|
||||
}
|
||||
}
|
||||
|
||||
.info-box {
|
||||
width: 100%;
|
||||
|
||||
.row-item {
|
||||
padding: 10px 0;
|
||||
height: 40px;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
|
||||
.label {
|
||||
width: 70px;
|
||||
height: 20px;
|
||||
background: transparent;
|
||||
color: $main-color;
|
||||
font-size: 16px;
|
||||
line-height: 20px;
|
||||
font-weight: 600;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.input-value {
|
||||
width: 100%;
|
||||
height: 21px;
|
||||
line-height: 20px;
|
||||
font-size: 16px;
|
||||
color: $main-color;
|
||||
border-bottom: 1px solid $border2-color;
|
||||
}
|
||||
|
||||
.tag-value {
|
||||
margin-left: 30px;
|
||||
padding: 0 20px;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
font-size: 18px;
|
||||
color: white;
|
||||
font-weight: 600;
|
||||
background: $border2-color;
|
||||
border-radius: 8px;
|
||||
|
||||
&.normal {
|
||||
background: $main-color;
|
||||
}
|
||||
|
||||
&.alarm {
|
||||
background: red;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.mini {
|
||||
padding: 20px;
|
||||
|
||||
.left-box {
|
||||
width: 240px;
|
||||
}
|
||||
|
||||
.center-box {
|
||||
width: calc(100% - 250px);
|
||||
}
|
||||
|
||||
&.is-total {
|
||||
.left-box {
|
||||
.info-box {
|
||||
display: block;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.row-item.yellow {
|
||||
.label {
|
||||
background: $main-color;
|
||||
}
|
||||
|
||||
.value {
|
||||
color: $main-color;
|
||||
border-color: $main-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,11 +1,5 @@
|
|||
<template>
|
||||
<div class="remote-manage-page">
|
||||
<button @click="getSurgeryData">123</button>
|
||||
<button @click="disconnectSurgeryData">断开</button>
|
||||
<button @click="sendMsg">发送消息</button>
|
||||
<button @click="closeChat">关闭消息</button>
|
||||
<button @click="addMedicine">给药</button>
|
||||
<button @click="closeAddMedicineWS">关闭给药</button>
|
||||
<div class="header-box">
|
||||
<div class="thumbnail" @click="viewThumbnail">
|
||||
<el-icon>
|
||||
|
@ -14,9 +8,9 @@
|
|||
<span>缩略图</span>
|
||||
</div>
|
||||
<div class="task-btn-item" v-for="(item, index) in remoteTask" :key="'task-' + index"
|
||||
:class="{ 'connecting': item.patientName || item.patientCode, 'alarm': item.dataAlarm }"
|
||||
@click="editTask(item, index)" @dblclick="toRemoteControl(item, index)">
|
||||
<span>{{ item.title || ('新建任务' + (index + 1)) }}</span>
|
||||
:class="{ 'connecting': item.patient || item.patientId, 'alarm': item.isException }"
|
||||
@click="editTask(item)" @dblclick="toRemoteControl(item)">
|
||||
<span>{{ item.taskName || ('新建任务' + (index + 1)) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-box">
|
||||
|
@ -32,268 +26,72 @@
|
|||
</template>
|
||||
|
||||
<script lang='ts' setup>
|
||||
import {ref} from 'vue'
|
||||
import {onMounted, ref} from 'vue'
|
||||
import {useRouter} from 'vue-router'
|
||||
import {useRemoteStore} from '@/stores/remote-info-store'
|
||||
import type {RemoteItem} from '@/utils/public-interface'
|
||||
import RemoteDialog from './part/remote-dialog.vue'
|
||||
import RemotePart from './part/remote-part.vue'
|
||||
import MessagePart from './part/message-part.vue'
|
||||
import {Session} from "@/utils/storage";
|
||||
import {useRemoteWsStore} from "@/stores/remote-ws-store";
|
||||
|
||||
const router = useRouter()
|
||||
const remoteStore = useRemoteStore()
|
||||
|
||||
const remotePartRef = ref()
|
||||
const messagePartRef = ref()
|
||||
const remoteDialogRef = ref()
|
||||
const remoteTask = ref([] as Array<RemoteItem>)
|
||||
const remoteTask = ref([] as Array<any>)
|
||||
const remoteWsStore = useRemoteWsStore();
|
||||
|
||||
initRemoteTask()
|
||||
|
||||
function resetRemoteTaskItem(e: RemoteItem) {
|
||||
Object.assign(remoteTask.value[e.index], {
|
||||
isRemote: false,
|
||||
dataAlarm: false,
|
||||
title: '',
|
||||
serverUser: '',
|
||||
patientName: '',
|
||||
patientCode: '',
|
||||
index: e.index,
|
||||
})
|
||||
}
|
||||
onMounted(() => {
|
||||
initRemoteTask()
|
||||
})
|
||||
|
||||
function initRemoteTask() {
|
||||
remoteTask.value = remoteStore.remoteTasks
|
||||
if (remoteTask.value.length < 1) {
|
||||
while (remoteTask.value.length < 10) {
|
||||
const obj = {
|
||||
isRemote: false, // 连接状态
|
||||
dataAlarm: false, // 异常状态
|
||||
title: '',
|
||||
serverUser: '', // 服务器用户名
|
||||
patientName: '', // 病人名称
|
||||
patientCode: '', // 病人身份证
|
||||
index: remoteTask.value.length,
|
||||
log: []
|
||||
}
|
||||
if (remoteTask.value.length < 3) {
|
||||
obj.isRemote = true
|
||||
obj.title = '远程控制' + (remoteTask.value.length + 1)
|
||||
obj.serverUser = 'root'
|
||||
obj.patientName = '测试' + (remoteTask.value.length + 1)
|
||||
}
|
||||
if (remoteTask.value.length == 1) obj.dataAlarm = true
|
||||
remoteTask.value.push(obj)
|
||||
}
|
||||
remoteStore.setRemoteTasks(remoteTask.value)
|
||||
if (!remoteStore.currentRemote.index) {
|
||||
remoteStore.$patch({currentRemote: remoteTask.value[0]})
|
||||
}
|
||||
}
|
||||
remoteTask.value = remoteWsStore.initRemoteTask()
|
||||
remotePartRef.value.showData(remoteWsStore.currentTaskIndex);
|
||||
}
|
||||
|
||||
const viewThumbnail = () => {
|
||||
router.push({
|
||||
path: '/remote-manage/remote-thumbnail'
|
||||
path: '/remote-manage/remote-thumbnail',
|
||||
query: {
|
||||
}
|
||||
})
|
||||
}
|
||||
// 打开任务连接弹窗
|
||||
const editTask = (item: RemoteItem, index: number) => {
|
||||
item.index = index
|
||||
const editTask = (item: any) => {
|
||||
// 如果当前任务是已连接状态则直接渲染content 否则打开弹窗
|
||||
if (item.isRemote) {
|
||||
confirmRemote(item)
|
||||
remotePartRef.value.showData(item.index)
|
||||
} else {
|
||||
remoteDialogRef.value.open(item)
|
||||
remoteDialogRef.value.open(item.index)
|
||||
}
|
||||
}
|
||||
// 跳转到远程控制
|
||||
const toRemoteControl = (item: RemoteItem, index: number) => {
|
||||
const toRemoteControl = (item: any) => {
|
||||
// 如果当前任务是已连接状态则跳转,否则打开弹窗
|
||||
if (item.isRemote) {
|
||||
router.push('/remote-manage/remote-control')
|
||||
} else {
|
||||
editTask(item, index)
|
||||
remoteDialogRef.value.open(item.index)
|
||||
}
|
||||
}
|
||||
// 连接成功
|
||||
const confirmRemote = (e: RemoteItem) => {
|
||||
messagePartRef.value.setData({
|
||||
time: new Date(),
|
||||
title: e.title,
|
||||
state: '连接成功'
|
||||
}, e.index)
|
||||
remoteTask.value[e.index] = e // 状态设置为可连接
|
||||
remotePartRef.value.initData(e)
|
||||
console.log(e);
|
||||
getSurgeryData();
|
||||
const confirmRemote = () => {
|
||||
messagePartRef.value.scrollToBottom()
|
||||
// 状态设置为可连接
|
||||
remotePartRef.value.initData()
|
||||
}
|
||||
// 连接失败
|
||||
const errorRemote = (e: RemoteItem) => {
|
||||
messagePartRef.value.setData({
|
||||
time: new Date(),
|
||||
title: e.title,
|
||||
state: '连接失败'
|
||||
}, e.index)
|
||||
const errorRemote = () => {
|
||||
messagePartRef.value.scrollToBottom()
|
||||
}
|
||||
// 断开连接
|
||||
const breakRemote = (e: RemoteItem) => {
|
||||
resetRemoteTaskItem(e)
|
||||
remotePartRef.value.initData()
|
||||
messagePartRef.value.setData({
|
||||
time: new Date(),
|
||||
title: e.title,
|
||||
state: '断开连接'
|
||||
}, e.index)
|
||||
// disconnectSurgeryData("", "1")
|
||||
const breakRemote = () => {
|
||||
messagePartRef.value.scrollToBottom()
|
||||
}
|
||||
const addLogAfter = () => {
|
||||
messagePartRef.value.scrollToBottom()
|
||||
}
|
||||
|
||||
const ws = new WebSocket("ws://localhost:5173/socket.io/admin/rax/vitalSignsMedicine?token=" + Session.getToken());
|
||||
|
||||
function getSurgeryData() {
|
||||
const params = {
|
||||
patientName: "1111111",
|
||||
idNum: "123567890",
|
||||
date: "20230505"
|
||||
}
|
||||
ws.send(JSON.stringify(params))
|
||||
}
|
||||
|
||||
function disconnectSurgeryData() {
|
||||
ws.close();
|
||||
}
|
||||
|
||||
ws.onmessage = function (e) {
|
||||
console.log(e)
|
||||
}
|
||||
|
||||
const chatws = new WebSocket("ws://localhost:5173/socket.io/admin/rax/chatRoom?token=" + Session.getToken());
|
||||
|
||||
function sendMsg() {
|
||||
const params = {
|
||||
patientName: "1111111",
|
||||
idNum: "123567890",
|
||||
date: "20230505",
|
||||
msg: "测试消息"
|
||||
}
|
||||
chatws.send(JSON.stringify(params))
|
||||
}
|
||||
|
||||
chatws.onmessage = function (e) {
|
||||
console.log(e)
|
||||
}
|
||||
|
||||
function closeChat() {
|
||||
chatws.close()
|
||||
}
|
||||
|
||||
const addMedicineWS = new WebSocket("ws://localhost:5173/socket.io/admin/rax/addMedicine?token=" + Session.getToken())
|
||||
|
||||
function addMedicine() {
|
||||
const params = {
|
||||
patientName: "1111111",
|
||||
idNum: "123567890",
|
||||
date: "20230505",
|
||||
flag: "2",
|
||||
medicine: "丙泊酚",
|
||||
value: "1"
|
||||
}
|
||||
addMedicineWS.send(JSON.stringify(params))
|
||||
}
|
||||
|
||||
addMedicineWS.onmessage = function (e) {
|
||||
console.log(e)
|
||||
}
|
||||
|
||||
function closeAddMedicineWS() {
|
||||
addMedicineWS.close()
|
||||
}
|
||||
|
||||
/*const surgeryClient = new Client({
|
||||
brokerURL: 'ws://localhost:5173/socket.io/admin/rax/SurgeryData',
|
||||
connectHeaders: {
|
||||
token: Session.get('token')
|
||||
},
|
||||
reconnectDelay: 5000,
|
||||
heartbeatIncoming: 60000,
|
||||
heartbeatOutgoing: 60000
|
||||
})
|
||||
surgeryClient.activate()
|
||||
|
||||
surgeryClient.onConnect = (data: any) => {
|
||||
console.log("connect", data);
|
||||
}
|
||||
|
||||
surgeryClient.onWebSocketError = (error) => {
|
||||
console.log('Error with websocket', error)
|
||||
};
|
||||
|
||||
surgeryClient.onStompError = (frame) => {
|
||||
console.log('Broker reported error: ' + frame.headers['message'])
|
||||
console.log('Additional details: ' + frame.body)
|
||||
};
|
||||
|
||||
function getSurgeryData(username: string, db: string) {
|
||||
console.log(username, db);
|
||||
surgeryClient.publish({
|
||||
destination: "/front/getSurgeryData",
|
||||
headers: {
|
||||
token: Session.get('token')
|
||||
},
|
||||
body: JSON.stringify({status: "start", db})
|
||||
});
|
||||
const account = "admin";
|
||||
surgeryClient.subscribe('/topic/user/' + account + ":" + db + '/surgeryData', (data: any) => {
|
||||
console.log(data);
|
||||
})
|
||||
}*/
|
||||
|
||||
/*function disconnectSurgeryData(username: string, db: string) {
|
||||
const account = "admin";
|
||||
surgeryClient.unsubscribe("/topic/user/" + account + ":" + db + "/surgeryData");
|
||||
}
|
||||
|
||||
const chatClient = new Client({
|
||||
brokerURL: 'ws://localhost:5173/socket.io/admin/rax/chat',
|
||||
connectHeaders: {
|
||||
token: Session.get('token')
|
||||
},
|
||||
reconnectDelay: 5000,
|
||||
heartbeatIncoming: 60000,
|
||||
heartbeatOutgoing: 60000
|
||||
})
|
||||
chatClient.activate()
|
||||
|
||||
const patientName = '111'
|
||||
const idNum = '111'
|
||||
const date = '20230505'
|
||||
|
||||
function sendChatMessage() {
|
||||
const message = {
|
||||
patientName: patientName,
|
||||
idNum: idNum,
|
||||
date: date,
|
||||
msg: '测试消息'
|
||||
}
|
||||
chatClient.publish({
|
||||
destination: '/front/sendMessage',
|
||||
headers: {
|
||||
token: Session.get('token')
|
||||
},
|
||||
body: JSON.stringify(message)
|
||||
})
|
||||
}*/
|
||||
|
||||
/*chatClient.onConnect = () => {
|
||||
chatClient.subscribe('/topic/user/' + patientName + idNum + date + '/chatroomMessage', (data: any) => {
|
||||
console.log(data)
|
||||
})
|
||||
}*/
|
||||
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
|
|
|
@ -1,55 +1,52 @@
|
|||
<template>
|
||||
<el-scrollbar style="width: 100%;height: 100%;">
|
||||
<div class="remote-thumbnail-page">
|
||||
<div class="remote-box row1">
|
||||
<div class="remote-item" v-for="item in remoteTask.slice(0, 4)" :key="item.title" @click="openRemote(item)">
|
||||
<RemoteItemPart :ref="'remoteItemPartRef' + item.index" :index="item.index" @addLogAfter="addLogAfter"></RemoteItemPart>
|
||||
</div>
|
||||
</div>
|
||||
<div class="remote-box row2">
|
||||
<div class="left-box">
|
||||
<div class="remote-item" v-for="item in remoteTask.slice(4)" :key="item.title" @click="openRemote(item)">
|
||||
<RemoteItemPart :ref="'remoteItemPartRef' + item.index" :index="item.index" @addLogAfter="addLogAfter"></RemoteItemPart>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right-box">
|
||||
<div class="message-title">异常信息</div>
|
||||
<div class="message-item" v-for="item in remoteTask" :key="'message-item' + item">
|
||||
<MessageItemPart ref="messageItemPartRef" :logs="item.log" :index="item.index"></MessageItemPart>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
<el-scrollbar style="width: 100%;height: 100%;">
|
||||
<div class="remote-thumbnail-page">
|
||||
<div class="remote-box row1">
|
||||
<div class="remote-item" v-for="item in remoteTask.slice(0, 4)" :key="item.title" @click="openRemote(item)">
|
||||
<RemoteItemPart :ref="'remoteItemPartRef' + item.index" :index="item.index"
|
||||
@addLogAfter="addLogAfter"></RemoteItemPart>
|
||||
</div>
|
||||
</div>
|
||||
<div class="remote-box row2">
|
||||
<div class="left-box">
|
||||
<div class="remote-item" v-for="item in remoteTask.slice(4)" :key="item.title" @click="openRemote(item)">
|
||||
<RemoteItemPart :ref="'remoteItemPartRef' + item.index" :index="item.index"
|
||||
@addLogAfter="addLogAfter"></RemoteItemPart>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right-box">
|
||||
<div class="message-title">异常信息</div>
|
||||
<div class="message-item" v-for="item in remoteTask" :key="'message-item' + item">
|
||||
<MessageItemPart ref="messageItemPartRef" :index="item.index"></MessageItemPart>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
</template>
|
||||
|
||||
<script lang='ts' setup>
|
||||
import { onMounted, reactive, ref, toRefs, watch } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { useRemoteStore } from '@/stores/remote-info-store'
|
||||
import type { RemoteItem } from '@/utils/public-interface'
|
||||
import RemoteItemPart from './part/remote-item-part.vue'
|
||||
import MessageItemPart from './part/message-item-part.vue'
|
||||
import {onMounted, ref} from 'vue';
|
||||
import {useRoute, useRouter} from 'vue-router';
|
||||
import RemoteItemPart from './part/remote-item-part.vue';
|
||||
import MessageItemPart from './part/message-item-part.vue';
|
||||
import {useRemoteWsStore} from "@/stores/remote-ws-store";
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const messageItemPartRef = ref();
|
||||
const remoteTask = ref([] as any);
|
||||
const remoteWsStore = useRemoteWsStore();
|
||||
|
||||
const messageItemPartRef = ref()
|
||||
const remoteTask = ref([] as Array<RemoteItem>)
|
||||
|
||||
remoteTask.value = useRemoteStore().getRemoteTasks()
|
||||
|
||||
// 路由初始化后执行
|
||||
router.isReady().then(() => {
|
||||
console.log(route)
|
||||
onMounted(() => {
|
||||
remoteTask.value = remoteWsStore.remoteTasks;
|
||||
})
|
||||
|
||||
const openRemote = (params: RemoteItem) => {
|
||||
useRemoteStore().setCurrentRemote(params)
|
||||
router.push('/remote-manage/remote-manage')
|
||||
const openRemote = (params: any) => {
|
||||
router.push('/remote-manage/remote-manage');
|
||||
}
|
||||
const addLogAfter = (index: number) => {
|
||||
messageItemPartRef.value[index].scrollToBottom()
|
||||
messageItemPartRef.value[index].scrollToBottom()
|
||||
}
|
||||
|
||||
</script>
|
||||
|
|
Loading…
Reference in New Issue
Block a user