Merge branch 'dev' of https://gitea.rk-health.com/renkang/xj-screen into dev
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 5.8 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="72.000000pt" height="176.000000pt" viewBox="0 0 72.000000 176.000000"
|
||||
preserveAspectRatio="xMidYMid meet">
|
||||
|
||||
<g transform="translate(0.000000,176.000000) scale(0.100000,-0.100000)"
|
||||
fill="#000000" stroke="none">
|
||||
<path d="M269 1715 c-107 -34 -194 -124 -225 -233 -43 -146 37 -312 185 -380
|
||||
45 -22 71 -27 131 -27 130 1 234 66 292 183 63 127 39 271 -62 372 -82 82
|
||||
-218 118 -321 85z m151 -190 c5 -38 7 -40 45 -43 22 -2 43 -6 47 -10 4 -4 8
|
||||
-51 9 -105 1 -53 5 -100 10 -103 5 -3 9 -14 9 -25 0 -18 -9 -19 -165 -20 -91
|
||||
-1 -171 -2 -177 -3 -23 -2 -21 41 1 47 19 5 21 13 21 95 0 49 3 117 6 151 l7
|
||||
62 91 -3 91 -3 5 -40z"/>
|
||||
<path d="M298 1536 c-24 -18 -23 -39 3 -62 22 -19 43 -13 63 19 8 12 5 21 -8
|
||||
36 -22 24 -34 26 -58 7z"/>
|
||||
<path d="M431 1366 c2 -102 18 -126 21 -32 1 36 2 76 2 88 1 12 -5 23 -12 26
|
||||
-10 3 -13 -15 -11 -82z"/>
|
||||
<path d="M267 1424 c-14 -15 6 -24 54 -24 36 0 49 4 47 13 -5 13 -89 23 -101
|
||||
11z"/>
|
||||
<path d="M272 1358 c5 -15 87 -18 91 -3 1 6 -20 11 -47 13 -36 2 -47 0 -44
|
||||
-10z"/>
|
||||
<path d="M283 1313 c-7 -2 -13 -9 -13 -14 0 -12 87 -12 94 0 11 17 -49 27 -81
|
||||
14z"/>
|
||||
<path d="M345 718 c-8 -308 -5 -393 15 -393 12 0 16 16 18 75 5 114 -9 560
|
||||
-18 560 -4 0 -11 -109 -15 -242z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 8.8 KiB |
@@ -1,4 +1,4 @@
|
||||
import { mapIcon1, mapIcon11, mapIcon4, mapIcon41, mapIcon5, mapIcon51, watchIconR } from '/@/components/chinaMap/chinaHooks.ts';
|
||||
import { mapIcon1, mapIcon11, mapIcon3, mapIcon4, mapIcon41, mapIcon5, mapIcon51, watchIconR } from '/@/components/chinaMap/chinaHooks.ts';
|
||||
import * as turf from '@turf/turf';
|
||||
|
||||
/**
|
||||
@@ -20,22 +20,27 @@ export function createIcon({ icon, iconSize, imageSize }) {
|
||||
* @type 1:油田医院,2:健康小屋,4:AED
|
||||
*/
|
||||
export function typeToIcon(type: string) {
|
||||
const iconSize = [28, 49];
|
||||
const imageSize = [28, 49];
|
||||
// const iconSize = [28, 49];
|
||||
// const imageSize = [28, 49];
|
||||
if (type == '1') {
|
||||
return createIcon({ icon: mapIcon1, iconSize, imageSize });
|
||||
}
|
||||
if (type == '2') {
|
||||
return createIcon({ icon: mapIcon5, iconSize, imageSize });
|
||||
// return createIcon({ icon: mapIcon1, iconSize, imageSize });
|
||||
return mapIcon1;
|
||||
}
|
||||
if (type == '3') {
|
||||
return createIcon({ icon: mapIcon5, iconSize, imageSize });
|
||||
// return createIcon({ icon: mapIcon5, iconSize, imageSize });
|
||||
return mapIcon5;
|
||||
}
|
||||
if (type == '4') {
|
||||
return createIcon({ icon: mapIcon4, iconSize, imageSize });
|
||||
// return createIcon({ icon: mapIcon4, iconSize, imageSize });
|
||||
return mapIcon4;
|
||||
}
|
||||
if (type == '5') {
|
||||
// return createIcon({ icon: mapIcon3, iconSize, imageSize });
|
||||
return mapIcon3;
|
||||
}
|
||||
if (type === 'user') {
|
||||
return createIcon({ icon: watchIconR, iconSize, imageSize });
|
||||
// return createIcon({ icon: watchIconR, iconSize, imageSize });
|
||||
return watchIconR;
|
||||
}
|
||||
}
|
||||
export function typeToIcon1(type: string) {
|
||||
@@ -44,15 +49,15 @@ export function typeToIcon1(type: string) {
|
||||
if (type == '1') {
|
||||
return createIcon({ icon: mapIcon11, iconSize, imageSize });
|
||||
}
|
||||
if (type == '2') {
|
||||
return createIcon({ icon: mapIcon51, iconSize, imageSize });
|
||||
}
|
||||
if (type == '3') {
|
||||
return createIcon({ icon: mapIcon51, iconSize, imageSize });
|
||||
}
|
||||
if (type == '4') {
|
||||
return createIcon({ icon: mapIcon41, iconSize, imageSize });
|
||||
}
|
||||
if (type == '5') {
|
||||
return createIcon({ icon: mapIcon3, iconSize, imageSize });
|
||||
}
|
||||
if (type === 'user') {
|
||||
const iconS = [36, 88];
|
||||
const imageS = [36, 88];
|
||||
|
||||
@@ -22,7 +22,6 @@ export const Map = {
|
||||
emergencyMarker: null, // 应急人员marker
|
||||
startMarker: null,
|
||||
endMarker: null,
|
||||
clearSOrE: null,
|
||||
/**
|
||||
* @desc 地图舒适化
|
||||
* @param el dom元素 id选择器
|
||||
@@ -140,6 +139,70 @@ export const Map = {
|
||||
* @param computedCenter 是否计算中心点
|
||||
*/
|
||||
createOverlay(result: ResultType[], extData?: ExtDataType, callback?: Callback, computedCenter?: boolean, iconType?: string) {
|
||||
this.removeOverlayGroup();
|
||||
this.overlayGroup = new AMap.OverlayGroup();
|
||||
// const list: any[] = getLonLat(result);
|
||||
// const center = getCenter(list);
|
||||
// const zoom = getZoom(list);
|
||||
let arr: any[] = [];
|
||||
for (let i = 0; i < result.length; i++) {
|
||||
let { type, lon, lat, longitude, latitude, lng, centerResource } = result[i];
|
||||
|
||||
if (longitude) {
|
||||
lon = longitude;
|
||||
}
|
||||
if (latitude) {
|
||||
lat = latitude;
|
||||
}
|
||||
if (lng) {
|
||||
lon = lng;
|
||||
}
|
||||
if (!lon || !lat || !type) {
|
||||
continue;
|
||||
}
|
||||
// 创建一个 Icon
|
||||
let startIcon = typeToIcon1(type);
|
||||
// 将 icon 传入 marker
|
||||
let startMarker = new AMap.Marker({
|
||||
// 点的坐标
|
||||
position: [lon, lat], // 指定点的icon,也可以是个url ,但这样就不能对图片进行设置了
|
||||
icon: startIcon, //启用点击事件 如果需要点击事件,必须开启
|
||||
clickable: true, //点额外携带的数据,用户自定义属性,支持JavaScript API任意数据类型
|
||||
offset: [-18, -32],
|
||||
maxZoom: 14,
|
||||
extData: result[i],
|
||||
label: {
|
||||
content: isFunction(extData?.content) && extData?.content(result[i]),
|
||||
},
|
||||
...extData?.extOption,
|
||||
});
|
||||
arr.push(startMarker);
|
||||
// 可以调用setExtData()设置自定义属性
|
||||
//将组 挂载到地图上
|
||||
this.overlayGroup && this.overlayGroup.setMap(this.map);
|
||||
//将需要批量控制的点放到一个组中,通过控制组,就可以操作组内所有所有覆盖物
|
||||
this.overlayGroup && this.overlayGroup.addOverlay(startMarker);
|
||||
}
|
||||
|
||||
this.overlayGroup &&
|
||||
this.overlayGroup.on('click', function (e: any) {
|
||||
//拿到点中携带的数据
|
||||
if (!isFunction(callback)) return;
|
||||
callback(e.target.getExtData());
|
||||
});
|
||||
if (computedCenter) {
|
||||
this.map && this.map.setFitView(arr, false, [50, 50, 0, 50]);
|
||||
}
|
||||
return arr;
|
||||
},
|
||||
/**
|
||||
* @desc 创建覆盖物组,用于批量处理点 (控制显隐,点击事件等)
|
||||
* @param result
|
||||
* @param extData
|
||||
* @param callback
|
||||
* @param computedCenter 是否计算中心点
|
||||
*/
|
||||
async createOverlay1(result: ResultType[], extData?: ExtDataType, callback?: Callback, computedCenter?: boolean, iconType?: string) {
|
||||
this.removeOverlayGroup();
|
||||
this.overlayGroup = new AMap.OverlayGroup();
|
||||
const list: any[] = getLonLat(result);
|
||||
@@ -148,6 +211,49 @@ export const Map = {
|
||||
if (computedCenter) {
|
||||
this.setZoomCenter(center, zoom);
|
||||
}
|
||||
function createTextOverlayIcon(originalIconUrl, text, options = {}) {
|
||||
return new Promise((resolve) => {
|
||||
const canvas = document.createElement('canvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
const img = new Image();
|
||||
|
||||
img.crossOrigin = 'anonymous';
|
||||
img.onload = function () {
|
||||
// 设置画布大小(比原图稍大以容纳文字)
|
||||
canvas.width = 28;
|
||||
canvas.height = 49 + 15; // 为文字留出空间
|
||||
|
||||
// 绘制原始图标
|
||||
ctx.drawImage(img, 0, 10, 28, 49);
|
||||
// 绘制圆形文字背景
|
||||
const textX = 22; // 文字X坐标(居右对齐)
|
||||
|
||||
const textY = 11; // 文字Y坐标
|
||||
const textWidth = ctx.measureText(text).width;
|
||||
const circleRadius = Math.max(textWidth / 2 + 1, 6); // 根据文字宽度计算半径
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.arc(textX, textY, circleRadius, 0, Math.PI * 2);
|
||||
ctx.fillStyle = 'red';
|
||||
ctx.fill();
|
||||
|
||||
// 绘制文字背景(可选)
|
||||
// ctx.fillStyle = 'red';
|
||||
// ctx.fillRect(0, 0, 28, 15);
|
||||
|
||||
// 绘制文字
|
||||
ctx.font = `bold 10px Arial`;
|
||||
ctx.textAlign = 'right';
|
||||
ctx.textBaseline = 'middle';
|
||||
ctx.fillStyle = '#ffffff';
|
||||
ctx.fillText(text, 25, 10);
|
||||
|
||||
resolve(canvas.toDataURL());
|
||||
};
|
||||
|
||||
img.src = originalIconUrl;
|
||||
});
|
||||
}
|
||||
let arr = [];
|
||||
for (let i = 0; i < result.length; i++) {
|
||||
let { type, lon, lat, longitude, latitude, lng, centerResource } = result[i];
|
||||
@@ -165,12 +271,13 @@ export const Map = {
|
||||
continue;
|
||||
}
|
||||
// 创建一个 Icon
|
||||
let startIcon = iconType === '1' ? typeToIcon(type) : typeToIcon1(type);
|
||||
const startIcon: any = typeToIcon(type);
|
||||
const newIconUrl = await createTextOverlayIcon(startIcon, i + 1 + '');
|
||||
// 将 icon 传入 marker
|
||||
let startMarker = new AMap.Marker({
|
||||
const startMarker = new AMap.Marker({
|
||||
// 点的坐标
|
||||
position: [lon, lat], // 指定点的icon,也可以是个url ,但这样就不能对图片进行设置了
|
||||
icon: startIcon, //启用点击事件 如果需要点击事件,必须开启
|
||||
icon: newIconUrl, //启用点击事件 如果需要点击事件,必须开启
|
||||
clickable: true, //点额外携带的数据,用户自定义属性,支持JavaScript API任意数据类型
|
||||
offset: [-18, -32],
|
||||
maxZoom: 14,
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
:style="{
|
||||
cursor: item.key == 'allotDeviceNum' ? 'pointer' : 'default',
|
||||
}"
|
||||
:key="`footer-list-${item.key}`"
|
||||
class="col-item nowrap"
|
||||
@click="openWatchList(item)"
|
||||
>
|
||||
@@ -35,10 +36,10 @@
|
||||
class="footer-dialog-con"
|
||||
style="--moveUp: 20px; --moveDown: -180px"
|
||||
>
|
||||
<FooterDialog :detailLeft="detailLeft" :detailRight="detailRight" @closeDialog="closeDialog"></FooterDialog>
|
||||
<FooterDialog :detailLeft="detailLeft" :detailRight="detailRight" @closeDialog="closeDialog" />
|
||||
</div>
|
||||
</div>
|
||||
<WatchListDialog ref="watchDialogRef" @close="closeWatch"></WatchListDialog>
|
||||
<WatchListDialog ref="watchDialogRef" @close="closeWatch" />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
|
||||
@@ -23,6 +23,10 @@ export const useUserStore = defineStore({
|
||||
centerId: '', //中心点id
|
||||
centerInfo: null, //应急中心信息
|
||||
count: 0,
|
||||
typeFour: 0, // aed
|
||||
typeThree: 0, // 健康小屋
|
||||
typeOne: 0, // 油田医院
|
||||
typeFive: 0, // 救护车
|
||||
}),
|
||||
getters: {
|
||||
getUserInfo(): UserInfo {
|
||||
@@ -58,6 +62,18 @@ export const useUserStore = defineStore({
|
||||
getCount(): any {
|
||||
return this.count || getAuthCache('count');
|
||||
},
|
||||
getTypeOne(): any {
|
||||
return this.typeOne || getAuthCache('typeOne');
|
||||
},
|
||||
getTypeFive(): any {
|
||||
return this.typeFive || getAuthCache('typeTwo');
|
||||
},
|
||||
getTypeThree(): any {
|
||||
return this.typeThree || getAuthCache('typeThree');
|
||||
},
|
||||
getTypeFour(): any {
|
||||
return this.typeFour || getAuthCache('typeFour');
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
setToken(info: string | undefined) {
|
||||
@@ -103,6 +119,22 @@ export const useUserStore = defineStore({
|
||||
this.count++;
|
||||
setAuthCache('count', this.count);
|
||||
},
|
||||
setTypeOne(info: number) {
|
||||
this.typeOne = info;
|
||||
setAuthCache('typeOne', this.typeOne);
|
||||
},
|
||||
setTypeFive(info: number) {
|
||||
this.typeFive = info;
|
||||
setAuthCache('typeTwo', this.typeFive);
|
||||
},
|
||||
setTypeThree(info: number) {
|
||||
this.typeThree = info;
|
||||
setAuthCache('typeThree', this.typeThree);
|
||||
},
|
||||
setTypeFour(info: number) {
|
||||
this.typeFour = info;
|
||||
setAuthCache('typeFour', this.typeFour);
|
||||
},
|
||||
/**
|
||||
* 登录事件
|
||||
*/
|
||||
|
||||
@@ -19,24 +19,26 @@
|
||||
<twoL @handle-view="handleTwoLClick" :center-id="centerId" :bKey="`two-l-${count}`" />
|
||||
</div>
|
||||
<div class="sun-body-left-three">
|
||||
<three-left-new :bKey="`three-l-n-${count}`" :center-id="centerId" />
|
||||
<!-- <threeL />-->
|
||||
<threeNewL :bKey="`three-l-${count}`" :center-id="centerId" />
|
||||
</div>
|
||||
<div class="sun-body-left-four" style="margin-bottom: 0">
|
||||
<threeR @handle-click="handleThreeRClick" :center-id="centerId" :bKey="`four-l-${count}`" />
|
||||
<!-- <threeNewL :bKey="`three-l-${count}`" :center-id="centerId" />-->
|
||||
</div>
|
||||
<!-- <div class="sun-body-left-four" style="margin-bottom: 0">-->
|
||||
<!-- <threeR @handle-click="handleThreeRClick" :center-id="centerId" :bKey="`four-l-${count}`" />-->
|
||||
<!-- </div>-->
|
||||
</div>
|
||||
<div class="sun-body-center">
|
||||
<CenterMap
|
||||
ref="centerMapRef"
|
||||
:showHospitalList="showHospitalList"
|
||||
:hospitalList="hospitalList"
|
||||
@clear-hospital-list="clearHospitalList"
|
||||
:show-rest-b="showRestB"
|
||||
@handle-detail="handleCenterMapClick"
|
||||
:map-bottom-info="mapBottom"
|
||||
:show-map-bottom="showMapBottom"
|
||||
@show-rest-b="
|
||||
() => {
|
||||
userData = {};
|
||||
showRestB = false;
|
||||
showMapBottom = false;
|
||||
}
|
||||
@@ -44,7 +46,10 @@
|
||||
/>
|
||||
</div>
|
||||
<div class="sun-body-right">
|
||||
<div class="sun-body-right-one" style="height: calc((100% - 350px) / 2 - 10px); margin-bottom: 10px">
|
||||
<div class="sun-body-right-one">
|
||||
<one-right-new :user-data="userData" @handle-view="handleOneRightView" @handle-archives="handleArchives" />
|
||||
</div>
|
||||
<div class="sun-body-right-two">
|
||||
<oneR
|
||||
@handle-view="handleOneRClick"
|
||||
@show-reset="
|
||||
@@ -55,11 +60,8 @@
|
||||
:bKey="`one-r-${count}`"
|
||||
/>
|
||||
</div>
|
||||
<div class="sun-body-right-two" style="height: calc((100% - 350px) / 2 - 10px); margin-bottom: 10px">
|
||||
<rwo-new-r :center-id="centerId" :bKey="`two-n-r-${count}`" @handle-view="handleTwoNewRClick" />
|
||||
</div>
|
||||
<div class="sun-body-right-three" style="height: 350px">
|
||||
<twoR @handle-click="handleTwoRClick" :center-id="centerId" :bKey="`two-r-${count}`" />
|
||||
<div class="sun-body-right-three">
|
||||
<two-new-r :center-id="centerId" :bKey="`two-n-r-${count}`" @handle-view="handleTwoNewRClick" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -79,16 +81,18 @@
|
||||
:firstForm="firstFormOne"
|
||||
:need-dept="needDept"
|
||||
:twoROnly="twoROnly"
|
||||
/>
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.dataIndex === 'cz'">
|
||||
<a-button type="link" @click="forHelp(record)">救助信息</a-button>
|
||||
</template>
|
||||
</template>
|
||||
</IndexModal>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
// import threeL from '/@/views/indexSun/threeL.vue';
|
||||
import OneL from '/@/views/indexSun/oneL.vue';
|
||||
import twoL from '/@/views/indexSun/twoL.vue';
|
||||
import threeNewL from '/@/views/indexSun/threeNewL.vue';
|
||||
import oneR from '/@/views/indexSun/oneR.vue';
|
||||
import twoR from '/@/views/indexSun/twoR.vue';
|
||||
import threeR from '/@/views/indexSun/threeR.vue';
|
||||
import CenterMap from '/@/views/indexSun/centerMap.vue';
|
||||
import { ServerDetailType } from '/@/components/body-d-left/bodyLeftHooks.ts';
|
||||
import {
|
||||
@@ -97,6 +101,7 @@
|
||||
columns,
|
||||
fromLists,
|
||||
infoContentSpecial,
|
||||
oneRNewColumns,
|
||||
threeRModalColumns,
|
||||
threeRModalFromList,
|
||||
towRcolumns,
|
||||
@@ -120,9 +125,12 @@
|
||||
|
||||
const { getCenterInfo, setCount } = useUserStore();
|
||||
import {
|
||||
healthArchivesApi,
|
||||
nearResourcesApi,
|
||||
oneLApi,
|
||||
roomDetailApi,
|
||||
threeRModalApi,
|
||||
todayEmergencyListApi,
|
||||
twoLModalApi,
|
||||
twoRModal1Api,
|
||||
twoRModal2Api,
|
||||
@@ -130,7 +138,9 @@
|
||||
twoRNApi,
|
||||
} from '/@/views/indexSun/indexSun.api.ts';
|
||||
import dayjs from 'dayjs';
|
||||
import RwoNewR from '/@/views/indexSun/rwoNewR.vue';
|
||||
import ThreeLeftNew from '/@/views/indexSun/threeLeftNew.vue';
|
||||
import OneRightNew from '/@/views/indexSun/oneRightNew.vue';
|
||||
import TwoNewR from '/@/views/indexSun/twoNewR.vue';
|
||||
//0:处置 1:处理 2:呼入 3:全部
|
||||
const phoneType = ref('');
|
||||
const phoneDialogTitle = ref('呼入电话');
|
||||
@@ -152,8 +162,9 @@
|
||||
const qhInterval = ref();
|
||||
const cInterval = ref();
|
||||
const initDate = ref(startTime);
|
||||
const mapBottom = ref({});
|
||||
const showMapBottom = ref(false);
|
||||
const userData = ref<object>({});
|
||||
const centerMapRef = ref();
|
||||
|
||||
onMounted(() => {
|
||||
getTime();
|
||||
@@ -185,16 +196,40 @@
|
||||
}
|
||||
);
|
||||
|
||||
async function forHelp(record: any) {
|
||||
showMapBottom.value = false;
|
||||
indexModalRef.value.closeDialog();
|
||||
record['lat'] = record?.latitude;
|
||||
record['lon'] = record?.longitude;
|
||||
if (record['lat']) {
|
||||
let list: any = [];
|
||||
const res: any = await nearResourcesApi({ longitude: record?.lon, latitude: record?.lat });
|
||||
if (res.code === 200) {
|
||||
list = res.result || [];
|
||||
}
|
||||
record['hospitalList'] = list.map((item: any) => {
|
||||
item['latitude'] = item['lat'];
|
||||
item['longitude'] = item['lon'];
|
||||
return item;
|
||||
});
|
||||
} else {
|
||||
centerMapRef.value.resetMap();
|
||||
showRestB.value = false;
|
||||
userData.value = record;
|
||||
}
|
||||
confirmHelp(record);
|
||||
}
|
||||
|
||||
function toOther() {
|
||||
window.open('http://aygc.jy.pc.iosp.ydpt.tech/envShow/envFullscreen', '_blank');
|
||||
}
|
||||
|
||||
function handleOneLeftClick(item) {
|
||||
function handleOneLeftClick(item: any) {
|
||||
const { name, key } = item;
|
||||
//呼入电话
|
||||
//受理电话
|
||||
if (key == 'alerdyreceive' || key == 'gross') {
|
||||
phoneType.value = ServerDetailType[key];
|
||||
phoneType.value = (ServerDetailType as any)[key];
|
||||
indexModalTitle.value = name;
|
||||
firstFormOne.value = fromLists[0];
|
||||
indexColumn.value = columns[0];
|
||||
@@ -247,56 +282,6 @@
|
||||
orgName: '硬件部',
|
||||
departCode: 'A01A01',
|
||||
departName: '软硬件开发部',
|
||||
hospitalList: [
|
||||
{
|
||||
id: null,
|
||||
name: '吉祥作业区',
|
||||
lat: 44.000833,
|
||||
lon: 89.214722,
|
||||
type: null,
|
||||
centerResource: false,
|
||||
manageName: null,
|
||||
managePhone: null,
|
||||
address: null,
|
||||
ambulance: null,
|
||||
docNum: null,
|
||||
nurseNum: null,
|
||||
expertNum: null,
|
||||
distance: '383km',
|
||||
},
|
||||
{
|
||||
id: null,
|
||||
name: '吉祥作业区',
|
||||
lat: 44.000833,
|
||||
lon: 89.214722,
|
||||
type: null,
|
||||
centerResource: false,
|
||||
manageName: null,
|
||||
managePhone: null,
|
||||
address: null,
|
||||
ambulance: null,
|
||||
docNum: null,
|
||||
nurseNum: null,
|
||||
expertNum: null,
|
||||
distance: '383km',
|
||||
},
|
||||
{
|
||||
id: null,
|
||||
name: '页岩油作业区',
|
||||
lat: 44.233333,
|
||||
lon: 89.105278,
|
||||
type: null,
|
||||
centerResource: false,
|
||||
manageName: null,
|
||||
managePhone: null,
|
||||
address: null,
|
||||
ambulance: null,
|
||||
docNum: null,
|
||||
nurseNum: null,
|
||||
expertNum: null,
|
||||
distance: '363km',
|
||||
},
|
||||
],
|
||||
type: '0',
|
||||
centerId: '1940693902422519809',
|
||||
popType: 1,
|
||||
@@ -341,8 +326,8 @@
|
||||
const hospitalList = ref([]); //医院列表
|
||||
const showHospitalList = ref(false);
|
||||
|
||||
async function confirmHelp(data) {
|
||||
if (!data.lon) return;
|
||||
async function confirmHelp(data: any) {
|
||||
if (!data.lon) return (showMapBottom.value = true);
|
||||
Map.removeOverlayGroup();
|
||||
hospitalList.value = data.hospitalList;
|
||||
// showHospitalList.value = true;
|
||||
@@ -350,7 +335,8 @@
|
||||
let point = [data.lon, data.lat];
|
||||
// if (data.hospitalList && data.hospitalList.length > 0) {
|
||||
// try {
|
||||
hospitalList.value = await getHospitalList(data.hospitalList, point);
|
||||
const a = ((await getHospitalList(data.hospitalList, point)) as any) || [];
|
||||
hospitalList.value = a.sort((a: any, b: any) => a.distance - b.distance);
|
||||
// showHospitalList.value = true;
|
||||
// } catch (error) {
|
||||
// console.log('获取医院列表时出错:', error);
|
||||
@@ -358,13 +344,8 @@
|
||||
// } else {
|
||||
// console.log('没有医院list');
|
||||
// }
|
||||
mapBottom.value = data;
|
||||
// mapBottom.value['careLiaisonName'] = '1';
|
||||
// mapBottom.value['careLiaisonPhone'] = '1';
|
||||
// mapBottom.value['lifeguardName'] = '1';
|
||||
// mapBottom.value['lifeguardPhone'] = '1';
|
||||
showMapBottom.value = true;
|
||||
const arr = Map.createOverlay(
|
||||
// showMapBottom.value = true;
|
||||
const arr = await Map.createOverlay1(
|
||||
[...hospitalList.value, { latitude: data.lat, longitude: data.lon }],
|
||||
{
|
||||
content: (val) => {
|
||||
@@ -410,9 +391,9 @@
|
||||
Map.createEmergencyMarker(option);
|
||||
Map.map.setFitView([...arr, Map.emergencyMarker], false, [180, 180, 180, 180]);
|
||||
})
|
||||
.catch((err) => {
|
||||
Map.map.setFitView(arr, false, [180, 180, 180, 180]);
|
||||
});
|
||||
.catch((err) => {});
|
||||
|
||||
userData.value = data;
|
||||
}
|
||||
|
||||
async function getHospitalList(hospitalList, userLocation) {
|
||||
@@ -566,6 +547,34 @@
|
||||
indexModalRef.value.openDialog();
|
||||
});
|
||||
}
|
||||
function handleOneRightView() {
|
||||
indexColumn.value = oneRNewColumns;
|
||||
firstFormOne.value = [];
|
||||
const params = {
|
||||
centerId: centerId.value,
|
||||
startDate: '2000-01-01',
|
||||
endDate: '2025-09-25',
|
||||
};
|
||||
indexModalTitle.value = '今日应急';
|
||||
modalApi.value = todayEmergencyListApi;
|
||||
apiParams.value = params;
|
||||
nextTick(() => {
|
||||
indexModalRef.value.openDialog();
|
||||
});
|
||||
}
|
||||
function handleArchives(userId: string) {
|
||||
indexColumn.value = oneRNewColumns;
|
||||
firstFormOne.value = [];
|
||||
const params = {
|
||||
userId: userId,
|
||||
};
|
||||
indexModalTitle.value = '今日应急';
|
||||
modalApi.value = healthArchivesApi;
|
||||
apiParams.value = params;
|
||||
nextTick(() => {
|
||||
indexModalRef.value.openDialog();
|
||||
});
|
||||
}
|
||||
|
||||
function handleCenterMapClick(res: any) {
|
||||
indexColumn.value = centerMapColumns;
|
||||
@@ -632,7 +641,7 @@
|
||||
width: 22%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
//justify-content: space-between;
|
||||
}
|
||||
|
||||
.sun-body-center {
|
||||
@@ -663,25 +672,29 @@
|
||||
}
|
||||
|
||||
.sun-body-left-two {
|
||||
height: 34%;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.sun-body-left-three {
|
||||
height: 28%;
|
||||
}
|
||||
.sun-body-left-four {
|
||||
height: 18%;
|
||||
//height: 45%;
|
||||
}
|
||||
//.sun-body-left-four {
|
||||
// height: 18%;
|
||||
//}
|
||||
}
|
||||
|
||||
.sun-body-right {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.sun-body-right-one,
|
||||
.sun-body-right-two,
|
||||
.sun-body-right-three {
|
||||
//display: flex;
|
||||
//flex-direction: column;
|
||||
> div {
|
||||
border: 1px solid #00ccff;
|
||||
border-radius: 14px;
|
||||
overflow: hidden;
|
||||
overflow: hidden;
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.one-r-box,
|
||||
.two-r-box,
|
||||
@@ -689,6 +702,14 @@
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
.sun-body-right-one {
|
||||
}
|
||||
.sun-body-right-two {
|
||||
flex: 1;
|
||||
}
|
||||
.sun-body-right-three {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
<div v-show="false" id="panel"></div>
|
||||
<div class="map-legend">
|
||||
<div v-for="(item, i) in legendList" :key="i" class="legend-item">
|
||||
<div :style="{ color: item.color }"><img :src="item.img" alt="" class="legend-img" /> {{ item.text }} </div>
|
||||
<div :style="{ color: item.color }"><img :src="item.img" alt="" class="legend-img" /> {{ item.text }}({{ numList[i] }}) </div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -64,38 +64,17 @@
|
||||
</div>
|
||||
|
||||
<div class="hospital-list" :class="[themeType]" v-if="showMapBottom">
|
||||
<!-- <div class="hospital-item" v-for="(item, index) in hospitalList" :key="index" @click.stop="showDrivingLine(item)">-->
|
||||
<!-- <div>{{ item?.name }}</div>-->
|
||||
<!-- <div>相距{{ item?.distance }}</div>-->
|
||||
<!-- <div>驾车大约{{ item?.driveTime }}</div>-->
|
||||
<!-- </div>-->
|
||||
<div class="map-bottom">
|
||||
<div>
|
||||
<div class="title">关爱联络员</div>
|
||||
<template v-if="mapBottomInfo?.careLiaisonName && mapBottomInfo?.careLiaisonPhone">
|
||||
<div>{{ mapBottomInfo?.careLiaisonName }}</div>
|
||||
<div>{{ mapBottomInfo?.careLiaisonPhone }}</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="no-data"> 该员工暂未设置关爱联络员 <img :src="pointPng" alt="" /></div>
|
||||
</template>
|
||||
</div>
|
||||
<div>
|
||||
<div class="title">急救人员</div>
|
||||
<template v-if="mapBottomInfo?.lifeguardName && mapBottomInfo?.lifeguardPhone">
|
||||
<div>{{ mapBottomInfo?.lifeguardName }}</div>
|
||||
<div>{{ mapBottomInfo?.lifeguardPhone }}</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="no-data"> 该员工暂未设置急救人员 <img :src="pointPng" alt="" /></div>
|
||||
</template>
|
||||
<img :src="noLocationPng" alt="" />
|
||||
</div>
|
||||
<div> 未获取到当前救助人员的位置信息 </div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { nextTick, onMounted, ref, watch } from 'vue';
|
||||
import { nextTick, onMounted, reactive, ref, watch } from 'vue';
|
||||
import { infoContent, infoContent1, infoContent4, legendList, tabList } from '/@/views/indexSun/indexSun.ts';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { innerLineLight, outerLineOption } from '/@/assets/mapUtils/mapConstant.ts';
|
||||
@@ -106,8 +85,11 @@
|
||||
import { earlyWarning } from '/@/utils/busConstant.ts';
|
||||
import { useTheme } from '/@/hooks/theme/useTheme.ts';
|
||||
import { RedoOutlined } from '@ant-design/icons-vue';
|
||||
import pointPng from '/@/assets/indexSun/point.png';
|
||||
import { useUserStore } from '/@/store/modules/user.ts';
|
||||
import noLocationPng from '/@/assets/images/map/noLocation.png';
|
||||
|
||||
const useDetail = useDetailStore();
|
||||
const useStore = useUserStore();
|
||||
const { themeType } = useTheme();
|
||||
const list = ref(tabList);
|
||||
const currentIndex = ref(0);
|
||||
@@ -116,6 +98,8 @@
|
||||
start: '',
|
||||
end: '',
|
||||
});
|
||||
// 1 aed 2 健康小屋 3 油田医院 4 救护车
|
||||
const numList = reactive([useStore.getTypeThree, useStore.getTypeOne, useStore.getTypeFive, useStore.getTypeFour]);
|
||||
const props = defineProps({
|
||||
//是否展示底部统计
|
||||
showFooter: {
|
||||
@@ -139,16 +123,11 @@
|
||||
return [];
|
||||
},
|
||||
},
|
||||
mapBottomInfo: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
showMapBottom: {
|
||||
type: Boolean,
|
||||
default: () => false,
|
||||
},
|
||||
});
|
||||
const useDetail = useDetailStore();
|
||||
const showRoutePanel = ref(false);
|
||||
const panelTitle = ref();
|
||||
const level = ref(0);
|
||||
@@ -312,6 +291,16 @@
|
||||
async function getMapData(type, params = { type: '' }) {
|
||||
try {
|
||||
const { code, result } = await mapApiSwitch(type, params);
|
||||
if (!params.type) {
|
||||
// aed
|
||||
useStore.setTypeFour(result ? result.filter((item: any) => item?.type === '4').length : 0);
|
||||
// 健康小屋
|
||||
useStore.setTypeThree(result ? result.filter((item: any) => item?.type === '3').length : 0);
|
||||
// 油田医院
|
||||
useStore.setTypeOne(result ? result.filter((item: any) => item?.type === '1').length : 0);
|
||||
// 救护车
|
||||
useStore.setTypeFive(result ? result.filter((item: any) => item?.type === '5').length : 0);
|
||||
}
|
||||
if (code == 200) {
|
||||
if (Array.isArray(result) && result.length > 0) {
|
||||
Map.createOverlay(
|
||||
@@ -403,6 +392,10 @@
|
||||
changeTab(list.value[currentIndex.value === 4 ? 0 : currentIndex.value], currentIndex.value);
|
||||
emits('showRestB');
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
resetMap,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@@ -767,31 +760,28 @@
|
||||
|
||||
.map-bottom {
|
||||
border-radius: 10px;
|
||||
background: #073148;
|
||||
width: 570px;
|
||||
height: 100px;
|
||||
padding: 5px 0;
|
||||
display: flex;
|
||||
line-height: 30px;
|
||||
|
||||
> div {
|
||||
width: 50%;
|
||||
text-align: center;
|
||||
}
|
||||
.title {
|
||||
color: #45ffa1;
|
||||
}
|
||||
|
||||
.no-data {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 60px;
|
||||
line-height: 60px;
|
||||
|
||||
img {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
width: 100%;
|
||||
&:nth-child(1) {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 0 0 12px;
|
||||
img {
|
||||
width: 100px;
|
||||
height: 70px;
|
||||
}
|
||||
}
|
||||
&:nth-child(2) {
|
||||
height: 60px;
|
||||
line-height: 60px;
|
||||
text-align: center;
|
||||
background: rgba(242, 68, 57, 0.3);
|
||||
color: #f24439;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
<template>
|
||||
<Dialog class="index-modal" :openVis="visible" width="60%" :title="dialogTitle" @close="handleClose" :maskClosable="false">
|
||||
<template #container>
|
||||
<div v-if="useForm" class="form-container">
|
||||
<div v-if="useForm && firstForm.length > 0" class="form-container">
|
||||
<Form :model="formRecord" v-bind="formItemLayout">
|
||||
<slot name="searchFirst"></slot>
|
||||
<a-form-item v-for="(item, index) in firstForm" :label="item.label" :key="index">
|
||||
<a-input :placeholder="item.placeholder" v-if="item.type == 'input'" v-model:value="formRecord[item.field]" />
|
||||
<a-form-item v-for="(item, index) in firstForm" :label="item?.label" :key="index">
|
||||
<a-input :placeholder="item?.placeholder" v-if="item?.type == 'input'" v-model:value="formRecord[item?.field]" />
|
||||
<a-select
|
||||
v-if="item.type == 'select'"
|
||||
:placeholder="item.placeholder"
|
||||
v-model:value="formRecord[item.field]"
|
||||
:options="item.options"
|
||||
v-if="item?.type == 'select'"
|
||||
:placeholder="item?.placeholder"
|
||||
v-model:value="formRecord[item?.field]"
|
||||
:options="item?.options"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="单位" v-if="needDept">
|
||||
@@ -48,7 +48,11 @@
|
||||
:key="visible"
|
||||
:columns="props.column"
|
||||
:apiParams="formState"
|
||||
/>
|
||||
>
|
||||
<template #bodyCell="{ column, record, index, text }">
|
||||
<slot name="bodyCell" v-bind="{ column, record, index, text } || {}"></slot>
|
||||
</template>
|
||||
</BasicTable>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
@@ -60,6 +64,7 @@
|
||||
import BasicTable from '/@/components/secondaryScreen/secondMap/components/basicTable/BasicTable.vue';
|
||||
import { allSecondaryDepartsApi, getThreeDepartByOrgCodeApi } from '/@/views/indexSun/indexSun.api.ts';
|
||||
import dayjs from 'dayjs';
|
||||
import { isFunction } from '/@/utils/is.ts';
|
||||
|
||||
const props = defineProps({
|
||||
title: {
|
||||
@@ -307,6 +312,7 @@
|
||||
}
|
||||
defineExpose({
|
||||
openDialog,
|
||||
closeDialog,
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
|
||||
@@ -19,6 +19,8 @@ enum Api {
|
||||
getSecondaryDepartment = '/sys/sysDepart/allSecondaryDeparts',
|
||||
twoRN = '/health-emergency/emergency/LargeScreenNew/loveTrend',
|
||||
nearResources = '/health-emergency/emergency/LargeScreenNew/nearResources',
|
||||
todayEmergencyList = '/health-emergency/emergency/LargeScreenNew/todayEmergencyList',
|
||||
healthArchives = '/health-emergency/emergency/LargeScreenNew/healthArchives',
|
||||
}
|
||||
|
||||
export const statisticsNewApi = (params: any) => post(Api.statisticsNew, params);
|
||||
@@ -31,6 +33,8 @@ export const threeRApi = (params: any) => post(Api.threeR, params);
|
||||
export const twoRApi = (params: any) => post(Api.twoR, params);
|
||||
export const twoRNApi = (params: any) => get(Api.twoRN, params);
|
||||
export const nearResourcesApi = (params: any) => get(Api.nearResources, params);
|
||||
export const todayEmergencyListApi = (params: any) => post(Api.todayEmergencyList, params);
|
||||
export const healthArchivesApi = (params: any) => get(Api.healthArchives, params);
|
||||
|
||||
export const threeRModalApi = (params: any) => post(Api.threeRModal, params);
|
||||
export const twoRModal1Api = (params: any) => post(Api.twoRModal1, params);
|
||||
|
||||
@@ -816,3 +816,62 @@ export const twoRNewForm = [
|
||||
defaultValue: '',
|
||||
},
|
||||
];
|
||||
|
||||
export const oneRNewColumns = [
|
||||
{
|
||||
title: '单位',
|
||||
dataIndex: 'departName',
|
||||
key: 'departName',
|
||||
},
|
||||
{
|
||||
title: '部门',
|
||||
dataIndex: 'orgName',
|
||||
key: 'orgName',
|
||||
},
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'realName',
|
||||
key: 'name',
|
||||
},
|
||||
{
|
||||
title: '性别',
|
||||
dataIndex: 'sex',
|
||||
key: 'sex',
|
||||
customRender: ({ text }) => {
|
||||
if (text == '1') {
|
||||
return '女';
|
||||
} else {
|
||||
return '男';
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '年龄',
|
||||
dataIndex: 'age',
|
||||
key: 'age',
|
||||
},
|
||||
{
|
||||
title: '应急方式',
|
||||
dataIndex: 'emergencyType',
|
||||
key: 'emergencyType',
|
||||
customRender: ({ text }) => {
|
||||
switch (text) {
|
||||
case '0':
|
||||
return '120';
|
||||
case '1':
|
||||
return '紧急求助';
|
||||
case '2':
|
||||
return '云坐席';
|
||||
case '3':
|
||||
return '终端报警';
|
||||
default:
|
||||
return '-';
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'cz',
|
||||
key: 'cz',
|
||||
},
|
||||
];
|
||||
|
||||
@@ -0,0 +1,323 @@
|
||||
<template>
|
||||
<div class="one-r-box">
|
||||
<div class="title">
|
||||
<div>救助信息</div>
|
||||
|
||||
<!-- <div class="top-button-d">-->
|
||||
<a-button size="small" class="title-button title-button-one" @click="handleView">今日应急</a-button>
|
||||
<!-- </div>-->
|
||||
</div>
|
||||
<template v-if="props.userData && Object.keys(props.userData).length > 0">
|
||||
<div class="basic-info">
|
||||
<span>{{ userData.realName }}</span>
|
||||
<a-button v-if="props.userData && Object.keys(props.userData).length > 0" size="small" class="title-button" @click="handleArchives"
|
||||
>健康档案</a-button
|
||||
>
|
||||
</div>
|
||||
<div class="emer-top-d-outer">
|
||||
<div class="emer-top-d">
|
||||
<div style="display: flex; color: #ffffff">
|
||||
<div class="emer-item-d">
|
||||
<div>性别/年龄:</div>
|
||||
<div class="emer-item-d-t">{{ getSex(userData.sex) }}/{{ userData.age || '-' }}</div>
|
||||
</div>
|
||||
<div class="emer-item-d">
|
||||
<div>应急方式:</div>
|
||||
<div class="emer-item-d-t">{{ getTypeName(userData.emergencyType) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex; color: #ffffff">
|
||||
<div class="emer-item-d">
|
||||
<div>单位:</div>
|
||||
<div class="emer-item-d-t">{{ userData.departName }}</div>
|
||||
</div>
|
||||
<div class="emer-item-d">
|
||||
<div>手机号码:</div>
|
||||
<div class="emer-item-d-t">{{ userData.phone }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="emer-item-d">
|
||||
<div>当前位置:</div>
|
||||
<div class="emer-item-d-t" :style="{ color: !userData?.lon || !userData?.lat ? '#F24439' : '' }">
|
||||
{{ !userData?.lon || !userData?.lat ? '未获取到位置信息' : locationInfo }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="title title-two">
|
||||
<span>联系人</span>
|
||||
<a-button size="small" class="title-button">紧急联系人</a-button>
|
||||
</div>
|
||||
<div class="emer-info-outer">
|
||||
<div class="emer-info">
|
||||
<div>
|
||||
<div class="emer-info-title">关爱联络员</div>
|
||||
<template v-if="props.userData?.careLiaisonName && props.userData?.careLiaisonPhone">
|
||||
<div style="color: #ffffff">{{ props.userData?.careLiaisonName }}</div>
|
||||
<div style="color: #ffffff">{{ props.userData?.careLiaisonPhone }}</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="no-data"> 该员工暂未设置关爱联络员 <img :src="pointPng" alt="" /></div>
|
||||
</template>
|
||||
</div>
|
||||
<div>
|
||||
<div class="emer-info-title">急救人员</div>
|
||||
<template v-if="props.userData?.lifeguardName && props.userData?.lifeguardPhone">
|
||||
<div style="color: #ffffff">{{ props.userData?.lifeguardName }}</div>
|
||||
<div style="color: #ffffff">{{ props.userData?.lifeguardPhone }}</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="no-data"> 该员工暂未设置急救人员 <img :src="pointPng" alt="" /></div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<Empty class="empty-d" :description="'暂无救助人员'" />
|
||||
</template>
|
||||
|
||||
<Dialog :openVis="openInfo" width="30%" title="健康报警员工信息" @close="handlePoliceClose">
|
||||
<template #container>
|
||||
<div class="police-con" :class="[themeType]">
|
||||
<Row style="font-size: 14px; font-weight: bold"> 个人信息 </Row>
|
||||
<Row>
|
||||
<Col :span="8">姓名:{{ archives?.realName || '--' }}</Col>
|
||||
<Col :span="8">性别:{{ archives?.sex_dictText || '--' }}</Col>
|
||||
<Col :span="8">年龄:{{ archives?.age || '--' }}</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col :span="8">二级单位:{{ archives?.orgName2 || '--' }}</Col>
|
||||
<Col :span="8">部门:{{ archives?.orgName || '--' }}</Col>
|
||||
<Col :span="8">手机号码:{{ archives?.phone || '--' }}</Col>
|
||||
</Row>
|
||||
<Row style="font-size: 14px; font-weight: bold"> 健康信息 </Row>
|
||||
<Row> 异常事件:{{ archives?.eventType_dictText || '--' }} </Row>
|
||||
<Row>
|
||||
<Col :span="8">异常值:{{ archives?.dataValue || '--' }}</Col>
|
||||
<Col :span="16">发生时间:{{ archives?.warnTime || '--' }}</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</template>
|
||||
</Dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import pointPng from '/@/assets/indexSun/point.png';
|
||||
import { Col, Empty, Row } from 'ant-design-vue';
|
||||
import { Map } from '/@/assets/mapUtils/map.ts';
|
||||
import { ref, watch } from 'vue';
|
||||
import Dialog from '/@/components/dialog/Dialog.vue';
|
||||
import { useTheme } from '/@/hooks/theme/useTheme.ts';
|
||||
import { healthArchivesApi } from '/@/views/indexSun/indexSun.api.ts';
|
||||
|
||||
const props = defineProps({
|
||||
userData: { type: Object, default: () => {} },
|
||||
});
|
||||
const { themeType } = useTheme();
|
||||
const locationInfo = ref<string>('');
|
||||
|
||||
const emit = defineEmits(['handleView']);
|
||||
const openInfo = ref<boolean>(false);
|
||||
const archives = ref<object>({});
|
||||
|
||||
watch(
|
||||
() => props.userData,
|
||||
(v) => {
|
||||
locationInfo.value = '';
|
||||
if (v && v?.lat && v?.lat) {
|
||||
getAddress();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
function handleView() {
|
||||
emit('handleView');
|
||||
}
|
||||
function handleArchives() {
|
||||
healthArchivesApi({ userId: props.userData?.userId })
|
||||
.then((res) => {})
|
||||
.catch((err) => {});
|
||||
}
|
||||
|
||||
function handlePoliceClose() {
|
||||
archives.value = {};
|
||||
}
|
||||
|
||||
function getTypeName(type: string) {
|
||||
switch (type) {
|
||||
case '0':
|
||||
return '120';
|
||||
case '1':
|
||||
return '紧急求助';
|
||||
case '2':
|
||||
return '云坐席';
|
||||
case '3':
|
||||
return '终端报警';
|
||||
default:
|
||||
return '-';
|
||||
}
|
||||
}
|
||||
function getSex(type: string) {
|
||||
switch (type) {
|
||||
case '1':
|
||||
return '女';
|
||||
case '2':
|
||||
return '男';
|
||||
default:
|
||||
return '-';
|
||||
}
|
||||
}
|
||||
|
||||
function getAddress() {
|
||||
Map.getAddressByPoint([props.userData?.lon, props.userData?.lat])
|
||||
.then((res: string) => {
|
||||
locationInfo.value = res;
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
locationInfo.value = '';
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.one-r-box {
|
||||
background: rgba(8, 75, 100, 0.2);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
letter-spacing: 0px;
|
||||
.title {
|
||||
height: 40px;
|
||||
border-radius: 14px 14px 0 0;
|
||||
font-weight: bold;
|
||||
font-size: 20px;
|
||||
letter-spacing: 2px;
|
||||
color: #ffffff;
|
||||
line-height: 40px;
|
||||
padding: 0 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background: linear-gradient(to right, rgba(8, 75, 100, 0.5) 0%, rgba(255, 255, 255, 0) 100%);
|
||||
}
|
||||
}
|
||||
|
||||
.title-two {
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
|
||||
.title-button {
|
||||
color: #ffffff;
|
||||
font-weight: bold;
|
||||
font-size: 10px !important;
|
||||
padding: 2px 10px;
|
||||
background: radial-gradient(ellipse at center, #082147 0%, #08254c 55%, #085faa 100%);
|
||||
border-radius: 8px;
|
||||
border: 1px solid #55d3ff;
|
||||
}
|
||||
|
||||
.title-button-one {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
//.top-button-d {
|
||||
// display: flex;
|
||||
// align-items: center;
|
||||
// button {
|
||||
// &:nth-child(1) {
|
||||
// margin-right: 10px;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
.basic-info {
|
||||
color: #ffffff;
|
||||
display: flex;
|
||||
padding: 3px 30px 0;
|
||||
justify-content: space-between;
|
||||
|
||||
span {
|
||||
color: #c9daff;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
.emer-top-d-outer {
|
||||
padding: 10px 20px;
|
||||
}
|
||||
|
||||
.emer-top-d {
|
||||
color: #ffffff;
|
||||
padding: 10px 10px;
|
||||
border-radius: 2px;
|
||||
background: #152657;
|
||||
|
||||
.emer-item-d {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
padding: 2px 0;
|
||||
|
||||
> div {
|
||||
&:nth-child(1) {
|
||||
color: #82a9ef;
|
||||
}
|
||||
&:nth-child(2) {
|
||||
color: #c9daff;
|
||||
}
|
||||
}
|
||||
|
||||
.emer-item-d-t {
|
||||
white-space: wrap;
|
||||
word-break: break-all;
|
||||
flex: 1;
|
||||
padding-right: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.emer-info-outer {
|
||||
padding: 10px 20px;
|
||||
}
|
||||
|
||||
.emer-info {
|
||||
border-radius: 2px;
|
||||
background: #152657;
|
||||
height: 100px;
|
||||
padding: 5px 0;
|
||||
display: flex;
|
||||
line-height: 30px;
|
||||
> div {
|
||||
width: 50%;
|
||||
text-align: center;
|
||||
}
|
||||
.emer-info-title {
|
||||
color: #45ffa1;
|
||||
}
|
||||
|
||||
.no-data {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 60px;
|
||||
line-height: 60px;
|
||||
color: #ffffff;
|
||||
|
||||
img {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.empty-d {
|
||||
padding: 10px 0;
|
||||
:deep(.ant-empty-image) {
|
||||
margin-top: 5px;
|
||||
height: 30px;
|
||||
}
|
||||
:deep(.ant-empty-description) {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,468 @@
|
||||
<template>
|
||||
<div class="two-l-box">
|
||||
<div class="title">
|
||||
<span>心血管监测</span>
|
||||
</div>
|
||||
<div style="flex: 1" class="content">
|
||||
<div class="content-search content-search-select">
|
||||
<a-select v-model:value="selectValue" class="type-select" :options="selectOptions" @change="getData">
|
||||
<a-select-option value="全部数据">全部数据</a-select-option>
|
||||
</a-select>
|
||||
<a-select v-model:value="selectValue1" class="type-select" :options="selectOption1" @change="getData" />
|
||||
</div>
|
||||
<div class="content-search content-search-new">
|
||||
<div class="type-time">
|
||||
<div
|
||||
v-for="(item, index) in tabList"
|
||||
@click="clickChooseType(item.value)"
|
||||
:class="[chooseType === item.value ? 'selected' : 'no-selected']"
|
||||
:key="`tab-lef-list-key-${index}`"
|
||||
>
|
||||
{{ item.label }}
|
||||
<div>
|
||||
<div v-if="chooseType === item.value" class="triangle"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; height: 100%; padding: 5px; justify-content: center">
|
||||
<div class="item-title" style="width: 99%">
|
||||
<div class="title chart-title" style="display: flex; font-weight: normal !important">
|
||||
<div> <img :src="imgList[chooseType]" alt="" />{{ tabList[chooseType].label }}</div>
|
||||
<div v-if="[0, 1].includes(chooseType)"> 参考范围: {{ tabList[chooseType].tips }} </div>
|
||||
</div>
|
||||
<div style="height: 210px">
|
||||
<div style="height: 100%" class="content-chart">
|
||||
<template v-if="[0, 1, 2, 3].includes(chooseType)">
|
||||
<three-left-new-item :choose-type="chooseType" />
|
||||
</template>
|
||||
<template v-if="[4].includes(chooseType)">
|
||||
<sleep-item :orgCode="selectValue" :type="selectValue1" style="height: 100%" />
|
||||
</template>
|
||||
<template v-if="[5].includes(chooseType)">
|
||||
<step-item :orgCode="selectValue" :type="selectValue1" style="height: 100%" />
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, watch, reactive, onBeforeUnmount, nextTick } from 'vue';
|
||||
import * as echarts from 'echarts';
|
||||
import { getClassCharts } from '/@/views/indexSun/indexSun.ts';
|
||||
import { allSecondaryDepartsApi, twoLApi } from '/@/views/indexSun/indexSun.api.ts';
|
||||
import { useUserStore } from '/@/store/modules/user.ts';
|
||||
import ThreeLeftNewItem from '/src/views/indexSun/threeLeftNewItem/threeLeftNewItem.vue';
|
||||
import SleepItem from '/@/views/indexSun/threeLeftNewItem/sleepItem.vue';
|
||||
import StepItem from '/@/views/indexSun/threeLeftNewItem/stepItem.vue';
|
||||
|
||||
import item0Png from '/@/assets/images/threeLeftNew/item0.png';
|
||||
import item1Png from '/@/assets/images/threeLeftNew/item1.png';
|
||||
import item2Png from '/@/assets/images/threeLeftNew/item2.png';
|
||||
import item3Png from '/@/assets/images/threeLeftNew/item3.png';
|
||||
import item4Png from '/@/assets/images/threeLeftNew/item4.png';
|
||||
import item5Png from '/@/assets/images/threeLeftNew/item5.png';
|
||||
import item6Png from '/@/assets/images/threeLeftNew/item6.png';
|
||||
|
||||
const { getCenterInfo } = useUserStore();
|
||||
const props = defineProps({
|
||||
bKey: {
|
||||
type: String,
|
||||
default: () => '',
|
||||
},
|
||||
});
|
||||
const imgList = reactive([item0Png, item1Png, item2Png, item3Png, item4Png, item5Png, item6Png]);
|
||||
const tabList = reactive([
|
||||
{
|
||||
label: '心率',
|
||||
value: 0,
|
||||
tips: '正常范围60~100次/分',
|
||||
},
|
||||
{
|
||||
label: '血氧',
|
||||
value: 1,
|
||||
tips: '血氧饱和度范围95%~100%',
|
||||
},
|
||||
{
|
||||
label: '血压',
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
label: '体温',
|
||||
value: 3,
|
||||
},
|
||||
{
|
||||
label: '睡眠',
|
||||
value: 4,
|
||||
},
|
||||
{
|
||||
label: '步数',
|
||||
value: 5,
|
||||
},
|
||||
]);
|
||||
const chooseType = ref(0);
|
||||
const selectValue = ref<string>('');
|
||||
const timer = ref<any>(null);
|
||||
const selectOptions = ref([{ label: '全部数据', value: '' }]);
|
||||
const selectValue1 = ref('week');
|
||||
const selectOption1 = ref([
|
||||
{ label: '近一周', value: 'week' },
|
||||
{ label: '近一月', value: 'month' },
|
||||
{ label: '近一年', value: 'year' },
|
||||
]);
|
||||
const newChart = ref<HTMLElement>();
|
||||
function clickChooseType(type: any) {
|
||||
if (chooseType.value === type) return;
|
||||
chooseType.value = type;
|
||||
getData();
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (selectOptions.value.length === 1) {
|
||||
getAllDepart();
|
||||
}
|
||||
setTimer();
|
||||
});
|
||||
watch(props, () => {
|
||||
selectValue.value = '';
|
||||
getData();
|
||||
});
|
||||
|
||||
function setTimer() {
|
||||
if (timer.value) {
|
||||
clearInterval(timer.value);
|
||||
}
|
||||
chooseType.value = 0;
|
||||
getData();
|
||||
timer.value = setInterval(() => {
|
||||
if (chooseType.value !== 5) {
|
||||
chooseType.value += 1;
|
||||
} else {
|
||||
chooseType.value = 0;
|
||||
}
|
||||
getData();
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
timer.value && clearInterval(timer.value);
|
||||
});
|
||||
|
||||
function getAllDepart() {
|
||||
allSecondaryDepartsApi({})
|
||||
.then((res: any) => {
|
||||
if (res.code === 200) {
|
||||
const op: any[] = res?.result
|
||||
? res.result.map((it: any) => {
|
||||
return {
|
||||
label: it.departName,
|
||||
value: it.orgCode,
|
||||
};
|
||||
})
|
||||
: [];
|
||||
selectOptions.value = selectOptions.value.concat(op);
|
||||
} else {
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
}
|
||||
|
||||
const myChart = ref();
|
||||
function getData() {
|
||||
twoLApi({
|
||||
sex: chooseType.value,
|
||||
depart: selectValue.value,
|
||||
centerId: getCenterInfo?.id,
|
||||
})
|
||||
.then((res: any) => {
|
||||
if (res.code == 200) {
|
||||
initChart(res.result);
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
}
|
||||
|
||||
function initChart(value: any) {
|
||||
nextTick(() => {
|
||||
myChart.value = echarts.init(newChart.value!);
|
||||
const dx =
|
||||
value.map((item: any) => {
|
||||
return item.name;
|
||||
}) || [];
|
||||
const dy =
|
||||
value.map((item: any) => {
|
||||
return item.count;
|
||||
}) || [];
|
||||
|
||||
const max =
|
||||
value.sort((a: any, b: any) => b.count - a.count).length > 0 ? value.sort((a: any, b: any) => b.count - a.count)[0].count : [];
|
||||
const m = max % 25 === 0 ? max : (parseInt(max / 25) + 1) * 25;
|
||||
let option = getClassCharts(dx, dy, m);
|
||||
myChart.value.setOption(option);
|
||||
window.addEventListener('resize', () => {
|
||||
myChart.value.resize();
|
||||
});
|
||||
});
|
||||
}
|
||||
const emit = defineEmits(['handleView']);
|
||||
function handleView() {
|
||||
emit('handleView');
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.two-l-box {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: rgba(8, 75, 100, 0.2);
|
||||
.title {
|
||||
height: 40px;
|
||||
border-radius: 25px 25px 0 0;
|
||||
font-weight: bold;
|
||||
font-size: 20px;
|
||||
letter-spacing: 2px;
|
||||
color: #ffffff;
|
||||
line-height: 40px;
|
||||
padding: 0 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background: linear-gradient(to right, rgba(8, 75, 100, 0.5) 0%, rgba(255, 255, 255, 0) 100%);
|
||||
.look-view {
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 28px;
|
||||
height: 24px;
|
||||
margin: 0 5px 2px 0;
|
||||
}
|
||||
}
|
||||
.content {
|
||||
height: calc(100% - 40px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.content-search {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin: 5px 10px;
|
||||
.type-select {
|
||||
width: 200px;
|
||||
}
|
||||
}
|
||||
|
||||
.content-search-new {
|
||||
display: inline;
|
||||
.type-time {
|
||||
justify-content: space-between;
|
||||
margin: 7px 0 !important;
|
||||
font-size: 12px;
|
||||
> div {
|
||||
padding: 3px 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content-search-select {
|
||||
> div {
|
||||
margin-top: 5px;
|
||||
&:nth-child(1) {
|
||||
flex: 1;
|
||||
}
|
||||
&:nth-child(2) {
|
||||
width: 100px;
|
||||
margin-left: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.type-time {
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
> div {
|
||||
cursor: pointer;
|
||||
padding: 3px 15px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
//width: 60px;
|
||||
}
|
||||
.selected {
|
||||
color: #00ccff;
|
||||
background: rgba(0, 204, 255, 0.2);
|
||||
position: relative;
|
||||
&:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 8px; /* 线条宽度 */
|
||||
height: 8px; /* 线条高度 */
|
||||
border-top: 3px solid #00ccff; /* 顶部线条 */
|
||||
border-left: 3px solid #00ccff; /* 左侧线条 */
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
width: 8px; /* 线条宽度 */
|
||||
height: 8px; /* 线条高度 */
|
||||
border-bottom: 3px solid #00ccff; /* 顶部线条 */
|
||||
border-right: 3px solid #00ccff; /* 左侧线条 */
|
||||
}
|
||||
> div {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 8px; /* 线条宽度 */
|
||||
height: 8px; /* 线条高度 */
|
||||
border-top: 3px solid #00ccff; /* 顶部线条 */
|
||||
border-right: 3px solid #00ccff; /* 左侧线条 */
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 8px; /* 线条宽度 */
|
||||
height: 8px; /* 线条高度 */
|
||||
border-bottom: 3px solid #00ccff; /* 顶部线条 */
|
||||
border-left: 3px solid #00ccff; /* 左侧线条 */
|
||||
}
|
||||
}
|
||||
}
|
||||
.no-selected {
|
||||
color: #b6b6b6;
|
||||
background: rgba(26, 69, 126, 0.2);
|
||||
position: relative;
|
||||
&:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 8px; /* 线条宽度 */
|
||||
height: 8px; /* 线条高度 */
|
||||
border-top: 3px solid #1a457e; /* 顶部线条 */
|
||||
border-left: 3px solid #1a457e; /* 左侧线条 */
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
width: 8px; /* 线条宽度 */
|
||||
height: 8px; /* 线条高度 */
|
||||
border-bottom: 3px solid #1a457e; /* 顶部线条 */
|
||||
border-right: 3px solid #1a457e; /* 左侧线条 */
|
||||
}
|
||||
> div {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 8px; /* 线条宽度 */
|
||||
height: 8px; /* 线条高度 */
|
||||
border-top: 3px solid #1a457e; /* 顶部线条 */
|
||||
border-right: 3px solid #1a457e; /* 左侧线条 */
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 8px; /* 线条宽度 */
|
||||
height: 8px; /* 线条高度 */
|
||||
border-bottom: 3px solid #1a457e; /* 顶部线条 */
|
||||
border-left: 3px solid #1a457e; /* 左侧线条 */
|
||||
}
|
||||
}
|
||||
}
|
||||
.triangle {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
bottom: 0;
|
||||
transform: translateX(-50%);
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 5px solid transparent; /* 左边透明 */
|
||||
border-right: 5px solid transparent; /* 右边透明 */
|
||||
border-bottom: 6px solid #00ccff; /* 底部为黑色,形成三角形 */
|
||||
}
|
||||
}
|
||||
.server-container {
|
||||
color: #fff;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
overflow-y: auto;
|
||||
position: relative;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
letter-spacing: 2px;
|
||||
margin-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
.spin {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
}
|
||||
}
|
||||
.server-item {
|
||||
// font-size: 16px;
|
||||
padding: 5px 3% 5px 5%;
|
||||
&.hasCursor {
|
||||
cursor: pointer;
|
||||
}
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.content-chart {
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
flex: 1;
|
||||
.charts {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.item-title {
|
||||
background: url('/@/assets/images/threeLeftNew/item-bg.png') no-repeat !important;
|
||||
background-size: 100% 100% !important;
|
||||
}
|
||||
|
||||
.chart-title {
|
||||
font-size: 16px !important;
|
||||
}
|
||||
</style>
|
||||
@@ -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>
|
||||
@@ -56,7 +56,7 @@
|
||||
import { twoRNApi } from '/@/views/indexSun/indexSun.api.ts';
|
||||
import dayjs from 'dayjs';
|
||||
import { Row, Col } from 'ant-design-vue';
|
||||
import { getName, list } from '/@/views/indexSun/rowNewR.data.ts';
|
||||
import { getName, list } from '/@/views/indexSun/twoNewR.data.ts';
|
||||
|
||||
const { themeType } = useTheme();
|
||||
const step = ref(0.2);
|
||||