update
1.新需求2025.9.19新需求: 去掉"健康监测"副屏, 修改后健康终端报警点击查看详情弹出告警记录分页列表; 去掉【体检人数统计】【体检数据】【健康打卡数据】,增加【心血管监测】模块功能,【心血管监测】功能将原心血管监测大屏上的内容整理并移动到急救服务平台大屏中; 员工求助时,地图中推荐两个医院、两个健康小屋、两个AED坐标信息,并按距离排序,体现距离远近顺序; 地图中油田医院、健康小屋等各个图例,显示总数信息; 救护车坐标信息维护,并在大屏上标记; 右上角"增加【救助信息】板块, 当出现应急弹窗后或从今日应急选中应急事件 , 该板块需展示应急事件的相关信息(开发中);
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
<template>
|
||||
<div class="left-pie" style="height: 100%">
|
||||
<div class="inner" ref="healthChart"></div>
|
||||
<div class="count">
|
||||
<div class="t">总人数</div>
|
||||
<div class="v" style="text-align: center">{{ userCount }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { circleRing } from '/src/views/indexSun/threeLeftNewItem/pieCharts.ts';
|
||||
import { nextTick, onMounted, ref, watch } from 'vue';
|
||||
import * as echarts from 'echarts';
|
||||
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: () => '',
|
||||
},
|
||||
data: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
color: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
tips: {
|
||||
type: String,
|
||||
default: () => '',
|
||||
},
|
||||
userCount: {
|
||||
type: Number,
|
||||
},
|
||||
themeType: {
|
||||
type: String,
|
||||
default: () => '',
|
||||
},
|
||||
});
|
||||
const healthChart = ref<HTMLElement>();
|
||||
onMounted(() => {
|
||||
init();
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.data,
|
||||
() => {
|
||||
init();
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
}
|
||||
);
|
||||
|
||||
async function init() {
|
||||
initChart(props.data, props.userCount, props.color);
|
||||
}
|
||||
|
||||
function initChart(chartData, total, color) {
|
||||
nextTick(() => {
|
||||
let myChart = echarts.init(healthChart.value);
|
||||
let options = circleRing(chartData, total, color);
|
||||
myChart.setOption(options);
|
||||
window.addEventListener('resize', () => {
|
||||
myChart.resize();
|
||||
});
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.inner {
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.inner::after {
|
||||
//content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-color: #051a2b;
|
||||
}
|
||||
|
||||
.left-pie {
|
||||
position: relative;
|
||||
padding-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.count {
|
||||
position: absolute;
|
||||
//left: 41%;
|
||||
//top: 30%;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #fff;
|
||||
font-size: 22px;
|
||||
font-weight: bold;
|
||||
z-index: 1;
|
||||
pointer-events: none;
|
||||
|
||||
> div {
|
||||
width: 80px;
|
||||
text-align: center;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.t {
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,97 @@
|
||||
// 步数
|
||||
import { visibleChartLabel } from '/@/utils/utils.ts';
|
||||
|
||||
export function screenPie(chartData) {
|
||||
const data = visibleChartLabel(chartData).map((item) => {
|
||||
// item = { ...item, label: { show: item.value > 0 }, labelLine: { show: item.value > 0 } };
|
||||
return item;
|
||||
});
|
||||
return {
|
||||
color: ['#B750BE', '#6C63F0', '#3AACFF', '#ED589D', '#FB466C'],
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
show: true,
|
||||
textStyle: {
|
||||
color: '#fff',
|
||||
},
|
||||
backgroundColor: 'rgba(50,50,50,0.7)',
|
||||
borderColor: '#1b7ef2',
|
||||
},
|
||||
series: [
|
||||
{
|
||||
type: 'pie',
|
||||
radius: ['50%', '72%'],
|
||||
center: ['50%', '50%'],
|
||||
avoidLabelOverlap: false,
|
||||
label: {
|
||||
show: true,
|
||||
position: 'outside',
|
||||
formatter: function (params: any) {
|
||||
return `${params.name}\n占比:${params.percent}%\n人次:${params.value}次`;
|
||||
},
|
||||
color: '#ffffff',
|
||||
fontSize: 14,
|
||||
},
|
||||
labelLine: {
|
||||
show: true,
|
||||
length: 2,
|
||||
length2: 30,
|
||||
minTurnAngle: 120,
|
||||
},
|
||||
data: data,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
//左侧圆
|
||||
export function circleRing(chartData, total, color) {
|
||||
const data = visibleChartLabel(chartData);
|
||||
return {
|
||||
color: color,
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
show: true,
|
||||
textStyle: {
|
||||
color: '#fff',
|
||||
},
|
||||
backgroundColor: 'rgba(50,50,50,0.7)',
|
||||
borderColor: '#1b7ef2',
|
||||
},
|
||||
series: [
|
||||
{
|
||||
type: 'pie',
|
||||
radius: ['50%', '75%'],
|
||||
center: ['50%', '50%'],
|
||||
avoidLabelOverlap: false,
|
||||
// label: {
|
||||
// show: true,
|
||||
// // position: 'inner',
|
||||
// formatter: '{d}%',
|
||||
// color: '#ffffff',
|
||||
// fontSize: 14,
|
||||
// },
|
||||
// labelLine: {
|
||||
// show: false,
|
||||
// },
|
||||
label: {
|
||||
show: true,
|
||||
position: 'outside',
|
||||
// formatter: '{a}{d}%\n{c}人次',
|
||||
formatter: function (params: any) {
|
||||
return `${params.name}:${params.percent}%\n${params.value}次`;
|
||||
},
|
||||
color: '#ffffff',
|
||||
fontSize: 14,
|
||||
},
|
||||
labelLine: {
|
||||
show: true,
|
||||
length: 2,
|
||||
length2: 30,
|
||||
minTurnAngle: 120,
|
||||
},
|
||||
data: data,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
<template>
|
||||
<div class="terminal-container self">
|
||||
<div class="inner">
|
||||
<div class="title">
|
||||
<span class="lightSleep">平均睡眠 {{ nums.avg || 0 }} 深睡 {{ nums.avgLong || 0 }} 浅睡 {{ nums.avgShort || 0 }}</span>
|
||||
</div>
|
||||
<div class="sleepChart" ref="sleepChart"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import * as echarts from 'echarts';
|
||||
import { ref, watch } from 'vue';
|
||||
import { formatStr, sleepCharts } from '/@/components/secondaryScreen/screen-right/screenRightHooks';
|
||||
import { getSleep } from '/@/components/secondaryScreen/commonApi.ts';
|
||||
import { useSession, caching } from '/@/hooks/autoRefresh/caching.ts';
|
||||
|
||||
const { setSession, getSession } = useSession();
|
||||
const { PAGE2_RIGHT1 } = caching;
|
||||
const props = defineProps({
|
||||
orgCode: String,
|
||||
type: String,
|
||||
themeType: String,
|
||||
});
|
||||
const sleepChart = ref<HTMLElement>();
|
||||
watch(
|
||||
props,
|
||||
() => {
|
||||
init();
|
||||
},
|
||||
{ immediate: true, deep: true }
|
||||
);
|
||||
const nums = ref({
|
||||
avgShort: '',
|
||||
avgLong: '',
|
||||
avg: '',
|
||||
});
|
||||
|
||||
async function init() {
|
||||
try {
|
||||
const params = {
|
||||
orgCode: props.orgCode,
|
||||
type: props.type,
|
||||
};
|
||||
const { code, result } = await getSleep(params);
|
||||
if (code == 200 && result.length > 0) {
|
||||
setSession(PAGE2_RIGHT1, JSON.stringify(result));
|
||||
setValue(result);
|
||||
}
|
||||
} catch {
|
||||
const result = JSON.parse(getSession(PAGE2_RIGHT1));
|
||||
setValue(result);
|
||||
}
|
||||
}
|
||||
|
||||
function setValue(result: any) {
|
||||
let time = result?.map((item: any) => item.dataDate);
|
||||
let short = result?.map((item: any) => item.avgShortDuration);
|
||||
let long = result?.map((item: any) => item.avgLongDuration);
|
||||
let awake = result?.map((item: any) => item.awakeDuration);
|
||||
let avg = result?.map((item: any) => item.averageDuration);
|
||||
initChart({ time, short, long, awake, type: props.type });
|
||||
const len = time.length;
|
||||
if (!len > 0) {
|
||||
return;
|
||||
}
|
||||
nums.value = {
|
||||
avgShort: formatStr({ list: short, len }),
|
||||
avgLong: formatStr({ list: long, len }),
|
||||
avg: formatStr({ list: avg, len }), //平均
|
||||
};
|
||||
}
|
||||
|
||||
function initChart({ time, short, long, awake, type }) {
|
||||
let myChart = echarts.init(sleepChart.value);
|
||||
let options = sleepCharts({ time, short, long, awake, type });
|
||||
myChart.setOption(options);
|
||||
window.addEventListener('resize', () => {
|
||||
myChart.resize();
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.terminal-container.self {
|
||||
position: relative;
|
||||
padding-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.inner {
|
||||
height: 100%;
|
||||
|
||||
.title {
|
||||
color: #cfcfcf;
|
||||
text-align: left;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
|
||||
.count {
|
||||
font-size: 28px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.lightSleep {
|
||||
padding: 3px 0 3px 2%;
|
||||
}
|
||||
}
|
||||
|
||||
.sleepChart {
|
||||
height: 90%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,105 @@
|
||||
<template>
|
||||
<div class="pie-container self">
|
||||
<div class="inner" ref="healthChart"></div>
|
||||
<div class="count">
|
||||
<div class="t">总人数</div>
|
||||
<div class="v">{{ total }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue';
|
||||
import * as echarts from 'echarts';
|
||||
import { useStep } from '/@/components/secondaryScreen/screen-right/screenRightHooks.ts';
|
||||
import { screenPie } from '/@/views/indexSun/threeLeftNewItem/pieCharts.ts';
|
||||
import { getStepNew } from '/@/components/secondaryScreen/commonApi.ts';
|
||||
import { caching, useSession } from '/@/hooks/autoRefresh/caching.ts';
|
||||
|
||||
const props = defineProps({
|
||||
orgCode: String,
|
||||
type: String,
|
||||
themeType: String,
|
||||
});
|
||||
const { setSession, getSession } = useSession();
|
||||
const { PAGE2_RIGHT2 } = caching;
|
||||
watch(
|
||||
props,
|
||||
() => {
|
||||
init();
|
||||
},
|
||||
{ immediate: true, deep: true }
|
||||
);
|
||||
const healthChart = ref<HTMLElement>();
|
||||
const { total, setStep, getStepData } = useStep();
|
||||
|
||||
async function init() {
|
||||
try {
|
||||
const params = {
|
||||
orgCode: props.orgCode,
|
||||
type: props.type,
|
||||
};
|
||||
// const { code, result } = await getStep(params);
|
||||
const { code, result } = await getStepNew(params);
|
||||
if (code == 200) {
|
||||
setValue(result);
|
||||
setSession(PAGE2_RIGHT2, JSON.stringify(result));
|
||||
}
|
||||
} catch {
|
||||
const result = JSON.parse(getSession(PAGE2_RIGHT2));
|
||||
setValue(result);
|
||||
}
|
||||
}
|
||||
|
||||
function setValue(result: any) {
|
||||
setStep(result);
|
||||
initChart(getStepData());
|
||||
}
|
||||
|
||||
function initChart(chartData: any) {
|
||||
let myChart = echarts.init(healthChart.value);
|
||||
let options = screenPie(chartData);
|
||||
myChart.setOption(options);
|
||||
window.addEventListener('resize', () => {
|
||||
myChart.resize();
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.inner {
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.pie-container.self {
|
||||
position: relative;
|
||||
padding-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.count {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #fff;
|
||||
font-size: 22px;
|
||||
font-weight: bold;
|
||||
z-index: 1;
|
||||
pointer-events: none;
|
||||
|
||||
> div {
|
||||
width: 80px;
|
||||
text-align: center;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.t {
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,129 @@
|
||||
<template>
|
||||
<item-d
|
||||
:themeType="themeType"
|
||||
:keu="spinning"
|
||||
:title="dataList[props.chooseType].title"
|
||||
:data="dataList[props.chooseType].data"
|
||||
:tips="dataList[props.chooseType].tips"
|
||||
:color="dataList[props.chooseType].color"
|
||||
:user-count="dataList[props.chooseType].userCount"
|
||||
/>
|
||||
</template>
|
||||
r
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref, watch } from 'vue';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
import { getWatchDataByOrgCodeNew } from '/@/components/secondaryScreen/commonApi.ts';
|
||||
import { useSpin } from '/@/components/body-d-left/bodyLeftHooks.ts';
|
||||
import ItemD from '/src/views/indexSun/threeLeftNewItem/item-d.vue';
|
||||
|
||||
const { spinning, setSpin } = useSpin();
|
||||
const dataList = ref([
|
||||
{
|
||||
title: '心率',
|
||||
data: [
|
||||
{ name: '正常', value: 0, key: 'normalCount' },
|
||||
{ name: '警戒', value: 0, key: 'warnCount' },
|
||||
{ name: '危险', value: 0, key: 'riskCount' },
|
||||
],
|
||||
type: '1',
|
||||
color: ['#0098FA', '#FF6648', '#FB466C'],
|
||||
tips: '正常范围60~100次/分',
|
||||
userCount: 0,
|
||||
},
|
||||
{
|
||||
title: '血氧',
|
||||
data: [
|
||||
{ name: '正常', value: 0, key: 'normalCount' },
|
||||
{ name: '警戒', value: 0, key: 'warnCount' },
|
||||
{ name: '危险', value: 0, key: 'riskCount' },
|
||||
],
|
||||
type: '2',
|
||||
color: ['#0098FA', '#FF6648', '#FB466C'],
|
||||
tips: '血氧饱和度范围95%~100%',
|
||||
userCount: 0,
|
||||
},
|
||||
{
|
||||
title: '压力',
|
||||
data: [
|
||||
{ name: '正常', value: 0, key: 'normalCount' },
|
||||
{ name: '放松', value: 0, key: 'unwindCount' },
|
||||
{ name: '中等', value: 0, key: 'warnCount' },
|
||||
{ name: '偏高', value: 0, key: 'riskCount' },
|
||||
],
|
||||
type: '3',
|
||||
color: ['#1DCC79', '#0098FA', '#0CD9B5', '#6C63F0'],
|
||||
tips: '',
|
||||
userCount: 0,
|
||||
},
|
||||
{
|
||||
title: '体温',
|
||||
data: [
|
||||
{ name: '<37.2', value: 0, key: 'normalCount' },
|
||||
{ name: '37.2-38', value: 0, key: 'warnCount' },
|
||||
{ name: '>38', value: 0, key: 'riskCount' },
|
||||
],
|
||||
type: '5',
|
||||
color: ['#0098FA', '#0CD9B5', '#3B72AD'],
|
||||
tips: '',
|
||||
userCount: 0,
|
||||
},
|
||||
]);
|
||||
|
||||
const props = defineProps({
|
||||
orgCode: String,
|
||||
type: String,
|
||||
themeType: String,
|
||||
refreshState: {
|
||||
type: Boolean,
|
||||
default: () => false,
|
||||
},
|
||||
chooseType: {
|
||||
type: Number,
|
||||
default: () => 0,
|
||||
},
|
||||
});
|
||||
onMounted(() => {
|
||||
init();
|
||||
});
|
||||
watch(props, () => {
|
||||
init();
|
||||
});
|
||||
|
||||
async function init() {
|
||||
setSpin(true);
|
||||
try {
|
||||
// const { code, result } = await getWatchDataByOrgCode(props);
|
||||
const { code, result } = await getWatchDataByOrgCodeNew(props);
|
||||
if (code == 200) {
|
||||
setValue(result);
|
||||
// setSession(PAGE2_LEFT, JSON.stringify(result));
|
||||
}
|
||||
} catch {
|
||||
// const result = JSON.parse(getSession(PAGE2_LEFT));
|
||||
// setValue(result);
|
||||
}
|
||||
}
|
||||
|
||||
function setValue(result) {
|
||||
setSpin(false);
|
||||
let data = cloneDeep(dataList.value);
|
||||
data.forEach((item) => {
|
||||
let resData = result.find((v) => v.type == item.type);
|
||||
item.userCount = resData.userCount;
|
||||
item.data = item.data.map((val) => {
|
||||
val.value = resData[val.key];
|
||||
val = { ...val, label: { show: val.value > 0 }, labelLine: { show: val.value > 0 } };
|
||||
return val;
|
||||
});
|
||||
});
|
||||
dataList.value = data;
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
init,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
Reference in New Issue
Block a user