update 添加银川大屏

This commit is contained in:
zk
2024-05-16 15:51:02 +08:00
parent 1c908b0615
commit adca7ae65e
8 changed files with 620 additions and 8 deletions
+8 -6
View File
@@ -19,21 +19,23 @@ export const caching = {
PAGE2_RIGHT2: 'PAGE2_RIGHT2',
//心血管监测-预警
PAGE2_RIGHT3: 'PAGE2_RIGHT3',
// 一线医疗点每日工作动态
WORK_DAILY: 'WORK_DAILY',
//员工队伍健康状况
TEAM_HEALTH: 'TEAM_HEALTH',
};
export function useSession() {
function getSession(key: string) {
return localStorage.getItem(key)
return localStorage.getItem(key);
}
function setSession(key: string, value: any) {
localStorage.setItem(key, value)
localStorage.setItem(key, value);
}
return {
getSession,
setSession
}
setSession,
};
}
+8 -1
View File
@@ -22,6 +22,14 @@ const routes: Array<RouteRecordRaw> = [
},
component: () => import('/@/views/index.vue'),
},
{
path: '/yinChuanHome',
name: 'yinChuanHome',
meta: {
title: '副屏',
},
component: () => import('/@/views/yinChuan/yinChuan.vue'),
},
{
path: '/secondScreen',
name: 'secondScreen',
@@ -37,5 +45,4 @@ const router: Router = createRouter({
routes: [...routes],
});
export default router;
+43
View File
@@ -0,0 +1,43 @@
const xian = {
dataType: '',
};
export enum DataType {
xian = '1',
yinChuan = '2',
}
export enum SexType {
male = '2', //男
female = '1', //女
all = '0', //全部
}
export const sexTypeList = [
{
label: '男',
value: SexType.male,
},
{
label: '女',
value: SexType.female,
},
{
label: '全部',
value: SexType.all,
},
];
interface Settings {
dataType: string;
orgCode?: string;
}
export function getSettings(type: string) {
if (type == DataType.xian) {
return { dataType: '1', orgCode: '' } as Settings;
}
if (type == DataType.yinChuan) {
return { dataType: '2', orgCode: 'A01A59' } as Settings;
}
}
@@ -0,0 +1,78 @@
<template>
<Dialog :openVis="visible" width="50%" title="健康终端报警列表" @close="closeDialog" :maskClosable="false">
<template #container>
<BasicTable class="table-container" :columns="columns" :api="getPhoneList" :apiParams="formState"></BasicTable>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import Dialog from '/@/components/dialog/Dialog.vue';
import { useDialog } from '/@/views/components/dialogHooks.ts';
import BasicTable from '/@/components/secondaryScreen/secondMap/components/basicTable/BasicTable.vue';
import { SexType, sexTypeList } from '/@/utils/settings.ts';
import { getPhoneList } from '/@/views/yinChuan/yinChuan.api.ts';
const props = defineProps({
record: Object,
title: String,
useForm: Boolean,
labelCol: Object,
wrapperCol: Object,
setting: Object,
phoneType: String,
});
const columns = [
{
title: '姓名',
dataIndex: 'name',
key: 'name',
},
{
title: '二级单位',
dataIndex: 'department',
key: 'department',
},
{
title: '联系电话',
dataIndex: 'sex',
key: 'sex',
},
{
title: '异常事件',
dataIndex: 'time',
key: 'time',
},
{
title: '异常值',
dataIndex: 'time',
key: 'time',
},
{
title: '发生时间',
dataIndex: 'time',
key: 'time',
},
{
title: '发生地点',
dataIndex: 'time',
key: 'time',
},
];
const formState = ref({
sex: SexType.all,
dataType: props.setting.dataType,
phoneType: props.phoneType,
});
const { visible, title, closeDialog, openDialog } = useDialog({ title: props.title });
defineExpose({
openDialog,
});
</script>
<style scoped lang="less">
.table-container {
margin: 0 10px;
}
</style>
@@ -0,0 +1,90 @@
<template>
<div>
<public-title title="一线医疗点每日工作动态" />
<div class="inner">
<div class="trends-item" v-for="(item, k) in trendsData" :key="k">
<div class="trends-title-con">
<span class="icon-medical"></span>
<span class="trends-item-title">{{ item.name }}</span>
</div>
<div class="trends-item-span-box">
<span class="trends-item-span">高风险干预{{ item?.high }}</span>
<span class="trends-item-span">慢病管理{{ item?.slow }}</span>
<span class="trends-item-span">巡诊{{ item?.tour }}</span>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import PublicTitle from '/@/components/publicTitle.vue';
import { onMounted, ref } from 'vue';
import { getWorkDaily } from '/@/views/yinChuan/yinChuan.api.ts';
import { caching, useSession } from '/@/hooks/autoRefresh/caching.ts';
const props = defineProps({});
const { setSession, getSession } = useSession();
const { WORK_DAILY } = caching;
const trendsData = ref([]);
async function getTrendsData() {
try {
const { code, result } = await getWorkDaily({});
if (code != 200) {
return;
}
setSession(WORK_DAILY, result);
trendsData.value = result;
} catch {
trendsData.value = JSON.parse(getSession(WORK_DAILY));
}
}
onMounted(() => {
getTrendsData();
});
</script>
<style scoped lang="less">
.inner {
height: calc(100% - 40px);
overflow: auto;
.trends-item {
font-size: 16px;
padding: 10px 20px;
.trends-title-con {
display: flex;
align-items: center;
}
.icon-medical {
display: inline-block;
width: 26px;
height: 26px;
background: url('/@/assets/images/medical-center.png') no-repeat;
background-size: 100% 100%;
}
.trends-item-title {
margin-left: 8px;
font-size: 18px;
color: #fff;
}
.trends-item-span-box {
display: flex;
flex-wrap: wrap;
}
.trends-item-span {
flex: 1;
color: #ededed;
}
.trends-item-span:first-child {
margin-left: 0;
}
}
}
</style>
@@ -0,0 +1,104 @@
<template>
<div>
<public-title title="员工队伍健康状况">
<template #right>
<!-- <span class="right-text" @click="viewDetail">更多</span>-->
</template>
</public-title>
<div class="inner">
<div v-for="item in list" :key="item.label" class="health-item">
<span>{{ item.label }}</span>
<span>{{ item.value }}</span>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { onMounted, ref } from 'vue';
import PublicTitle from '/@/components/publicTitle.vue';
import { caching, useSession } from '/@/hooks/autoRefresh/caching.ts';
import { getTeamHealth } from '/@/views/yinChuan/yinChuan.api.ts';
const { setSession, getSession } = useSession();
const { TEAM_HEALTH } = caching;
const list = ref([
{
label: '在册总人数',
value: '',
key: 'total',
},
{
label: '患重大疾病人数',
value: '',
key: 'bigIll',
},
{
label: '健康高风险人数',
value: '',
key: 'highRisk',
},
{
label: '患慢性病人数',
value: '',
key: 'slowIll',
},
{
label: '健康指标异常人数',
value: '',
key: 'focusErr',
},
{
label: '健康人数',
value: '',
key: 'health',
},
]);
function setList(data = {}) {
list.value.forEach((item) => {
const { key } = item;
item.value = data[key];
});
}
async function viewDetail() {
try {
const { code, result } = await getTeamHealth({});
if (code != 200) {
return;
}
setList(result);
setSession(TEAM_HEALTH, result);
} catch {
let data = JSON.parse(getSession(TEAM_HEALTH));
setList(data);
}
}
onMounted(() => {
viewDetail();
});
</script>
<style scoped lang="less">
.inner {
height: calc(100% - 40px);
display: flex;
flex-direction: column;
padding: 0 10px;
.right-text {
font-weight: 100;
cursor: pointer;
margin-right: 3px;
}
.health-item {
flex: 1;
color: #fff;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 16px;
}
}
</style>
+14
View File
@@ -0,0 +1,14 @@
import { get } from '/@/api/request';
export enum Api {
phoneList = '/health-emergency/emergency/tblUserHelp/phoneList',
getWorkDaily = '/health-emergency/emergency/ycLargeScreen/medicalCenter',
getTeamHealth = '/health-emergency/emergency/ycLargeScreen/userHealthCenter',
}
// 呼入电话、受理电话
export const getPhoneList = (params: any) => get(Api.phoneList, params);
//一线医疗点每日工作动态
export const getWorkDaily = (params: any) => get(Api.getWorkDaily, params);
//员工队伍健康状况
export const getTeamHealth = (params: any) => get(Api.getTeamHealth, params);
+274
View File
@@ -0,0 +1,274 @@
<template>
<div class="outer">
<div class="title-d">
<div class="title-d-left">
{{ dayTimeO }}
</div>
<div class="title-d-middle"> 银川应急就医服务中心</div>
<div class="title-d-right"> 累计运行时间{{ dayTimeT }}</div>
</div>
<div class="body-d">
<div class="yichuan-body-left">
<!--服务详情数据-->
<ServiceDetails :setting="setting" class="service-details" :refreshState="refreshState" @handleClick="handlePhoneDialog" />
<!--一线医疗点每日工作动态-->
<DailyWorkTrends class="daily-work-trends" :refreshState="refreshState" />
</div>
<div class="body-d-middle">
<china-map />
</div>
<div class="body-d-right">
<!--健康终端报警-->
<TerminalAlarm :setting="setting" :refreshState="refreshState" @emit-view-detail="handleEmployeeDialog" />
<!--员工队伍健康状况-->
<EmployeeHealth :refreshState="refreshState" />
<!--体检数据-->
<PhysicalExaminationData :setting="setting" :refreshState="refreshState" />
</div>
</div>
<div class="bottom-d"></div>
<EmployeeDialog ref="employeeDialogRef" :record="socketData" />
<EmergencyDialog ref="emergencyDialogRef" :record="emergencyData" />
<PhoneDialog ref="phoneDialogRef" :title="phoneDialogTitle" :useForm="true" :setting="setting" :phoneType="phoneType" />
<TerminalAlarmDialog ref="terminalAlarmDialogRef" :setting="setting" />
</div>
</template>
<script setup lang="ts">
import { onUnmounted, ref, watch, nextTick, onMounted } from 'vue';
import ServiceDetails from '/@/components/body-d-left/oneL.vue';
import DailyWorkTrends from '/@/views/yinChuan/componetns/dailyWorkTrends/dailyWorkTrends.vue';
import PhysicalExaminationData from '/@/components/body-d-left/threeL.vue';
import TerminalAlarm from '/@/components/body-d-right/oneR.vue';
import EmployeeHealth from '/@/views/yinChuan/componetns/employeeHealth/employeeHealth.vue';
import ChinaMap from '/@/components/chinaMap/chinaMap.vue';
import EmployeeDialog from '/@/views/components/employeeDialog.vue';
import EmergencyDialog from '/@/views/components/emergencyDialog.vue';
import PhoneDialog from '/@/views/components/phoneDialog/phoneDialog.vue';
import TerminalAlarmDialog from '/@/views/yinChuan/componetns/TerminalAlarmDialog/TerminalAlarmDialog.vue';
import { useTopTime } from '/@/utils/utils.ts';
import { basicPath, emergencyPath, useSocket } from '/@/utils/socket.ts';
import { useRefresh } from '/@/hooks/autoRefresh';
import { DEFAULT_TIME } from '/@/hooks/autoRefresh/pageRefreshTime.ts';
// import { useUserStore } from '/@/store/modules/user.ts';
import { useRoute } from 'vue-router';
import { DataType, getSettings } from '/@/utils/settings.ts';
const route = useRoute();
const setting = getSettings(DataType.yinChuan);
onMounted(() => {
// const userStore = useUserStore();
// let data = JSON.parse(route.query.data as string);
// if (data.token) {
// localStorage.setItem('token', data.token);
// userStore.setToken(data.token);
// userStore.setUserInfo(data.userInfo);
// console.log(useUserStore);
// }
});
const { refreshState } = useRefresh(DEFAULT_TIME);
const dayTimeO = ref();
const dayTimeT = ref();
const interval = ref(1);
function init() {
getTime();
interval.value = setInterval(() => {
getTime();
}, 1000);
}
function getTime() {
const { timeLeft, timeRight } = useTopTime();
dayTimeO.value = timeLeft;
dayTimeT.value = timeRight;
}
onUnmounted(() => {
clearInterval(interval.value);
});
init();
// 健康监测工具报警
const { socketData, setSocketData, closeSocket } = useSocket(basicPath);
const employeeDialogRef = ref();
watch(socketData, (nVal) => {
if (nVal) {
nextTick(() => {
setSocketData(nVal);
employeeDialogRef.value.openDialog();
});
}
});
//应急求助
const { socketData: emergencyData, setSocketData: setEmergencyData, closeSocket: closeSocket2 } = useSocket(emergencyPath);
const emergencyDialogRef = ref();
watch(emergencyData, (nVal) => {
if (nVal) {
nextTick(() => {
setEmergencyData(nVal);
emergencyDialogRef.value.openDialog;
});
}
});
onUnmounted(() => {
// 监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function () {
closeSocket();
closeSocket2();
};
clearInterval(interval.value);
});
const phoneDialogTitle = ref('呼入电话');
const phoneDialogRef = ref();
//0:处置 1:处理 2:呼入 3:全部
const phoneType = ref('');
//呼入电话、受理电话弹窗
function handlePhoneDialog(item) {
const { name, key } = item;
//呼入电话
if (key == 'gross') {
phoneType.value = '2';
}
//受理电话
if (key == 'alerdyreceive') {
phoneType.value = '1';
}
nextTick(() => {
phoneDialogTitle.value = name;
phoneDialogRef.value.openDialog();
});
}
const terminalAlarmDialogRef = ref();
//终端预警列表弹窗
function handleEmployeeDialog() {
terminalAlarmDialogRef.value.openDialog();
}
// function test() {
// let nVal = {
// watchNo: 'CRFTQ22C03000080',
// eventType: 'heart_rate',
// bindUserId: 'fd358031299d4816b5d304fd818ecc73',
// createBy: null,
// createDate: null,
// dataValue: '999',
// address:
// '一段文字一段文字一段文字一段文字一段文字一段文字一段文字一段文字一段文字一段文字一段文字一段文字一段文字一段文字一段文字一段文字一段文字一段文字一段文字一段文字一段文字一段文字一段文字一段文字一段文字一段文字一段文字一段文字一段文字',
// lon: 108.6666,
// lat: 29.8888,
// dataDate: '2023-12-07',
// warnTime: '2023-12-07',
// gpsErrorMsg: '',
// lonGd: 108.67084314886117,
// latGd: 29.88607705672868,
// addressGd: null,
// sendFlag: '0',
// largeScreenFlag: '0',
// orgCode: null,
// orgName: '冯地坑采油作业区',
// realName: '王志文',
// phone: '15229020494',
// };
// nextTick(() => {
// setEmergencyData(nVal);
// emergencyDialogRef.value.openDialog();
// });
// }
</script>
<style lang="less" scoped>
.outer {
height: 100%;
box-sizing: border-box;
background: url('/@/assets/images/bg.png') no-repeat;
background-size: 100% 100%;
}
.title-d {
height: 80px;
line-height: 80px;
display: flex;
padding-bottom: 9px;
background: url('/@/assets/images/top-title.png') no-repeat;
background-size: 100% 100%;
.title-d-left,
.title-d-middle,
.title-d-right {
font-size: 27px;
color: #ffffff;
line-height: 60px;
text-align: center;
}
> :nth-child(1) {
width: 29%;
}
> :nth-child(2) {
width: 42%;
font-size: 40px;
font-weight: bold;
}
> :nth-child(3) {
width: 29%;
}
}
.body-d {
display: flex;
height: calc(100% - 120px);
padding-top: 10px;
> :nth-child(1) {
width: 24%;
}
> :nth-child(2) {
width: 52%;
}
> :nth-child(3) {
width: 24%;
}
//.yichuan-body-left,
//.body-d-right {
// text-align: center;
//}
.yichuan-body-left {
.service-details {
height: 33%;
}
.daily-work-trends {
height: 67%;
}
}
.body-d-right {
> :nth-child(n) {
width: 100%;
height: calc(100% / 3);
padding: 10px;
}
}
.body-d-middle {
display: flex;
flex-direction: column;
}
}
.bottom-d {
height: 40px;
background: url('/@/assets/images/bottom-b.png') no-repeat;
background-size: 100% 100%;
}
</style>