This commit is contained in:
zk
2023-12-21 09:02:45 +08:00
parent 1c65f18bab
commit 9230f659c1
34 changed files with 473 additions and 327 deletions
+2
View File
@@ -5,5 +5,7 @@ VITE_GLOB_API_URL=http://cqyt.dev.yg.dt.io
#应急求助-websocket
VITE_GLOB_API_YIN_JI=ws://cqyt.dev.yg.dt.io/health-watch/websocket/watchMonitor
#VITE_GLOB_API_YIN_JI=ws://192.168.1.3:7098/websocket/watchMonitor
#健康监测工具报警-websocket
VITE_GLOB_API_JIAN_CE=ws://cqyt.dev.yg.dt.io/health-emergency/websocket/emergency
#VITE_GLOB_API_JIAN_CE=ws://192.168.1.3:7011/websocket/emergency
+5
View File
@@ -15,6 +15,7 @@
"dependencies": {
"@amap/amap-jsapi-loader": "^1.0.1",
"@iamzzg/data-view": "^2.10.0",
"autoprefixer": "^10.4.16",
"axios": "^1.6.2",
"dayjs": "^1.11.10",
"jsencrypt": "^3.3.2",
@@ -22,6 +23,10 @@
"mitt": "^3.0.1",
"path": "^0.12.7",
"pinia": "^2.1.7",
"postcss": "^8.4.32",
"postcss-loader": "^7.3.3",
"postcss-plugin-px2rem": "^0.8.1",
"postcss-px2rem": "^0.3.0",
"prettier": "^3.1.0",
"qs": "^6.11.2",
"vue-router": "^4.2.5",
+2
View File
@@ -4,6 +4,7 @@ enum Api {
code = '/sys/dictItem/list',
}
//锻炼字典
export const getCodeInfo = (params: any) =>
get(Api.code, {
pageNo: 1,
@@ -11,3 +12,4 @@ export const getCodeInfo = (params: any) =>
dictId: '1722171687208849409',
...params,
});
export const montionFieldNames = { label: 'itemText', value: 'itemValue' };
+1 -1
View File
@@ -31,7 +31,7 @@ export function typeToIcon(type: string) {
if (type == '3') {
return createIcon({ icon: mapIcon2, iconSize, imageSize });
}
if (type == '4') {
if (type == '5') {
return createIcon({ icon: mapIcon3, iconSize, imageSize });
}
if (type == '6') {
@@ -1,4 +1,5 @@
import { computed, ref } from 'vue';
import { visibleChartLabel } from '/@/utils/utils.ts';
// 列表字段
export const columns = [
{
@@ -95,6 +96,7 @@ export function useHealth() {
}
export function ringOption(chartData, total) {
const data = visibleChartLabel(chartData);
return {
title: {
text: '总人数',
@@ -147,7 +149,7 @@ export function ringOption(chartData, total) {
labelLine: {
show: false,
},
data: chartData,
data: data,
},
],
};
+180 -182
View File
@@ -6,8 +6,7 @@
</template>
</public-title>
<div class="inner">
<vue3-seamless-scroll :list="scrollList" class="scroll" :hover="true" :limitScrollNum="4"
v-bind="classOption">
<vue3-seamless-scroll :list="scrollList" class="scroll" :hover="true" :limitScrollNum="4" v-bind="classOption">
<div class="item" v-for="(item, i) in scrollList" :key="i">
<span class="fixed-width" :title="item?.realName">{{ item?.realName }}</span>
<span class="fixed-width" :title="item?.eventType_dictText">{{ item?.eventType_dictText }}</span>
@@ -59,225 +58,224 @@
</div>
</template>
<script setup lang="ts">
import {onMounted, ref} from 'vue';
import {useRouter} from 'vue-router';
import $bus from '/@/utils/bus.ts';
import {columns} from '/@/components/body-d-right/bodyRightHooks.ts';
import PublicTitle from '/@/components/publicTitle.vue';
import Dialog from '/@/components/dialog/Dialog.vue';
import {Vue3SeamlessScroll} from 'vue3-seamless-scroll';
import {getMonitorList} from '/@/components/body-d-right/right.api.ts';
import {Map} from '/@/assets/mapUtils/map.ts';
import { onMounted, ref } from 'vue';
import { useRouter } from 'vue-router';
import $bus from '/@/utils/bus.ts';
import { columns } from '/@/components/body-d-right/bodyRightHooks.ts';
import PublicTitle from '/@/components/publicTitle.vue';
import Dialog from '/@/components/dialog/Dialog.vue';
import { Vue3SeamlessScroll } from 'vue3-seamless-scroll';
import { getMonitorList } from '/@/components/body-d-right/right.api.ts';
import { Map } from '/@/assets/mapUtils/map.ts';
const router = useRouter();
const classOption = ref({
step: 0.3, // 速度
});
const open = ref<boolean>(false);
const openInfor = ref<boolean>(false);
const userInfo = ref({
realName: '',
orgName1: '',
phone: '',
eventType_dictText: '',
warnTime: '',
address: '',
});
const router = useRouter();
const classOption = ref({
step: 0.3, // 速度
});
const open = ref<boolean>(false);
const openInfor = ref<boolean>(false);
const userInfo = ref({
realName: '',
orgName1: '',
phone: '',
eventType_dictText: '',
warnTime: '',
address: '',
});
const dataSource = ref([
{
key: '1',
name: '胡彦斌',
age: 32,
address: '西湖区湖底公园1号',
},
]);
const dataSource = ref([
{
key: '1',
name: '胡彦斌',
age: 32,
address: '西湖区湖底公园1号',
},
]);
/**
* @desc open员工信息
*/
function handlePolice(item) {
userInfo.value = item;
openInfor.value = true;
classOption.value.step = 0;
}
/**
* @desc close员工信息
*/
function handlePoliceClose() {
openInfor.value = false;
classOption.value.step = 0.3;
}
onMounted(() => {
getScrollList();
});
/**
* @desc 终端报警
* */
const scrollList = ref([]);
async function getScrollList() {
const {code, result} = await getMonitorList({pageSize: 10, pageNo: 1});
if (code == 200) {
scrollList.value = result.records;
/**
* @desc open员工信息
*/
function handlePolice(item) {
userInfo.value = item;
openInfor.value = true;
classOption.value.step = 0;
}
}
function sendPosition(item) {
let {lon, lat} = item;
if (lon && lat) {
Map.createMarker(item, () => {
handlePolice(item);
});
/**
* @desc close员工信息
*/
function handlePoliceClose() {
openInfor.value = false;
classOption.value.step = 0.3;
}
}
function viewDetail() {
router.push({path: '/secondScreen'});
}
onMounted(() => {
getScrollList();
});
/**
* @desc 终端报警
* */
const scrollList = ref([]);
async function getScrollList() {
const { code, result } = await getMonitorList({ pageSize: 10, pageNo: 1 });
if (code == 200) {
scrollList.value = result.records;
}
}
function sendPosition(item) {
let { lon, lat } = item;
if (lon && lat) {
Map.createMarker(item, () => {
handlePolice(item);
});
}
}
function viewDetail() {
router.push({ path: '/secondScreen' });
}
</script>
<style scoped lang="less">
.right-text {
font-size: 14px;
font-weight: 100;
cursor: pointer;
margin-right: 3px;
}
.right-text {
font-weight: 100;
cursor: pointer;
margin-right: 3px;
}
.right-text:hover {
color: #129bff;
}
.right-text:hover {
color: #129bff;
}
.inner {
height: calc(100% - 40px);
display: flex;
align-items: center;
justify-content: center;
.inner {
height: calc(100% - 40px);
display: flex;
align-items: center;
justify-content: center;
.scroll {
width: 98%;
height: 88%;
overflow: hidden;
.scroll {
width: 98%;
height: 88%;
overflow: hidden;
.item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 3% 0;
.fixed-width {
display: inline-flex;
width: 100px;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
span {
color: #ffffff;
font-size: 16px;
}
.time-icon {
.item {
display: flex;
align-items: center;
}
justify-content: space-between;
padding: 3% 0;
.terminal-icon {
margin-left: 15px;
display: inline-block;
width: 18px;
height: 18px;
background: url('/@/assets/images/terminal.png') no-repeat;
background-size: 100% 100%;
cursor: pointer;
}
.fixed-width {
display: inline-flex;
width: 100px;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.position {
margin-left: 5px;
display: inline-block;
width: 20px;
height: 20px;
background: url('/@/assets/img/position.png') no-repeat;
background-size: 100% 100%;
cursor: pointer;
span {
color: #ffffff;
font-size: 16px;
}
.time-icon {
display: flex;
align-items: center;
}
.terminal-icon {
margin-left: 15px;
display: inline-block;
width: 18px;
height: 18px;
background: url('/@/assets/images/terminal.png') no-repeat;
background-size: 100% 100%;
cursor: pointer;
}
.position {
margin-left: 5px;
display: inline-block;
width: 20px;
height: 20px;
background: url('/@/assets/img/position.png') no-repeat;
background-size: 100% 100%;
cursor: pointer;
}
}
}
}
}
.police-con {
color: #ffffff;
background-color: #00152b;
border: 1px solid #129bff;
padding: 2% 0 2% 5%;
.police-con {
color: #ffffff;
background-color: #00152b;
border: 1px solid #129bff;
padding: 2% 0 2% 5%;
.con-item {
padding: 1.3% 0;
.con-item {
padding: 1.3% 0;
span:nth-child(1) {
font-weight: bold;
display: inline-block;
width: 20%;
text-align: right;
}
span:nth-child(1) {
font-weight: bold;
display: inline-block;
width: 20%;
text-align: right;
}
span:nth-child(2) {
padding-left: 2%;
span:nth-child(2) {
padding-left: 2%;
}
}
}
}
</style>
<style lang="less">
.dialog-con {
background-color: #00152b;
border: 1px solid #129bff;
/*
.dialog-con {
background-color: #00152b;
border: 1px solid #129bff;
/*
antd表格样式
*/
.ant-table-thead > tr > th {
border-bottom: 1px solid #1e73c2 !important;
}
.ant-table-thead > tr > th {
border-bottom: 1px solid #1e73c2 !important;
}
.ant-table-body {
background-color: #00152b !important;
}
.ant-table-body {
background-color: #00152b !important;
}
.ant-modal-header {
border-bottom: none !important;
}
.ant-modal-header {
border-bottom: none !important;
}
.ant-table-tbody > tr > td {
border-bottom: 1px solid #1e73c2 !important;
background-color: #00152b !important;
color: #ffffff !important;
}
.ant-table-tbody > tr > td {
border-bottom: 1px solid #1e73c2 !important;
background-color: #00152b !important;
color: #ffffff !important;
}
.ant-table-tbody > tr.ant-table-row:hover > td,
.ant-table-tbody > tr > td.ant-table-cell-row-hover,
.ant-table-thead > tr > th {
background-color: #00152b !important;
color: #ffffff !important;
}
.ant-table-tbody > tr.ant-table-row:hover > td,
.ant-table-tbody > tr > td.ant-table-cell-row-hover,
.ant-table-thead > tr > th {
background-color: #00152b !important;
color: #ffffff !important;
}
.ant-table-cell-scrollbar {
box-shadow: none !important;
}
.ant-table-cell-scrollbar {
box-shadow: none !important;
}
/*
/*
表格滚动条
*/
.ant-table-body::-webkit-scrollbar-thumb {
border: 4px solid rgba(0, 0, 0, 0);
height: 6px;
border-radius: 25px;
background-clip: padding-box;
background-color: rgba(30, 115, 194, 0.3);
.ant-table-body::-webkit-scrollbar-thumb {
border: 4px solid rgba(0, 0, 0, 0);
height: 6px;
border-radius: 25px;
background-clip: padding-box;
background-color: rgba(30, 115, 194, 0.3);
}
}
}
</style>
+6 -6
View File
@@ -5,8 +5,8 @@ export enum TabType {
youTianYiYuan = '1', //油田医院
heZuoYiYuan = '2', //合作医院
yiLiaoDian = '3', //医疗点
jiuHuChe = '4', //救护车
zhiShengJi = '5', //直升机
jiuHuChe = '5', //救护车
zhiShengJi = '4', //直升机
diFangYiYuan = '6', //地方医院
}
@@ -105,12 +105,12 @@ export function mapApiSwitch(type, params: any) {
lon: 108, //经度
};
// 全部 油田 医疗点 合作医院
if ([TabType.all, TabType.youTianYiYuan, TabType.yiLiaoDian, TabType.heZuoYiYuan].includes(type)) {
if ([TabType.all, TabType.youTianYiYuan, TabType.yiLiaoDian, TabType.heZuoYiYuan, TabType.jiuHuChe, TabType.jiuHuChe].includes(type)) {
return getAllList({ ...basicParams, ...params });
}
if ([TabType.jiuHuChe].includes(type)) {
return getAmbulanceList({});
}
// if ([TabType.jiuHuChe].includes(type)) {
// return getAmbulanceList({});
// }
}
export const mapIcon1 = new URL('/@/assets/img/mapIcon1.png', import.meta.url).href;
+11 -10
View File
@@ -87,7 +87,6 @@
if (TabType.diFangYiYuan == item.type) {
Map.clearActiveHospital();
Map.map.on('moveend', logMapinfo);
// debugger;
return;
}
if (TabType.zhiShengJi == item.type) {
@@ -116,25 +115,26 @@
async function getMapData(type, params = {}) {
try {
const { code, result } = await mapApiSwitch(type, params);
if (code == 200 && Array.isArray(result) && result.length > 0) {
Map.createOverlay(result, {
content: (val) => {
return `<div style="
if (code == 200) {
if (Array.isArray(result) && result.length > 0) {
Map.createOverlay(result, {
content: (val) => {
return `<div style="
width: 21px;
height: 44px;
position: absolute;
left: -20px;
top: -20px;" title="${val?.name}">
</div>`;
},
});
},
});
} else {
Map.removeOverlayGroup();
}
}
} catch (e) {
console.log('error------------------------------');
console.warn(e);
}
1;
// console.log('--->data', result);
}
const footerData = ref({
@@ -241,6 +241,7 @@
display: flex;
flex-wrap: wrap;
justify-content: space-between;
font-size: 16px;
.tab {
width: calc(100% / 8);
+5 -2
View File
@@ -6,7 +6,7 @@
</template>
</public-title>
<div class="inner" ref="healthChart"></div>
<div class="count" v-show="props.tips">
<div class="count">
<div class="t">总人数</div>
<div class="v">{{ userCount }}</div>
</div>
@@ -48,6 +48,9 @@
() => props.data,
() => {
init();
},
{
deep: true,
}
);
@@ -57,7 +60,7 @@
function initChart(chartData, total, color) {
let myChart = echarts.init(healthChart.value);
let options = circleRing(chartData, total, color, '{d}%');
let options = circleRing(chartData, total, color);
myChart.setOption(options);
window.addEventListener('resize', () => {
myChart.resize();
+10 -9
View File
@@ -1,3 +1,6 @@
// 步数
import {visibleChartLabel} from "/@/utils/utils.ts";
export function screenPie(chartData, total, color, formatter) {
return {
color: color,
@@ -11,7 +14,7 @@ export function screenPie(chartData, total, color, formatter) {
borderColor: '#1b7ef2',
},
legend: {
left: '74%',
left: '72%',
top: 'center',
orient: 'vertical',
icon: 'circle',
@@ -24,22 +27,19 @@ export function screenPie(chartData, total, color, formatter) {
series: [
{
type: 'pie',
// radius: ['50%', '86%'],
// center: ['42%', '55%'],
radius: ['50%', '76%'],
center: ['42%', '49%'],
center: ['40%', '49%'],
avoidLabelOverlap: false,
label: {
show: true,
position: 'outside',
formatter: formatter,
color: '#ffffff',
fontSize: 14,
},
labelLine: {
show: true,
length: 6,
length2: 20,
length2: 10,
minTurnAngle: 120,
},
data: chartData,
@@ -49,7 +49,8 @@ export function screenPie(chartData, total, color, formatter) {
}
//左侧圆
export function circleRing(chartData, total, color, formatter) {
export function circleRing(chartData, total, color) {
const data = visibleChartLabel(chartData)
return {
color: color,
tooltip: {
@@ -81,14 +82,14 @@ export function circleRing(chartData, total, color, formatter) {
label: {
show: true,
position: 'inner',
formatter: formatter,
formatter: '{d}%',
color: '#ffffff',
fontSize: 14,
},
labelLine: {
show: false,
},
data: chartData,
data: data,
},
],
};
+1 -1
View File
@@ -58,7 +58,7 @@
}
.tips {
font-size: 13px;
font-size: 16px;
padding-right: 10px;
font-weight: normal;
}
@@ -1,6 +1,6 @@
<template>
<template v-for="(item, index) in dataList" :key="`list${index}`">
<item-d :title="item.title" :data="item.data" :tips="item.tips" :color="item.color" :userCount="item.userCount" />
<item-d :keu="spinning" :title="item.title" :data="item.data" :tips="item.tips" :color="item.color" :userCount="item.userCount" />
</template>
</template>
@@ -9,7 +9,9 @@
import { cloneDeep } from 'lodash-es';
import ItemD from '/@/components/item-d/item-d.vue';
import { getWatchDataByOrgCode } from '/@/components/secondaryScreen/commonApi.ts';
import { useSpin } from '/@/components/body-d-left/bodyLeftHooks.ts';
const { spinning, setSpin } = useSpin();
const dataList = ref([
{
title: '心率',
@@ -51,7 +53,7 @@
{
title: '体温',
data: [
{ name: '37.2', value: 0, key: 'normalCountCount' },
{ name: '<37.2', value: 0, key: 'normalCount' },
{ name: '37.2-38', value: 0, key: 'warnCount' },
{ name: '>38', value: 0, key: 'riskCount' },
],
@@ -73,6 +75,7 @@
async function init() {
const { code, result } = await getWatchDataByOrgCode(props);
// debugger;
if (code == 200) {
let data = cloneDeep(dataList.value);
data.forEach((item) => {
@@ -82,7 +85,9 @@
val.value = resData[val.key];
});
});
dataList.value = data;
setSpin(!spinning.value);
}
}
@@ -24,7 +24,6 @@
watch(
props,
() => {
console.log(111111111111);
init();
},
{ immediate: true }
@@ -69,7 +69,7 @@ export function sleepCharts({ time, short, long, awake, type }) {
height: 40,
itemHeight: 14,
top: -5,
left: '55%',
left: '52%',
},
color: ['#14B3F8', '#6D7BEB', '#5451DC'],
xAxis: {
@@ -23,7 +23,7 @@
</div>
</template>
<script lang="ts" setup>
import { onMounted, onUnmounted, ref, watch } from 'vue';
import { onUnmounted, ref, watch } from 'vue';
import PublicTitle from '/@/components/publicTitle.vue';
import { getMonitorList } from '/@/components/secondaryScreen/commonApi.ts';
import { monitorColumns } from '/@/components/secondaryScreen/screen-right/screenRightHooks.ts';
@@ -58,7 +58,6 @@
tableHeight.value == 0 && setHeight();
window.addEventListener('resize', setHeight);
timer.value && clearInterval(timer.value);
// interval();
},
{ immediate: true }
);
@@ -74,7 +73,7 @@
}
async function init(page) {
const { pageSize, current } = pagination.value;
const { pageSize } = pagination.value;
const { code, result } = await getMonitorList({ pageSize, pageNo: page, orgCode: props.orgCode });
if (code == 200) {
dataSource.value = result.records;
@@ -91,10 +90,8 @@
}
function interval() {
// timer.value = setInterval(() => {
let page = pagination.value.current < pages.value ? pagination.value.current + 1 : 1;
init(page);
// }, 3000);
}
const { refreshState } = useRefresh(PAGE_SWITCH, () => {
@@ -42,9 +42,10 @@
const { code, result } = await getStep(params);
setSpin(true);
if (code != 200) {
return;
return initChart(unref(stepData), 0);
}
setStep(result);
initChart(unref(stepData), '15000');
} catch {
initChart(unref(stepData), 0);
@@ -74,7 +75,7 @@
.count {
position: absolute;
width: 80%;
width: 77%;
top: 51%;
display: flex;
flex-direction: column;
@@ -56,7 +56,8 @@
function tableReload() {
apiParams.value = {
...getParams(),
flag: 0,
userId: props.userId,
pageSize: 10,
pageNo: 1,
};
@@ -84,8 +85,6 @@
status.value = s;
if (s) {
initEchart('0');
} else {
tableReload();
}
}
@@ -57,7 +57,8 @@
function tableReload() {
apiParams.value = {
...getParams(),
flag: 0,
userId: props.userId,
pageSize: 10,
pageNo: 1,
};
@@ -87,8 +88,6 @@
nextTick(() => {
initEchart('0');
});
} else {
tableReload();
}
}
@@ -52,7 +52,8 @@
function tableReload() {
apiParams.value = {
...getParams(),
flag: 0,
userId: props.userId,
pageSize: 10,
pageNo: 1,
};
@@ -55,7 +55,8 @@
function tableReload() {
apiParams.value = {
...getParams(),
flag: 0,
userId: props.userId,
pageSize: 10,
pageNo: 1,
};
@@ -83,8 +84,6 @@
nextTick(() => {
initEchart('0');
});
} else {
tableReload();
}
}
@@ -15,7 +15,7 @@
style="display: flex; justify-content: center; margin-top: 20px; align-items: center; position: relative"
:style="{ minHeight: props.showList ? '' : '30px' }"
>
<div style="position: absolute; left: 10px; display: flex; align-items: center" v-if="!props.showList">
<div class="fff" style="position: absolute; left: 10px; display: flex; align-items: center; color: #fff" v-if="!props.showList">
锻炼类型
<!-- <JDictSelectTag-->
<!-- v-model:value="motionType"-->
@@ -24,6 +24,13 @@
<!-- dictCode="watch_exercise_type"-->
<!-- @change="changeSelect"-->
<!-- />-->
<a-select
v-model:value="motionType"
class="type-select"
:field-names="montionFieldNames"
:options="selectOptions"
@change="changeSelect"
></a-select>
</div>
<div class="item-picker" style="display: flex; font-size: 20px" v-if="showStatus && props.showList">
<span style="margin: 0 0 0 5px; cursor: pointer" @click="changeDate('0')">&lt;</span>
@@ -52,13 +59,14 @@
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { nextTick, onMounted, ref } from 'vue';
import chartImg from '/@/assets/images/chart.png';
import listImg from '/@/assets/images/list.png';
import dayjs from 'dayjs';
import { propTypes } from '/@/utils/propTypes';
// import JDictSelectTag from '/@/components/Form/src/jeecg/components/JDictSelectTag.vue';
import { userDataDayByYearApi } from '/@/components/secondaryScreen/secondMap/secondMapApi.ts';
import { getCodeInfo, montionFieldNames } from '/@/api/dictCode.ts';
const props = defineProps({
showOne: propTypes.bool.def(true),
@@ -66,6 +74,21 @@
keyType: propTypes.string.def(''),
userId: propTypes.string.def(''),
});
const selectOptions = ref([]);
onMounted(() => {
getOptions();
});
async function getOptions() {
try {
const { code, result } = await getCodeInfo();
if (code == 0) {
nextTick(() => {
selectOptions.value = result?.records;
});
}
} catch {}
}
const emit = defineEmits(['changeV', 'changeShowStatus', 'changeM']);
@@ -93,7 +116,7 @@
};
userDataDayByYearApi(params)
.then((res) => {
infoData.value = res.month;
infoData.value = res?.result?.month;
})
.catch(() => {});
}
@@ -239,4 +262,4 @@
border: 1px solid #1890ff;
border-radius: 50px;
}
</style>
</style>
@@ -60,7 +60,8 @@
function tableReload() {
nextTick(() => {
apiParams.value = {
...getParams(),
flag: 0,
userId: props.userId,
pageSize: 10,
pageNo: 1,
};
@@ -93,8 +94,6 @@
nextTick(() => {
initEchart('0');
});
} else {
tableReload();
}
}
@@ -130,22 +129,29 @@
echart = echarts.init(chartRef.value);
const option = {
title: {},
legend: {},
legend: {
textStyle: {
color: '#fff',
},
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow',
},
textStyle: {
color: '#fff',
},
backgroundColor: 'rgba(50,50,50,0.7)',
borderColor: '#1b7ef2',
formatter: function (params) {
let tar1 = params[1];
let tar = params[0];
// let tar = params[1];
// return (tar1.value > 0 ? '短睡' : '长睡') + '<br/>' + tar.seriesName + ' : ' + tar.value;
let str = '';
if (type.value === 1) {
str = tar1.value > 0 ? '睡' : '睡';
str = tar1.value > 0 ? '睡' : '睡';
} else {
str = '睡' + ' : ' + (tar.value ? tar.value : 0) + '<br/>' + '睡' + ' : ' + (tar1.value ? tar1.value : 0);
str = '睡' + ' : ' + (tar.value ? tar.value : 0) + '<br/>' + '睡' + ' : ' + (tar1.value ? tar1.value : 0);
}
return str;
},
@@ -159,14 +165,18 @@
xAxis: {
type: 'category',
splitLine: { show: false },
data: xArr,
data: xArr || ['', ''],
axisLabel: {
color: '#fff',
},
min: 5,
},
yAxis: {
show: false,
},
series: [
{
name: '睡',
name: '睡',
type: 'bar',
barMaxWidth: '20px',
itemStyle: {
@@ -174,16 +184,10 @@
borderWidth: 0,
color: '#5087ec',
},
// emphasis: {
// itemStyle: {
// borderColor: '#68bbc4',
// color: '#68bbc4',
// },
// },
data: yArr,
},
{
name: '睡',
name: '睡',
barMaxWidth: '20px',
itemStyle: {
borderColor: '#85d0dc',
@@ -234,4 +238,4 @@
initEchart('0');
});
</script>
<style scoped lang="less"></style>
<style scoped lang="less"></style>
@@ -59,7 +59,8 @@
function tableReload() {
apiParams.value = {
...getParams(),
flag: 0,
userId: props.userId,
pageSize: 10,
pageNo: 1,
};
@@ -89,8 +90,6 @@
nextTick(() => {
initEchart('0');
});
} else {
tableReload();
}
}
@@ -123,7 +122,11 @@
backgroundColor: 'rgba(50,50,50,0.7)',
borderColor: '#1b7ef2',
},
legend: {},
legend: {
textStyle: {
color: '#fff',
},
},
xAxis: {
type: 'category',
boundaryGap: true,
@@ -56,7 +56,8 @@
function tableReload() {
apiParams.value = {
...getParams(),
flag: 0,
userId: props.userId,
pageSize: 10,
pageNo: 1,
};
@@ -86,8 +87,6 @@
nextTick(() => {
initEchart('0');
});
} else {
tableReload();
}
}
@@ -201,4 +200,4 @@
initEchart('0');
});
</script>
<style scoped lang="less"></style>
<style scoped lang="less"></style>
@@ -21,13 +21,19 @@
}
}
.fff {
color: #fff;
}
:deep(.ant-radio-button-checked) {
background-color: #1B7EF2 !important;
border-color: #1B7EF2 !important;
}
:deep(.ant-radio-button-wrapper-checked) {
border-color: #1B7EF2 !important;
}
:deep(.ant-radio-button-wrapper) {
background-color: #d8dce5 !important;
border-color: #d8dce5 !important;
@@ -29,6 +29,8 @@
import UserInfoModal from '/@/components/secondaryScreen/secondMap/components/userInfoModal/userInfoModal.vue';
import { columns } from '/@/components/secondaryScreen/secondMap/secondMapHooks.ts';
import { getUserListByDeptId } from '/@/components/secondaryScreen/secondMap/secondMapApi.ts';
const emit = defineEmits(['close']);
//分页相关
const current = ref(1);
const pageSize = ref(10);
@@ -61,6 +63,7 @@
function closeModal() {
visible.value = false;
emit('close');
}
async function getRecords(id: string) {
@@ -76,7 +79,6 @@
const userInfoModal = ref();
function openUserInfoModal(item) {
console.log('item', item);
const data = {
...item,
username: item?.realName,
@@ -9,32 +9,32 @@
</div>
<div v-show="false" id="container"></div>
<div v-show="false" id="panel"></div>
<div class="footer-data" v-show="isShow" style="--moveUp: 50px; --moveDown: -90px" :class="className">
<div v-show="isShow" :class="className" class="footer-data" style="--moveUp: 50px; --moveDown: -90px">
<div class="empty-png"></div>
<div
class="col-item nowrap"
v-for="item in footerList"
:style="{ cursor: item.key == 'allotDeviceNum' ? 'pointer' : 'default' }"
class="col-item nowrap"
@click="openWatchList(item)"
>
<div class="col-text">{{ item?.name }}</div>
<div class="col-value nowrap" :title="item.value">{{ item?.value }}</div>
<div :title="item.value" class="col-value nowrap">{{ item?.value }}</div>
</div>
</div>
<div
v-show="isShowAlarm"
:class="isShowAlarm ? 'slide-top' : 'slide-bottom'"
class="footer-dialog-con"
style="--moveUp: 120px; --moveDown: -120px"
:class="isShowAlarm ? 'slide-top' : 'slide-bottom'"
v-show="isShowAlarm"
>
<FooterDialog :detailLeft="detailLeft" :detailRight="detailRight" @closeDialog="closeDialog"></FooterDialog>
</div>
</div>
<WatchListDialog ref="watchDialogRef"></WatchListDialog>
<WatchListDialog ref="watchDialogRef" @close="closeWatch"></WatchListDialog>
</div>
</template>
<script lang="ts" setup>
import { onMounted, ref } from 'vue';
import { onMounted, ref, watch } from 'vue';
import { Map } from '/@/assets/mapUtils/map';
import $bus from '/@/utils/bus.ts';
import FooterDialog from '/@/components/secondaryScreen/secondMap/components/footerDialog.vue';
@@ -109,6 +109,12 @@
} catch {}
}
watch(
() => props.orgCode,
() => {
getMapList();
}
);
const { detailLeft, detailRight, setDetail } = useAlarmDetail();
onMounted(() => {
init();
@@ -121,12 +127,18 @@
});
/**
*@desc 预警弹窗关闭
*@desc 底部信息
*/
function closeDialog() {
setIsShowAlarm(!isShowAlarm.value);
Map.clearMarker();
}
/**
* @desc 预警弹窗关闭
*/
function closeWatch() {}
function drawMarker(data: any) {
const { lon, lat } = data;
if (!lon || !lat) return;
@@ -24,7 +24,8 @@ export function useDepart() {
async function getOptionData() {
const { result, code } = await allSecondaryDeparts();
if (code == 200) {
setOption(result);
let res = [{ departName: '长庆油田', orgCode: 'A01' }, ...result];
setOption(res);
}
}
+1 -1
View File
@@ -4,4 +4,4 @@ const BASIC_SECOND = 1000; //1s
//副屏 心率、血氧、压力、睡眠、步数
export const DEFAULT_TIME = BASIC_MIN * 10;
//预警分页切换
export const PAGE_SWITCH = BASIC_SECOND * 300;
export const PAGE_SWITCH = BASIC_SECOND * 3;
+74 -33
View File
@@ -15,9 +15,52 @@ export const basicPath = VITE_GLOB_API_YIN_JI;
export const emergencyPath = VITE_GLOB_API_JIAN_CE;
let t = token || getAuthCache(TOKEN_KEY);
export function useSocket(path = basicPath) {
export function useSocket(p = basicPath) {
const socket = ref();
let socketData = ref({});
let lockReconnect = ref(false); //避免ws重复连接
const path = ref(p);
function reconnect(path) {
if (lockReconnect.value) return;
lockReconnect.value = true;
setTimeout(function () {
//没连接上会一直重连,设置延迟避免请求过多
init(path);
lockReconnect.value = false;
}, 2000);
}
//心跳检测
const heartCheck = {
timeout: 1000 * 10, //1分钟发一次心跳
timeoutObj: null,
serverTimeoutObj: null,
reset: function () {
clearTimeout(this.timeoutObj);
clearTimeout(this.serverTimeoutObj);
return this;
},
start: function () {
let self = this;
this.timeoutObj = setTimeout(function () {
//这里发送一个心跳,后端收到后,返回一个心跳消息,
//onmessage拿到返回的心跳就说明连接正常
if (socket.value.readyState === WebSocket.OPEN) {
//console.log('p1' + new Date().toLocaleString());
socket.value.send('ping');
} else {
//console.log('p2');
init();
}
self.serverTimeoutObj = setTimeout(function () {
//如果超过一定时间还没重置,说明后端主动断开了
// TODO
// socket.value.close(); //如果onclose会执行reconnect,我们执行ws.close()就行了.如果直接执行reconnect 会触发onclose导致重连两次
}, self.timeout);
}, this.timeout);
},
};
function init() {
if (!t) {
@@ -27,44 +70,42 @@ export function useSocket(path = basicPath) {
alert('您的浏览器不支持socket');
} else {
// 实例化socket
socket.value = new WebSocket(path, [t]);
// 监听socket连接
socket.value.onopen = open;
// 监听socket错误信息
socket.value.onerror = error;
// 监听socket消息
socket.value.onmessage = getMessage;
socket.value.onclose = close;
socket.value = new WebSocket(path.value + Date.now(), [t]);
socket.value.onclose = function () {
reconnect(path.value);
//console.log('连接关闭!:', new Date().toLocaleString());
};
socket.value.onerror = function () {
reconnect(path.value);
//console.log('连接错误!');
};
socket.value.onopen = function () {
heartCheck.reset().start(); //心跳检测重置
//console.log('连接成功!' + new Date().toLocaleString());
};
socket.value.onmessage = function (event) {
//如果获取到消息,心跳检测重置
heartCheck.reset().start(); //拿到任何消息都说明当前连接是正常的
//console.log('收到消息啦:', event);
if (event.data != 'pong') {
let data = JSON.parse(event.data);
socketData.value = data;
}
};
}
}
function open() {
console.log('socket连接成功');
}
function error() {
console.log('socket连接错误');
}
function getMessage(msg) {
console.log('getMessage', msg);
socketData.value = JSON.parse(msg.data);
}
function setSocketData(data) {
socketData.value = data;
}
function close(data) {
console.log(data);
console.log('socket已经关闭');
init();
function closeSocket() {
socket.value && socket.value.close;
}
onMounted(() => {
init();
});
onUnmounted(() => {
//socket.value.onclose = close;
});
return { socket, socketData, setSocketData };
}
return { socket, socketData, setSocketData, closeSocket };
}
+24 -9
View File
@@ -1,4 +1,5 @@
import dayjs from 'dayjs';
import { cloneDeep } from 'lodash-es';
export function getZero(num: any) {
if (num < 10) {
@@ -9,15 +10,14 @@ export function getZero(num: any) {
export function useTopTime() {
const timeLeft = dayjs().format('YYYY年MM月DD日 HH时mm分ss秒');
const timeRight =
dayjs().diff(dayjs('2018-10-01'), 'day') +
'天' +
getZero(dayjs().diff(dayjs(dayjs().format('YYYY-MM-DD') + ' 00:00:00'), 'hours')) +
'时' +
getZero(dayjs().diff(dayjs(dayjs().format('YYYY-MM-DD HH') + ':00:00'), 'minutes')) +
'分' +
getZero(dayjs().diff(dayjs(dayjs().format('YYYY-MM-DD HH:mm') + ':00'), 'seconds')) +
'秒';
const timeRight = dayjs().diff(dayjs('2018-10-01'), 'day') + '天';
// +
// getZero(dayjs().diff(dayjs(dayjs().format('YYYY-MM-DD') + ' 00:00:00'), 'hours')) +
// '时' +
// getZero(dayjs().diff(dayjs(dayjs().format('YYYY-MM-DD HH') + ':00:00'), 'minutes')) +
// '分' +
// getZero(dayjs().diff(dayjs(dayjs().format('YYYY-MM-DD') + ':00'), 'seconds')) +
// '秒';
return {
timeLeft,
timeRight,
@@ -38,4 +38,19 @@ export function minuteToStr(minutes) {
return `${h}小时${m > 0 ? `${m}分钟` : ''}`;
}
return `${m}分钟`;
}
//处理echarts-环形图 数据为0时不显示label
export function visibleChartLabel(chartData) {
const data = cloneDeep(chartData);
let list = data?.map((item) => item?.value);
let flag = list.every((item) => item == 0);
if (!flag) {
data.forEach((val) => {
if (val.value == 0) {
val.value = null;
}
});
}
return data;
}
+19 -10
View File
@@ -66,7 +66,7 @@
});
init();
// 健康监测工具报警
const { socketData, setSocketData } = useSocket(basicPath);
const { socketData, setSocketData, closeSocket } = useSocket(basicPath);
const employeeDialogRef = ref();
watch(socketData, (nVal) => {
if (nVal) {
@@ -78,16 +78,25 @@
});
//应急求助
const { socketData: emergencyData, setSocketData: setEmergencyData } = useSocket(emergencyPath);
const emergencyDialogRef = ref();
// 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();
};
watch(emergencyData, (nVal) => {
if (nVal) {
nextTick(() => {
setEmergencyData(nVal);
emergencyDialogRef.value.openDialog;
});
}
clearInterval(interval.value);
});
function test() {
+1 -1
View File
@@ -9,7 +9,7 @@
返回
</span>
</div>
<div class="title-d-middle"> 应急就医服务中</div>
<div class="title-d-middle"> 血管监测</div>
<div class="title-d-right"> 累计运行时间{{ dayTimeT }}</div>
</div>
<div class="body-d">
+17
View File
@@ -2,12 +2,26 @@ import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import { resolve } from 'path';
import postcssPluginPx2rem from 'postcss-plugin-px2rem';
import resolveExternalsPlugin from 'vite-plugin-resolve-externals';
function pathResolve(dir: string) {
return resolve(process.cwd(), '.', dir);
}
const px2remOptions = {
remUnit: 14,
rootValue: 19, //换算基数, 默认100 ,也就是1440px ,这样的话把根标签的字体规定为1rem为50px,这样就可以从设计稿上量出多少个px直接在代码中写多少px了
unitPrecision: 5, //允许REM单位增长到的十进制数字,其实就是精度控制
// propWhiteList: [], // 默认值是一个空数组,这意味着禁用白名单并启用所有属性。
// propBlackList: [], // 黑名单
// exclude:false, //默认false,可以(reg)利用正则表达式排除某些文件夹的方法,例如/(node_module)/ 。如果想把前端UI框架内的px也转换成rem,请把此属性设为默认值
// selectorBlackList: [], //要忽略并保留为px的选择器
// ignoreIdentifier: false, //boolean/string)忽略单个属性的方法,启用ignoreidentifier后,replace将自动设置为true。
// replace: true, // (布尔值)替换包含REM的规则,而不是添加回退。
mediaQuery: false, //(布尔值)允许在媒体查询中转换px
minPixelValue: 0, //设置要替换的最小像素值(3px会被转rem)。 默认 0
};
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
@@ -22,6 +36,9 @@ export default defineConfig({
javascriptEnabled: true,
},
},
postcss: {
plugins: [postcssPluginPx2rem(px2remOptions)],
},
},
resolve: {
alias: [